This commit is contained in:
Michael Zhang 2021-03-10 05:07:08 -06:00
parent e437d95b9b
commit 4e3d2e63f3
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
6 changed files with 31 additions and 9 deletions

View file

@ -3,8 +3,7 @@
Panorama is a personal information manager. Panorama is a personal information manager.
- [rustdoc autogenerated API docs][1] - [rustdoc autogenerated API docs][1]
- [Github repository][3] - [Github][3] ( [issues][4] )
- [Issue tracker][4]
- [Matrix chat #panorama:mozilla.org][5] - [Matrix chat #panorama:mozilla.org][5]
## Quick Start ## Quick Start

View file

@ -240,7 +240,7 @@ pub enum MailboxData {
}, },
} }
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub enum MailboxFlag { pub enum MailboxFlag {
Answered, Answered,
Flagged, Flagged,

View file

@ -1,12 +1,19 @@
design ideas design ideas
--- ---
- instead of dumb search with `/`, have like an omnibar with recency info built in? - instead of dumb search, have like an omnibar with recency info built in?
- this requires some kind of cache and text search - this requires some kind of cache and text search
- mail view has like a "filter stack"
- initially, this is empty, but when u do `/` u can add stuff like `acct:personal`, or `date<2020-03` or `has:attachment` or `from:*@gmail.com`
- then, when u hit enter, it gets added to a stack and u can like pop off filters
- example wld be liek `[acct:personal] [is:unread] [subject:"(?i)*github*"]` and then when u pop off the filter u just get `[acct:personal] [is:unread]`
- tmux-like windows - tmux-like windows
- maybe some of the familiar commands? `<C-b %>` for split for ex, - maybe some of the familiar commands? `<C-b %>` for split for ex,
- gluon for scripting language - gluon for scripting language
- hook into some global keybinds/hooks struct - hook into some global keybinds/hooks struct
- need commands:
- create dir
- move email to dir
- transparent self-updates?? this could work with some kind of deprecation scheme for the config files - transparent self-updates?? this could work with some kind of deprecation scheme for the config files
- for ex: v1 has `{ x: Int }`, v2 has `{ [deprecated] x: Int, x2: Float }` and v3 has `{ x2: Float }` - for ex: v1 has `{ x: Int }`, v2 has `{ [deprecated] x: Int, x2: Float }` and v3 has `{ x2: Float }`
this means v1 -> v2 upgrade can be done automatically but because there are _any_ pending deprecated values being used this means v1 -> v2 upgrade can be done automatically but because there are _any_ pending deprecated values being used

View file

@ -1,3 +1,5 @@
use std::collections::HashSet;
use chrono::{DateTime, Local}; use chrono::{DateTime, Local};
use panorama_imap::response::*; use panorama_imap::response::*;
@ -8,7 +10,7 @@ pub struct EmailMetadata {
pub uid: Option<u32>, pub uid: Option<u32>,
/// Whether or not this message is unread /// Whether or not this message is unread
pub unread: Option<bool>, pub unread: bool,
/// Date /// Date
pub date: Option<DateTime<Local>>, pub date: Option<DateTime<Local>>,
@ -27,6 +29,12 @@ impl EmailMetadata {
for attr in attrs { for attr in attrs {
match attr { match attr {
AttributeValue::Flags(flags) => {
let flags = flags.into_iter().collect::<HashSet<_>>();
if !flags.contains(&MailboxFlag::Seen) {
meta.unread = true;
}
}
AttributeValue::Uid(new_uid) => meta.uid = Some(new_uid), AttributeValue::Uid(new_uid) => meta.uid = Some(new_uid),
AttributeValue::InternalDate(new_date) => { AttributeValue::InternalDate(new_date) => {
meta.date = Some(new_date.with_timezone(&Local)); meta.date = Some(new_date.with_timezone(&Local));

View file

@ -121,13 +121,21 @@ impl MailTabState {
.iter() .iter()
.rev() .rev()
.map(|meta| { .map(|meta| {
Row::new(vec![ let mut row = Row::new(vec![
"".to_owned(), String::from(if meta.unread { "\u{2b24}" } else { "" }),
meta.uid.map(|u| u.to_string()).unwrap_or_default(), meta.uid.map(|u| u.to_string()).unwrap_or_default(),
meta.date.map(|d| humanize_timestamp(d)).unwrap_or_default(), meta.date.map(|d| humanize_timestamp(d)).unwrap_or_default(),
meta.from.clone(), meta.from.clone(),
meta.subject.clone(), meta.subject.clone(),
]) ]);
if meta.unread {
row = row.style(
Style::default()
.fg(Color::LightCyan)
.add_modifier(Modifier::BOLD),
);
}
row
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View file

@ -78,7 +78,7 @@ pub async fn run_ui(
.split(f.size()); .split(f.size());
// this is the title bar // this is the title bar
let titles = vec!["panorama mail"].into_iter().map(Spans::from).collect(); let titles = vec!["email"].into_iter().map(Spans::from).collect();
let tabs = Tabs::new(titles); let tabs = Tabs::new(titles);
f.render_widget(tabs, chunks[0]); f.render_widget(tabs, chunks[0]);