melib/MailBackend: add MailBackendCapabilities struct
parent
4aaa784d8f
commit
3f8aa560f0
|
@ -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<T> = Result<Pin<Box<dyn Future<Output = Result<T>> + 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."))
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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<()> {
|
||||
|
|
|
@ -175,16 +175,14 @@ pub fn move_to_cur(p: PathBuf) -> Result<PathBuf> {
|
|||
}
|
||||
|
||||
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<()> {
|
||||
|
|
|
@ -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<()> {
|
||||
|
|
|
@ -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<()> {
|
||||
|
|
|
@ -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,30 +459,19 @@ 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 {
|
||||
(SearchBackend::Sqlite3, _) => {
|
||||
if let Ok(path) = crate::sqlite3::db_path() {
|
||||
format!("sqlite3 database {}", path.display())
|
||||
} else {
|
||||
"sqlite3 database".to_string()
|
||||
}
|
||||
} else {
|
||||
"none (search will be slow)".to_string()
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "sqlite3"))]
|
||||
{
|
||||
"none (search will be slow)".to_string()
|
||||
}
|
||||
},
|
||||
&mut self.content,
|
||||
|
|
|
@ -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<ThreadEvent>,
|
||||
event_queue: VecDeque<(MailboxHash, RefreshEvent)>,
|
||||
notify_fn: Arc<NotifyFn>,
|
||||
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()
|
||||
|
|
|
@ -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<()> {
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue