From 5e68d600b9ac19ce318d9658d3a5508bb6e63516 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sat, 18 Jan 2020 02:46:59 +0200 Subject: [PATCH] melib/threads: Split ThreadGroup::Group to Thread Create Thread struct. --- melib/src/thread.rs | 199 +++++++++--------- ui/src/components/mail/listing/compact.rs | 110 +++++----- .../components/mail/listing/conversations.rs | 43 ++-- ui/src/conf/accounts.rs | 5 +- 4 files changed, 182 insertions(+), 175 deletions(-) diff --git a/melib/src/thread.rs b/melib/src/thread.rs index 736eb5cad..102ef9144 100644 --- a/melib/src/thread.rs +++ b/melib/src/thread.rs @@ -122,7 +122,9 @@ macro_rules! make { $threads.thread_nodes.entry($c).and_modify(|e| { e.parent = Some($p); }); - let old_group = $threads.groups[&old_group_hash].clone(); + let old_group = std::mem::replace($threads.groups.entry(old_group_hash).or_default(), ThreadGroup::Node { + parent: RefCell::new(parent_group_hash), + }); $threads.thread_nodes.entry($c).and_modify(|e| { e.group = parent_group_hash; }); @@ -130,21 +132,21 @@ macro_rules! make { e.group = parent_group_hash; }); { - let parent_group = $threads.groups.entry(parent_group_hash).or_default(); + let parent_group = $threads.thread_ref_mut(parent_group_hash); match (parent_group, old_group) { - (ThreadGroup::Group { + (Thread { ref mut date, ref mut len, ref mut unseen, ref mut snoozed, .. - }, ThreadGroup::Group { + }, ThreadGroup::Root(Thread { date: old_date, len: old_len, unseen: old_unseen, snoozed: old_snoozed, .. - }) => { + })) => { *date = std::cmp::max(old_date, *date); *len += old_len; *unseen |= old_unseen; @@ -153,14 +155,10 @@ macro_rules! make { _ => unreachable!(), } } - { - let old_group = $threads.groups.entry(old_group_hash).or_default(); - *old_group = ThreadGroup::Node { - parent: RefCell::new(parent_group_hash), - }; - } - prev_parent - } else { None } + prev_parent + } else { + None + } }}; } @@ -269,69 +267,62 @@ impl FromStr for SortOrder { } } +#[derive(Default, Clone, Debug, Deserialize, Serialize)] +pub struct Thread { + root: ThreadNodeHash, + date: UnixTimestamp, + len: usize, + unseen: usize, + + snoozed: bool, +} + #[derive(Clone, Debug, Deserialize, Serialize)] pub enum ThreadGroup { - Group { - root: ThreadNodeHash, - date: UnixTimestamp, - len: usize, - unseen: usize, - - snoozed: bool, - }, - Node { - parent: RefCell, - }, + Root(Thread), + Node { parent: RefCell }, } impl Default for ThreadGroup { fn default() -> Self { - ThreadGroup::Group { - root: ThreadNodeHash::null(), - date: 0, - len: 0, - unseen: 0, - snoozed: false, + ThreadGroup::Root(Thread::default()) + } +} + +impl ThreadGroup { + fn root(&self) -> Option<&Thread> { + if let ThreadGroup::Root(ref root) = self { + Some(root) + } else { + None + } + } + fn root_mut(&mut self) -> Option<&mut Thread> { + if let ThreadGroup::Root(ref mut root) = self { + Some(root) + } else { + None } } } macro_rules! property { - ($name:ident: $t:ty, $e:expr) => { + ($name:ident: $t:ty) => { pub fn $name(&self) -> $t { - match self { - ThreadGroup::Group { $name, .. } => (*$name).into(), - _ => { - debug!( - "ThreadGroup::{}() called on a ThreadGroup::Node: {:?}", - stringify!($name), - self - ); - $e - } - } + (self.$name).into() } } } -impl ThreadGroup { - property!(root: Option, None); - property!(len: usize, 0); - property!(unseen: usize, 0); - property!(snoozed: bool, false); - property!(date: UnixTimestamp, 0); + +impl Thread { + property!(root: ThreadNodeHash); + property!(len: usize); + property!(unseen: usize); + property!(snoozed: bool); + property!(date: UnixTimestamp); pub fn set_snoozed(&mut self, val: bool) { - match self { - ThreadGroup::Group { - ref mut snoozed, .. - } => *snoozed = val, - _ => { - debug!( - "ThreadGroup::set_snoozed() called on a ThreadGroup::Node: {:?}", - self - ); - } - } + self.snoozed = val; } } @@ -504,13 +495,26 @@ impl PartialEq for ThreadNode { impl Threads { pub fn is_snoozed(&self, h: ThreadNodeHash) -> bool { - let root = &self.find_group(self.thread_nodes[&h].group); - self.groups[&root].snoozed() + self.thread_ref(self.thread_nodes[&h].group).snoozed() + } + + pub fn thread_ref(&self, h: ThreadHash) -> &Thread { + match self.groups[&self.find_group(h)] { + ThreadGroup::Root(ref root) => root, + ThreadGroup::Node { .. } => unreachable!(), + } + } + + pub fn thread_ref_mut(&mut self, h: ThreadHash) -> &mut Thread { + match self.groups.get_mut(&self.find_group(h)) { + Some(ThreadGroup::Root(ref mut root)) => root, + Some(ThreadGroup::Node { .. }) | None => unreachable!(), + } } pub fn find_group(&self, h: ThreadHash) -> ThreadHash { let p = match self.groups[&h] { - ThreadGroup::Group { .. } => return h, + ThreadGroup::Root(_) => return h, ThreadGroup::Node { ref parent } => *parent.borrow(), }; @@ -579,7 +583,7 @@ impl Threads { pub fn thread_group_iter(&self, index: ThreadHash) -> ThreadGroupIterator { ThreadGroupIterator { - group: self.groups[&index].root().unwrap(), + group: self.thread_ref(index).root(), pos: 0, stack: SmallVec::new(), thread_nodes: &self.thread_nodes, @@ -610,16 +614,15 @@ impl Threads { let was_unseen = self.thread_nodes[&thread_hash].unseen; let is_unseen = !envelopes.read().unwrap()[&new_hash].is_seen(); if was_unseen != is_unseen { - let thread = self.find_group(self.thread_nodes[&thread_hash].group); - self.groups.entry(thread).and_modify(|e| { - if let ThreadGroup::Group { ref mut unseen, .. } = e { - if was_unseen { - *unseen -= 1; - } else { - *unseen += 1; - } + if let Thread { ref mut unseen, .. } = + self.thread_ref_mut(self.thread_nodes[&thread_hash].group) + { + if was_unseen { + *unseen -= 1; + } else { + *unseen += 1; } - }); + } } self.thread_nodes.get_mut(&thread_hash).unwrap().unseen = is_unseen; self.hash_set.remove(&old_hash); @@ -753,7 +756,7 @@ impl Threads { self.groups.insert( self.thread_nodes[&new_id].group, - ThreadGroup::Group { + ThreadGroup::Root(Thread { root: new_id, date: envelopes_lck[&env_hash].date(), len: 1, @@ -763,7 +766,7 @@ impl Threads { 0 }, snoozed: false, - }, + }), ); self.message_ids .insert(envelopes_lck[&env_hash].message_id().raw().to_vec(), new_id); @@ -795,13 +798,13 @@ impl Threads { self.groups.insert( self.thread_nodes[&reply_to_id].group, - ThreadGroup::Group { + ThreadGroup::Root(Thread { root: reply_to_id, date: envelopes_lck[&env_hash].date(), len: 0, unseen: 0, snoozed: false, - }, + }), ); make!((reply_to_id) parent of (new_id), self); self.missing_message_ids.insert(r.to_vec()); @@ -838,13 +841,13 @@ impl Threads { ); self.groups.insert( self.thread_nodes[&id].group, - ThreadGroup::Group { + ThreadGroup::Root(Thread { root: id, date: envelopes_lck[&env_hash].date(), len: 0, unseen: 0, snoozed: false, - }, + }), ); make!((id) parent of (current_descendant_id), self); self.missing_message_ids.insert(reference.raw().to_vec()); @@ -960,18 +963,18 @@ impl Threads { let envelopes = envelopes.read().unwrap(); vec.sort_by(|a, b| match sort { (SortField::Date, SortOrder::Desc) => { - let a = self.groups[&a].date(); - let b = self.groups[&b].date(); + let a = self.thread_ref(*a).date(); + let b = self.thread_ref(*b).date(); b.cmp(&a) } (SortField::Date, SortOrder::Asc) => { - let a = self.groups[&a].date(); - let b = self.groups[&b].date(); + let a = self.thread_ref(*a).date(); + let b = self.thread_ref(*b).date(); a.cmp(&b) } (SortField::Subject, SortOrder::Desc) => { - let a = &self.thread_nodes[&self.groups[&a].root().unwrap()].message(); - let b = &self.thread_nodes[&self.groups[&b].root().unwrap()].message(); + let a = &self.thread_nodes[&self.thread_ref(*a).root()].message(); + let b = &self.thread_nodes[&self.thread_ref(*b).root()].message(); match (a, b) { (Some(_), Some(_)) => {} @@ -999,8 +1002,8 @@ impl Threads { } } (SortField::Subject, SortOrder::Asc) => { - let a = &self.thread_nodes[&self.groups[&a].root().unwrap()].message(); - let b = &self.thread_nodes[&self.groups[&b].root().unwrap()].message(); + let a = &self.thread_nodes[&self.thread_ref(*a).root()].message(); + let b = &self.thread_nodes[&self.thread_ref(*b).root()].message(); match (a, b) { (Some(_), Some(_)) => {} @@ -1040,17 +1043,13 @@ impl Threads { let envelopes = envelopes.read().unwrap(); vec.sort_by(|a, b| match sort { (SortField::Date, SortOrder::Desc) => { - let a_group = self.find_group(self.thread_nodes[&a].group); - let b_group = self.find_group(self.thread_nodes[&b].group); - let a = self.groups[&a_group].date(); - let b = self.groups[&b_group].date(); + let a = self.thread_ref(self.thread_nodes[&a].group).date(); + let b = self.thread_ref(self.thread_nodes[&b].group).date(); b.cmp(&a) } (SortField::Date, SortOrder::Asc) => { - let a_group = self.find_group(self.thread_nodes[&a].group); - let b_group = self.find_group(self.thread_nodes[&b].group); - let a = self.groups[&a_group].date(); - let b = self.groups[&b_group].date(); + let a = self.thread_ref(self.thread_nodes[&a].group).date(); + let b = self.thread_ref(self.thread_nodes[&b].group).date(); a.cmp(&b) } (SortField::Subject, SortOrder::Desc) => { @@ -1120,17 +1119,13 @@ impl Threads { let envelopes = envelopes.read().unwrap(); tree.sort_by(|a, b| match sort { (SortField::Date, SortOrder::Desc) => { - let a_group = self.find_group(self.thread_nodes[&a].group); - let b_group = self.find_group(self.thread_nodes[&b].group); - let a = self.groups[&a_group].date(); - let b = self.groups[&b_group].date(); + let a = self.thread_ref(self.thread_nodes[&a].group).date(); + let b = self.thread_ref(self.thread_nodes[&b].group).date(); b.cmp(&a) } (SortField::Date, SortOrder::Asc) => { - let a_group = self.find_group(self.thread_nodes[&a].group); - let b_group = self.find_group(self.thread_nodes[&b].group); - let a = self.groups[&a_group].date(); - let b = self.groups[&b_group].date(); + let a = self.thread_ref(self.thread_nodes[&a].group).date(); + let b = self.thread_ref(self.thread_nodes[&b].group).date(); a.cmp(&b) } (SortField::Subject, SortOrder::Desc) => { diff --git a/ui/src/components/mail/listing/compact.rs b/ui/src/components/mail/listing/compact.rs index d15f7c7f5..b153ac4c3 100644 --- a/ui/src/components/mail/listing/compact.rs +++ b/ui/src/components/mail/listing/compact.rs @@ -118,13 +118,14 @@ impl ListingTrait for CompactListing { if self.length == 0 { return; } - let thread = self.get_thread_under_cursor(idx, context); + let thread_hash = self.get_thread_under_cursor(idx, context); let account = &context.accounts[self.cursor_pos.0]; let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash(); let threads = &account.collection.threads[&folder_hash]; + let thread = threads.thread_ref(thread_hash); - let fg_color = if threads.groups[&thread].unseen() > 0 { + let fg_color = if thread.unseen() > 0 { Color::Byte(0) } else { Color::Default @@ -132,9 +133,9 @@ impl ListingTrait for CompactListing { let bg_color = if context.settings.terminal.theme == "light" { if self.cursor_pos.2 == idx { Color::Byte(244) - } else if self.selection[&thread] { + } else if self.selection[&thread_hash] { Color::Byte(210) - } else if threads.groups[&thread].unseen() > 0 { + } else if thread.unseen() > 0 { Color::Byte(251) } else if idx % 2 == 0 { Color::Byte(252) @@ -144,9 +145,9 @@ impl ListingTrait for CompactListing { } else { if self.cursor_pos.2 == idx { Color::Byte(246) - } else if self.selection[&thread] { + } else if self.selection[&thread_hash] { Color::Byte(210) - } else if threads.groups[&thread].unseen() > 0 { + } else if thread.unseen() > 0 { Color::Byte(251) } else if idx % 2 == 0 { Color::Byte(236) @@ -549,7 +550,7 @@ impl CompactListing { threads: &Threads, hash: ThreadHash, ) -> EntryStrings { - let thread = &threads.groups[&hash]; + let thread = threads.thread_ref(hash); let folder_hash = &context.accounts[self.cursor_pos.0][self.cursor_pos.1] .unwrap() .folder @@ -714,7 +715,7 @@ impl CompactListing { for (idx, thread) in items.enumerate() { debug!(thread); self.length += 1; - let thread_node = &threads.thread_nodes()[&threads.groups[&thread].root().unwrap()]; + let thread_node = &threads.thread_nodes()[&threads.thread_ref(thread).root()]; let root_env_hash = thread_node.message().unwrap_or_else(|| { let mut iter_ptr = thread_node.children()[0]; while threads.thread_nodes()[&iter_ptr].message().is_none() { @@ -811,13 +812,14 @@ impl CompactListing { panic!(); } - let fg_color = if threads.groups[&thread].unseen() > 0 { + let thread = threads.thread_ref(thread); + let fg_color = if thread.unseen() > 0 { Color::Byte(0) } else { Color::Default }; let bg_color = if context.settings.terminal.theme == "light" { - if threads.groups[&thread].unseen() > 0 { + if thread.unseen() > 0 { Color::Byte(251) } else if idx % 2 == 0 { Color::Byte(252) @@ -825,7 +827,7 @@ impl CompactListing { Color::Default } } else { - if threads.groups[&thread].unseen() > 0 { + if thread.unseen() > 0 { Color::Byte(251) } else if idx % 2 == 0 { Color::Byte(236) @@ -921,7 +923,7 @@ impl CompactListing { self.data_columns.columns[4][(x, idx)].set_bg(bg_color); } match ( - threads.groups[&thread].snoozed(), + thread.snoozed(), context.accounts[self.cursor_pos.0] .collection .get_env(root_env_hash) @@ -983,9 +985,9 @@ impl CompactListing { let account = &context.accounts[self.cursor_pos.0]; let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash(); let threads = &account.collection.threads[&folder_hash]; - if let Some(env_hash) = - threads.thread_nodes()[&threads.groups[&thread_hash].root().unwrap()].message() - { + let thread = threads.thread_ref(thread_hash); + // FIXME: Thread root doesn't nessessarily have message set + if let Some(env_hash) = threads.thread_nodes()[&thread.root()].message() { if !account.contains_key(env_hash) { /* The envelope has been renamed or removed, so wait for the appropriate event to * arrive */ @@ -993,14 +995,14 @@ impl CompactListing { } let envelope: EnvelopeRef = account.collection.get_env(env_hash); let has_attachments = envelope.has_attachments(); - let fg_color = if threads.groups[&thread_hash].unseen() > 0 { + let fg_color = if thread.unseen() > 0 { Color::Byte(0) } else { Color::Default }; let idx = self.order[&thread_hash]; let bg_color = if context.settings.terminal.theme == "light" { - if threads.groups[&thread_hash].unseen() > 0 { + if thread.unseen() > 0 { Color::Byte(251) } else if idx % 2 == 0 { Color::Byte(252) @@ -1008,7 +1010,7 @@ impl CompactListing { Color::Default } } else { - if threads.groups[&thread_hash].unseen() > 0 { + if thread.unseen() > 0 { Color::Byte(253) } else if idx % 2 == 0 { Color::Byte(236) @@ -1117,7 +1119,7 @@ impl CompactListing { columns[4][c].set_ch(' '); columns[4][c].set_bg(bg_color); } - match (threads.groups[&thread_hash].snoozed(), has_attachments) { + match (thread.snoozed(), has_attachments) { (true, true) => { columns[3][(0, idx)].set_fg(Color::Byte(103)); columns[3][(2, idx)].set_fg(Color::Red); @@ -1246,41 +1248,45 @@ impl Component for CompactListing { let thread_hash = self.get_thread_under_cursor(self.cursor_pos.2, context); self.selection.entry(thread_hash).and_modify(|e| *e = !*e); } - UIEvent::Action(ref action) => match action { - Action::Sort(field, order) if !self.unfocused => { - debug!("Sort {:?} , {:?}", field, order); - self.sort = (*field, *order); - if !self.filtered_selection.is_empty() { - // FIXME: perform sort - self.dirty = true; - } else { - self.refresh_mailbox(context); + UIEvent::Action(ref action) => { + match action { + Action::Sort(field, order) if !self.unfocused => { + debug!("Sort {:?} , {:?}", field, order); + self.sort = (*field, *order); + if !self.filtered_selection.is_empty() { + // FIXME: perform sort + self.dirty = true; + } else { + self.refresh_mailbox(context); + } + return true; + } + Action::SubSort(field, order) if !self.unfocused => { + debug!("SubSort {:?} , {:?}", field, order); + self.subsort = (*field, *order); + // FIXME: perform subsort. + return true; + } + Action::ToggleThreadSnooze if !self.unfocused => { + let thread = self.get_thread_under_cursor(self.cursor_pos.2, context); + let account = &mut context.accounts[self.cursor_pos.0]; + let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash(); + account + .collection + .threads + .entry(folder_hash) + .and_modify(|threads| { + let is_snoozed = threads.thread_ref(thread).snoozed(); + threads.thread_ref_mut(thread).set_snoozed(!is_snoozed); + }); + self.row_updates.push(thread); + self.refresh_mailbox(context); + return true; } - return true; - } - Action::SubSort(field, order) if !self.unfocused => { - debug!("SubSort {:?} , {:?}", field, order); - self.subsort = (*field, *order); - // FIXME: perform subsort. - return true; - } - Action::ToggleThreadSnooze if !self.unfocused => { - let thread = self.get_thread_under_cursor(self.cursor_pos.2, context); - let account = &mut context.accounts[self.cursor_pos.0]; - let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash(); - let threads = account.collection.threads.entry(folder_hash).or_default(); - let is_snoozed = threads.groups[&thread].snoozed(); - threads - .groups - .entry(thread) - .and_modify(|entry| entry.set_snoozed(!is_snoozed)); - self.row_updates.push(thread); - self.refresh_mailbox(context); - return true; - } - _ => {} - }, + _ => {} + } + } _ => {} } } diff --git a/ui/src/components/mail/listing/conversations.rs b/ui/src/components/mail/listing/conversations.rs index 4012657f9..67fcf46d3 100644 --- a/ui/src/components/mail/listing/conversations.rs +++ b/ui/src/components/mail/listing/conversations.rs @@ -149,22 +149,23 @@ impl ListingTrait for ConversationsListing { if self.length == 0 { return; } - let thread = self.get_thread_under_cursor(idx, context); + let thread_hash = self.get_thread_under_cursor(idx, context); let account = &context.accounts[self.cursor_pos.0]; let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash(); let threads = &account.collection.threads[&folder_hash]; + let thread = threads.thread_ref(thread_hash); - let fg_color = if threads.groups[&thread].unseen() > 0 { + let fg_color = if thread.unseen() > 0 { Color::Byte(0) } else { Color::Default }; let bg_color = if self.cursor_pos.2 == idx { Color::Byte(246) - } else if self.selection[&thread] { + } else if self.selection[&thread_hash] { Color::Byte(210) - } else if threads.groups[&thread].unseen() > 0 { + } else if thread.unseen() > 0 { Color::Byte(251) } else { Color::Default @@ -186,7 +187,7 @@ impl ListingTrait for ConversationsListing { let (upper_left, bottom_right) = area; let width = self.content.size().0; let (x, y) = upper_left; - if self.cursor_pos.2 == idx || self.selection[&thread] { + if self.cursor_pos.2 == idx || self.selection[&thread_hash] { for x in x..=get_x(bottom_right) { grid[(x, y)].set_fg(fg_color); grid[(x, y)].set_bg(bg_color); @@ -522,7 +523,7 @@ impl ConversationsListing { threads: &Threads, hash: ThreadHash, ) -> EntryStrings { - let thread = &threads.groups[&hash]; + let thread = threads.thread_ref(hash); let folder_hash = &context.accounts[self.cursor_pos.0][self.cursor_pos.1] .unwrap() .folder @@ -676,7 +677,7 @@ impl ConversationsListing { std::collections::HashSet::new(); for (idx, thread) in items.enumerate() { self.length += 1; - let thread_node = &threads.thread_nodes()[&threads.groups[&thread].root().unwrap()]; + let thread_node = &threads.thread_nodes()[&threads.thread_ref(thread).root()]; let root_env_hash = thread_node.message().unwrap_or_else(|| { let mut iter_ptr = thread_node.children()[0]; while threads.thread_nodes()[&iter_ptr].message().is_none() { @@ -750,12 +751,13 @@ impl ConversationsListing { if !context.accounts[self.cursor_pos.0].contains_key(root_env_hash) { panic!(); } - let fg_color = if threads.groups[&thread].unseen() > 0 { + let thread = threads.thread_ref(thread); + let fg_color = if thread.unseen() > 0 { Color::Byte(0) } else { Color::Default }; - let bg_color = if threads.groups[&thread].unseen() > 0 { + let bg_color = if thread.unseen() > 0 { Color::Byte(251) } else { Color::Default @@ -919,19 +921,18 @@ impl ConversationsListing { let account = &context.accounts[self.cursor_pos.0]; let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash(); let threads = &account.collection.threads[&folder_hash]; + let thread = threads.thread_ref(thread_hash); let idx: usize = self.order[&thread_hash]; let width = self.content.size().0; - let env_hash = threads.thread_nodes()[&threads.groups[&thread_hash].root().unwrap()] - .message() - .unwrap(); + let env_hash = threads.thread_nodes()[&thread.root()].message().unwrap(); - let fg_color = if threads.groups[&thread_hash].unseen() > 0 { + let fg_color = if thread.unseen() > 0 { Color::Byte(0) } else { Color::Default }; - let bg_color = if threads.groups[&thread_hash].unseen() > 0 { + let bg_color = if thread.unseen() > 0 { Color::Byte(251) } else { Color::Default @@ -1262,12 +1263,14 @@ impl Component for ConversationsListing { let thread = self.get_thread_under_cursor(self.cursor_pos.2, context); let account = &mut context.accounts[self.cursor_pos.0]; let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash(); - let threads = account.collection.threads.entry(folder_hash).or_default(); - let is_snoozed = threads.groups[&thread].snoozed(); - threads - .groups - .entry(thread) - .and_modify(|entry| entry.set_snoozed(!is_snoozed)); + account + .collection + .threads + .entry(folder_hash) + .and_modify(|threads| { + let is_snoozed = threads.thread_ref(thread).snoozed(); + threads.thread_ref_mut(thread).set_snoozed(!is_snoozed); + }); self.row_updates.push(thread); self.refresh_mailbox(context); return true; diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs index 0241f3d91..33c2534fd 100644 --- a/ui/src/conf/accounts.rs +++ b/ui/src/conf/accounts.rs @@ -599,7 +599,10 @@ impl Account { self.collection.threads[&folder_hash] .find_group(self.collection.threads[&folder_hash][&thread_hash].group) }; - if self.collection.threads[&folder_hash].groups[&thread].snoozed() { + if self.collection.threads[&folder_hash] + .thread_ref(thread) + .snoozed() + { return Some(UIEvent::MailboxUpdate((self.index, folder_hash))); } if is_seen || is_draft {