From 3f8aa560f041c36e1799476f4ff67141db1a0f2b Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sat, 25 Jul 2020 17:53:04 +0300 Subject: [PATCH] melib/MailBackend: add MailBackendCapabilities struct --- melib/src/backends.rs | 12 +++++++--- melib/src/backends/imap.rs | 17 +++++++------- melib/src/backends/jmap.rs | 18 +++++++-------- melib/src/backends/maildir/backend.rs | 18 +++++++-------- melib/src/backends/mbox.rs | 18 +++++++-------- melib/src/backends/notmuch.rs | 18 +++++++-------- src/components/mail/status.rs | 33 +++++++++------------------ src/conf/accounts.rs | 32 +++++++++++--------------- src/plugins/backend.rs | 21 +++++++---------- src/state.rs | 2 +- 10 files changed, 82 insertions(+), 107 deletions(-) diff --git a/melib/src/backends.rs b/melib/src/backends.rs index bf5568ac..a84b3586 100644 --- a/melib/src/backends.rs +++ b/melib/src/backends.rs @@ -282,12 +282,18 @@ impl NotifyFn { } } +#[derive(Debug, Copy, Clone)] +pub struct MailBackendCapabilities { + pub is_async: bool, + pub is_remote: bool, + pub supports_search: bool, + pub supports_tags: bool, +} + pub type ResultFuture = Result> + Send + 'static>>>; pub trait MailBackend: ::std::fmt::Debug + Send + Sync { - fn is_async(&self) -> bool; - fn is_remote(&self) -> bool; - fn supports_search(&self) -> bool; + fn capabilities(&self) -> MailBackendCapabilities; fn is_online(&self) -> Result<()> { Err(MeliError::new("Unimplemented.")) } diff --git a/melib/src/backends/imap.rs b/melib/src/backends/imap.rs index 9a6a1dbc..945adfca 100644 --- a/melib/src/backends/imap.rs +++ b/melib/src/backends/imap.rs @@ -186,15 +186,14 @@ pub struct ImapType { } impl MailBackend for ImapType { - fn is_async(&self) -> bool { - true - } - fn is_remote(&self) -> bool { - true - } - - fn supports_search(&self) -> bool { - true + fn capabilities(&self) -> MailBackendCapabilities { + const CAPABILITIES: MailBackendCapabilities = MailBackendCapabilities { + is_async: true, + is_remote: true, + supports_search: true, + supports_tags: true, + }; + CAPABILITIES } fn fetch_async( diff --git a/melib/src/backends/jmap.rs b/melib/src/backends/jmap.rs index f065ad19..b3d3ce7c 100644 --- a/melib/src/backends/jmap.rs +++ b/melib/src/backends/jmap.rs @@ -190,16 +190,14 @@ pub struct JmapType { } impl MailBackend for JmapType { - fn is_async(&self) -> bool { - false - } - - fn is_remote(&self) -> bool { - true - } - - fn supports_search(&self) -> bool { - true + fn capabilities(&self) -> MailBackendCapabilities { + const CAPABILITIES: MailBackendCapabilities = MailBackendCapabilities { + is_async: false, + is_remote: true, + supports_search: true, + supports_tags: true, + }; + CAPABILITIES } fn is_online(&self) -> Result<()> { diff --git a/melib/src/backends/maildir/backend.rs b/melib/src/backends/maildir/backend.rs index 11258b42..a708aef7 100644 --- a/melib/src/backends/maildir/backend.rs +++ b/melib/src/backends/maildir/backend.rs @@ -175,16 +175,14 @@ pub fn move_to_cur(p: PathBuf) -> Result { } impl MailBackend for MaildirType { - fn is_async(&self) -> bool { - false - } - - fn is_remote(&self) -> bool { - false - } - - fn supports_search(&self) -> bool { - false + fn capabilities(&self) -> MailBackendCapabilities { + const CAPABILITIES: MailBackendCapabilities = MailBackendCapabilities { + is_async: false, + is_remote: false, + supports_search: false, + supports_tags: false, + }; + CAPABILITIES } fn is_online(&self) -> Result<()> { diff --git a/melib/src/backends/mbox.rs b/melib/src/backends/mbox.rs index 449d5d0a..3b282c0a 100644 --- a/melib/src/backends/mbox.rs +++ b/melib/src/backends/mbox.rs @@ -694,16 +694,14 @@ pub struct MboxType { } impl MailBackend for MboxType { - fn is_async(&self) -> bool { - false - } - - fn is_remote(&self) -> bool { - false - } - - fn supports_search(&self) -> bool { - false + fn capabilities(&self) -> MailBackendCapabilities { + const CAPABILITIES: MailBackendCapabilities = MailBackendCapabilities { + is_async: false, + is_remote: false, + supports_search: false, + supports_tags: false, + }; + CAPABILITIES } fn is_online(&self) -> Result<()> { diff --git a/melib/src/backends/notmuch.rs b/melib/src/backends/notmuch.rs index 343d1354..f4344234 100644 --- a/melib/src/backends/notmuch.rs +++ b/melib/src/backends/notmuch.rs @@ -318,16 +318,14 @@ impl NotmuchDb { } impl MailBackend for NotmuchDb { - fn is_async(&self) -> bool { - false - } - - fn is_remote(&self) -> bool { - false - } - - fn supports_search(&self) -> bool { - true + fn capabilities(&self) -> MailBackendCapabilities { + const CAPABILITIES: MailBackendCapabilities = MailBackendCapabilities { + is_async: false, + is_remote: false, + supports_search: true, + supports_tags: true, + }; + CAPABILITIES } fn is_online(&self) -> Result<()> { diff --git a/src/components/mail/status.rs b/src/components/mail/status.rs index 0b314da5..962e84b2 100644 --- a/src/components/mail/status.rs +++ b/src/components/mail/status.rs @@ -436,7 +436,7 @@ impl Component for AccountStatus { None, ); write_string_to_grid( - if backend_lck.tags().is_some() { + if a.backend_capabilities.supports_tags { "yes" } else { "no" @@ -459,31 +459,20 @@ impl Component for AccountStatus { None, ); write_string_to_grid( - &if a.settings.account().format() == "imap" - && *a.settings.conf.search_backend() == SearchBackend::None - { - "server-side search".to_string() - } else if a.settings.account().format() == "notmuch" - && *a.settings.conf.search_backend() == SearchBackend::None - { - "notmuch database".to_string() - } else { + &match ( + a.settings.conf.search_backend(), + a.backend_capabilities.supports_search, + ) { + (SearchBackend::None, true) => "backend-side search".to_string(), + (SearchBackend::None, false) => "none (search will be slow)".to_string(), #[cfg(feature = "sqlite3")] - { - if *a.settings.conf.search_backend() == SearchBackend::Sqlite3 { - if let Ok(path) = crate::sqlite3::db_path() { - format!("sqlite3 database {}", path.display()) - } else { - "sqlite3 database".to_string() - } + (SearchBackend::Sqlite3, _) => { + if let Ok(path) = crate::sqlite3::db_path() { + format!("sqlite3 database {}", path.display()) } else { - "none (search will be slow)".to_string() + "sqlite3 database".to_string() } } - #[cfg(not(feature = "sqlite3"))] - { - "none (search will be slow)".to_string() - } }, &mut self.content, self.theme_default.fg, diff --git a/src/conf/accounts.rs b/src/conf/accounts.rs index c427c19b..23e73e9c 100644 --- a/src/conf/accounts.rs +++ b/src/conf/accounts.rs @@ -26,11 +26,7 @@ use super::{AccountConf, FileMailboxConf}; use crate::jobs::{JobChannel, JobExecutor, JobId, JoinHandle}; use melib::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext}; -use melib::backends::{ - AccountHash, BackendOp, Backends, EnvelopeHashBatch, MailBackend, Mailbox, MailboxHash, - NotifyFn, ReadOnlyOp, RefreshEvent, RefreshEventConsumer, RefreshEventKind, ResultFuture, - SpecialUsageMailbox, -}; +use melib::backends::*; use melib::email::*; use melib::error::{MeliError, Result}; use melib::text_processing::GlobMatch; @@ -160,8 +156,7 @@ pub struct Account { sender: Sender, event_queue: VecDeque<(MailboxHash, RefreshEvent)>, notify_fn: Arc, - pub is_async: bool, - pub is_remote: bool, + pub backend_capabilities: MailBackendCapabilities, } pub enum JobRequest { @@ -366,7 +361,7 @@ impl Account { let mut active_jobs = HashMap::default(); let mut active_job_instants = BTreeMap::default(); - if backend.is_async() { + if backend.capabilities().is_async { if let Ok(mailboxes_job) = backend.mailboxes_async() { if let Ok(online_job) = backend.is_online_async() { let (rcvr, handle, job_id) = @@ -380,7 +375,7 @@ impl Account { index, hash, name, - is_online: if !backend.is_remote() { + is_online: if !backend.capabilities().is_remote { Ok(()) } else { Err(MeliError::new("Attempting connection.")) @@ -399,12 +394,11 @@ impl Account { active_jobs, active_job_instants, event_queue: VecDeque::with_capacity(8), - is_async: backend.is_async(), - is_remote: backend.is_remote(), + backend_capabilities: backend.capabilities(), backend: Arc::new(RwLock::new(backend)), }; - if !ret.is_remote && !ret.is_async { + if !ret.backend_capabilities.is_remote && !ret.backend_capabilities.is_async { ret.init(None)?; } @@ -543,7 +537,7 @@ impl Account { || entry.ref_mailbox.special_usage() == SpecialUsageMailbox::Inbox { entry.status = MailboxStatus::Parsing(0, 0); - if self.is_async { + if self.backend_capabilities.is_async { if let Ok(mailbox_job) = self.backend.write().unwrap().fetch_async(*h) { let mailbox_job = mailbox_job.into_future(); let (rcvr, handle, job_id) = @@ -916,7 +910,7 @@ impl Account { let r = RefreshEventConsumer::new(Box::new(move |r| { sender_.send(ThreadEvent::from(r)).unwrap(); })); - if self.is_async { + if self.backend_capabilities.is_async { if let Ok(refresh_job) = self.backend.write().unwrap().refresh_async(mailbox_hash, r) { let (rcvr, handle, job_id) = self.job_executor.spawn_specialized(refresh_job); self.sender @@ -944,7 +938,7 @@ impl Account { let r = RefreshEventConsumer::new(Box::new(move |r| { sender_.send(ThreadEvent::from(r)).unwrap(); })); - if self.is_async { + if self.backend_capabilities.is_async { if !self.active_jobs.values().any(|j| j.is_watch()) { match self.backend.read().unwrap().watch_async(r) { Ok(fut) => { @@ -1044,7 +1038,7 @@ impl Account { Ok(()) } MailboxStatus::None => { - if self.is_async { + if self.backend_capabilities.is_async { if !self.active_jobs.values().any(|j| j.is_fetch(mailbox_hash)) { let mailbox_job = self.backend.write().unwrap().fetch_async(mailbox_hash); @@ -1572,11 +1566,11 @@ impl Account { /* Call only in Context::is_online, since only Context can launch the watcher threads if an * account goes from offline to online. */ pub fn is_online(&mut self) -> Result<()> { - if !self.is_remote && !self.is_async { + if !self.backend_capabilities.is_remote && !self.backend_capabilities.is_async { return Ok(()); } - if self.is_async { + if self.backend_capabilities.is_async { if self.is_online.is_ok() { return Ok(()); } @@ -1617,7 +1611,7 @@ impl Account { #[cfg(feature = "sqlite3")] crate::conf::SearchBackend::Sqlite3 => crate::sqlite3::search(search_term, _sort), crate::conf::SearchBackend::None => { - if self.backend.read().unwrap().supports_search() { + if self.backend_capabilities.supports_search { self.backend .read() .unwrap() diff --git a/src/plugins/backend.rs b/src/plugins/backend.rs index b3038af4..8f3a78d2 100644 --- a/src/plugins/backend.rs +++ b/src/plugins/backend.rs @@ -65,19 +65,14 @@ impl Drop for PluginBackend { } impl MailBackend for PluginBackend { - fn is_async(&self) -> bool { - // TODO - false - } - - fn is_remote(&self) -> bool { - // TODO - false - } - - fn supports_search(&self) -> bool { - // TODO - false + fn capabilities(&self) -> MailBackendCapabilities { + const CAPABILITIES: MailBackendCapabilities = MailBackendCapabilities { + is_async: false, + is_remote: false, + supports_search: false, + supports_tags: false, + }; + CAPABILITIES } fn is_online(&self) -> Result<()> { diff --git a/src/state.rs b/src/state.rs index 91f3c389..a3858c9f 100644 --- a/src/state.rs +++ b/src/state.rs @@ -375,7 +375,7 @@ impl State { s.switch_to_alternate_screen(); for i in 0..s.context.accounts.len() { - if !s.context.accounts[i].is_remote { + if !s.context.accounts[i].backend_capabilities.is_remote { s.context.accounts[i].watch(); } if s.context.is_online(i).is_ok() && s.context.accounts[i].is_empty() {