From 817c338a1371b92edc7ebafed2d4bf66512a44b3 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sun, 15 Sep 2019 09:44:15 +0300 Subject: [PATCH] melib: fix metadata updates in Envelope updates --- melib/src/collection.rs | 25 ++++++++++++++++------ melib/src/thread.rs | 47 ++++++++++++++++++++++++++++++++++------- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/melib/src/collection.rs b/melib/src/collection.rs index 7feb4f20b..e850f7edd 100644 --- a/melib/src/collection.rs +++ b/melib/src/collection.rs @@ -99,7 +99,7 @@ impl Collection { .threads .entry(folder_hash) .or_default() - .update_envelope(old_hash, new_hash) + .update_envelope(&self.envelopes, old_hash, new_hash) .is_ok() { return; @@ -114,7 +114,9 @@ impl Collection { if *h == folder_hash { continue; } - t.update_envelope(old_hash, new_hash).ok().take(); + t.update_envelope(&self.envelopes, old_hash, new_hash) + .ok() + .take(); } } @@ -227,15 +229,22 @@ impl Collection { } } - pub fn update(&mut self, old_hash: EnvelopeHash, envelope: Envelope, folder_hash: FolderHash) { - self.envelopes.remove(&old_hash); + pub fn update( + &mut self, + old_hash: EnvelopeHash, + mut envelope: Envelope, + folder_hash: FolderHash, + ) { + let old_env = self.envelopes.remove(&old_hash).unwrap(); + envelope.set_thread(old_env.thread()); let new_hash = envelope.hash(); self.message_ids .insert(envelope.message_id().raw().to_vec(), new_hash); self.envelopes.insert(new_hash, envelope); if self.sent_folder.map(|f| f == folder_hash).unwrap_or(false) { for (_, t) in self.threads.iter_mut() { - t.update_envelope(old_hash, new_hash).unwrap_or(()); + t.update_envelope(&self.envelopes, old_hash, new_hash) + .unwrap_or(()); } } { @@ -243,7 +252,7 @@ impl Collection { .threads .entry(folder_hash) .or_default() - .update_envelope(old_hash, new_hash) + .update_envelope(&self.envelopes, old_hash, new_hash) .is_ok() { return; @@ -258,7 +267,9 @@ impl Collection { if *h == folder_hash { continue; } - t.update_envelope(old_hash, new_hash).ok().take(); + t.update_envelope(&self.envelopes, old_hash, new_hash) + .ok() + .take(); } } diff --git a/melib/src/thread.rs b/melib/src/thread.rs index 9e76879da..ed2c8adbc 100644 --- a/melib/src/thread.rs +++ b/melib/src/thread.rs @@ -139,12 +139,14 @@ macro_rules! make { } let child_date = $buf[&$c].date; let child_len = $buf[&$c].len; + let has_unseen = $buf[&$c].has_unseen; $buf.entry($c).and_modify(|e| { e.parent = Some($p); }); $buf.entry($p).and_modify(|e| { e.len += child_len + 1; e.date = std::cmp::max(e.date, child_date); + e.has_unseen |= has_unseen; }); union($buf, $c, $p); prev_parent @@ -698,6 +700,7 @@ impl Threads { pub fn update_envelope( &mut self, + envelopes: &Envelopes, old_hash: EnvelopeHash, new_hash: EnvelopeHash, ) -> Result<(), ()> { @@ -705,15 +708,36 @@ impl Threads { * - hash_set * - message fields in thread_nodes */ - if let Some(node) = self + let thread_hash = if let Some((key, _)) = self .thread_nodes - .values_mut() - .find(|n| n.message.map(|n| n == old_hash).unwrap_or(false)) + .iter() + .find(|(_, n)| n.message.map(|n| n == old_hash).unwrap_or(false)) { - node.message = Some(new_hash); + *key } else { return Err(()); }; + + self.thread_nodes.get_mut(&thread_hash).unwrap().message = Some(new_hash); + self.thread_nodes.get_mut(&thread_hash).unwrap().has_unseen = !envelopes[&new_hash] + .is_seen() + || self.thread_nodes[&thread_hash] + .children + .iter() + .fold(false, |acc, x| acc || self.thread_nodes[x].has_unseen); + + let mut thread_hash_iter = thread_hash; + while self.thread_nodes[&thread_hash_iter].parent.is_some() { + let parent_hash = self.thread_nodes[&thread_hash_iter].parent.unwrap(); + + self.thread_nodes.get_mut(&parent_hash).unwrap().has_unseen = self.thread_nodes + [&parent_hash] + .children + .iter() + .fold(false, |acc, x| acc || self.thread_nodes[x].has_unseen); + thread_hash_iter = parent_hash; + } + self.hash_set.remove(&old_hash); self.hash_set.insert(new_hash); Ok(()) @@ -760,7 +784,12 @@ impl Threads { } /// Update show_subject details of ThreadNode - pub fn update_node(&mut self, id: ThreadHash, env_hash: EnvelopeHash, envelopes: &Envelopes) { + pub fn update_show_subject( + &mut self, + id: ThreadHash, + env_hash: EnvelopeHash, + envelopes: &Envelopes, + ) { let mut subject = envelopes[&env_hash].subject(); let mut subject = subject.to_mut().as_bytes(); let stripped_subject = subject.strip_prefixes(); @@ -818,6 +847,7 @@ impl Threads { message: Some(env_hash), parent: reply_to_id, date: envelopes[&env_hash].date(), + has_unseen: !envelopes[&env_hash].is_seen(), ..ThreadNode::new(new_id) }, ); @@ -854,7 +884,7 @@ impl Threads { } self.tree_insert_root(new_id, envelopes); } - self.update_node(new_id, env_hash, envelopes); + self.update_show_subject(new_id, env_hash, envelopes); } /* Insert or update */ @@ -904,7 +934,7 @@ impl Threads { } } } - self.update_node(id, env_hash, envelopes); + self.update_show_subject(id, env_hash, envelopes); true } else if let Some(reply_to_id) = reply_to_id { let new_id = ThreadHash::new(); @@ -914,6 +944,7 @@ impl Threads { message: Some(env_hash), parent: Some(reply_to_id), date: envelopes[&env_hash].date(), + has_unseen: !envelopes[&env_hash].is_seen(), ..ThreadNode::new(new_id) }, ); @@ -927,7 +958,7 @@ impl Threads { self.hash_set.insert(env_hash); self.union(reply_to_id, new_id); make!((reply_to_id) parent of (new_id), &mut self.thread_nodes); - self.update_node(new_id, env_hash, envelopes); + self.update_show_subject(new_id, env_hash, envelopes); true } else { false