From 6f76cd9acc45f1ef1c7eee224b530e5e34a91860 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Wed, 11 Dec 2019 00:15:36 +0200 Subject: [PATCH] melib: add special_usage() method to BackendFolder Eventually after loading potential usage values from configuration, backends will be able to change the usage values themselves. IMAP and JMAP have the ability to set Mailbox roles (IMAP needs LIST-SPECIAL extension --- melib/src/backends.rs | 14 ++++++++++++-- melib/src/backends/imap/folder.rs | 8 +++++++- melib/src/backends/imap/protocol_parser.rs | 7 +++++++ melib/src/backends/imap/watch.rs | 3 ++- melib/src/backends/maildir.rs | 7 +++++++ melib/src/backends/mbox.rs | 6 +++++- melib/src/backends/notmuch.rs | 7 +++++++ melib/src/conf.rs | 4 ++-- melib/src/lib.rs | 2 +- ui/src/components/mail/compose.rs | 10 +++++----- ui/src/components/mail/view.rs | 2 +- ui/src/conf.rs | 22 +++++++++++----------- ui/src/conf/accounts.rs | 20 ++++++++++---------- 13 files changed, 77 insertions(+), 35 deletions(-) diff --git a/melib/src/backends.rs b/melib/src/backends.rs index 5f3149f47..aa433c703 100644 --- a/melib/src/backends.rs +++ b/melib/src/backends.rs @@ -339,7 +339,7 @@ impl BackendOp for ReadOnlyOp { } #[derive(Debug, Copy, Hash, Eq, Clone, Serialize, Deserialize, PartialEq)] -pub enum SpecialUseMailbox { +pub enum SpecialUsageMailbox { Normal, Inbox, Archive, @@ -350,6 +350,12 @@ pub enum SpecialUseMailbox { Trash, } +impl Default for SpecialUsageMailbox { + fn default() -> Self { + SpecialUsageMailbox::Normal + } +} + pub trait BackendFolder: Debug { fn hash(&self) -> FolderHash; fn name(&self) -> &str; @@ -359,7 +365,7 @@ pub trait BackendFolder: Debug { fn clone(&self) -> Folder; fn children(&self) -> &[FolderHash]; fn parent(&self) -> Option; - + fn special_usage(&self) -> SpecialUsageMailbox; fn permissions(&self) -> FolderPermissions; } @@ -387,6 +393,10 @@ impl BackendFolder for DummyFolder { folder_default() } + fn special_usage(&self) -> SpecialUsageMailbox { + SpecialUsageMailbox::Normal + } + fn children(&self) -> &[FolderHash] { &self.v } diff --git a/melib/src/backends/imap/folder.rs b/melib/src/backends/imap/folder.rs index 5a0535abf..3ca20047a 100644 --- a/melib/src/backends/imap/folder.rs +++ b/melib/src/backends/imap/folder.rs @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * along with meli. If not, see . */ -use crate::backends::{BackendFolder, Folder, FolderHash, FolderPermissions}; +use crate::backends::{BackendFolder, Folder, FolderHash, FolderPermissions, SpecialUsageMailbox}; use std::sync::{Arc, Mutex}; #[derive(Debug, Default, Clone)] @@ -28,6 +28,7 @@ pub struct ImapFolder { pub(super) name: String, pub(super) parent: Option, pub(super) children: Vec, + pub usage: SpecialUsageMailbox, pub no_select: bool, pub permissions: Arc>, @@ -62,12 +63,17 @@ impl BackendFolder for ImapFolder { name: self.name.clone(), parent: self.parent, children: self.children.clone(), + usage: self.usage, no_select: self.no_select, permissions: self.permissions.clone(), exists: self.exists.clone(), }) } + fn special_usage(&self) -> SpecialUsageMailbox { + self.usage + } + fn parent(&self) -> Option { self.parent } diff --git a/melib/src/backends/imap/protocol_parser.rs b/melib/src/backends/imap/protocol_parser.rs index 9fa8b3bdf..067ee279a 100644 --- a/melib/src/backends/imap/protocol_parser.rs +++ b/melib/src/backends/imap/protocol_parser.rs @@ -89,8 +89,15 @@ named!( let mut f = ImapFolder::default(); f.no_select = false; for p in properties.split(|&b| b == b' ') { + use crate::backends::SpecialUsageMailbox; if p.eq_ignore_ascii_case(b"\\NoSelect") { f.no_select = true; + } else if p.eq_ignore_ascii_case(b"\\Sent") { + f.usage = SpecialUsageMailbox::Sent; + } else if p.eq_ignore_ascii_case(b"\\Junk") { + f.usage = SpecialUsageMailbox::Trash; + } else if p.eq_ignore_ascii_case(b"\\Drafts") { + f.usage = SpecialUsageMailbox::Drafts; } } f.hash = get_path_hash!(path); diff --git a/melib/src/backends/imap/watch.rs b/melib/src/backends/imap/watch.rs index df631f21f..1a92f433a 100644 --- a/melib/src/backends/imap/watch.rs +++ b/melib/src/backends/imap/watch.rs @@ -19,6 +19,7 @@ * along with meli. If not, see . */ use super::*; +use crate::backends::SpecialUsageMailbox; use std::sync::{Arc, Mutex, RwLock}; /// Arguments for IMAP watching functions @@ -123,7 +124,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> { .read() .unwrap() .values() - .find(|f| f.parent.is_none() && f.path().eq_ignore_ascii_case("INBOX")) + .find(|f| f.parent.is_none() && (f.usage == SpecialUsageMailbox::Inbox)) .map(std::clone::Clone::clone) { Some(folder) => folder, diff --git a/melib/src/backends/maildir.rs b/melib/src/backends/maildir.rs index b2bbe5b6a..177c86c20 100644 --- a/melib/src/backends/maildir.rs +++ b/melib/src/backends/maildir.rs @@ -176,6 +176,7 @@ pub struct MaildirFolder { path: PathBuf, parent: Option, children: Vec, + usage: SpecialUsageMailbox, permissions: FolderPermissions, } @@ -237,6 +238,7 @@ impl MaildirFolder { fs_path: pathbuf, parent, children, + usage: SpecialUsageMailbox::Normal, permissions: FolderPermissions { create_messages: !read_only, remove_messages: !read_only, @@ -300,11 +302,16 @@ impl BackendFolder for MaildirFolder { fs_path: self.fs_path.clone(), path: self.path.clone(), children: self.children.clone(), + usage: self.usage, parent: self.parent, permissions: self.permissions, }) } + fn special_usage(&self) -> SpecialUsageMailbox { + self.usage + } + fn parent(&self) -> Option { self.parent } diff --git a/melib/src/backends/mbox.rs b/melib/src/backends/mbox.rs index a69e10106..f10674d45 100644 --- a/melib/src/backends/mbox.rs +++ b/melib/src/backends/mbox.rs @@ -28,7 +28,7 @@ use crate::backends::BackendOp; use crate::backends::FolderHash; use crate::backends::{ BackendFolder, Folder, FolderPermissions, MailBackend, RefreshEvent, RefreshEventConsumer, - RefreshEventKind, + RefreshEventKind, SpecialUsageMailbox, }; use crate::conf::AccountSettings; use crate::email::parser::BytesExt; @@ -128,6 +128,10 @@ impl BackendFolder for MboxFolder { self.parent } + fn special_usage(&self) -> SpecialUsageMailbox { + SpecialUsageMailbox::Normal + } + fn permissions(&self) -> FolderPermissions { self.permissions } diff --git a/melib/src/backends/notmuch.rs b/melib/src/backends/notmuch.rs index 70bac2b53..95582d2ba 100644 --- a/melib/src/backends/notmuch.rs +++ b/melib/src/backends/notmuch.rs @@ -2,6 +2,7 @@ use crate::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext}; use crate::backends::FolderHash; use crate::backends::{ BackendFolder, BackendOp, Folder, FolderPermissions, MailBackend, RefreshEventConsumer, + SpecialUsageMailbox, }; use crate::conf::AccountSettings; use crate::email::{Envelope, EnvelopeHash, Flag}; @@ -66,6 +67,7 @@ struct NotmuchFolder { parent: Option, name: String, path: String, + usage: SpecialUsageMailbox, query_str: String, query: Option<*mut notmuch_query_t>, phantom: std::marker::PhantomData<&'static mut notmuch_query_t>, @@ -98,6 +100,10 @@ impl BackendFolder for NotmuchFolder { self.parent } + fn special_usage(&self) -> SpecialUsageMailbox { + self.usage + } + fn permissions(&self) -> FolderPermissions { FolderPermissions::default() } @@ -156,6 +162,7 @@ impl NotmuchDb { parent: None, query: None, query_str: query_str.to_string(), + usage: SpecialUsageMailbox::Normal, phantom: std::marker::PhantomData, }, ); diff --git a/melib/src/conf.rs b/melib/src/conf.rs index d5199213f..6b5f82982 100644 --- a/melib/src/conf.rs +++ b/melib/src/conf.rs @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * along with meli. If not, see . */ -use crate::backends::SpecialUseMailbox; +use crate::backends::SpecialUsageMailbox; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::collections::HashMap; @@ -81,7 +81,7 @@ pub struct FolderConf { #[serde(deserialize_with = "toggleflag_de")] pub ignore: ToggleFlag, #[serde(default = "none")] - pub usage: Option, + pub usage: Option, #[serde(flatten)] pub extra: HashMap, } diff --git a/melib/src/lib.rs b/melib/src/lib.rs index 84361f1d7..0ff5c75a9 100644 --- a/melib/src/lib.rs +++ b/melib/src/lib.rs @@ -141,7 +141,7 @@ extern crate uuid; pub use crate::conf::*; pub use crate::mailbox::*; -pub use crate::backends::{Backends, RefreshEvent, RefreshEventConsumer, SpecialUseMailbox}; +pub use crate::backends::{Backends, RefreshEvent, RefreshEventConsumer, SpecialUsageMailbox}; pub use crate::email::{Envelope, Flag}; pub use crate::error::{MeliError, Result}; diff --git a/ui/src/components/mail/compose.rs b/ui/src/components/mail/compose.rs index 66f278b04..cbf137f4c 100644 --- a/ui/src/components/mail/compose.rs +++ b/ui/src/components/mail/compose.rs @@ -574,7 +574,7 @@ impl Component for Composer { context, self.account_cursor, self.draft.clone(), - SpecialUseMailbox::Sent, + SpecialUsageMailbox::Sent, Flag::SEEN, ) { context @@ -584,7 +584,7 @@ impl Component for Composer { save_draft( self.draft.clone().finalise().unwrap().as_bytes(), context, - SpecialUseMailbox::Drafts, + SpecialUsageMailbox::Drafts, Flag::SEEN | Flag::DRAFT, self.account_cursor, ); @@ -633,7 +633,7 @@ impl Component for Composer { save_draft( self.draft.clone().finalise().unwrap().as_bytes(), context, - SpecialUseMailbox::Drafts, + SpecialUsageMailbox::Drafts, Flag::SEEN | Flag::DRAFT, self.account_cursor, ); @@ -1069,7 +1069,7 @@ pub fn send_draft( context: &mut Context, account_cursor: usize, mut draft: Draft, - folder_type: SpecialUseMailbox, + folder_type: SpecialUsageMailbox, flags: Flag, ) -> bool { use std::io::Write; @@ -1216,7 +1216,7 @@ pub fn send_draft( pub fn save_draft( bytes: &[u8], context: &mut Context, - folder_type: SpecialUseMailbox, + folder_type: SpecialUsageMailbox, flags: Flag, account_cursor: usize, ) { diff --git a/ui/src/components/mail/view.rs b/ui/src/components/mail/view.rs index 657c268a7..27c2e52f8 100644 --- a/ui/src/components/mail/view.rs +++ b/ui/src/components/mail/view.rs @@ -1200,7 +1200,7 @@ impl Component for MailView { unsafe { &mut *(unsafe_context) }, self.coordinates.0, draft, - SpecialUseMailbox::Sent, + SpecialUsageMailbox::Sent, Flag::SEEN, ); } diff --git a/ui/src/conf.rs b/ui/src/conf.rs index 31f201a7e..65af869c1 100644 --- a/ui/src/conf.rs +++ b/ui/src/conf.rs @@ -44,7 +44,7 @@ use self::default_vals::*; use self::notifications::NotificationsSettings; use self::terminal::TerminalSettings; use crate::pager::PagerSettings; -use melib::backends::SpecialUseMailbox; +use melib::backends::SpecialUsageMailbox; use melib::conf::{toggleflag_de, AccountSettings, FolderConf, ToggleFlag}; use melib::error::*; @@ -186,7 +186,7 @@ impl From for AccountConf { } if folder_confs[s].folder_conf().ignore.is_unset() { - use SpecialUseMailbox::*; + use SpecialUsageMailbox::*; if [Junk, Sent, Trash] .contains(&folder_confs[s].folder_conf().usage.as_ref().unwrap()) { @@ -564,23 +564,23 @@ impl Serialize for CacheType { } } -pub fn usage(name: &str) -> Option { +pub fn usage(name: &str) -> Option { if name.eq_ignore_ascii_case("inbox") { - Some(SpecialUseMailbox::Inbox) + Some(SpecialUsageMailbox::Inbox) } else if name.eq_ignore_ascii_case("archive") { - Some(SpecialUseMailbox::Archive) + Some(SpecialUsageMailbox::Archive) } else if name.eq_ignore_ascii_case("drafts") { - Some(SpecialUseMailbox::Drafts) + Some(SpecialUsageMailbox::Drafts) } else if name.eq_ignore_ascii_case("junk") { - Some(SpecialUseMailbox::Junk) + Some(SpecialUsageMailbox::Junk) } else if name.eq_ignore_ascii_case("spam") { - Some(SpecialUseMailbox::Junk) + Some(SpecialUsageMailbox::Junk) } else if name.eq_ignore_ascii_case("sent") { - Some(SpecialUseMailbox::Sent) + Some(SpecialUsageMailbox::Sent) } else if name.eq_ignore_ascii_case("trash") { - Some(SpecialUseMailbox::Trash) + Some(SpecialUsageMailbox::Trash) } else { - Some(SpecialUseMailbox::Normal) + Some(SpecialUsageMailbox::Normal) } } diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs index 7f22f6902..867c6fc6c 100644 --- a/ui/src/conf/accounts.rs +++ b/ui/src/conf/accounts.rs @@ -28,7 +28,7 @@ use fnv::FnvHashMap; use melib::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext}; use melib::backends::{ BackendOp, Backends, Folder, FolderHash, FolderOperation, MailBackend, NotifyFn, ReadOnlyOp, - RefreshEvent, RefreshEventConsumer, RefreshEventKind, SpecialUseMailbox, + RefreshEvent, RefreshEventConsumer, RefreshEventKind, SpecialUsageMailbox, }; use melib::error::{MeliError, Result}; use melib::mailbox::*; @@ -335,7 +335,7 @@ impl Account { if self.settings.folder_confs.contains_key(f.path()) { match self.settings.folder_confs[f.path()].folder_conf().usage { - Some(SpecialUseMailbox::Sent) => { + Some(SpecialUsageMailbox::Sent) => { sent_folder = Some(f.hash()); } _ => {} @@ -452,9 +452,9 @@ impl Account { let our_tx = builder.tx(); let folder_hash = folder.hash(); let priority = match folder_confs[&folder.hash()].folder_conf().usage { - Some(SpecialUseMailbox::Inbox) => 0, - Some(SpecialUseMailbox::Sent) => 1, - Some(SpecialUseMailbox::Drafts) | Some(SpecialUseMailbox::Trash) => 2, + Some(SpecialUsageMailbox::Inbox) => 0, + Some(SpecialUsageMailbox::Sent) => 1, + Some(SpecialUsageMailbox::Drafts) | Some(SpecialUsageMailbox::Trash) => 2, Some(_) | None => { 3 * folder .path() @@ -876,14 +876,14 @@ impl Account { pub fn save_special( &self, bytes: &[u8], - folder_type: SpecialUseMailbox, + folder_type: SpecialUsageMailbox, flags: Flag, ) -> Result<()> { let mut failure = true; for folder in &[ self.special_use_folder(folder_type), - self.special_use_folder(SpecialUseMailbox::Inbox), - self.special_use_folder(SpecialUseMailbox::Normal), + self.special_use_folder(SpecialUsageMailbox::Inbox), + self.special_use_folder(SpecialUsageMailbox::Normal), ] { if folder.is_none() { continue; @@ -965,7 +965,7 @@ impl Account { let sent_folder = self .folder_confs .iter() - .find(|(_, f)| f.folder_conf().usage == Some(SpecialUseMailbox::Sent)); + .find(|(_, f)| f.folder_conf().usage == Some(SpecialUsageMailbox::Sent)); if let Some(sent_folder) = sent_folder.as_ref() { &self.folder_names[&sent_folder.0] } else { @@ -973,7 +973,7 @@ impl Account { } } - pub fn special_use_folder(&self, special_use: SpecialUseMailbox) -> Option<&str> { + pub fn special_use_folder(&self, special_use: SpecialUsageMailbox) -> Option<&str> { let ret = self .folder_confs .iter()