accounts: split mailbox to enum out of JobRequest

Split mailbox related jobs out of JobRequest enum to its own enum since
JobRequest is getting too big to be readable.

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
pull/458/head
Manos Pitsidianakis 3 months ago
parent 3216324ccc
commit 6906585942
No known key found for this signature in database
GPG Key ID: 7729C7707F7E09D0

@ -63,6 +63,7 @@ use crate::{
mod backend_ops;
mod jobs;
mod mailbox;
mod mailbox_ops;
#[cfg(test)]
mod tests;
@ -266,7 +267,10 @@ impl Account {
.spawn_blocking("mailboxes".into(), online_job.then(|_| mailboxes_job))
};
let job_id = handle.job_id;
active_jobs.insert(job_id, JobRequest::Mailboxes { handle });
active_jobs.insert(
job_id,
JobRequest::Mailbox(MailboxJobRequest::Mailboxes { handle }),
);
active_job_instants.insert(std::time::Instant::now(), job_id);
main_loop_handler.send(ThreadEvent::UIEvent(UIEvent::StatusEvent(
StatusEvent::NewJob(job_id),
@ -1220,115 +1224,6 @@ impl Account {
})
}
pub fn mailbox_operation(
&mut self,
op: crate::command::actions::MailboxOperation,
) -> Result<()> {
use crate::command::actions::MailboxOperation;
if self.settings.account.read_only {
return Err(Error::new("Account is read-only."));
}
match op {
MailboxOperation::Create(path) => {
let job = self
.backend
.write()
.unwrap()
.create_mailbox(path.to_string())?;
let handle = if self.backend_capabilities.is_async {
self.main_loop_handler
.job_executor
.spawn_specialized("create_mailbox".into(), job)
} else {
self.main_loop_handler
.job_executor
.spawn_blocking("create_mailbox".into(), job)
};
self.insert_job(handle.job_id, JobRequest::CreateMailbox { path, handle });
Ok(())
}
MailboxOperation::Delete(path) => {
if self.mailbox_entries.len() == 1 {
return Err(Error::new("Cannot delete only mailbox."));
}
let mailbox_hash = self.mailbox_by_path(&path)?;
let job = self.backend.write().unwrap().delete_mailbox(mailbox_hash)?;
let handle = if self.backend_capabilities.is_async {
self.main_loop_handler
.job_executor
.spawn_specialized("delete_mailbox".into(), job)
} else {
self.main_loop_handler
.job_executor
.spawn_blocking("delete_mailbox".into(), job)
};
self.insert_job(
handle.job_id,
JobRequest::DeleteMailbox {
mailbox_hash,
handle,
},
);
Ok(())
}
MailboxOperation::Subscribe(path) => {
let mailbox_hash = self.mailbox_by_path(&path)?;
let job = self
.backend
.write()
.unwrap()
.set_mailbox_subscription(mailbox_hash, true)?;
let handle = if self.backend_capabilities.is_async {
self.main_loop_handler
.job_executor
.spawn_specialized("subscribe_mailbox".into(), job)
} else {
self.main_loop_handler
.job_executor
.spawn_blocking("subscribe_mailbox".into(), job)
};
self.insert_job(
handle.job_id,
JobRequest::SetMailboxSubscription {
mailbox_hash,
new_value: true,
handle,
},
);
Ok(())
}
MailboxOperation::Unsubscribe(path) => {
let mailbox_hash = self.mailbox_by_path(&path)?;
let job = self
.backend
.write()
.unwrap()
.set_mailbox_subscription(mailbox_hash, false)?;
let handle = if self.backend_capabilities.is_async {
self.main_loop_handler
.job_executor
.spawn_specialized("unsubscribe_mailbox".into(), job)
} else {
self.main_loop_handler
.job_executor
.spawn_blocking("unsubscribe_mailbox".into(), job)
};
self.insert_job(
handle.job_id,
JobRequest::SetMailboxSubscription {
mailbox_hash,
new_value: false,
handle,
},
);
Ok(())
}
MailboxOperation::Rename(_, _) => Err(Error::new("Not implemented.")),
MailboxOperation::SetPermissions(_) => Err(Error::new("Not implemented.")),
}
}
pub fn special_use_mailbox(&self, special_use: SpecialUsageMailbox) -> Option<MailboxHash> {
let ret = self
.mailbox_entries
@ -1464,52 +1359,9 @@ impl Account {
if let Some(mut job) = self.active_jobs.remove(job_id) {
let job_id = *job_id;
match job {
JobRequest::Mailboxes { ref mut handle } => {
if let Ok(Some(mailboxes)) = handle.chan.try_recv() {
if let Err(err) = mailboxes.and_then(|mailboxes| self.init(mailboxes)) {
if !err.is_recoverable() {
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::Notification {
title: Some(self.name.clone().into()),
source: Some(err.clone()),
body: err.to_string().into(),
kind: Some(NotificationType::Error(err.kind)),
},
));
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::AccountStatusChange(
self.hash,
Some(err.to_string().into()),
),
));
self.is_online.set_err(err);
self.main_loop_handler
.job_executor
.set_job_success(job_id, false);
return true;
}
let mailboxes_job = self.backend.read().unwrap().mailboxes();
if let Ok(mailboxes_job) = mailboxes_job {
let handle = if self.backend_capabilities.is_async {
self.main_loop_handler
.job_executor
.spawn_specialized("mailboxes_list".into(), mailboxes_job)
} else {
self.main_loop_handler
.job_executor
.spawn_blocking("mailboxes_list".into(), mailboxes_job)
};
self.insert_job(handle.job_id, JobRequest::Mailboxes { handle });
};
} else {
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::AccountStatusChange(
self.hash,
Some("Loaded mailboxes.".into()),
),
));
}
}
JobRequest::Mailbox(ref mut inner) => {
self.process_mailbox_event(job_id, inner);
return true;
}
JobRequest::Fetch {
mailbox_hash,
@ -1816,277 +1668,6 @@ impl Account {
}));
}
}
JobRequest::CreateMailbox {
ref path,
ref mut handle,
..
} => {
if let Ok(Some(r)) = handle.chan.try_recv() {
match r {
Err(err) => {
self.main_loop_handler
.job_executor
.set_job_success(job_id, false);
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::Notification {
title: Some(
format!(
"{}: could not create mailbox {}",
&self.name, path
)
.into(),
),
source: None,
body: err.to_string().into(),
kind: Some(NotificationType::Error(err.kind)),
},
));
}
Ok((mailbox_hash, mut mailboxes)) => {
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::MailboxCreate((self.hash, mailbox_hash)),
));
let mut new = FileMailboxConf::default();
new.mailbox_conf.subscribe = super::ToggleFlag::InternalVal(true);
new.mailbox_conf.usage = if mailboxes[&mailbox_hash].special_usage()
!= SpecialUsageMailbox::Normal
{
Some(mailboxes[&mailbox_hash].special_usage())
} else {
let tmp = SpecialUsageMailbox::detect_usage(
mailboxes[&mailbox_hash].name(),
);
if let Some(tmp) =
tmp.filter(|&v| v != SpecialUsageMailbox::Normal)
{
mailboxes.entry(mailbox_hash).and_modify(|entry| {
let _ = entry.set_special_usage(tmp);
});
}
tmp
};
/* if new mailbox has parent, we need to update its children
* field */
if let Some(parent_hash) = mailboxes[&mailbox_hash].parent() {
self.mailbox_entries
.entry(parent_hash)
.and_modify(|parent| {
parent.ref_mailbox =
mailboxes.remove(&parent_hash).unwrap();
});
}
let status = MailboxStatus::default();
self.mailbox_entries.insert(
mailbox_hash,
MailboxEntry::new(
status,
mailboxes[&mailbox_hash].path().to_string(),
mailboxes.remove(&mailbox_hash).unwrap(),
new,
),
);
self.collection
.threads
.write()
.unwrap()
.insert(mailbox_hash, Threads::default());
self.collection
.mailboxes
.write()
.unwrap()
.insert(mailbox_hash, Default::default());
build_mailboxes_order(
&mut self.tree,
&self.mailbox_entries,
&mut self.mailboxes_order,
);
//Ok(format!("`{}` successfully created.",
// &path))
}
}
}
}
JobRequest::DeleteMailbox {
mailbox_hash,
ref mut handle,
..
} => {
match handle.chan.try_recv() {
Err(_) => { /* canceled */ }
Ok(None) => {}
Ok(Some(Err(err))) => {
self.main_loop_handler
.job_executor
.set_job_success(job_id, false);
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::Notification {
title: Some(
format!("{}: could not delete mailbox", &self.name).into(),
),
source: None,
body: err.to_string().into(),
kind: Some(NotificationType::Error(err.kind)),
},
));
}
Ok(Some(Ok(mut mailboxes))) => {
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::MailboxDelete((self.hash, mailbox_hash)),
));
if let Some(pos) =
self.mailboxes_order.iter().position(|&h| h == mailbox_hash)
{
self.mailboxes_order.remove(pos);
}
if let Some(pos) = self.tree.iter().position(|n| n.hash == mailbox_hash)
{
self.tree.remove(pos);
}
if self.settings.sent_mailbox == Some(mailbox_hash) {
self.settings.sent_mailbox = None;
}
self.collection
.threads
.write()
.unwrap()
.remove(&mailbox_hash);
let deleted_mailbox =
self.mailbox_entries.remove(&mailbox_hash).unwrap();
/* if deleted mailbox had parent, we need to update its children
* field */
if let Some(parent_hash) = deleted_mailbox.ref_mailbox.parent() {
self.mailbox_entries
.entry(parent_hash)
.and_modify(|parent| {
parent.ref_mailbox =
mailboxes.remove(&parent_hash).unwrap();
});
}
self.collection
.mailboxes
.write()
.unwrap()
.remove(&mailbox_hash);
build_mailboxes_order(
&mut self.tree,
&self.mailbox_entries,
&mut self.mailboxes_order,
);
// [ref:FIXME] remove from settings as well
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::Notification {
title: Some(
format!("{}: mailbox deleted successfully", &self.name)
.into(),
),
source: None,
body: "".into(),
kind: Some(NotificationType::Info),
},
));
}
}
}
//JobRequest::RenameMailbox,
JobRequest::SetMailboxPermissions { ref mut handle, .. } => {
match handle.chan.try_recv() {
Err(_) => { /* canceled */ }
Ok(None) => {}
Ok(Some(Err(err))) => {
self.main_loop_handler
.job_executor
.set_job_success(job_id, false);
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::Notification {
title: Some(
format!(
"{}: could not set mailbox permissions",
&self.name
)
.into(),
),
source: None,
body: err.to_string().into(),
kind: Some(NotificationType::Error(err.kind)),
},
));
}
Ok(Some(Ok(_))) => {
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::Notification {
title: Some(
format!(
"{}: mailbox permissions set successfully",
&self.name
)
.into(),
),
source: None,
body: "".into(),
kind: Some(NotificationType::Info),
},
));
}
}
}
JobRequest::SetMailboxSubscription {
ref mut handle,
ref mailbox_hash,
ref new_value,
} => {
match handle.chan.try_recv() {
Err(_) => { /* canceled */ }
Ok(None) => {}
Ok(Some(Err(err))) => {
self.main_loop_handler
.job_executor
.set_job_success(job_id, false);
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::Notification {
title: Some(
format!(
"{}: could not set mailbox subscription",
&self.name
)
.into(),
),
source: None,
body: err.to_string().into(),
kind: Some(NotificationType::Error(err.kind)),
},
));
}
Ok(Some(Ok(()))) if self.mailbox_entries.contains_key(mailbox_hash) => {
self.mailbox_entries.entry(*mailbox_hash).and_modify(|m| {
m.conf.mailbox_conf.subscribe = if *new_value {
super::ToggleFlag::True
} else {
super::ToggleFlag::False
};
let _ = m.ref_mailbox.set_is_subscribed(*new_value);
});
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::Notification {
title: Some(
format!(
"{}: `{}` has been {}subscribed.",
&self.name,
self.mailbox_entries[mailbox_hash].name(),
if *new_value { "" } else { "un" }
)
.into(),
),
source: None,
body: "".into(),
kind: Some(NotificationType::Info),
},
));
}
Ok(Some(Ok(()))) => {}
}
}
JobRequest::Watch { ref mut handle } => {
log::trace!("JobRequest::Watch finished??? ");
if let Ok(Some(Err(err))) = handle.chan.try_recv() {

@ -28,10 +28,71 @@ use smallvec::SmallVec;
use crate::{is_variant, jobs::JoinHandle};
pub enum JobRequest {
pub enum MailboxJobRequest {
Mailboxes {
handle: JoinHandle<Result<HashMap<MailboxHash, Mailbox>>>,
},
CreateMailbox {
path: String,
handle: JoinHandle<Result<(MailboxHash, HashMap<MailboxHash, Mailbox>)>>,
},
DeleteMailbox {
mailbox_hash: MailboxHash,
handle: JoinHandle<Result<HashMap<MailboxHash, Mailbox>>>,
},
SetMailboxPermissions {
mailbox_hash: MailboxHash,
handle: JoinHandle<Result<()>>,
},
SetMailboxSubscription {
mailbox_hash: MailboxHash,
new_value: bool,
handle: JoinHandle<Result<()>>,
},
}
impl Drop for MailboxJobRequest {
fn drop(&mut self) {
match self {
Self::CreateMailbox { handle, .. } => handle.cancel(),
Self::SetMailboxPermissions { handle, .. }
| Self::SetMailboxSubscription { handle, .. } => handle.cancel(),
Self::DeleteMailbox { handle, .. } | Self::Mailboxes { handle } => handle.cancel(),
};
}
}
impl std::fmt::Debug for MailboxJobRequest {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::CreateMailbox { .. } => write!(f, "JobRequest::CreateMailbox"),
Self::DeleteMailbox { mailbox_hash, .. } => {
write!(f, "JobRequest::DeleteMailbox({})", mailbox_hash)
}
Self::SetMailboxPermissions { .. } => {
write!(f, "JobRequest::SetMailboxPermissions")
}
Self::SetMailboxSubscription { .. } => {
write!(f, "JobRequest::SetMailboxSubscription")
}
Self::Mailboxes { .. } => write!(f, "JobRequest::Mailboxes"),
}
}
}
impl std::fmt::Display for MailboxJobRequest {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Mailboxes { .. } => write!(f, "Get mailbox list"),
Self::CreateMailbox { path, .. } => write!(f, "Create mailbox {}", path),
Self::DeleteMailbox { .. } => write!(f, "Delete mailbox"),
Self::SetMailboxPermissions { .. } => write!(f, "Set mailbox permissions"),
Self::SetMailboxSubscription { .. } => write!(f, "Set mailbox subscription"),
}
}
}
pub enum JobRequest {
Fetch {
mailbox_hash: MailboxHash,
#[allow(clippy::type_complexity)]
@ -72,60 +133,31 @@ pub enum JobRequest {
env_hashes: EnvelopeHashBatch,
handle: JoinHandle<Result<()>>,
},
CreateMailbox {
path: String,
handle: JoinHandle<Result<(MailboxHash, HashMap<MailboxHash, Mailbox>)>>,
},
DeleteMailbox {
mailbox_hash: MailboxHash,
handle: JoinHandle<Result<HashMap<MailboxHash, Mailbox>>>,
},
//RenameMailbox,
SetMailboxPermissions {
mailbox_hash: MailboxHash,
handle: JoinHandle<Result<()>>,
},
SetMailboxSubscription {
mailbox_hash: MailboxHash,
new_value: bool,
handle: JoinHandle<Result<()>>,
},
Watch {
handle: JoinHandle<Result<()>>,
},
Mailbox(MailboxJobRequest),
}
impl Drop for JobRequest {
fn drop(&mut self) {
match self {
Self::Generic { handle, .. } |
Self::IsOnline { handle, .. } |
Self::Refresh { handle, .. } |
Self::SetFlags { handle, .. } |
Self::SaveMessage { handle, .. } |
//JobRequest::RenameMailbox,
Self::SetMailboxPermissions { handle, .. } |
Self::SetMailboxSubscription { handle, .. } |
Self::Watch { handle, .. } |
Self::SendMessageBackground { handle, .. } => {
Self::Generic { handle, .. }
| Self::IsOnline { handle, .. }
| Self::Refresh { handle, .. }
| Self::SetFlags { handle, .. }
| Self::SaveMessage { handle, .. }
| Self::Watch { handle, .. }
| Self::SendMessageBackground { handle, .. } => {
handle.cancel();
}
Self::DeleteMessages { handle, .. } => {
handle.cancel();
}
Self::CreateMailbox { handle, .. } => {
handle.cancel();
}
Self::DeleteMailbox { handle, .. } => {
handle.cancel();
}
Self::Fetch { handle, .. } => {
handle.cancel();
}
Self::Mailboxes { handle, .. } => {
handle.cancel();
}
Self::SendMessage => {}
Self::SendMessage | Self::Mailbox(_) => {}
}
}
}
@ -134,7 +166,7 @@ impl std::fmt::Debug for JobRequest {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Generic { name, .. } => write!(f, "JobRequest::Generic({})", name),
Self::Mailboxes { .. } => write!(f, "JobRequest::Mailboxes"),
Self::Mailbox(inner) => std::fmt::Debug::fmt(inner, f),
Self::Fetch { mailbox_hash, .. } => {
write!(f, "JobRequest::Fetch({})", mailbox_hash)
}
@ -153,17 +185,6 @@ impl std::fmt::Debug for JobRequest {
.finish(),
Self::SaveMessage { .. } => write!(f, "JobRequest::SaveMessage"),
Self::DeleteMessages { .. } => write!(f, "JobRequest::DeleteMessages"),
Self::CreateMailbox { .. } => write!(f, "JobRequest::CreateMailbox"),
Self::DeleteMailbox { mailbox_hash, .. } => {
write!(f, "JobRequest::DeleteMailbox({})", mailbox_hash)
}
//JobRequest::RenameMailbox,
Self::SetMailboxPermissions { .. } => {
write!(f, "JobRequest::SetMailboxPermissions")
}
Self::SetMailboxSubscription { .. } => {
write!(f, "JobRequest::SetMailboxSubscription")
}
Self::Watch { .. } => write!(f, "JobRequest::Watch"),
Self::SendMessage => write!(f, "JobRequest::SendMessage"),
Self::SendMessageBackground { .. } => {
@ -177,7 +198,7 @@ impl std::fmt::Display for JobRequest {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Generic { name, .. } => write!(f, "{}", name),
Self::Mailboxes { .. } => write!(f, "Get mailbox list"),
Self::Mailbox(inner) => std::fmt::Display::fmt(inner, f),
Self::Fetch { .. } => write!(f, "Mailbox fetch"),
Self::IsOnline { .. } => write!(f, "Online status check"),
Self::Refresh { .. } => write!(f, "Refresh mailbox"),
@ -197,11 +218,6 @@ impl std::fmt::Display for JobRequest {
env_hashes.len(),
if env_hashes.len() == 1 { "" } else { "s" }
),
Self::CreateMailbox { path, .. } => write!(f, "Create mailbox {}", path),
Self::DeleteMailbox { .. } => write!(f, "Delete mailbox"),
//JobRequest::RenameMailbox,
Self::SetMailboxPermissions { .. } => write!(f, "Set mailbox permissions"),
Self::SetMailboxSubscription { .. } => write!(f, "Set mailbox subscription"),
Self::Watch { .. } => write!(f, "Background watch"),
Self::SendMessageBackground { .. } | Self::SendMessage => {
write!(f, "Sending message")

@ -0,0 +1,440 @@
//
// meli
//
// Copyright 2024 Emmanouil Pitsidianakis <manos@pitsidianak.is>
//
// This file is part of meli.
//
// meli is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// meli is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with meli. If not, see <http://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: EUPL-1.2 OR GPL-3.0-or-later
use melib::conf::ToggleFlag;
use super::*;
use crate::command::actions::MailboxOperation;
impl Account {
pub fn mailbox_operation(&mut self, op: MailboxOperation) -> Result<()> {
if self.settings.account.read_only {
return Err(Error::new("Account is read-only."));
}
match op {
MailboxOperation::Create(path) => {
let job = self
.backend
.write()
.unwrap()
.create_mailbox(path.to_string())?;
let handle = if self.backend_capabilities.is_async {
self.main_loop_handler
.job_executor
.spawn_specialized("create_mailbox".into(), job)
} else {
self.main_loop_handler
.job_executor
.spawn_blocking("create_mailbox".into(), job)
};
self.insert_job(
handle.job_id,
JobRequest::Mailbox(MailboxJobRequest::CreateMailbox { path, handle }),
);
Ok(())
}
MailboxOperation::Delete(path) => {
if self.mailbox_entries.len() == 1 {
return Err(Error::new("Cannot delete only mailbox."));
}
let mailbox_hash = self.mailbox_by_path(&path)?;
let job = self.backend.write().unwrap().delete_mailbox(mailbox_hash)?;
let handle = if self.backend_capabilities.is_async {
self.main_loop_handler
.job_executor
.spawn_specialized("delete_mailbox".into(), job)
} else {
self.main_loop_handler
.job_executor
.spawn_blocking("delete_mailbox".into(), job)
};
self.insert_job(
handle.job_id,
JobRequest::Mailbox(MailboxJobRequest::DeleteMailbox {
mailbox_hash,
handle,
}),
);
Ok(())
}
MailboxOperation::Subscribe(path) => {
let mailbox_hash = self.mailbox_by_path(&path)?;
let job = self
.backend
.write()
.unwrap()
.set_mailbox_subscription(mailbox_hash, true)?;
let handle = if self.backend_capabilities.is_async {
self.main_loop_handler
.job_executor
.spawn_specialized("subscribe_mailbox".into(), job)
} else {
self.main_loop_handler
.job_executor
.spawn_blocking("subscribe_mailbox".into(), job)
};
self.insert_job(
handle.job_id,
JobRequest::Mailbox(MailboxJobRequest::SetMailboxSubscription {
mailbox_hash,
new_value: true,
handle,
}),
);
Ok(())
}
MailboxOperation::Unsubscribe(path) => {
let mailbox_hash = self.mailbox_by_path(&path)?;
let job = self
.backend
.write()
.unwrap()
.set_mailbox_subscription(mailbox_hash, false)?;
let handle = if self.backend_capabilities.is_async {
self.main_loop_handler
.job_executor
.spawn_specialized("unsubscribe_mailbox".into(), job)
} else {
self.main_loop_handler
.job_executor
.spawn_blocking("unsubscribe_mailbox".into(), job)
};
self.insert_job(
handle.job_id,
JobRequest::Mailbox(MailboxJobRequest::SetMailboxSubscription {
mailbox_hash,
new_value: false,
handle,
}),
);
Ok(())
}
MailboxOperation::Rename(_, _) => Err(Error::new("Not implemented.")),
MailboxOperation::SetPermissions(_) => Err(Error::new("Not implemented.")),
}
}
pub fn process_mailbox_event(&mut self, job_id: JobId, job: &mut MailboxJobRequest) {
match job {
MailboxJobRequest::Mailboxes { ref mut handle } => {
if let Ok(Some(mailboxes)) = handle.chan.try_recv() {
if let Err(err) = mailboxes.and_then(|mailboxes| self.init(mailboxes)) {
if !err.is_recoverable() {
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::Notification {
title: Some(self.name.clone().into()),
source: Some(err.clone()),
body: err.to_string().into(),
kind: Some(NotificationType::Error(err.kind)),
},
));
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::AccountStatusChange(
self.hash,
Some(err.to_string().into()),
),
));
self.is_online.set_err(err);
self.main_loop_handler
.job_executor
.set_job_success(job_id, false);
return;
}
let mailboxes_job = self.backend.read().unwrap().mailboxes();
if let Ok(mailboxes_job) = mailboxes_job {
let handle = if self.backend_capabilities.is_async {
self.main_loop_handler
.job_executor
.spawn_specialized("mailboxes_list".into(), mailboxes_job)
} else {
self.main_loop_handler
.job_executor
.spawn_blocking("mailboxes_list".into(), mailboxes_job)
};
self.insert_job(
handle.job_id,
JobRequest::Mailbox(MailboxJobRequest::Mailboxes { handle }),
);
};
} else {
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::AccountStatusChange(
self.hash,
Some("Loaded mailboxes.".into()),
),
));
}
}
}
MailboxJobRequest::CreateMailbox {
ref path,
ref mut handle,
..
} => {
if let Ok(Some(r)) = handle.chan.try_recv() {
match r {
Err(err) => {
self.main_loop_handler
.job_executor
.set_job_success(job_id, false);
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::Notification {
title: Some(
format!(
"{}: could not create mailbox {}",
&self.name, path
)
.into(),
),
source: None,
body: err.to_string().into(),
kind: Some(NotificationType::Error(err.kind)),
},
));
}
Ok((mailbox_hash, mut mailboxes)) => {
self.main_loop_handler.send(ThreadEvent::UIEvent(
UIEvent::MailboxCreate((self.hash, mailbox_hash)),
));
let mut new = FileMailboxConf::default();
new.mailbox_conf.subscribe = ToggleFlag::InternalVal(true);
new.mailbox_conf.usage = if mailboxes[&mailbox_hash].special_usage()
!= SpecialUsageMailbox::Normal
{
Some(mailboxes[&mailbox_hash].special_usage())
} else {
let tmp = SpecialUsageMailbox::detect_usage(
mailboxes[&mailbox_hash].name(),
);
if let Some(tmp) = tmp.filter(|&v| v != SpecialUsageMailbox::Normal)
{
mailboxes.entry(mailbox_hash).and_modify(|entry| {
let _ = entry.set_special_usage(tmp);
});
}
tmp
};
// if new mailbox has parent, we need to update its children field
if let Some(parent_hash) = mailboxes[&mailbox_hash].parent() {
self.mailbox_entries
.entry(parent_hash)
.and_modify(|parent| {
parent.ref_mailbox =
mailboxes.remove(&parent_hash).unwrap();
});
}
let status = MailboxStatus::default();
self.mailbox_entries.insert(
mailbox_hash,
MailboxEntry::new(
status,
mailboxes[&mailbox_hash].path().to_string(),
mailboxes.remove(&mailbox_hash).unwrap(),
new,
),
);
self.collection
.threads
.write()
.unwrap()
.insert(mailbox_hash, Threads::default());
self.collection
.mailboxes
.write()
.unwrap()
.insert(mailbox_hash, Default::default());
build_mailboxes_order(
&mut self.tree,
&self.mailbox_entries,
&mut self.mailboxes_order,
);
}
}
}
}
MailboxJobRequest::DeleteMailbox {
mailbox_hash,
ref mut handle,
..
} => {
match handle.chan.try_recv() {
Err(_) => { /* canceled */ }
Ok(None) => {}
Ok(Some(Err(err))) => {
self.main_loop_handler
.job_executor
.set_job_success(job_id, false);
self.main_loop_handler
.send(ThreadEvent::UIEvent(UIEvent::Notification {
title: Some(
format!("{}: could not delete mailbox", &self.name).into(),
),
source: None,
body: err.to_string().into(),
kind: Some(NotificationType::Error(err.kind)),
}));
}
Ok(Some(Ok(mut mailboxes))) => {
let mailbox_hash = *mailbox_hash;
self.main_loop_handler
.send(ThreadEvent::UIEvent(UIEvent::MailboxDelete((
self.hash,
mailbox_hash,
))));
if let Some(pos) =
self.mailboxes_order.iter().position(|&h| h == mailbox_hash)
{
self.mailboxes_order.remove(pos);
}
if let Some(pos) = self.tree.iter().position(|n| n.hash == mailbox_hash) {
self.tree.remove(pos);
}
if self.settings.sent_mailbox == Some(mailbox_hash) {
self.settings.sent_mailbox = None;
}
self.collection
.threads
.write()
.unwrap()
.remove(&mailbox_hash);
let deleted_mailbox = self.mailbox_entries.remove(&mailbox_hash).unwrap();
// if deleted mailbox had parent, we need to update its children field
if let Some(parent_hash) = deleted_mailbox.ref_mailbox.parent() {
self.mailbox_entries
.entry(parent_hash)
.and_modify(|parent| {
parent.ref_mailbox = mailboxes.remove(&parent_hash).unwrap();
});
}
self.collection
.mailboxes
.write()
.unwrap()
.remove(&mailbox_hash);
build_mailboxes_order(
&mut self.tree,
&self.mailbox_entries,
&mut self.mailboxes_order,
);
// [ref:FIXME] remove from settings as well
self.main_loop_handler
.send(ThreadEvent::UIEvent(UIEvent::Notification {
title: Some(
format!("{}: mailbox deleted successfully", &self.name).into(),
),
source: None,
body: "".into(),
kind: Some(NotificationType::Info),
}));
}
}
}
MailboxJobRequest::SetMailboxPermissions { ref mut handle, .. } => {
match handle.chan.try_recv() {
Err(_) => { /* canceled */ }
Ok(None) => {}
Ok(Some(Err(err))) => {
self.main_loop_handler
.job_executor
.set_job_success(job_id, false);
self.main_loop_handler
.send(ThreadEvent::UIEvent(UIEvent::Notification {
title: Some(
format!("{}: could not set mailbox permissions", &self.name)
.into(),
),
source: None,
body: err.to_string().into(),
kind: Some(NotificationType::Error(err.kind)),
}));
}
Ok(Some(Ok(_))) => {
self.main_loop_handler
.send(ThreadEvent::UIEvent(UIEvent::Notification {
title: Some(
format!("{}: mailbox permissions set successfully", &self.name)
.into(),
),
source: None,
body: "".into(),
kind: Some(NotificationType::Info),
}));
}
}
}
MailboxJobRequest::SetMailboxSubscription {
ref mut handle,
ref mailbox_hash,
ref new_value,
} => {
match handle.chan.try_recv() {
Err(_) => { /* canceled */ }
Ok(None) => {}
Ok(Some(Err(err))) => {
self.main_loop_handler
.job_executor
.set_job_success(job_id, false);
self.main_loop_handler
.send(ThreadEvent::UIEvent(UIEvent::Notification {
title: Some(
format!("{}: could not set mailbox subscription", &self.name)
.into(),
),
source: None,
body: err.to_string().into(),
kind: Some(NotificationType::Error(err.kind)),
}));
}
Ok(Some(Ok(()))) if self.mailbox_entries.contains_key(mailbox_hash) => {
self.mailbox_entries.entry(*mailbox_hash).and_modify(|m| {
m.conf.mailbox_conf.subscribe = if *new_value {
ToggleFlag::True
} else {
ToggleFlag::False
};
let _ = m.ref_mailbox.set_is_subscribed(*new_value);
});
self.main_loop_handler
.send(ThreadEvent::UIEvent(UIEvent::Notification {
title: Some(
format!(
"{}: `{}` has been {}subscribed.",
&self.name,
self.mailbox_entries[mailbox_hash].name(),
if *new_value { "" } else { "un" }
)
.into(),
),
source: None,
body: "".into(),
kind: Some(NotificationType::Info),
}));
}
Ok(Some(Ok(()))) => {}
}
}
}
}
}
Loading…
Cancel
Save