diff --git a/melib/src/mailbox/collection.rs b/melib/src/mailbox/collection.rs index 31638114..6b2ed9d9 100644 --- a/melib/src/mailbox/collection.rs +++ b/melib/src/mailbox/collection.rs @@ -63,6 +63,11 @@ impl Collection { self.threads.insert(&mut envelope); self.envelopes.insert(hash, envelope); } + pub(crate) fn insert_reply(&mut self, hash: EnvelopeHash, mut envelope: Envelope) { + if self.threads.insert_reply(&mut envelope) { + self.envelopes.insert(hash, envelope); + } + } } impl Deref for Collection { diff --git a/melib/src/mailbox/mod.rs b/melib/src/mailbox/mod.rs index 9c8e2683..e2575945 100644 --- a/melib/src/mailbox/mod.rs +++ b/melib/src/mailbox/mod.rs @@ -44,6 +44,7 @@ use std::option::Option; pub struct Mailbox { pub folder: Folder, pub collection: Collection, + has_sent: bool, } impl Clone for Mailbox { @@ -51,6 +52,7 @@ impl Clone for Mailbox { Mailbox { folder: self.folder.clone(), collection: self.collection.clone(), + has_sent: self.has_sent, } } } @@ -59,22 +61,20 @@ impl Default for Mailbox { Mailbox { folder: folder_default(), collection: Collection::default(), + has_sent: false, } } } impl Mailbox { - pub fn new( - folder: &Folder, - sent_folder: &Option>, - envelopes: Result>, - ) -> Result { + pub fn new(folder: &Folder, envelopes: Result>) -> Result { let mut envelopes: Vec = envelopes?; envelopes.sort_by(|a, b| a.date().cmp(&b.date())); let collection = Collection::new(envelopes, folder.name()); Ok(Mailbox { folder: (*folder).clone(), collection, + ..Default::default() }) } pub fn is_empty(&self) -> bool { @@ -107,6 +107,15 @@ impl Mailbox { &self.collection.threads.thread_nodes()[i] } + pub fn insert_sent_folder(&mut self, sent: &Mailbox) { + if !self.has_sent { + for envelope in sent.collection.envelopes.values().cloned() { + self.insert_reply(envelope); + } + self.has_sent = true; + } + } + pub fn update(&mut self, old_hash: EnvelopeHash, envelope: Envelope) { self.collection.remove(&old_hash); self.collection.insert(envelope.hash(), envelope); @@ -115,10 +124,14 @@ impl Mailbox { pub fn insert(&mut self, envelope: Envelope) -> &Envelope { let hash = envelope.hash(); self.collection.insert(hash, envelope); - eprintln!("Inserted envelope"); &self.collection[&hash] } + fn insert_reply(&mut self, envelope: Envelope) { + let hash = envelope.hash(); + self.collection.insert_reply(hash, envelope); + } + pub fn remove(&mut self, envelope_hash: EnvelopeHash) { self.collection.remove(&envelope_hash); // eprintln!("envelope_hash: {}\ncollection:\n{:?}", envelope_hash, self.collection); diff --git a/melib/src/mailbox/thread.rs b/melib/src/mailbox/thread.rs index 9e441d35..ee7f1600 100644 --- a/melib/src/mailbox/thread.rs +++ b/melib/src/mailbox/thread.rs @@ -338,6 +338,62 @@ impl Threads { ); } + pub fn insert_reply(&mut self, envelope: &mut Envelope) -> bool { + { + let in_reply_to = envelope.in_reply_to_raw(); + if !self.message_ids.contains_key(in_reply_to.as_ref()) { + return false; + } + } + /* FIXME: This does not update show_subject and len which is done in node_build upon + * creation */ + link_envelope( + &mut self.thread_nodes, + &mut self.message_ids, + &mut self.hash_set, + envelope, + ); + self.rebuild_thread(envelope); + return true; + } + + /* Update thread tree information on envelope insertion */ + fn rebuild_thread(&mut self, envelope: &Envelope) { + let m_id = envelope.message_id_raw(); + let mut node_idx = self.message_ids[m_id.as_ref()]; + let mut stack = Vec::with_capacity(32); + + /* Trace path back to root ThreadNode */ + while let Some(p) = &self.thread_nodes[node_idx].parent { + node_idx = *p; + stack.push(node_idx); + } + for &p in stack.iter() { + self.thread_nodes[p].len += 1; + } + + /* Trace path from root ThreadTree to the envelope's parent */ + let mut tree = self.tree.get_mut(); + for &s in stack.iter().rev() { + /* Borrow checker is being a tad silly here, so the following + * is basically this: + * + * let tree = &mut tree[s].children; + */ + let temp_tree = tree; + let pos = temp_tree.iter().position(|v| v.id == s).unwrap(); + match temp_tree[pos].children { + ref mut v => { + tree = v; + } + } + } + /* Add new child */ + tree.push(ThreadTree::new(self.message_ids[m_id.as_ref()])); + } + + /* + * Finalize instance by building the thread tree, set show subject and thread lengths etc. */ fn build_collection(&mut self, collection: &FnvHashMap) { { let tree = self.tree.get_mut(); @@ -649,11 +705,6 @@ fn node_build( } } } - if thread_nodes[idx].has_parent() - && !thread_nodes[thread_nodes[idx].parent().unwrap()].has_message() - { - thread_nodes[idx].parent = None; - } let indentation = if thread_nodes[idx].has_message() { thread_nodes[idx].indentation = indentation; indentation + 1 diff --git a/ui/src/types/accounts.rs b/ui/src/types/accounts.rs index f411249e..d60adf18 100644 --- a/ui/src/types/accounts.rs +++ b/ui/src/types/accounts.rs @@ -141,39 +141,54 @@ impl Account { } fn load_mailbox(&mut self, index: usize, envelopes: Result>) { - // TODO: Cleanup this function let folders = self.backend.folders(); let folder = &folders[index]; - if self.sent_folder.is_some() { - let id = self.sent_folder.unwrap(); - if id == index { - /* ======================== */ - self.folders[index] = Some(Mailbox::new(folder, &None, envelopes)); - /* ======================== */ - } else { + if self.sent_folder.is_some() && self.sent_folder.unwrap() == index { + self.folders[index] = Some(Mailbox::new(folder, envelopes)); + /* Add our replies to other folders */ + for id in (0..self.folders.len()).filter(|i| *i != index) { + self.add_replies_to_folder(id); + } + } else { + self.folders[index] = Some(Mailbox::new(folder, envelopes)); + self.add_replies_to_folder(index); + }; + } + + fn add_replies_to_folder(&mut self, folder_index: usize) { + if let Some(sent_index) = self.sent_folder.as_ref() { + if self.folders[*sent_index] + .as_ref() + .map(|v| v.is_ok()) + .unwrap_or(false) + && self.folders[folder_index] + .as_ref() + .map(|v| v.is_ok()) + .unwrap_or(false) + { let (sent, cur) = { let ptr = self.folders.as_mut_ptr(); unsafe { use std::slice::from_raw_parts_mut; ( - from_raw_parts_mut(ptr.offset(id as isize), id + 1), - from_raw_parts_mut(ptr.offset(index as isize), index + 1), + from_raw_parts_mut(ptr.offset(*sent_index as isize), *sent_index + 1) + [0] + .as_mut() + .unwrap() + .as_mut() + .unwrap(), + from_raw_parts_mut(ptr.offset(folder_index as isize), folder_index + 1) + [0] + .as_mut() + .unwrap() + .as_mut() + .unwrap(), ) } }; - let sent_path = &folders[id]; - if sent[0].is_none() { - sent[0] = Some(Mailbox::new(sent_path, &None, envelopes.clone())); - } - /* ======================== */ - cur[0] = Some(Mailbox::new(folder, &sent[0], envelopes)); - /* ======================== */ + cur.insert_sent_folder(&sent); } - } else { - /* ======================== */ - self.folders[index] = Some(Mailbox::new(folder, &None, envelopes)); - /* ======================== */ - }; + } } pub fn status(&mut self, index: usize) -> result::Result<(), usize> {