summaryrefslogtreecommitdiffstats
path: root/ui/src/conf/accounts.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ui/src/conf/accounts.rs')
-rw-r--r--ui/src/conf/accounts.rs166
1 files changed, 101 insertions, 65 deletions
diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs
index fe2981ba..3bf8bd8a 100644
--- a/ui/src/conf/accounts.rs
+++ b/ui/src/conf/accounts.rs
@@ -46,24 +46,75 @@ use std::ops::{Index, IndexMut};
use std::result;
use std::sync::Arc;
-pub type Worker = Option<Async<(Result<FnvHashMap<EnvelopeHash, Envelope>>, Result<Mailbox>)>>;
+pub type Worker = Option<Async<Result<(FnvHashMap<EnvelopeHash, Envelope>, Mailbox)>>>;
macro_rules! mailbox {
($idx:expr, $folders:expr) => {
- $folders
- .get_mut(&$idx)
- .unwrap()
- .as_mut()
- .unwrap()
- .as_mut()
- .unwrap()
+ $folders.get_mut(&$idx).unwrap().unwrap_mut()
};
}
+#[derive(Serialize, Debug)]
+pub enum MailboxEntry {
+ Available(Mailbox),
+ Failed(MeliError),
+ /// first argument is done work, and second is total work
+ Parsing(usize, usize),
+ /// first argument is done work, and second is total work
+ Threading(usize, usize),
+}
+
+impl std::fmt::Display for MailboxEntry {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(
+ f,
+ "{}",
+ match self {
+ MailboxEntry::Available(ref m) => m.name().to_string(),
+ MailboxEntry::Failed(ref e) => e.to_string(),
+ MailboxEntry::Parsing(done, total) => {
+ format!("Parsing messages. [{}/{}]", done, total)
+ }
+ MailboxEntry::Threading(done, total) => {
+ format!("Calculating threads. [{}/{}]", done, total)
+ }
+ }
+ )
+ }
+}
+impl MailboxEntry {
+ pub fn is_available(&self) -> bool {
+ if let MailboxEntry::Available(_) = self {
+ true
+ } else {
+ false
+ }
+ }
+ pub fn is_parsing(&self) -> bool {
+ if let MailboxEntry::Parsing(_, _) = self {
+ true
+ } else {
+ false
+ }
+ }
+ pub fn unwrap_mut(&mut self) -> &mut Mailbox {
+ match self {
+ MailboxEntry::Available(ref mut m) => m,
+ e => panic!(format!("mailbox is not available! {:#}", e)),
+ }
+ }
+ pub fn unwrap(&self) -> &Mailbox {
+ match self {
+ MailboxEntry::Available(ref m) => m,
+ e => panic!(format!("mailbox is not available! {:#}", e)),
+ }
+ }
+}
+
#[derive(Debug)]
pub struct Account {
name: String,
- pub(crate) folders: FnvHashMap<FolderHash, Option<Result<Mailbox>>>,
+ pub(crate) folders: FnvHashMap<FolderHash, MailboxEntry>,
pub(crate) folders_order: Vec<FolderHash>,
folder_names: FnvHashMap<FolderHash, String>,
tree: Vec<FolderNode>,
@@ -113,31 +164,21 @@ impl Drop for Account {
pub struct MailboxIterator<'a> {
folders_order: &'a [FolderHash],
- folders: &'a FnvHashMap<FolderHash, Option<Result<Mailbox>>>,
+ folders: &'a FnvHashMap<FolderHash, MailboxEntry>,
pos: usize,
}
impl<'a> Iterator for MailboxIterator<'a> {
- type Item = Option<&'a Mailbox>;
+ type Item = &'a MailboxEntry;
- fn next(&mut self) -> Option<Option<&'a Mailbox>> {
+ fn next(&mut self) -> Option<&'a MailboxEntry> {
if self.pos == self.folders.len() {
return None;
}
let fh = &self.folders_order[self.pos];
- if self.pos == self.folders.len() {
- return None;
- }
-
self.pos += 1;
- if self.folders[&fh].is_none() {
- return Some(None);
- }
- if let Some(Err(_)) = self.folders[&fh] {
- return Some(None);
- }
- Some(Some(self.folders[&fh].as_ref().unwrap().as_ref().unwrap()))
+ Some(&self.folders[&fh])
}
}
@@ -156,7 +197,7 @@ impl Account {
) -> Self {
let mut backend = map.get(settings.account().format())(settings.account());
let mut ref_folders: FnvHashMap<FolderHash, Folder> = backend.folders();
- let mut folders: FnvHashMap<FolderHash, Option<Result<Mailbox>>> =
+ let mut folders: FnvHashMap<FolderHash, MailboxEntry> =
FnvHashMap::with_capacity_and_hasher(ref_folders.len(), Default::default());
let mut folders_order: Vec<FolderHash> = Vec::with_capacity(ref_folders.len());
let mut workers: FnvHashMap<FolderHash, Worker> = FnvHashMap::default();
@@ -208,7 +249,7 @@ impl Account {
}
}
}
- folders.insert(*h, None);
+ folders.insert(*h, MailboxEntry::Parsing(0, 0));
workers.insert(
*h,
Account::new_worker(f.clone(), &mut backend, notify_fn.clone()),
@@ -282,15 +323,19 @@ impl Account {
.collect::<FnvHashMap<EnvelopeHash, Envelope>>()
});
let hash = folder.hash();
- let m = Mailbox::new(folder, envelopes.as_ref().map_err(Clone::clone));
- tx.send(AsyncStatus::Payload((envelopes, m)));
+ if envelopes.is_err() {
+ tx.send(AsyncStatus::Payload(Err(envelopes.unwrap_err())));
+ notify_fn.notify(hash);
+ return;
+ }
+ let envelopes = envelopes.unwrap();
+ let m = Mailbox::new(folder, &envelopes);
+ tx.send(AsyncStatus::Payload(Ok((envelopes, m))));
notify_fn.notify(hash);
})))
}
pub fn reload(&mut self, event: RefreshEvent, folder_hash: FolderHash) -> Option<UIEvent> {
- if self.folders[&folder_hash].is_none()
- || self.folders[&folder_hash].as_ref().unwrap().is_err()
- {
+ if !self.folders[&folder_hash].is_available() {
self.event_queue.push_back((folder_hash, event));
return None;
}
@@ -306,15 +351,13 @@ impl Account {
}
RefreshEventKind::Rename(old_hash, new_hash) => {
debug!("rename {} to {}", old_hash, new_hash);
- let mailbox = mailbox!(&folder_hash, self.folders);
- mailbox.rename(old_hash, new_hash);
+ mailbox!(&folder_hash, self.folders).rename(old_hash, new_hash);
self.collection.rename(old_hash, new_hash, folder_hash);
return Some(EnvelopeRename(old_hash, new_hash));
}
RefreshEventKind::Create(envelope) => {
let env_hash = envelope.hash();
- let mailbox = mailbox!(&folder_hash, self.folders);
- mailbox.insert(env_hash);
+ mailbox!(&folder_hash, self.folders).insert(env_hash);
self.collection.insert(*envelope, folder_hash);
if self
.sent_folder
@@ -367,7 +410,7 @@ impl Account {
pub fn watch(&self, r: RefreshEventConsumer) {
self.backend.watch(r).unwrap();
}
- /* This doesn't represent the number of correctly parsed mailboxes though */
+
pub fn len(&self) -> usize {
self.folders.len()
}
@@ -417,17 +460,18 @@ impl Account {
fn load_mailbox(
&mut self,
folder_hash: FolderHash,
- mailbox: (Result<FnvHashMap<EnvelopeHash, Envelope>>, Result<Mailbox>),
+ payload: (Result<(FnvHashMap<EnvelopeHash, Envelope>, Mailbox)>),
) {
- let (envs, mut mailbox) = mailbox;
- if envs.is_err() {
- self.folders.insert(folder_hash, None);
+ if payload.is_err() {
+ self.folders
+ .insert(folder_hash, MailboxEntry::Failed(payload.unwrap_err()));
return;
}
- let envs = envs.unwrap();
+ let (envelopes, mut mailbox) = payload.unwrap();
self.collection
- .merge(envs, folder_hash, &mut mailbox, self.sent_folder);
- self.folders.insert(folder_hash, Some(mailbox));
+ .merge(envelopes, folder_hash, &mut mailbox, self.sent_folder);
+ self.folders
+ .insert(folder_hash, MailboxEntry::Available(mailbox));
}
pub fn status(&mut self, folder_hash: FolderHash) -> result::Result<(), usize> {
@@ -435,12 +479,17 @@ impl Account {
None => {
return Ok(());
}
- Some(ref mut w) if self.folders[&folder_hash].is_none() => match w.poll() {
+ Some(ref mut w) if self.folders[&folder_hash].is_parsing() => match w.poll() {
Ok(AsyncStatus::NoUpdate) => {
return Err(0);
}
Ok(AsyncStatus::Finished) => {}
Ok(AsyncStatus::ProgressReport(n)) => {
+ self.folders.entry(folder_hash).and_modify(|f| {
+ if let MailboxEntry::Parsing(ref mut d, _) = f {
+ *d += n;
+ }
+ });
return Err(n);
}
_ => {
@@ -496,7 +545,7 @@ impl Account {
}
pub fn operation(&self, h: EnvelopeHash) -> Box<BackendOp> {
for mailbox in self.folders.values() {
- if let Some(Ok(m)) = mailbox {
+ if let MailboxEntry::Available(ref m) = mailbox {
if m.envelopes.contains(&h) {
let operation = self.backend.operation(h, m.folder.hash());
if self.settings.account.read_only() {
@@ -542,41 +591,28 @@ impl Account {
}
impl Index<FolderHash> for Account {
- type Output = Result<Mailbox>;
- fn index(&self, index: FolderHash) -> &Result<Mailbox> {
+ type Output = MailboxEntry;
+ fn index(&self, index: FolderHash) -> &MailboxEntry {
&self.folders[&index]
- .as_ref()
- .expect("BUG: Requested mailbox that is not yet available.")
}
}
-/// Will panic if mailbox hasn't loaded, ask `status()` first.
impl IndexMut<FolderHash> for Account {
- fn index_mut(&mut self, index: FolderHash) -> &mut Result<Mailbox> {
- self.folders
- .get_mut(&index)
- .unwrap()
- .as_mut()
- .expect("BUG: Requested mailbox that is not yet available.")
+ fn index_mut(&mut self, index: FolderHash) -> &mut MailboxEntry {
+ self.folders.get_mut(&index).unwrap()
}
}
impl Index<usize> for Account {
- type Output = Result<Mailbox>;
- fn index(&self, index: usize) -> &Result<Mailbox> {
+ type Output = MailboxEntry;
+ fn index(&self, index: usize) -> &MailboxEntry {
&self.folders[&self.folders_order[index]]
- .as_ref()
- .expect("BUG: Requested mailbox that is not yet available.")
}
}
/// Will panic if mailbox hasn't loaded, ask `status()` first.
impl IndexMut<usize> for Account {
- fn index_mut(&mut self, index: usize) -> &mut Result<Mailbox> {
- self.folders
- .get_mut(&self.folders_order[index])
- .unwrap()
- .as_mut()
- .expect("BUG: Requested mailbox that is not yet available.")
+ fn index_mut(&mut self, index: usize) -> &mut MailboxEntry {
+ self.folders.get_mut(&self.folders_order[index]).unwrap()
}
}