diff options
Diffstat (limited to 'ui/src/conf/accounts.rs')
-rw-r--r-- | ui/src/conf/accounts.rs | 166 |
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() } } |