diff --git a/melib/src/mailbox/backends.rs b/melib/src/mailbox/backends.rs index 0c86552a1..738c910c6 100644 --- a/melib/src/mailbox/backends.rs +++ b/melib/src/mailbox/backends.rs @@ -147,7 +147,7 @@ impl NotifyFn { pub trait MailBackend: ::std::fmt::Debug { fn get(&mut self, folder: &Folder) -> Async>>; fn watch(&self, sender: RefreshEventConsumer) -> Result<()>; - fn folders(&self) -> Vec; + fn folders(&self) -> FnvHashMap; fn operation(&self, hash: EnvelopeHash, folder_hash: FolderHash) -> Box; fn save(&self, bytes: &[u8], folder: &str) -> Result<()>; diff --git a/melib/src/mailbox/backends/maildir.rs b/melib/src/mailbox/backends/maildir.rs index 30be7d996..1f82dee47 100644 --- a/melib/src/mailbox/backends/maildir.rs +++ b/melib/src/mailbox/backends/maildir.rs @@ -19,6 +19,7 @@ * along with meli. If not, see . */ +#[macro_use] mod backend; pub use self::backend::*; @@ -165,14 +166,24 @@ impl<'a> BackendOp for MaildirOp { new_name.push('T'); } - eprint!("{}:{}_{}: ", file!(), line!(), column!()); - eprintln!("renaming {:?} to {:?}", path, new_name); + if cfg!(debug_assertions) { + eprint!("{}:{}_{}: ", file!(), line!(), column!()); + eprintln!("renaming {:?} to {:?}", path, new_name); + } fs::rename(&path, &new_name)?; - let hash = envelope.hash(); + if cfg!(debug_assertions) { + eprint!("{}:{}_{}: ", file!(), line!(), column!()); + eprintln!("success in rename"); + } + let old_hash = envelope.hash(); + let new_name: PathBuf = new_name.into(); + let new_hash = get_file_hash(&new_name); + envelope.set_hash(new_hash); let hash_index = self.hash_index.clone(); let mut map = hash_index.lock().unwrap(); let map = map.entry(self.folder_hash).or_default(); - *map.get_mut(&hash).unwrap() = PathBuf::from(new_name); + map.remove(&old_hash); + map.insert(new_hash, new_name); Ok(()) } } diff --git a/melib/src/mailbox/backends/maildir/backend.rs b/melib/src/mailbox/backends/maildir/backend.rs index 7f2e3daf8..878c40a51 100644 --- a/melib/src/mailbox/backends/maildir/backend.rs +++ b/melib/src/mailbox/backends/maildir/backend.rs @@ -91,6 +91,7 @@ macro_rules! path_is_new { }; } +#[macro_export] macro_rules! get_path_hash { ($path:expr) => {{ let mut path = $path.clone(); @@ -109,7 +110,7 @@ macro_rules! get_path_hash { }}; } -fn get_file_hash(file: &Path) -> EnvelopeHash { +pub(super) fn get_file_hash(file: &Path) -> EnvelopeHash { /* let mut buf = Vec::with_capacity(2048); let mut f = fs::File::open(&file).unwrap_or_else(|_| panic!("Can't open {}", file.display())); @@ -126,15 +127,13 @@ fn get_file_hash(file: &Path) -> EnvelopeHash { fn move_to_cur(p: PathBuf) -> PathBuf { let mut new = p.clone(); - { - let file_name = p.file_name().unwrap(); - new.pop(); - new.pop(); + let file_name = p.file_name().unwrap(); + new.pop(); + new.pop(); - new.push("cur"); - new.push(file_name); - new.set_extension(":2,"); - } + new.push("cur"); + new.push(file_name); + new.set_extension(":2,"); if cfg!(debug_assertions) { eprint!("{}:{}_{}: ", file!(), line!(), column!()); eprintln!("moved to cur: {}", new.display()); @@ -144,15 +143,15 @@ fn move_to_cur(p: PathBuf) -> PathBuf { } impl MailBackend for MaildirType { - fn folders(&self) -> Vec { - self.folders.iter().map(|f| f.clone()).collect() + fn folders(&self) -> FnvHashMap { + self.folders.iter().map(|f| (f.hash(), f.clone())).collect() } fn get(&mut self, folder: &Folder) -> Async>> { self.multicore(4, folder) } fn watch(&self, sender: RefreshEventConsumer) -> Result<()> { let (tx, rx) = channel(); - let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap(); + let mut watcher = watcher(tx, Duration::from_secs(2)).unwrap(); let root_path = self.path.to_path_buf(); let cache_dir = xdg::BaseDirectories::with_profile("meli", &self.name).unwrap(); for f in &self.folders { @@ -315,7 +314,7 @@ eprintln!("removed but not contained in index"); kind: Remove(hash), }); } - /* Envelope hasn't changed, so handle this here */ + /* Envelope hasn't changed */ DebouncedEvent::Rename(src, dest) => { eprint!("{}:{}_{}: ", file!(), line!(), column!()); eprintln!("DebouncedEvent::Rename(src = {:?}, dest = {:?})", src, dest); @@ -335,13 +334,43 @@ eprintln!("contains_key"); }); index_lock.remove(&old_hash); index_lock.insert(new_hash, dest); - } else { - /* Maybe a re-read should be triggered here just to be safe. */ - sender.send(RefreshEvent { - hash: get_path_hash!(dest), - kind: Rescan, - }); + continue; + } else if !index_lock.contains_key(&new_hash) { + eprint!("{}:{}_{}: ", file!(), line!(), column!()); + eprintln!("not contains_key"); + let file_name = dest + .as_path() + .strip_prefix(&root_path) + .unwrap() + .to_path_buf(); + eprint!("{}:{}_{}: ", file!(), line!(), column!()); + eprintln!("filename = {:?}", file_name); + if let Some(env) = add_path_to_index( + &hash_indexes, + folder_hash, + dest.as_path(), + &cache_dir, + file_name, + ) { + eprint!("{}:{}_{}: ", file!(), line!(), column!()); + eprintln!("Create event {} {} {}", env.hash(), env.subject(), dest.display()); + if cfg!(debug_assertions) { + } + sender.send(RefreshEvent { + hash: folder_hash, + kind: Create(Box::new(env)), + }); + continue; + } else { + eprint!("{}:{}_{}: ", file!(), line!(), column!()); + eprintln!("not valid email"); + } } + /* Maybe a re-read should be triggered here just to be safe. */ + sender.send(RefreshEvent { + hash: get_path_hash!(dest), + kind: Rescan, + }); } /* Trigger rescan of folder */ DebouncedEvent::Rescan => { diff --git a/melib/src/mailbox/collection.rs b/melib/src/mailbox/collection.rs index 353de2740..7a7f2e339 100644 --- a/melib/src/mailbox/collection.rs +++ b/melib/src/mailbox/collection.rs @@ -101,6 +101,9 @@ eprintln!("DEBUG: Removing {}", envelope_hash); } pub fn rename(&mut self, old_hash: EnvelopeHash, new_hash: EnvelopeHash) { + if !self.envelopes.contains_key(&old_hash) { + return; + } let mut env = self.envelopes.remove(&old_hash).unwrap(); env.set_hash(new_hash); self.envelopes.insert(new_hash, env); diff --git a/ui/src/components/mail.rs b/ui/src/components/mail.rs index 0bfcbb59f..f57fcf503 100644 --- a/ui/src/components/mail.rs +++ b/ui/src/components/mail.rs @@ -146,7 +146,7 @@ impl AccountMenu { return; } let len = s.len(); - match context.accounts[index].status(root) { + match context.accounts[index].status(entries[root].1.hash()) { Ok(_) => {} Err(_) => { return; @@ -263,10 +263,17 @@ impl Component for AccountMenu { context.dirty_areas.push_back(area); } - fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { match *event { - UIEvent::RefreshMailbox(c) => { - self.cursor = Some(c); + UIEvent::RefreshMailbox((idxa, folder_hash)) => { + self.cursor = Some(( + idxa, + context.accounts[idxa] + .folders_order + .iter() + .position(|&h| h == folder_hash) + .unwrap_or(0), + )); self.dirty = true; } UIEvent::ChangeMode(UIMode::Normal) => { diff --git a/ui/src/components/mail/listing/compact.rs b/ui/src/components/mail/listing/compact.rs index 0f00b9c04..7975676de 100644 --- a/ui/src/components/mail/listing/compact.rs +++ b/ui/src/components/mail/listing/compact.rs @@ -104,15 +104,15 @@ impl MailboxView { } self.cursor_pos.1 = self.new_cursor_pos.1; self.cursor_pos.0 = self.new_cursor_pos.0; + let folder_hash = context.accounts[self.cursor_pos.0].folders_order[self.cursor_pos.1]; // Inform State that we changed the current folder view. - context.replies.push_back(UIEvent::RefreshMailbox(( - self.cursor_pos.0, - self.cursor_pos.1, - ))); + context + .replies + .push_back(UIEvent::RefreshMailbox((self.cursor_pos.0, folder_hash))); // Get mailbox as a reference. // - match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) { + match context.accounts[self.cursor_pos.0].status(folder_hash) { Ok(_) => {} Err(_) => { self.content = CellBuffer::new(MAX_COLS, 1, Cell::with_char(' ')); @@ -442,17 +442,32 @@ impl Component for MailboxView { self.dirty = true; } UIEvent::MailboxUpdate((ref idxa, ref idxf)) - if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 => + if (*idxa, *idxf) + == ( + self.new_cursor_pos.0, + context.accounts[self.new_cursor_pos.0].folders_order + [self.new_cursor_pos.1], + ) => { self.refresh_mailbox(context); self.set_dirty(); } UIEvent::StartupCheck(ref f) - if context.mailbox_hashes[f] == (self.new_cursor_pos.0, self.new_cursor_pos.1) => + if *f + == context.accounts[self.new_cursor_pos.0].folders_order + [self.new_cursor_pos.1] => { self.refresh_mailbox(context); self.set_dirty(); } + UIEvent::EnvelopeRename(ref folder_hash, _, _) => { + if *folder_hash + == context.accounts[self.cursor_pos.0].folders_order[self.new_cursor_pos.1] + { + self.refresh_mailbox(context); + self.set_dirty(); + } + } UIEvent::ChangeMode(UIMode::Normal) => { self.dirty = true; } @@ -649,6 +664,7 @@ impl CompactListing { impl Component for CompactListing { fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { if !self.populated { + eprint!("{}:{}_{}: ", file!(), line!(), column!()); eprintln!("populating"); for (idx, a) in context.accounts.iter().enumerate() { for (fidx, _) in a.iter_mailboxes().enumerate() { diff --git a/ui/src/components/mail/listing/plain.rs b/ui/src/components/mail/listing/plain.rs index 6e45d07a8..b022b91e5 100644 --- a/ui/src/components/mail/listing/plain.rs +++ b/ui/src/components/mail/listing/plain.rs @@ -105,17 +105,15 @@ impl PlainListing { } self.cursor_pos.0 = self.new_cursor_pos.0; self.cursor_pos.1 = self.new_cursor_pos.1; + let folder_hash = context.accounts[self.cursor_pos.0].folders_order[self.cursor_pos.1]; // Inform State that we changed the current folder view. - context.replies.push_back(UIEvent::RefreshMailbox(( - self.cursor_pos.0, - self.cursor_pos.1, - ))); + context + .replies + .push_back(UIEvent::RefreshMailbox((self.cursor_pos.0, folder_hash))); // Get mailbox as a reference. // - // Get mailbox as a reference. - // - match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) { + match context.accounts[self.cursor_pos.0].status(folder_hash) { Ok(_) => {} Err(_) => { self.content = CellBuffer::new(MAX_COLS, 1, Cell::with_char(' ')); @@ -505,13 +503,20 @@ impl Component for PlainListing { self.view = None; } UIEvent::MailboxUpdate((ref idxa, ref idxf)) - if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 => + if (*idxa, *idxf) + == ( + self.new_cursor_pos.0, + context.accounts[self.new_cursor_pos.0].folders_order + [self.new_cursor_pos.1], + ) => { self.refresh_mailbox(context); self.set_dirty(); } UIEvent::StartupCheck(ref f) - if context.mailbox_hashes[f] == (self.new_cursor_pos.0, self.new_cursor_pos.1) => + if *f + == context.accounts[self.new_cursor_pos.0].folders_order + [self.new_cursor_pos.1] => { self.refresh_mailbox(context); self.set_dirty(); diff --git a/ui/src/components/mail/listing/thread.rs b/ui/src/components/mail/listing/thread.rs index 925d72892..182b6f8f3 100644 --- a/ui/src/components/mail/listing/thread.rs +++ b/ui/src/components/mail/listing/thread.rs @@ -103,15 +103,15 @@ impl ThreadListing { } self.cursor_pos.1 = self.new_cursor_pos.1; self.cursor_pos.0 = self.new_cursor_pos.0; + let folder_hash = context.accounts[self.cursor_pos.0].folders_order[self.cursor_pos.1]; // Inform State that we changed the current folder view. - context.replies.push_back(UIEvent::RefreshMailbox(( - self.cursor_pos.0, - self.cursor_pos.1, - ))); + context + .replies + .push_back(UIEvent::RefreshMailbox((self.cursor_pos.0, folder_hash))); // Get mailbox as a reference. // - match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) { + match context.accounts[self.cursor_pos.0].status(folder_hash) { Ok(_) => {} Err(_) => { self.content = CellBuffer::new(MAX_COLS, 1, Cell::with_char(' ')); @@ -668,13 +668,20 @@ impl Component for ThreadListing { self.view = None; } UIEvent::MailboxUpdate((ref idxa, ref idxf)) - if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 => + if (*idxa, *idxf) + == ( + self.new_cursor_pos.0, + context.accounts[self.new_cursor_pos.0].folders_order + [self.new_cursor_pos.1], + ) => { self.refresh_mailbox(context); self.set_dirty(); } UIEvent::StartupCheck(ref f) - if context.mailbox_hashes[f] == (self.new_cursor_pos.0, self.new_cursor_pos.1) => + if *f + == context.accounts[self.new_cursor_pos.0].folders_order + [self.new_cursor_pos.1] => { self.refresh_mailbox(context); self.set_dirty(); diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs index 84f276d84..b7d00dc15 100644 --- a/ui/src/conf/accounts.rs +++ b/ui/src/conf/accounts.rs @@ -24,7 +24,9 @@ */ use super::AccountConf; +use fnv::FnvHashMap; use melib::async_workers::{Async, AsyncBuilder, AsyncStatus}; +use melib::backends::FolderHash; use melib::error::Result; use melib::mailbox::backends::{ Backends, Folder, MailBackend, NotifyFn, RefreshEvent, RefreshEventConsumer, RefreshEventKind, @@ -44,19 +46,26 @@ pub type Worker = Option>>; macro_rules! mailbox { ($idx:expr, $folders:expr) => { - $folders[$idx].as_mut().unwrap().as_mut().unwrap() + $folders + .get_mut(&$idx) + .unwrap() + .as_mut() + .unwrap() + .as_mut() + .unwrap() }; } #[derive(Debug)] pub struct Account { name: String, - folders: Vec>>, + pub(crate) folders: FnvHashMap>>, + pub(crate) folders_order: Vec, sent_folder: Option, pub(crate) address_book: AddressBook, - pub(crate) workers: Vec, + pub(crate) workers: FnvHashMap, pub(crate) settings: AccountConf, pub(crate) runtime_settings: AccountConf, @@ -83,7 +92,8 @@ impl Drop for Account { } pub struct MailboxIterator<'a> { - folders: &'a [Option>], + folders_order: &'a [FolderHash], + folders: &'a FnvHashMap>>, pos: usize, } @@ -94,19 +104,19 @@ impl<'a> Iterator for MailboxIterator<'a> { if self.pos == self.folders.len() { return None; } - for f in self.folders[self.pos..].iter() { + for fh in self.folders_order[self.pos..].iter() { if self.pos == self.folders.len() { return None; } self.pos += 1; - if let Some(Err(_)) = f { + if self.folders[&fh].is_none() { return Some(None); } - if let None = f { + if let Some(Err(_)) = self.folders[&fh] { return Some(None); } - return Some(Some(f.as_ref().unwrap().as_ref().unwrap())); + return Some(Some(self.folders[&fh].as_ref().unwrap().as_ref().unwrap())); } return None; } @@ -115,26 +125,28 @@ impl<'a> Iterator for MailboxIterator<'a> { impl Account { pub fn new(name: String, settings: AccountConf, map: &Backends, notify_fn: NotifyFn) -> Self { let mut backend = map.get(settings.account().format())(settings.account()); - let mut ref_folders: Vec = backend.folders(); - let mut folders: Vec>> = Vec::with_capacity(ref_folders.len()); - let mut workers: Vec = Vec::new(); + let mut ref_folders: FnvHashMap = backend.folders(); + let mut folders: FnvHashMap>> = + FnvHashMap::with_capacity_and_hasher(ref_folders.len(), Default::default()); + let mut folders_order: Vec = ref_folders.values().map(|f| f.hash()).collect(); + let mut workers: FnvHashMap = FnvHashMap::default(); let notify_fn = Arc::new(notify_fn); if let Some(pos) = ref_folders - .iter() + .values() .position(|f| f.name().eq_ignore_ascii_case("INBOX")) { - ref_folders.swap(pos, 0); + folders_order.swap(pos, 0); } let sent_folder = ref_folders - .iter() + .values() .position(|x: &Folder| x.name() == settings.account().sent_folder); if let Some(folder_confs) = settings.conf().folders() { //if cfg!(debug_assertions) { //eprint!("{}:{}_{}: ", file!(), line!(), column!()); //eprintln!("folder renames: {:?}", folder_renames); //} - for f in &mut ref_folders { + for f in ref_folders.values_mut() { if let Some(r) = folder_confs.get(&f.name().to_ascii_lowercase()) { if let Some(rename) = r.rename() { f.change_name(rename); @@ -142,9 +154,9 @@ impl Account { } } } - for f in ref_folders { - folders.push(None); - workers.push(Account::new_worker(f, &mut backend, notify_fn.clone())); + for (h, f) in ref_folders.into_iter() { + folders.insert(h, None); + workers.insert(h, Account::new_worker(f, &mut backend, notify_fn.clone())); } let data_dir = xdg::BaseDirectories::with_profile("meli", &name).unwrap(); let address_book = if let Ok(data) = data_dir.place_data_file("addressbook") { @@ -166,6 +178,7 @@ impl Account { Account { name, folders, + folders_order, address_book, sent_folder, workers, @@ -196,13 +209,13 @@ impl Account { notify_fn.notify(hash); }))) } - pub fn reload(&mut self, event: RefreshEvent, idx: usize) -> Option { + pub fn reload(&mut self, event: RefreshEvent, folder_hash: FolderHash) -> Option { let kind = event.kind(); { //let mailbox: &mut Mailbox = self.folders[idx].as_mut().unwrap().as_mut().unwrap(); match kind { RefreshEventKind::Update(old_hash, envelope) => { - mailbox!(idx, self.folders).update(old_hash, *envelope); + mailbox!(&folder_hash, self.folders).update(old_hash, *envelope); return Some(EnvelopeUpdate(old_hash)); } RefreshEventKind::Rename(old_hash, new_hash) => { @@ -210,39 +223,40 @@ impl Account { eprint!("{}:{}_{}: ", file!(), line!(), column!()); eprintln!("rename {} to {}", old_hash, new_hash); } - mailbox!(idx, self.folders).rename(old_hash, new_hash); - return Some(EnvelopeRename(idx, old_hash, new_hash)); + let mailbox = mailbox!(&folder_hash, self.folders); + mailbox.rename(old_hash, new_hash); + return Some(EnvelopeRename(mailbox.folder.hash(), old_hash, new_hash)); } RefreshEventKind::Create(envelope) => { if cfg!(debug_assertions) { eprint!("{}:{}_{}: ", file!(), line!(), column!()); eprintln!("create {}", envelope.hash()); } - let env: &Envelope = mailbox!(idx, self.folders).insert(*envelope); - let ref_folders: Vec = self.backend.folders(); + let env: &Envelope = mailbox!(&folder_hash, self.folders).insert(*envelope); + let ref_folders: FnvHashMap = self.backend.folders(); return Some(Notification( Some("new mail".into()), format!( "{} {:.15}:\n\nFrom: {:.15}\nSubject: {:.15}", self.name, - ref_folders[idx].name(), + ref_folders[&folder_hash].name(), env.subject(), env.field_from_to_string(), ), )); } RefreshEventKind::Remove(envelope_hash) => { - mailbox!(idx, self.folders).remove(envelope_hash); + mailbox!(&folder_hash, self.folders).remove(envelope_hash); return Some(EnvelopeRemove(envelope_hash)); } RefreshEventKind::Rescan => { - let ref_folders: Vec = self.backend.folders(); + let ref_folders: FnvHashMap = self.backend.folders(); let handle = Account::new_worker( - ref_folders[idx].clone(), + ref_folders[&folder_hash].clone(), &mut self.backend, self.notify_fn.clone(), ); - self.workers[idx] = handle; + self.workers.insert(folder_hash, handle); } } } @@ -265,7 +279,7 @@ impl Account { //eprint!("{}:{}_{}: ", file!(), line!(), column!()); //eprintln!("folder renames: {:?}", folder_renames); //} - for f in &mut folders { + for f in folders.values_mut() { if let Some(r) = folder_confs.get(&f.name().to_ascii_lowercase()) { if let Some(rename) = r.rename() { f.change_name(rename); @@ -273,23 +287,28 @@ impl Account { } } } + /* if let Some(pos) = folders .iter() .position(|f| f.name().eq_ignore_ascii_case("INBOX")) { folders.swap(pos, 0); } - folders + */ + self.folders_order + .iter() + .map(|ref h| folders.remove(&h).unwrap()) + .collect() } pub fn name(&self) -> &str { &self.name } - pub fn workers(&mut self) -> &mut Vec { + pub fn workers(&mut self) -> &mut FnvHashMap { &mut self.workers } - fn load_mailbox(&mut self, index: usize, mailbox: Result) { - self.folders[index] = Some(mailbox); + fn load_mailbox(&mut self, folder_hash: FolderHash, mailbox: Result) { + self.folders.insert(folder_hash, Some(mailbox)); /* if self.sent_folder.is_some() && self.sent_folder.unwrap() == index { self.folders[index] = Some(mailbox); @@ -340,12 +359,12 @@ impl Account { } */ - pub fn status(&mut self, index: usize) -> result::Result<(), usize> { - match self.workers[index].as_mut() { + pub fn status(&mut self, folder_hash: FolderHash) -> result::Result<(), usize> { + match self.workers.get_mut(&folder_hash).unwrap() { None => { return Ok(()); } - Some(ref mut w) if self.folders[index].is_none() => match w.poll() { + Some(ref mut w) if self.folders[&folder_hash].is_none() => match w.poll() { Ok(AsyncStatus::NoUpdate) => { return Err(0); } @@ -359,11 +378,11 @@ impl Account { }, Some(_) => return Ok(()), }; - let m = mem::replace(&mut self.workers[index], None) + let m = mem::replace(self.workers.get_mut(&folder_hash).unwrap(), None) .unwrap() .extract(); - self.workers[index] = None; - self.load_mailbox(index, m); + self.workers.insert(folder_hash, None); + self.load_mailbox(folder_hash, m); Ok(()) } @@ -377,16 +396,36 @@ impl Account { } pub fn iter_mailboxes<'a>(&'a self) -> MailboxIterator<'a> { MailboxIterator { + folders_order: &self.folders_order, folders: &self.folders, pos: 0, } } } +impl Index for Account { + type Output = Result; + fn index(&self, index: FolderHash) -> &Result { + &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 for Account { + fn index_mut(&mut self, index: FolderHash) -> &mut Result { + self.folders + .get_mut(&index) + .unwrap() + .as_mut() + .expect("BUG: Requested mailbox that is not yet available.") + } +} impl Index for Account { type Output = Result; fn index(&self, index: usize) -> &Result { - &self.folders[index] + &self.folders[&self.folders_order[index]] .as_ref() .expect("BUG: Requested mailbox that is not yet available.") } @@ -395,7 +434,9 @@ impl Index for Account { /// Will panic if mailbox hasn't loaded, ask `status()` first. impl IndexMut for Account { fn index_mut(&mut self, index: usize) -> &mut Result { - self.folders[index] + self.folders + .get_mut(&self.folders_order[index]) + .unwrap() .as_mut() .expect("BUG: Requested mailbox that is not yet available.") } diff --git a/ui/src/state.rs b/ui/src/state.rs index 233cc8394..15dde71e8 100644 --- a/ui/src/state.rs +++ b/ui/src/state.rs @@ -75,7 +75,7 @@ impl InputHandler { /// A context container for loaded settings, accounts, UI changes, etc. pub struct Context { pub accounts: Vec, - pub mailbox_hashes: FnvHashMap, + pub mailbox_hashes: FnvHashMap, pub settings: Settings, pub runtime_settings: Settings, @@ -101,11 +101,15 @@ impl Context { pub fn restore_input(&self) { self.input.restore(self.sender.clone()); } - pub fn account_status(&mut self, idx_a: usize, idx_m: usize) -> result::Result<(), usize> { - match self.accounts[idx_a].status(idx_m) { + pub fn account_status( + &mut self, + idx_a: usize, + folder_hash: FolderHash, + ) -> result::Result<(), usize> { + match self.accounts[idx_a].status(folder_hash) { Ok(()) => { self.replies - .push_back(UIEvent::MailboxUpdate((idx_a, idx_m))); + .push_back(UIEvent::MailboxUpdate((idx_a, folder_hash))); Ok(()) } Err(n) => Err(n), @@ -220,7 +224,7 @@ impl State { work_controller: WorkController::new(), }; for a in s.context.accounts.iter_mut() { - for worker in a.workers.iter_mut() { + for worker in a.workers.values_mut() { if let Some(worker) = worker.as_mut() { if let Some(w) = worker.work() { s.work_controller.queue.add_work(w); @@ -249,7 +253,7 @@ impl State { eprint!("{}:{}_{}: ", file!(), line!(), column!()); eprintln!("hash & folder: {:?} {}", folder.hash(), folder.name()); } - s.context.mailbox_hashes.insert(folder.hash(), (x, y)); + s.context.mailbox_hashes.insert(folder.hash(), x); } let sender = s.context.sender.clone(); account.watch(RefreshEventConsumer::new(Box::new(move |r| { @@ -271,24 +275,25 @@ impl State { */ pub fn refresh_event(&mut self, event: RefreshEvent) { let hash = event.hash(); - if let Some(&(idxa, idxm)) = self.context.mailbox_hashes.get(&hash) { - if self.context.accounts[idxa].status(idxm).is_err() { + if let Some(&idxa) = self.context.mailbox_hashes.get(&hash) { + if self.context.accounts[idxa].status(hash).is_err() { self.context.replies.push_back(UIEvent::from(event)); return; } - if let Some(notification) = self.context.accounts[idxa].reload(event, idxm) { + if let Some(notification) = self.context.accounts[idxa].reload(event, hash) { self.context .sender .send(ThreadEvent::UIEvent(UIEvent::StartupCheck(hash))); self.context .sender - .send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((idxa, idxm)))); + .send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((idxa, hash)))); self.context.replies.push_back(notification); } self.context .replies - .push_back(UIEvent::MailboxUpdate((idxa, idxm))); + .push_back(UIEvent::MailboxUpdate((idxa, hash))); } else { + eprint!("{}:{}_{}: ", file!(), line!(), column!()); eprintln!( "BUG: mailbox with hash {} not found in mailbox_hashes.", hash diff --git a/ui/src/types.rs b/ui/src/types.rs index b01561657..1cb8378e5 100644 --- a/ui/src/types.rs +++ b/ui/src/types.rs @@ -72,7 +72,7 @@ pub enum UIEvent { Input(Key), ExInput(Key), InsertInput(Key), - RefreshMailbox((usize, usize)), + RefreshMailbox((usize, FolderHash)), //view has changed to FolderHash mailbox //Quit? Resize, /// Force redraw. @@ -83,12 +83,12 @@ pub enum UIEvent { Notification(Option, String), Action(Action), StatusEvent(StatusEvent), - MailboxUpdate((usize, usize)), // (account_idx, mailbox_idx) + MailboxUpdate((usize, FolderHash)), // (account_idx, mailbox_idx) ComponentKill(Uuid), StartupCheck(FolderHash), RefreshEvent(Box), EnvelopeUpdate(EnvelopeHash), - EnvelopeRename(usize, EnvelopeHash, EnvelopeHash), + EnvelopeRename(FolderHash, EnvelopeHash, EnvelopeHash), EnvelopeRemove(EnvelopeHash), }