From f38d03e43ab01de2159555e8d41829a60e87346f Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sat, 22 Feb 2020 10:57:59 +0200 Subject: [PATCH] melib: {create,delete}_folder returns updated folders Potential parent folders will have their children fields updated, so just return all folders. --- melib/src/backends.rs | 10 +++- melib/src/backends/imap.rs | 24 ++++----- melib/src/backends/maildir/backend.rs | 18 +++++-- melib/src/collection.rs | 12 ++--- src/conf/accounts.rs | 74 +++++++++++++++++---------- src/plugins/backend.rs | 5 +- 6 files changed, 88 insertions(+), 55 deletions(-) diff --git a/melib/src/backends.rs b/melib/src/backends.rs index 5d83fef6..66469adc 100644 --- a/melib/src/backends.rs +++ b/melib/src/backends.rs @@ -272,11 +272,17 @@ pub trait MailBackend: ::std::fmt::Debug + Send + Sync { unimplemented!() } - fn create_folder(&mut self, _path: String) -> Result { + fn create_folder( + &mut self, + _path: String, + ) -> Result<(FolderHash, FnvHashMap)> { Err(MeliError::new("Unimplemented.")) } - fn delete_folder(&mut self, _folder_hash: FolderHash) -> Result<()> { + fn delete_folder( + &mut self, + _folder_hash: FolderHash, + ) -> Result> { Err(MeliError::new("Unimplemented.")) } diff --git a/melib/src/backends/imap.rs b/melib/src/backends/imap.rs index b5b5327d..8b83978e 100644 --- a/melib/src/backends/imap.rs +++ b/melib/src/backends/imap.rs @@ -442,7 +442,10 @@ impl MailBackend for ImapType { } } - fn create_folder(&mut self, mut path: String) -> Result { + fn create_folder( + &mut self, + mut path: String, + ) -> Result<(FolderHash, FnvHashMap)> { /* Must transform path to something the IMAP server will accept * * Each root mailbox has a hierarchy delimeter reported by the LIST entry. All paths @@ -487,16 +490,13 @@ impl MailBackend for ImapType { } let ret: Result<()> = ImapResponse::from(&response).into(); ret?; + let new_hash = get_path_hash!(path.as_str()); folders.clear(); drop(folders); - self.folders().map_err(|err| format!("Mailbox create was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`", response, err))?; - let new_hash = get_path_hash!(path.as_str()); - Ok(BackendFolder::clone( - &self.folders.read().unwrap()[&new_hash], - )) + Ok((new_hash, self.folders().map_err(|err| MeliError::new(format!("Mailbox create was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`", response, err)))?)) } - fn delete_folder(&mut self, folder_hash: FolderHash) -> Result<()> { + fn delete_folder(&mut self, folder_hash: FolderHash) -> Result> { let mut folders = self.folders.write().unwrap(); let permissions = folders[&folder_hash].permissions(); if !permissions.delete_mailbox { @@ -541,12 +541,10 @@ impl MailBackend for ImapType { conn_lck.read_response(&mut response)?; } let ret: Result<()> = ImapResponse::from(&response).into(); - if ret.is_ok() { - folders.clear(); - drop(folders); - self.folders().map_err(|err| format!("Mailbox delete was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`", response, err))?; - } - ret + ret?; + folders.clear(); + drop(folders); + self.folders().map_err(|err| format!("Mailbox delete was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`", response, err).into()) } fn set_folder_subscription(&mut self, folder_hash: FolderHash, new_val: bool) -> Result<()> { diff --git a/melib/src/backends/maildir/backend.rs b/melib/src/backends/maildir/backend.rs index aa5d072d..4a5c38fa 100644 --- a/melib/src/backends/maildir/backend.rs +++ b/melib/src/backends/maildir/backend.rs @@ -636,7 +636,10 @@ impl MailBackend for MaildirType { self } - fn create_folder(&mut self, new_path: String) -> Result { + fn create_folder( + &mut self, + new_path: String, + ) -> Result<(FolderHash, FnvHashMap)> { let mut path = self.path.clone(); path.push(&new_path); if !path.starts_with(&self.path) { @@ -655,6 +658,11 @@ impl MailBackend for MaildirType { }); let folder_hash = get_path_hash!(&path); + if let Some(parent) = parent { + self.folders + .entry(parent) + .and_modify(|entry| entry.children.push(folder_hash)); + } let new_folder = MaildirFolder { hash: folder_hash, path: PathBuf::from(&new_path), @@ -669,12 +677,14 @@ impl MailBackend for MaildirType { total: Default::default(), }; - let ret = BackendFolder::clone(debug!(&new_folder)); self.folders.insert(folder_hash, new_folder); - Ok(ret) + Ok((folder_hash, self.folders()?)) } - fn delete_folder(&mut self, _folder_hash: FolderHash) -> Result<()> { + fn delete_folder( + &mut self, + _folder_hash: FolderHash, + ) -> Result> { Err(MeliError::new("Unimplemented.")) } diff --git a/melib/src/collection.rs b/melib/src/collection.rs index a64d820b..db4290e0 100644 --- a/melib/src/collection.rs +++ b/melib/src/collection.rs @@ -354,16 +354,12 @@ impl Collection { self.message_ids .insert(envelope.message_id().raw().to_vec(), hash); self.envelopes.write().unwrap().insert(hash, envelope); - if !self - .threads + self.threads .entry(folder_hash) .or_default() - .insert_reply(&mut self.envelopes, hash) - { - self.threads - .entry(folder_hash) - .or_default() - .insert(&mut self.envelopes, hash); + .insert(&mut self.envelopes, hash); + if self.sent_folder.map(|f| f == folder_hash).unwrap_or(false) { + self.insert_reply(hash); } } diff --git a/src/conf/accounts.rs b/src/conf/accounts.rs index a28ae62b..6a588118 100644 --- a/src/conf/accounts.rs +++ b/src/conf/accounts.rs @@ -865,7 +865,7 @@ impl Account { } match op { FolderOperation::Create(path) => { - let mut folder = self + let (folder_hash, mut folders) = self .backend .write() .unwrap() @@ -873,40 +873,51 @@ impl Account { self.sender .send(ThreadEvent::UIEvent(UIEvent::MailboxCreate(( self.index, - folder.hash(), + folder_hash, )))) .unwrap(); let mut new = FileFolderConf::default(); new.folder_conf.subscribe = super::ToggleFlag::InternalVal(true); - new.folder_conf.usage = if folder.special_usage() != SpecialUsageMailbox::Normal { - Some(folder.special_usage()) - } else { - let tmp = SpecialUsageMailbox::detect_usage(folder.name()); - if tmp != Some(SpecialUsageMailbox::Normal) && tmp != None { - let _ = folder.set_special_usage(tmp.unwrap()); - } - tmp - }; + new.folder_conf.usage = + if folders[&folder_hash].special_usage() != SpecialUsageMailbox::Normal { + Some(folders[&folder_hash].special_usage()) + } else { + let tmp = SpecialUsageMailbox::detect_usage(folders[&folder_hash].name()); + if tmp != Some(SpecialUsageMailbox::Normal) && tmp != None { + folders.entry(folder_hash).and_modify(|entry| { + let _ = entry.set_special_usage(tmp.unwrap()); + }); + } + tmp + }; + /* if new folder has parent, we need to update its children field */ + if let Some(parent_hash) = folders[&folder_hash].parent() { + self.folder_entries.entry(parent_hash).and_modify(|parent| { + parent.ref_folder = folders.remove(&parent_hash).unwrap(); + }); + } - let folder_hash = folder.hash(); self.folder_entries.insert( folder_hash, FolderEntry { - name: folder.path().to_string(), + name: folders[&folder_hash].path().to_string(), status: MailboxStatus::Parsing(0, 0), conf: new, worker: Account::new_worker( - folder.clone(), + folders[&folder_hash].clone(), &mut self.backend, &self.work_context, self.notify_fn.clone(), ), - ref_folder: folder, + ref_folder: folders.remove(&folder_hash).unwrap(), }, ); self.collection .threads .insert(folder_hash, Threads::default()); + self.collection + .mailboxes + .insert(folder_hash, Default::default()); build_folders_order( &mut self.tree, &self.folder_entries, @@ -927,7 +938,7 @@ impl Account { } else { return Err(MeliError::new("Mailbox with that path not found.")); }; - self.backend.write().unwrap().delete_folder(folder_hash)?; + let mut folders = self.backend.write().unwrap().delete_folder(folder_hash)?; self.sender .send(ThreadEvent::UIEvent(UIEvent::MailboxDelete(( self.index, @@ -944,8 +955,24 @@ impl Account { self.sent_folder = None; } self.collection.threads.remove(&folder_hash); + /* if deleted folder had parent, we need to update its children field */ + if let Some(parent_hash) = self + .folder_entries + .remove(&folder_hash) + .unwrap() + .ref_folder + .parent() + { + self.folder_entries.entry(parent_hash).and_modify(|parent| { + parent.ref_folder = folders.remove(&parent_hash).unwrap(); + }); + } self.collection.mailboxes.remove(&folder_hash); - self.folder_entries.remove(&folder_hash); + build_folders_order( + &mut self.tree, + &self.folder_entries, + &mut self.folders_order, + ); // FIXME Kill worker as well // FIXME remove from settings as well @@ -1063,7 +1090,6 @@ fn build_folders_order( folder_entries: &FnvHashMap, folders_order: &mut Vec, ) { - let mut stack: SmallVec<[FolderHash; 8]> = SmallVec::new(); tree.clear(); folders_order.clear(); for (h, f) in folder_entries.iter() { @@ -1079,20 +1105,14 @@ fn build_folders_order( depth, }; for &c in folder_entries[&h].ref_folder.children() { - node.children.push(rec(c, folder_entries, depth + 1)); + if folder_entries.contains_key(&c) { + node.children.push(rec(c, folder_entries, depth + 1)); + } } node }; tree.push(rec(*h, &folder_entries, 0)); - for &c in f.ref_folder.children() { - stack.push(c); - } - while let Some(next) = stack.pop() { - for c in folder_entries[&next].ref_folder.children() { - stack.push(*c); - } - } } } diff --git a/src/plugins/backend.rs b/src/plugins/backend.rs index b4db6382..f31b5bbb 100644 --- a/src/plugins/backend.rs +++ b/src/plugins/backend.rs @@ -213,7 +213,10 @@ impl MailBackend for PluginBackend { fn save(&self, _bytes: &[u8], _folder: &str, _flags: Option) -> Result<()> { Err(MeliError::new("Unimplemented.")) } - fn create_folder(&mut self, _name: String) -> Result { + fn create_folder( + &mut self, + _name: String, + ) -> Result<(FolderHash, FnvHashMap)> { Err(MeliError::new("Unimplemented.")) } fn tags(&self) -> Option>>> {