melib/Collection: put all fields behind a mutex
parent
1112ef4717
commit
0882dbbad0
|
@ -60,12 +60,19 @@ impl DerefMut for EnvelopeRefMut<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Collection {
|
||||
pub envelopes: Arc<RwLock<HashMap<EnvelopeHash, Envelope>>>,
|
||||
pub threads: HashMap<MailboxHash, Threads>,
|
||||
sent_mailbox: Option<MailboxHash>,
|
||||
pub mailboxes: HashMap<MailboxHash, HashSet<EnvelopeHash>>,
|
||||
pub message_id_index: Arc<RwLock<HashMap<Vec<u8>, EnvelopeHash>>>,
|
||||
pub threads: Arc<RwLock<HashMap<MailboxHash, Threads>>>,
|
||||
sent_mailbox: Arc<RwLock<Option<MailboxHash>>>,
|
||||
pub mailboxes: Arc<RwLock<HashMap<MailboxHash, HashSet<EnvelopeHash>>>>,
|
||||
}
|
||||
|
||||
impl Default for Collection {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -89,15 +96,26 @@ impl Drop for Collection {
|
|||
*/
|
||||
|
||||
impl Collection {
|
||||
pub fn new(envelopes: HashMap<EnvelopeHash, Envelope>) -> Collection {
|
||||
let threads = HashMap::with_capacity_and_hasher(16, Default::default());
|
||||
let mailboxes = HashMap::with_capacity_and_hasher(16, Default::default());
|
||||
pub fn new() -> Collection {
|
||||
let message_id_index = Arc::new(RwLock::new(HashMap::with_capacity_and_hasher(
|
||||
16,
|
||||
Default::default(),
|
||||
)));
|
||||
let threads = Arc::new(RwLock::new(HashMap::with_capacity_and_hasher(
|
||||
16,
|
||||
Default::default(),
|
||||
)));
|
||||
let mailboxes = Arc::new(RwLock::new(HashMap::with_capacity_and_hasher(
|
||||
16,
|
||||
Default::default(),
|
||||
)));
|
||||
|
||||
Collection {
|
||||
envelopes: Arc::new(RwLock::new(envelopes)),
|
||||
envelopes: Arc::new(RwLock::new(Default::default())),
|
||||
message_id_index,
|
||||
threads,
|
||||
mailboxes,
|
||||
sent_mailbox: None,
|
||||
sent_mailbox: Arc::new(RwLock::new(None)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,14 +130,19 @@ impl Collection {
|
|||
pub fn remove(&mut self, envelope_hash: EnvelopeHash, mailbox_hash: MailboxHash) {
|
||||
debug!("DEBUG: Removing {}", envelope_hash);
|
||||
self.envelopes.write().unwrap().remove(&envelope_hash);
|
||||
self.mailboxes.entry(mailbox_hash).and_modify(|m| {
|
||||
m.remove(&envelope_hash);
|
||||
});
|
||||
self.threads
|
||||
self.mailboxes
|
||||
.write()
|
||||
.unwrap()
|
||||
.entry(mailbox_hash)
|
||||
.and_modify(|m| {
|
||||
m.remove(&envelope_hash);
|
||||
});
|
||||
let mut threads_lck = self.threads.write().unwrap();
|
||||
threads_lck
|
||||
.entry(mailbox_hash)
|
||||
.or_default()
|
||||
.remove(envelope_hash);
|
||||
for (h, t) in self.threads.iter_mut() {
|
||||
for (h, t) in threads_lck.iter_mut() {
|
||||
if *h == mailbox_hash {
|
||||
continue;
|
||||
}
|
||||
|
@ -137,15 +160,19 @@ impl Collection {
|
|||
return false;
|
||||
}
|
||||
let mut envelope = self.envelopes.write().unwrap().remove(&old_hash).unwrap();
|
||||
self.mailboxes.entry(mailbox_hash).and_modify(|m| {
|
||||
m.remove(&old_hash);
|
||||
m.insert(new_hash);
|
||||
});
|
||||
self.mailboxes
|
||||
.write()
|
||||
.unwrap()
|
||||
.entry(mailbox_hash)
|
||||
.and_modify(|m| {
|
||||
m.remove(&old_hash);
|
||||
m.insert(new_hash);
|
||||
});
|
||||
envelope.set_hash(new_hash);
|
||||
self.envelopes.write().unwrap().insert(new_hash, envelope);
|
||||
let mut threads_lck = self.threads.write().unwrap();
|
||||
{
|
||||
if self
|
||||
.threads
|
||||
if threads_lck
|
||||
.entry(mailbox_hash)
|
||||
.or_default()
|
||||
.update_envelope(&self.envelopes, old_hash, new_hash)
|
||||
|
@ -155,11 +182,11 @@ impl Collection {
|
|||
}
|
||||
}
|
||||
/* envelope is not in threads, so insert it */
|
||||
self.threads
|
||||
threads_lck
|
||||
.entry(mailbox_hash)
|
||||
.or_default()
|
||||
.insert(&mut self.envelopes, new_hash);
|
||||
for (h, t) in self.threads.iter_mut() {
|
||||
for (h, t) in threads_lck.iter_mut() {
|
||||
if *h == mailbox_hash {
|
||||
continue;
|
||||
}
|
||||
|
@ -178,7 +205,7 @@ impl Collection {
|
|||
mailbox_hash: MailboxHash,
|
||||
sent_mailbox: Option<MailboxHash>,
|
||||
) -> Option<SmallVec<[MailboxHash; 8]>> {
|
||||
self.sent_mailbox = sent_mailbox;
|
||||
*self.sent_mailbox.write().unwrap() = sent_mailbox;
|
||||
|
||||
let &mut Collection {
|
||||
ref mut threads,
|
||||
|
@ -188,17 +215,19 @@ impl Collection {
|
|||
..
|
||||
} = self;
|
||||
|
||||
if !threads.contains_key(&mailbox_hash) {
|
||||
threads.insert(mailbox_hash, Threads::new(new_envelopes.len()));
|
||||
mailboxes.insert(mailbox_hash, new_envelopes.keys().cloned().collect());
|
||||
let mut threads_lck = threads.write().unwrap();
|
||||
let mut mailboxes_lck = mailboxes.write().unwrap();
|
||||
if !threads_lck.contains_key(&mailbox_hash) {
|
||||
threads_lck.insert(mailbox_hash, Threads::new(new_envelopes.len()));
|
||||
mailboxes_lck.insert(mailbox_hash, new_envelopes.keys().cloned().collect());
|
||||
for (h, e) in new_envelopes {
|
||||
envelopes.write().unwrap().insert(h, e);
|
||||
}
|
||||
} else {
|
||||
mailboxes.entry(mailbox_hash).and_modify(|m| {
|
||||
mailboxes_lck.entry(mailbox_hash).and_modify(|m| {
|
||||
m.extend(new_envelopes.keys().cloned());
|
||||
});
|
||||
threads.entry(mailbox_hash).and_modify(|t| {
|
||||
threads_lck.entry(mailbox_hash).and_modify(|t| {
|
||||
let mut ordered_hash_set =
|
||||
new_envelopes.keys().cloned().collect::<Vec<EnvelopeHash>>();
|
||||
ordered_hash_set.sort_by(|a, b| {
|
||||
|
@ -218,14 +247,19 @@ impl Collection {
|
|||
}
|
||||
|
||||
let mut ret = SmallVec::new();
|
||||
let keys = threads.keys().cloned().collect::<Vec<MailboxHash>>();
|
||||
let keys = threads_lck.keys().cloned().collect::<Vec<MailboxHash>>();
|
||||
for t_fh in keys {
|
||||
if t_fh == mailbox_hash {
|
||||
continue;
|
||||
}
|
||||
if sent_mailbox.map(|f| f == mailbox_hash).unwrap_or(false) {
|
||||
if sent_mailbox
|
||||
.read()
|
||||
.unwrap()
|
||||
.map(|f| f == mailbox_hash)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let envelopes_lck = envelopes.read().unwrap();
|
||||
let mut ordered_hash_set = threads[&mailbox_hash]
|
||||
let mut ordered_hash_set = threads_lck[&mailbox_hash]
|
||||
.hash_set
|
||||
.iter()
|
||||
.cloned()
|
||||
|
@ -239,16 +273,24 @@ impl Collection {
|
|||
drop(envelopes_lck);
|
||||
let mut updated = false;
|
||||
for h in ordered_hash_set {
|
||||
updated |= threads.entry(t_fh).or_default().insert_reply(envelopes, h);
|
||||
updated |= threads_lck
|
||||
.entry(t_fh)
|
||||
.or_default()
|
||||
.insert_reply(envelopes, h);
|
||||
}
|
||||
if updated {
|
||||
ret.push(t_fh);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if sent_mailbox.map(|f| f == t_fh).unwrap_or(false) {
|
||||
if sent_mailbox
|
||||
.read()
|
||||
.unwrap()
|
||||
.map(|f| f == t_fh)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let envelopes_lck = envelopes.read().unwrap();
|
||||
let mut ordered_hash_set = threads[&t_fh]
|
||||
let mut ordered_hash_set = threads_lck[&t_fh]
|
||||
.hash_set
|
||||
.iter()
|
||||
.cloned()
|
||||
|
@ -262,7 +304,7 @@ impl Collection {
|
|||
drop(envelopes_lck);
|
||||
let mut updated = false;
|
||||
for h in ordered_hash_set {
|
||||
updated |= threads
|
||||
updated |= threads_lck
|
||||
.entry(mailbox_hash)
|
||||
.or_default()
|
||||
.insert_reply(envelopes, h);
|
||||
|
@ -288,24 +330,30 @@ impl Collection {
|
|||
let old_env = self.envelopes.write().unwrap().remove(&old_hash).unwrap();
|
||||
envelope.set_thread(old_env.thread());
|
||||
let new_hash = envelope.hash();
|
||||
self.mailboxes.entry(mailbox_hash).and_modify(|m| {
|
||||
m.remove(&old_hash);
|
||||
m.insert(new_hash);
|
||||
});
|
||||
self.mailboxes
|
||||
.write()
|
||||
.unwrap()
|
||||
.entry(mailbox_hash)
|
||||
.and_modify(|m| {
|
||||
m.remove(&old_hash);
|
||||
m.insert(new_hash);
|
||||
});
|
||||
self.envelopes.write().unwrap().insert(new_hash, envelope);
|
||||
let mut threads_lck = self.threads.write().unwrap();
|
||||
if self
|
||||
.sent_mailbox
|
||||
.read()
|
||||
.unwrap()
|
||||
.map(|f| f == mailbox_hash)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
for (_, t) in self.threads.iter_mut() {
|
||||
for (_, t) in threads_lck.iter_mut() {
|
||||
t.update_envelope(&self.envelopes, old_hash, new_hash)
|
||||
.unwrap_or(());
|
||||
}
|
||||
}
|
||||
{
|
||||
if self
|
||||
.threads
|
||||
if threads_lck
|
||||
.entry(mailbox_hash)
|
||||
.or_default()
|
||||
.update_envelope(&self.envelopes, old_hash, new_hash)
|
||||
|
@ -315,11 +363,11 @@ impl Collection {
|
|||
}
|
||||
}
|
||||
/* envelope is not in threads, so insert it */
|
||||
self.threads
|
||||
threads_lck
|
||||
.entry(mailbox_hash)
|
||||
.or_default()
|
||||
.insert(&mut self.envelopes, new_hash);
|
||||
for (h, t) in self.threads.iter_mut() {
|
||||
for (h, t) in threads_lck.iter_mut() {
|
||||
if *h == mailbox_hash {
|
||||
continue;
|
||||
}
|
||||
|
@ -330,19 +378,21 @@ impl Collection {
|
|||
}
|
||||
|
||||
pub fn update_flags(&mut self, env_hash: EnvelopeHash, mailbox_hash: MailboxHash) {
|
||||
let mut threads_lck = self.threads.write().unwrap();
|
||||
if self
|
||||
.sent_mailbox
|
||||
.read()
|
||||
.unwrap()
|
||||
.map(|f| f == mailbox_hash)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
for (_, t) in self.threads.iter_mut() {
|
||||
for (_, t) in threads_lck.iter_mut() {
|
||||
t.update_envelope(&self.envelopes, env_hash, env_hash)
|
||||
.unwrap_or(());
|
||||
}
|
||||
}
|
||||
{
|
||||
if self
|
||||
.threads
|
||||
if threads_lck
|
||||
.entry(mailbox_hash)
|
||||
.or_default()
|
||||
.update_envelope(&self.envelopes, env_hash, env_hash)
|
||||
|
@ -352,11 +402,11 @@ impl Collection {
|
|||
}
|
||||
}
|
||||
/* envelope is not in threads, so insert it */
|
||||
self.threads
|
||||
threads_lck
|
||||
.entry(mailbox_hash)
|
||||
.or_default()
|
||||
.insert(&mut self.envelopes, env_hash);
|
||||
for (h, t) in self.threads.iter_mut() {
|
||||
for (h, t) in threads_lck.iter_mut() {
|
||||
if *h == mailbox_hash {
|
||||
continue;
|
||||
}
|
||||
|
@ -368,16 +418,24 @@ impl Collection {
|
|||
|
||||
pub fn insert(&mut self, envelope: Envelope, mailbox_hash: MailboxHash) -> bool {
|
||||
let hash = envelope.hash();
|
||||
self.mailboxes.entry(mailbox_hash).and_modify(|m| {
|
||||
m.insert(hash);
|
||||
});
|
||||
self.mailboxes
|
||||
.write()
|
||||
.unwrap()
|
||||
.entry(mailbox_hash)
|
||||
.and_modify(|m| {
|
||||
m.insert(hash);
|
||||
});
|
||||
self.envelopes.write().unwrap().insert(hash, envelope);
|
||||
self.threads
|
||||
.write()
|
||||
.unwrap()
|
||||
.entry(mailbox_hash)
|
||||
.or_default()
|
||||
.insert(&mut self.envelopes, hash);
|
||||
if self
|
||||
.sent_mailbox
|
||||
.read()
|
||||
.unwrap()
|
||||
.map(|f| f == mailbox_hash)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
|
@ -388,7 +446,7 @@ impl Collection {
|
|||
|
||||
pub fn insert_reply(&mut self, env_hash: EnvelopeHash) {
|
||||
debug_assert!(self.envelopes.read().unwrap().contains_key(&env_hash));
|
||||
for (_, t) in self.threads.iter_mut() {
|
||||
for (_, t) in self.threads.write().unwrap().iter_mut() {
|
||||
t.insert_reply(&mut self.envelopes, env_hash);
|
||||
}
|
||||
}
|
||||
|
@ -403,27 +461,45 @@ impl Collection {
|
|||
EnvelopeRefMut { guard, env_hash }
|
||||
}
|
||||
|
||||
pub fn get_threads(&'_ self, hash: MailboxHash) -> RwRef<'_, MailboxHash, Threads> {
|
||||
let guard = self.threads.read().unwrap();
|
||||
RwRef { guard, hash }
|
||||
}
|
||||
|
||||
pub fn get_mailbox(
|
||||
&'_ self,
|
||||
hash: MailboxHash,
|
||||
) -> RwRef<'_, MailboxHash, HashSet<EnvelopeHash>> {
|
||||
let guard = self.mailboxes.read().unwrap();
|
||||
RwRef { guard, hash }
|
||||
}
|
||||
|
||||
pub fn contains_key(&self, env_hash: &EnvelopeHash) -> bool {
|
||||
self.envelopes.read().unwrap().contains_key(env_hash)
|
||||
}
|
||||
|
||||
pub fn new_mailbox(&mut self, mailbox_hash: MailboxHash) {
|
||||
if !self.mailboxes.contains_key(&mailbox_hash) {
|
||||
self.mailboxes.insert(mailbox_hash, Default::default());
|
||||
self.threads.insert(mailbox_hash, Threads::default());
|
||||
let mut mailboxes_lck = self.mailboxes.write().unwrap();
|
||||
if !mailboxes_lck.contains_key(&mailbox_hash) {
|
||||
mailboxes_lck.insert(mailbox_hash, Default::default());
|
||||
self.threads
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(mailbox_hash, Threads::default());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<&MailboxHash> for Collection {
|
||||
type Output = HashSet<EnvelopeHash>;
|
||||
fn index(&self, index: &MailboxHash) -> &HashSet<EnvelopeHash> {
|
||||
&self.mailboxes[index]
|
||||
}
|
||||
|
||||
pub struct RwRef<'g, K: std::cmp::Eq + std::hash::Hash, V> {
|
||||
guard: RwLockReadGuard<'g, HashMap<K, V>>,
|
||||
hash: K,
|
||||
}
|
||||
|
||||
impl IndexMut<&MailboxHash> for Collection {
|
||||
fn index_mut(&mut self, index: &MailboxHash) -> &mut HashSet<EnvelopeHash> {
|
||||
self.mailboxes.get_mut(index).unwrap()
|
||||
impl<K: std::cmp::Eq + std::hash::Hash, V> Deref for RwRef<'_, K, V> {
|
||||
type Target = V;
|
||||
|
||||
fn deref(&self) -> &V {
|
||||
self.guard.get(&self.hash).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,9 +148,13 @@ pub trait MailListingTrait: ListingTrait {
|
|||
let account = &mut context.accounts[account_pos];
|
||||
let mut envs_to_set: SmallVec<[EnvelopeHash; 8]> = SmallVec::new();
|
||||
let mailbox_hash = self.coordinates().1;
|
||||
for (_, h) in account.collection.threads[&mailbox_hash].thread_group_iter(thread_hash) {
|
||||
for (_, h) in account
|
||||
.collection
|
||||
.get_threads(mailbox_hash)
|
||||
.thread_group_iter(thread_hash)
|
||||
{
|
||||
envs_to_set.push(
|
||||
account.collection.threads[&mailbox_hash].thread_nodes()[&h]
|
||||
account.collection.get_threads(mailbox_hash).thread_nodes()[&h]
|
||||
.message()
|
||||
.unwrap(),
|
||||
);
|
||||
|
@ -1209,7 +1213,7 @@ impl Component for Listing {
|
|||
MailboxStatus::Available | MailboxStatus::Parsing(_, _) => format!(
|
||||
"Mailbox: {}, Messages: {}, New: {}",
|
||||
account[&mailbox_hash].ref_mailbox.name(),
|
||||
account.collection[&mailbox_hash].len(),
|
||||
account.collection.get_mailbox(mailbox_hash).len(),
|
||||
account[&mailbox_hash]
|
||||
.ref_mailbox
|
||||
.count()
|
||||
|
|
|
@ -247,7 +247,9 @@ impl MailListingTrait for CompactListing {
|
|||
}
|
||||
}
|
||||
|
||||
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.cursor_pos.1];
|
||||
let threads = context.accounts[self.cursor_pos.0]
|
||||
.collection
|
||||
.get_threads(self.cursor_pos.1);
|
||||
let mut roots = threads.roots();
|
||||
threads.group_inner_sort_by(
|
||||
&mut roots,
|
||||
|
@ -276,7 +278,7 @@ impl MailListingTrait for CompactListing {
|
|||
) {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
self.order.clear();
|
||||
self.length = 0;
|
||||
let mut rows = Vec::with_capacity(1024);
|
||||
|
@ -341,7 +343,7 @@ impl MailListingTrait for CompactListing {
|
|||
}
|
||||
}
|
||||
|
||||
let entry_strings = self.make_entry_string(&root_envelope, context, threads, thread);
|
||||
let entry_strings = self.make_entry_string(&root_envelope, context, &threads, thread);
|
||||
row_widths.1.push(
|
||||
entry_strings
|
||||
.date
|
||||
|
@ -462,7 +464,7 @@ impl ListingTrait for CompactListing {
|
|||
let thread_hash = self.get_thread_under_cursor(idx);
|
||||
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
let thread = threads.thread_ref(thread_hash);
|
||||
|
||||
let row_attr = row_attr!(
|
||||
|
@ -685,7 +687,7 @@ impl ListingTrait for CompactListing {
|
|||
}
|
||||
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
for r in 0..cmp::min(self.length - top_idx, rows) {
|
||||
let thread_hash = self.get_thread_under_cursor(r + top_idx);
|
||||
let row_attr = row_attr!(
|
||||
|
@ -767,7 +769,7 @@ impl ListingTrait for CompactListing {
|
|||
let account = &context.accounts[self.cursor_pos.0];
|
||||
match results {
|
||||
Ok(results) => {
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
for env_hash in results {
|
||||
if !account.collection.contains_key(&env_hash) {
|
||||
continue;
|
||||
|
@ -971,7 +973,7 @@ impl CompactListing {
|
|||
|
||||
fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
let thread = threads.thread_ref(thread_hash);
|
||||
let thread_node_hash = threads.thread_group_iter(thread_hash).next().unwrap().1;
|
||||
if let Some(env_hash) = threads.thread_nodes()[&thread_node_hash].message() {
|
||||
|
@ -993,7 +995,7 @@ impl CompactListing {
|
|||
self.color_cache.odd
|
||||
};
|
||||
let envelope: EnvelopeRef = account.collection.get_env(env_hash);
|
||||
let strings = self.make_entry_string(&envelope, context, threads, thread_hash);
|
||||
let strings = self.make_entry_string(&envelope, context, &threads, thread_hash);
|
||||
drop(envelope);
|
||||
let columns = &mut self.data_columns.columns;
|
||||
let min_width = (
|
||||
|
@ -1136,7 +1138,7 @@ impl CompactListing {
|
|||
);
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
|
||||
for ((idx, (thread_hash, root_env_hash)), strings) in
|
||||
self.rows.iter().skip(start).take(end - start + 1)
|
||||
|
@ -1309,7 +1311,7 @@ impl CompactListing {
|
|||
let account = &context.accounts[self.cursor_pos.0];
|
||||
match results {
|
||||
Ok(results) => {
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
for env_hash in results {
|
||||
if !account.collection.contains_key(&env_hash) {
|
||||
continue;
|
||||
|
@ -1497,6 +1499,8 @@ impl Component for CompactListing {
|
|||
account
|
||||
.collection
|
||||
.threads
|
||||
.write()
|
||||
.unwrap()
|
||||
.entry(self.cursor_pos.1)
|
||||
.and_modify(|threads| {
|
||||
let is_snoozed = threads.thread_ref(thread).snoozed();
|
||||
|
@ -1526,7 +1530,7 @@ impl Component for CompactListing {
|
|||
}
|
||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
if !account.collection.contains_key(&new_hash) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1536,6 +1540,7 @@ impl Component for CompactListing {
|
|||
}
|
||||
let thread: ThreadHash =
|
||||
threads.find_group(threads.thread_nodes()[&new_env_thread_node_hash].group);
|
||||
drop(threads);
|
||||
if self.order.contains_key(&thread) {
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
|
@ -1553,7 +1558,7 @@ impl Component for CompactListing {
|
|||
}
|
||||
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
if !account.collection.contains_key(&env_hash) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1563,6 +1568,7 @@ impl Component for CompactListing {
|
|||
}
|
||||
let thread: ThreadHash =
|
||||
threads.find_group(threads.thread_nodes()[&new_env_thread_node_hash].group);
|
||||
drop(threads);
|
||||
if self.order.contains_key(&thread) {
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
|
|
|
@ -152,7 +152,9 @@ impl MailListingTrait for ConversationsListing {
|
|||
}
|
||||
}
|
||||
|
||||
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.cursor_pos.1];
|
||||
let threads = context.accounts[self.cursor_pos.0]
|
||||
.collection
|
||||
.get_threads(self.cursor_pos.1);
|
||||
self.all_threads.clear();
|
||||
let mut roots = threads.roots();
|
||||
threads.group_inner_sort_by(
|
||||
|
@ -183,7 +185,7 @@ impl MailListingTrait for ConversationsListing {
|
|||
) {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
self.order.clear();
|
||||
self.selection.clear();
|
||||
self.length = 0;
|
||||
|
@ -255,8 +257,13 @@ impl MailListingTrait for ConversationsListing {
|
|||
}
|
||||
}
|
||||
|
||||
let strings =
|
||||
self.make_entry_string(root_envelope, context, &from_address_list, threads, thread);
|
||||
let strings = self.make_entry_string(
|
||||
root_envelope,
|
||||
context,
|
||||
&from_address_list,
|
||||
&threads,
|
||||
thread,
|
||||
);
|
||||
max_entry_columns = std::cmp::max(
|
||||
max_entry_columns,
|
||||
strings.flag.len()
|
||||
|
@ -436,7 +443,7 @@ impl ListingTrait for ConversationsListing {
|
|||
let thread_hash = self.get_thread_under_cursor(idx);
|
||||
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
let thread = threads.thread_ref(thread_hash);
|
||||
|
||||
let fg_color = if thread.unseen() > 0 {
|
||||
|
@ -717,7 +724,7 @@ impl ListingTrait for ConversationsListing {
|
|||
let account = &context.accounts[self.cursor_pos.0];
|
||||
match results {
|
||||
Ok(results) => {
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
for env_hash in results {
|
||||
if !account.collection.contains_key(&env_hash) {
|
||||
continue;
|
||||
|
@ -952,7 +959,7 @@ impl ConversationsListing {
|
|||
|
||||
fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
let thread = threads.thread_ref(thread_hash);
|
||||
let thread_node_hash = threads.thread_group_iter(thread_hash).next().unwrap().1;
|
||||
let idx: usize = self.order[&thread_hash];
|
||||
|
@ -989,8 +996,13 @@ impl ConversationsListing {
|
|||
}
|
||||
}
|
||||
let envelope: EnvelopeRef = account.collection.get_env(env_hash);
|
||||
let strings =
|
||||
self.make_entry_string(&envelope, context, &from_address_list, threads, thread_hash);
|
||||
let strings = self.make_entry_string(
|
||||
&envelope,
|
||||
context,
|
||||
&from_address_list,
|
||||
&threads,
|
||||
thread_hash,
|
||||
);
|
||||
drop(envelope);
|
||||
/* draw flags */
|
||||
let (x, _) = write_string_to_grid(
|
||||
|
@ -1236,7 +1248,7 @@ impl Component for ConversationsListing {
|
|||
}
|
||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
if !account.collection.contains_key(&new_hash) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1246,6 +1258,7 @@ impl Component for ConversationsListing {
|
|||
}
|
||||
let thread: ThreadHash =
|
||||
threads.find_group(threads.thread_nodes()[&env_thread_node_hash].group);
|
||||
drop(threads);
|
||||
if self.order.contains_key(&thread) {
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
|
@ -1257,7 +1270,7 @@ impl Component for ConversationsListing {
|
|||
}
|
||||
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
if !account.collection.contains_key(&env_hash) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1267,6 +1280,7 @@ impl Component for ConversationsListing {
|
|||
}
|
||||
let thread: ThreadHash =
|
||||
threads.find_group(threads.thread_nodes()[&env_thread_node_hash].group);
|
||||
drop(threads);
|
||||
if self.order.contains_key(&thread) {
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
|
@ -1315,6 +1329,8 @@ impl Component for ConversationsListing {
|
|||
account
|
||||
.collection
|
||||
.threads
|
||||
.write()
|
||||
.unwrap()
|
||||
.entry(self.cursor_pos.1)
|
||||
.and_modify(|threads| {
|
||||
let is_snoozed = threads.thread_ref(thread).snoozed();
|
||||
|
|
|
@ -169,7 +169,9 @@ impl MailListingTrait for PlainListing {
|
|||
return;
|
||||
}
|
||||
}
|
||||
self.local_collection = context.accounts[self.cursor_pos.0].collection[&self.cursor_pos.1]
|
||||
self.local_collection = context.accounts[self.cursor_pos.0]
|
||||
.collection
|
||||
.get_mailbox(self.cursor_pos.1)
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect();
|
||||
|
@ -178,8 +180,9 @@ impl MailListingTrait for PlainListing {
|
|||
.envelopes
|
||||
.read()
|
||||
.unwrap();
|
||||
self.thread_node_hashes = context.accounts[self.cursor_pos.0].collection
|
||||
[&self.cursor_pos.1]
|
||||
self.thread_node_hashes = context.accounts[self.cursor_pos.0]
|
||||
.collection
|
||||
.get_mailbox(self.cursor_pos.1)
|
||||
.iter()
|
||||
.map(|h| (*h, env_lck[h].thread()))
|
||||
.collect();
|
||||
|
@ -232,7 +235,7 @@ impl MailListingTrait for PlainListing {
|
|||
items: Box<dyn Iterator<Item = ThreadHash>>,
|
||||
) {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
let roots = items
|
||||
.filter_map(|r| threads.groups[&r].root().map(|r| r.root))
|
||||
.collect::<_>();
|
||||
|
@ -1218,7 +1221,10 @@ impl Component for PlainListing {
|
|||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
if !account.collection.contains_key(new_hash)
|
||||
|| !account.collection[&self.cursor_pos.1].contains(new_hash)
|
||||
|| !account
|
||||
.collection
|
||||
.get_mailbox(self.cursor_pos.1)
|
||||
.contains(new_hash)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1244,7 +1250,10 @@ impl Component for PlainListing {
|
|||
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
if !account.collection.contains_key(env_hash)
|
||||
|| !account.collection[&self.cursor_pos.1].contains(env_hash)
|
||||
|| !account
|
||||
.collection
|
||||
.get_mailbox(self.cursor_pos.1)
|
||||
.contains(env_hash)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -121,7 +121,9 @@ impl MailListingTrait for ThreadListing {
|
|||
return;
|
||||
}
|
||||
}
|
||||
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.cursor_pos.1];
|
||||
let threads = context.accounts[self.cursor_pos.0]
|
||||
.collection
|
||||
.get_threads(self.cursor_pos.1);
|
||||
let mut roots = threads.roots();
|
||||
threads.group_inner_sort_by(
|
||||
&mut roots,
|
||||
|
@ -141,7 +143,7 @@ impl MailListingTrait for ThreadListing {
|
|||
items: Box<dyn Iterator<Item = ThreadHash>>,
|
||||
) {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||
self.length = 0;
|
||||
self.order.clear();
|
||||
let default_cell = {
|
||||
|
@ -226,7 +228,7 @@ impl MailListingTrait for ThreadListing {
|
|||
idx,
|
||||
indentation,
|
||||
thread_node_hash,
|
||||
threads,
|
||||
&threads,
|
||||
&indentations,
|
||||
has_sibling,
|
||||
is_root,
|
||||
|
@ -1164,7 +1166,6 @@ impl Component for ThreadListing {
|
|||
}
|
||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
if !account.collection.contains_key(&new_hash) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1188,7 +1189,6 @@ impl Component for ThreadListing {
|
|||
}
|
||||
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
||||
let account = &context.accounts[self.cursor_pos.0];
|
||||
let threads = &account.collection.threads[&self.cursor_pos.1];
|
||||
if !account.collection.contains_key(env_hash) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ impl ThreadView {
|
|||
|
||||
fn initiate(&mut self, expanded_hash: Option<ThreadNodeHash>, context: &Context) {
|
||||
let account = &context.accounts[self.coordinates.0];
|
||||
let threads = &account.collection.threads[&self.coordinates.1];
|
||||
let threads = account.collection.get_threads(self.coordinates.1);
|
||||
|
||||
if !threads.groups.contains_key(&self.thread_group) {
|
||||
return;
|
||||
|
@ -648,7 +648,7 @@ impl ThreadView {
|
|||
let y = if self.dirty {
|
||||
clear_area(grid, area, crate::conf::value(context, "theme_default"));
|
||||
let account = &context.accounts[self.coordinates.0];
|
||||
let threads = &account.collection.threads[&self.coordinates.1];
|
||||
let threads = account.collection.get_threads(self.coordinates.1);
|
||||
let thread_root = threads
|
||||
.thread_group_iter(self.thread_group)
|
||||
.next()
|
||||
|
@ -751,7 +751,7 @@ impl ThreadView {
|
|||
let y = {
|
||||
clear_area(grid, area, crate::conf::value(context, "theme_default"));
|
||||
let account = &context.accounts[self.coordinates.0];
|
||||
let threads = &account.collection.threads[&self.coordinates.1];
|
||||
let threads = account.collection.get_threads(self.coordinates.1);
|
||||
let thread_root = threads
|
||||
.thread_group_iter(self.thread_group)
|
||||
.next()
|
||||
|
|
|
@ -726,7 +726,10 @@ impl Account {
|
|||
RefreshEventKind::Create(envelope) => {
|
||||
let env_hash = envelope.hash();
|
||||
if self.collection.contains_key(&env_hash)
|
||||
&& self.collection[&mailbox_hash].contains(&env_hash)
|
||||
&& self
|
||||
.collection
|
||||
.get_mailbox(mailbox_hash)
|
||||
.contains(&env_hash)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
@ -770,10 +773,13 @@ impl Account {
|
|||
|
||||
let thread = {
|
||||
let thread_hash = self.collection.get_env(env_hash).thread();
|
||||
self.collection.threads[&mailbox_hash]
|
||||
.find_group(self.collection.threads[&mailbox_hash][&thread_hash].group)
|
||||
self.collection.get_threads(mailbox_hash).find_group(
|
||||
self.collection.get_threads(mailbox_hash)[&thread_hash].group,
|
||||
)
|
||||
};
|
||||
if self.collection.threads[&mailbox_hash]
|
||||
if self
|
||||
.collection
|
||||
.get_threads(mailbox_hash)
|
||||
.thread_ref(thread)
|
||||
.snoozed()
|
||||
{
|
||||
|
@ -797,8 +803,9 @@ impl Account {
|
|||
RefreshEventKind::Remove(env_hash) => {
|
||||
let thread_hash = {
|
||||
let thread_hash = self.collection.get_env(env_hash).thread();
|
||||
self.collection.threads[&mailbox_hash]
|
||||
.find_group(self.collection.threads[&mailbox_hash][&thread_hash].group)
|
||||
self.collection.get_threads(mailbox_hash).find_group(
|
||||
self.collection.get_threads(mailbox_hash)[&thread_hash].group,
|
||||
)
|
||||
};
|
||||
#[cfg(feature = "sqlite3")]
|
||||
{
|
||||
|
@ -1006,7 +1013,12 @@ impl Account {
|
|||
None => {
|
||||
return match self.mailbox_entries[&mailbox_hash].status {
|
||||
MailboxStatus::Available | MailboxStatus::Parsing(_, _)
|
||||
if self.collection.mailboxes.contains_key(&mailbox_hash) =>
|
||||
if self
|
||||
.collection
|
||||
.mailboxes
|
||||
.read()
|
||||
.unwrap()
|
||||
.contains_key(&mailbox_hash) =>
|
||||
{
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1157,7 +1169,12 @@ impl Account {
|
|||
}
|
||||
if self.mailbox_entries[&mailbox_hash].status.is_available()
|
||||
|| (self.mailbox_entries[&mailbox_hash].status.is_parsing()
|
||||
&& self.collection.mailboxes.contains_key(&mailbox_hash))
|
||||
&& self
|
||||
.collection
|
||||
.mailboxes
|
||||
.read()
|
||||
.unwrap()
|
||||
.contains_key(&mailbox_hash))
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
|
@ -1346,10 +1363,6 @@ impl Account {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn thread(&self, h: ThreadNodeHash, f: MailboxHash) -> &ThreadNode {
|
||||
&self.collection.threads[&f].thread_nodes()[&h]
|
||||
}
|
||||
|
||||
pub fn mailbox_operation(
|
||||
&mut self,
|
||||
op: crate::execute::actions::MailboxOperation,
|
||||
|
@ -1417,9 +1430,13 @@ impl Account {
|
|||
);
|
||||
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,
|
||||
|
@ -1451,7 +1468,11 @@ impl Account {
|
|||
if self.sent_mailbox == Some(mailbox_hash) {
|
||||
self.sent_mailbox = None;
|
||||
}
|
||||
self.collection.threads.remove(&mailbox_hash);
|
||||
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() {
|
||||
|
@ -1461,7 +1482,11 @@ impl Account {
|
|||
parent.ref_mailbox = mailboxes.remove(&parent_hash).unwrap();
|
||||
});
|
||||
}
|
||||
self.collection.mailboxes.remove(&mailbox_hash);
|
||||
self.collection
|
||||
.mailboxes
|
||||
.write()
|
||||
.unwrap()
|
||||
.remove(&mailbox_hash);
|
||||
build_mailboxes_order(
|
||||
&mut self.tree,
|
||||
&self.mailbox_entries,
|
||||
|
@ -1576,7 +1601,7 @@ impl Account {
|
|||
let mut ret = SmallVec::new();
|
||||
let envelopes = self.collection.envelopes.read().unwrap();
|
||||
|
||||
for &env_hash in self.collection[&mailbox_hash].iter() {
|
||||
for &env_hash in self.collection.get_mailbox(mailbox_hash).iter() {
|
||||
let envelope = &envelopes[&env_hash];
|
||||
if envelope.subject().contains(&search_term) {
|
||||
ret.push(env_hash);
|
||||
|
|
Loading…
Reference in New Issue