diff --git a/ui/src/conf.rs b/ui/src/conf.rs index 7b2e16737..463377f36 100644 --- a/ui/src/conf.rs +++ b/ui/src/conf.rs @@ -53,12 +53,56 @@ macro_rules! split_command { }}; } -#[derive(Debug, Clone, Default, Deserialize)] +#[derive(Debug, Clone, PartialEq)] +pub enum ToggleFlag { + Unset, + InternalVal(bool), + False, + True, +} + +impl Default for ToggleFlag { + fn default() -> Self { + ToggleFlag::Unset + } +} + +impl ToggleFlag { + pub fn is_unset(&self) -> bool { + ToggleFlag::Unset == *self + } + pub fn is_internal(&self) -> bool { + if let ToggleFlag::InternalVal(_) = *self { + true + } else { + false + } + } + pub fn is_false(&self) -> bool { + ToggleFlag::False == *self || ToggleFlag::InternalVal(false) == *self + } + pub fn is_true(&self) -> bool { + ToggleFlag::True == *self || ToggleFlag::InternalVal(true) == *self + } +} + +#[derive(Debug, Clone, Deserialize)] pub struct FolderConf { rename: Option, #[serde(default = "true_val")] autoload: bool, - ignore: bool, + #[serde(deserialize_with = "toggleflag_de", default)] + ignore: ToggleFlag, +} + +impl Default for FolderConf { + fn default() -> Self { + FolderConf { + rename: None, + autoload: true, + ignore: ToggleFlag::Unset, + } + } } impl FolderConf { @@ -105,9 +149,12 @@ impl From for AccountConf { display_name, }; + let folder_confs = x.folders.clone().unwrap_or_else(|| Default::default()); + AccountConf { account: acc, conf: x, + folder_confs, } } } @@ -143,6 +190,7 @@ struct FileSettings { pub struct AccountConf { account: AccountSettings, conf: FileAccount, + folder_confs: HashMap, } impl AccountConf { @@ -184,10 +232,11 @@ impl FileSettings { ); } let mut s = Config::new(); - let s = s.merge(File::new(config_path.to_str().unwrap(), FileFormat::Toml)); + s.merge(File::new(config_path.to_str().unwrap(), FileFormat::Toml)) + .unwrap(); /* No point in returning without a config file. */ - match s.unwrap().deserialize() { + match s.deserialize() { Ok(v) => Ok(v), Err(e) => Err(MeliError::new(e.to_string())), } @@ -254,6 +303,18 @@ where } } +fn toggleflag_de<'de, D>(deserializer: D) -> std::result::Result +where + D: Deserializer<'de>, +{ + let s = ::deserialize(deserializer); + Ok(match s { + Err(_) => ToggleFlag::Unset, + Ok(true) => ToggleFlag::True, + Ok(false) => ToggleFlag::False, + }) +} + /* * Deserialize default functions */ diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs index 27582122d..8b4d99656 100644 --- a/ui/src/conf/accounts.rs +++ b/ui/src/conf/accounts.rs @@ -24,6 +24,7 @@ */ use super::AccountConf; +use super::ToggleFlag; use crate::StackVec; use fnv::FnvHashMap; use melib::async_workers::{Async, AsyncBuilder, AsyncStatus}; @@ -62,6 +63,7 @@ pub struct Account { name: String, pub(crate) folders: FnvHashMap>>, pub(crate) folders_order: Vec, + folder_names: FnvHashMap, tree: Vec, sent_folder: Option, @@ -131,7 +133,12 @@ struct FolderNode { } impl Account { - pub fn new(name: String, settings: AccountConf, map: &Backends, notify_fn: NotifyFn) -> Self { + pub fn new( + name: String, + mut settings: AccountConf, + map: &Backends, + notify_fn: NotifyFn, + ) -> Self { let mut backend = map.get(settings.account().format())(settings.account()); let mut ref_folders: FnvHashMap = backend.folders(); let mut folders: FnvHashMap>> = @@ -139,17 +146,24 @@ impl Account { let mut folders_order: Vec = Vec::with_capacity(ref_folders.len()); let mut workers: FnvHashMap = FnvHashMap::default(); let notify_fn = Arc::new(notify_fn); + let mut folder_names = FnvHashMap::default(); - if let Some(folder_confs) = settings.conf().folders() { - //debug!("folder renames: {:?}", folder_renames); - for f in ref_folders.values_mut() { - if let Some(r) = folder_confs.get(&f.name().to_ascii_lowercase()) { - if let Some(rename) = r.rename() { - f.change_name(rename); - } - } + for f in ref_folders.values_mut() { + let entry = settings + .folder_confs + .entry(f.name().to_string()) + .or_default(); + if (f.name().eq_ignore_ascii_case("junk") + || f.name().eq_ignore_ascii_case("spam") + || f.name().eq_ignore_ascii_case("trash") + || f.name().eq_ignore_ascii_case("sent")) + && entry.ignore.is_unset() + { + entry.ignore = ToggleFlag::InternalVal(true); } + folder_names.insert(f.hash(), f.name().to_string()); } + let mut stack: StackVec = StackVec::new(); let mut tree: Vec = Vec::new(); for (h, f) in ref_folders.iter() { @@ -221,6 +235,7 @@ impl Account { name, folders, folders_order, + folder_names, tree, address_book, sent_folder: None, @@ -271,6 +286,10 @@ impl Account { debug!("create {}", envelope.hash()); let env: &Envelope = mailbox!(&folder_hash, self.folders).insert(*envelope); 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; + } return Some(Notification( Some("new mail".into()), format!( @@ -314,7 +333,7 @@ impl Account { if let Some(folder_confs) = self.settings.conf().folders() { //debug!("folder renames: {:?}", folder_renames); for f in folders.values_mut() { - if let Some(r) = folder_confs.get(&f.name().to_ascii_lowercase()) { + if let Some(r) = folder_confs.get(f.name()) { if let Some(rename) = r.rename() { f.change_name(rename); }