From 3c575c823da863573d831ab622c2f7b846bd60d5 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Wed, 15 May 2019 20:58:59 +0300 Subject: [PATCH] ui: toggle thread snooze flag snooze field translated to whether the user wants to be notified of new email in the thread or not. This is toggled with an (temp) EX cmd: `toggle_thread_snooze` closes #112 --- melib/src/mailbox/thread.rs | 31 +++++++++++- ui/src/components/mail/listing/compact.rs | 57 +++++++++++++++++++++-- ui/src/conf/accounts.rs | 10 +++- ui/src/execute.rs | 7 ++- ui/src/execute/actions.rs | 1 + 5 files changed, 97 insertions(+), 9 deletions(-) diff --git a/melib/src/mailbox/thread.rs b/melib/src/mailbox/thread.rs index a4e1c47fa..ded6b943d 100644 --- a/melib/src/mailbox/thread.rs +++ b/melib/src/mailbox/thread.rs @@ -359,6 +359,8 @@ pub struct ThreadNode { len: usize, has_unseen: bool, + snoozed: bool, + /* Union/Find set fields */ thread_group: ThreadHash, rank: i32, @@ -376,6 +378,8 @@ impl Default for ThreadNode { len: 0, has_unseen: false, + snoozed: false, + thread_group: ThreadHash::default(), rank: 0, } @@ -428,11 +432,23 @@ impl ThreadNode { pub fn indentation(&self) -> usize { self.indentation } + + pub fn snoozed(&self) -> bool { + self.snoozed + } + + pub fn thread_group(&self) -> ThreadHash { + self.thread_group + } + + pub fn set_snoozed(&mut self, set: bool) { + self.snoozed = set; + } } #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Threads { - thread_nodes: FnvHashMap, + pub thread_nodes: FnvHashMap, root_set: RefCell>, tree: RefCell>, @@ -468,6 +484,13 @@ impl<'a> Iterator for RootIterator<'a> { } } } +fn find_ref(buf: &FnvHashMap, h: ThreadHash) -> ThreadHash { + if buf[&h].thread_group == h { + return h; + } + let p = buf[&h].thread_group; + find_ref(buf, p) +} fn find(buf: &mut FnvHashMap, h: ThreadHash) -> ThreadHash { if buf[&h].thread_group == h { return h; @@ -502,7 +525,11 @@ fn union(buf: &mut FnvHashMap, x: ThreadHash, y: ThreadH } impl Threads { - fn find(&mut self, i: ThreadHash) -> ThreadHash { + pub fn is_snoozed(&self, h: ThreadHash) -> bool { + let root = find_ref(&self.thread_nodes, h); + self.thread_nodes[&root].snoozed() + } + pub fn find(&mut self, i: ThreadHash) -> ThreadHash { find(&mut self.thread_nodes, i) } fn union(&mut self, x: ThreadHash, y: ThreadHash) -> ThreadHash { diff --git a/ui/src/components/mail/listing/compact.rs b/ui/src/components/mail/listing/compact.rs index 39978e03f..242283a7d 100644 --- a/ui/src/components/mail/listing/compact.rs +++ b/ui/src/components/mail/listing/compact.rs @@ -104,20 +104,30 @@ impl MailboxView { e: &Envelope, len: usize, idx: usize, + is_snoozed: bool, ) -> (IndexNoString, FromString, DateString, SubjectString) { if len > 0 { ( IndexNoString(idx.to_string()), FromString(address_list!((e.from()) as comma_sep_list)), DateString(MailboxView::format_date(e)), - SubjectString(format!("{} ({})", e.subject(), len)), + SubjectString(format!( + "{} ({}){}", + e.subject(), + len, + if is_snoozed { " 💤" } else { "" } + )), ) } else { ( IndexNoString(idx.to_string()), FromString(address_list!((e.from()) as comma_sep_list)), DateString(MailboxView::format_date(e)), - SubjectString(e.subject().to_string()), + SubjectString(format!( + "{}{}", + e.subject(), + if is_snoozed { " 💤" } else { "" } + )), ) } } @@ -229,7 +239,13 @@ impl MailboxView { panic!(); } let root_envelope: &Envelope = &mailbox.collection[&i]; - let strings = MailboxView::make_entry_string(root_envelope, thread_node.len(), idx); + + let strings = MailboxView::make_entry_string( + root_envelope, + thread_node.len(), + idx, + threads.is_snoozed(root_idx), + ); min_width.0 = cmp::max(min_width.0, strings.0.len()); /* index */ min_width.1 = cmp::max(min_width.1, strings.2.split_graphemes().len()); /* date */ min_width.2 = cmp::max(min_width.2, strings.3.split_graphemes().len()); /* subject */ @@ -328,6 +344,9 @@ impl MailboxView { ((_x, idx), (widths.2 + _x, idx)), false, ); + if threads.is_snoozed(root_idx) { + self.content[(x - 1, idx)].set_fg(Color::Red); + } self.order.insert(i, idx); @@ -596,8 +615,7 @@ impl Component for MailboxView { } UIEvent::StartupCheck(ref f) if *f - == context.accounts[self.new_cursor_pos.0].folders_order - [self.new_cursor_pos.1] => + == context.accounts[self.cursor_pos.0].folders_order[self.new_cursor_pos.1] => { self.refresh_mailbox(context); self.set_dirty(); @@ -639,6 +657,35 @@ impl Component for MailboxView { self.refresh_mailbox(context); return true; } + Action::ToggleThreadSnooze => { + { + //FIXME NLL + + let mailbox = &mut context.accounts[self.cursor_pos.0][self.cursor_pos.1] + .as_mut() + .unwrap(); + let threads = &mut mailbox.collection.threads; + let thread_group = threads.thread_nodes() + [&threads.root_set(self.cursor_pos.2)] + .thread_group(); + let thread_group = threads.find(thread_group); + /*let i = if let Some(i) = threads.thread_nodes[&thread_group].message() { + i + } else { + let mut iter_ptr = threads.thread_nodes[&thread_group].children()[0]; + while threads.thread_nodes()[&iter_ptr].message().is_none() { + iter_ptr = threads.thread_nodes()[&iter_ptr].children()[0]; + } + threads.thread_nodes()[&iter_ptr].message().unwrap() + };*/ + let root_node = threads.thread_nodes.entry(thread_group).or_default(); + let is_snoozed = root_node.snoozed(); + root_node.set_snoozed(!is_snoozed); + //self.row_updates.push(i); + } + self.refresh_mailbox(context); + return true; + } _ => {} }, _ => {} diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs index a927193dc..88b8f177b 100644 --- a/ui/src/conf/accounts.rs +++ b/ui/src/conf/accounts.rs @@ -290,12 +290,20 @@ impl Account { } RefreshEventKind::Create(envelope) => { debug!("create {}", envelope.hash()); - let env: &Envelope = mailbox!(&folder_hash, self.folders).insert(*envelope); + let env_hash: EnvelopeHash = { + let mailbox = mailbox!(&folder_hash, self.folders); + mailbox.insert(*envelope).hash() + }; let ref_folders: FnvHashMap = self.backend.folders(); let folder_conf = &self.settings.folder_confs[&self.folder_names[&folder_hash]]; if folder_conf.ignore.is_true() { return None; } + let (env, thread_node) = + mailbox!(&folder_hash, self.folders).mail_and_thread(env_hash); + if thread_node.snoozed() { + return None; + } return Some(Notification( Some("new mail".into()), format!( diff --git a/ui/src/execute.rs b/ui/src/execute.rs index 0432d22fa..9282516fa 100644 --- a/ui/src/execute.rs +++ b/ui/src/execute.rs @@ -90,6 +90,11 @@ named!( preceded!(tag!("set "), alt_complete!(threaded | plain | compact)) ); +named!( + toggle_thread_snooze, + map!(ws!(tag!("toggle_thread_snooze")), |_| ToggleThreadSnooze) +); + named!(pub parse_command, - alt_complete!( goto | toggle | sort | subsort | close) + alt_complete!( goto | toggle | sort | subsort | close | toggle_thread_snooze) ); diff --git a/ui/src/execute/actions.rs b/ui/src/execute/actions.rs index 5402c846c..fa9070a37 100644 --- a/ui/src/execute/actions.rs +++ b/ui/src/execute/actions.rs @@ -54,4 +54,5 @@ pub enum Action { Sort(SortField, SortOrder), SubSort(SortField, SortOrder), Tab(TabAction), + ToggleThreadSnooze, }