diff options
author | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2018-09-06 13:05:35 +0300 |
---|---|---|
committer | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2019-06-10 19:40:33 +0300 |
commit | 6003bdd28c2b87425a6a23092130e7bf4dbc6586 (patch) | |
tree | e631714d41dbdb6a80c2a0f071036e7e7addc03f /ui | |
parent | 3e9d13731031885237f25435c138470766c6d43e (diff) |
WIP
Diffstat (limited to 'ui')
-rw-r--r-- | ui/src/components/mail/compose.rs | 18 | ||||
-rw-r--r-- | ui/src/components/mail/listing/compact.rs | 32 | ||||
-rw-r--r-- | ui/src/components/mail/listing/mod.rs | 263 | ||||
-rw-r--r-- | ui/src/components/mail/mod.rs | 2 | ||||
-rw-r--r-- | ui/src/components/mail/view/mod.rs | 12 | ||||
-rw-r--r-- | ui/src/components/mail/view/thread.rs | 56 | ||||
-rw-r--r-- | ui/src/components/utilities.rs | 2 | ||||
-rw-r--r-- | ui/src/state.rs | 2 |
8 files changed, 137 insertions, 250 deletions
diff --git a/ui/src/components/mail/compose.rs b/ui/src/components/mail/compose.rs index 21bdc187..f044078e 100644 --- a/ui/src/components/mail/compose.rs +++ b/ui/src/components/mail/compose.rs @@ -25,7 +25,7 @@ use melib::Draft; #[derive(Debug)] pub struct Composer { - reply_context: Option<((usize, usize), Box<ThreadView>)>, // (folder_index, container_index) + reply_context: Option<((usize, usize), Box<ThreadView>)>, // (folder_index, thread_node_index) account_cursor: usize, pager: Pager, @@ -98,19 +98,19 @@ impl fmt::Display for Composer { impl Composer { /* - * coordinates: (account index, mailbox index, root set container index) - * msg: index of message we reply to in containers + * coordinates: (account index, mailbox index, root set thread_node index) + * msg: index of message we reply to in thread_nodes * context: current context */ pub fn with_context(coordinates: (usize, usize, usize), msg: usize, context: &Context) -> Self { let mailbox = &context.accounts[coordinates.0][coordinates.1] .as_ref() .unwrap(); - let threads = &mailbox.threads; - let containers = &threads.containers(); + let threads = &mailbox.collection.threads; + let thread_nodes = &threads.thread_nodes(); let mut ret = Composer::default(); - let p = containers[msg]; - let parent_message = &mailbox.collection[p.message().unwrap()]; + let p = &thread_nodes[msg]; + let parent_message = &mailbox.collection[&p.message().unwrap()]; let mut op = context.accounts[coordinates.0] .backend .operation(parent_message.hash()); @@ -122,10 +122,10 @@ impl Composer { if p.show_subject() { format!( "Re: {}", - mailbox.collection[p.message().unwrap()].subject().clone() + mailbox.collection[&p.message().unwrap()].subject().clone() ) } else { - mailbox.collection[p.message().unwrap()].subject().into() + mailbox.collection[&p.message().unwrap()].subject().into() }, ); diff --git a/ui/src/components/mail/listing/compact.rs b/ui/src/components/mail/listing/compact.rs index 026fc6f3..c6280f7f 100644 --- a/ui/src/components/mail/listing/compact.rs +++ b/ui/src/components/mail/listing/compact.rs @@ -121,7 +121,7 @@ impl CompactListing { .as_ref() .unwrap(); - self.length = mailbox.threads.root_len(); + self.length = mailbox.collection.threads.root_set().len(); self.content = CellBuffer::new(MAX_COLS, self.length + 1, Cell::with_char(' ')); if self.length == 0 { write_string_to_grid( @@ -134,24 +134,24 @@ impl CompactListing { ); return; } - let threads = &mailbox.threads; + let threads = &mailbox.collection.threads; threads.sort_by(self.sort, self.subsort, &mailbox.collection); - for (idx, (t, len, has_unseen)) in threads.root_set_iter().enumerate() { - let container = &threads.containers()[t]; - let i = if let Some(i) = container.message() { + for (idx, root_idx) in threads.root_set().iter().enumerate() { + let thread_node = &threads.thread_nodes()[*root_idx]; + let i = if let Some(i) = thread_node.message() { i } else { - threads.containers()[container.first_child().unwrap()] + threads.thread_nodes()[thread_node.children()[0]] .message() .unwrap() }; - let root_envelope: &Envelope = &mailbox.collection[i]; - let fg_color = if has_unseen { + let root_envelope: &Envelope = &mailbox.collection[&i]; + let fg_color = if thread_node.has_unseen() { Color::Byte(0) } else { Color::Default }; - let bg_color = if has_unseen { + let bg_color = if thread_node.has_unseen() { Color::Byte(251) } else if idx % 2 == 0 { Color::Byte(236) @@ -159,7 +159,7 @@ impl CompactListing { Color::Default }; let (x, _) = write_string_to_grid( - &CompactListing::make_entry_string(root_envelope, len, idx), + &CompactListing::make_entry_string(root_envelope, thread_node.len(), idx), &mut self.content, fg_color, bg_color, @@ -179,17 +179,17 @@ impl CompactListing { let mailbox = &context.accounts[self.cursor_pos.0][self.cursor_pos.1] .as_ref() .unwrap(); - let threads = &mailbox.threads; - let container = threads.root_set()[idx]; - let container = &threads.containers()[container]; - let i = if let Some(i) = container.message() { + let threads = &mailbox.collection.threads; + let thread_node = threads.root_set()[idx]; + let thread_node = &threads.thread_nodes()[thread_node]; + let i = if let Some(i) = thread_node.message() { i } else { - threads.containers()[container.first_child().unwrap()] + threads.thread_nodes()[thread_node.children()[0]] .message() .unwrap() }; - let root_envelope: &Envelope = &mailbox.collection[i]; + let root_envelope: &Envelope = &mailbox.collection[&i]; let fg_color = if !root_envelope.is_seen() { Color::Byte(0) } else { diff --git a/ui/src/components/mail/listing/mod.rs b/ui/src/components/mail/listing/mod.rs index 5fa12240..be1a2ef8 100644 --- a/ui/src/components/mail/listing/mod.rs +++ b/ui/src/components/mail/listing/mod.rs @@ -34,7 +34,7 @@ pub struct PlainListing { cursor_pos: (usize, usize, usize), new_cursor_pos: (usize, usize, usize), length: usize, - local_collection: Vec<usize>, + local_collection: Vec<EnvelopeHash>, sort: (SortField, SortOrder), subsort: (SortField, SortOrder), /// Cache current view. @@ -118,11 +118,7 @@ impl PlainListing { .as_ref() .unwrap(); - self.length = if threaded { - mailbox.threads.threaded_collection().len() - } else { - mailbox.len() - }; + self.length = mailbox.len(); self.content = CellBuffer::new(MAX_COLS, self.length + 1, Cell::with_char(' ')); if self.length == 0 { write_string_to_grid( @@ -136,160 +132,68 @@ impl PlainListing { return; } - // TODO: Fix the threaded hell and refactor stuff into seperate functions and/or modules. - if threaded { - let mut indentations: Vec<bool> = Vec::with_capacity(6); - let mut thread_idx = 0; // needed for alternate thread colors - /* Draw threaded view. */ - let threads = &mailbox.threads; - threads.sort_by(self.sort, self.subsort, &mailbox.collection); - let containers: &Vec<Container> = &threads.containers(); - let mut iter = threads.into_iter().peekable(); - let len = threads - .threaded_collection() - .len() - .to_string() - .chars() - .count(); - /* This is just a desugared for loop so that we can use .peek() */ - let mut idx = 0; - while let Some(i) = iter.next() { - let container = &containers[i]; - let indentation = container.indentation(); - - if indentation == 0 { - thread_idx += 1; - } - - if !container.has_message() { - continue; + // Populate `CellBuffer` with every entry. + let mut idx = 0; + for y in 0..=self.length { + if idx >= self.length { + /* No more entries left, so fill the rest of the area with empty space */ + clear_area(&mut self.content, ((0, y), (MAX_COLS - 1, self.length))); + break; + } + /* Write an entire line for each envelope entry. */ + self.local_collection = mailbox.collection.keys().map(|v| *v).collect(); + let sort = self.sort; + self.local_collection.sort_by(|a, b| match sort { + (SortField::Date, SortOrder::Desc) => { + let ma = &mailbox.collection[a]; + let mb = &mailbox.collection[b]; + mb.date().cmp(&ma.date()) } - - match iter.peek() { - Some(&x) if threads[x].indentation() == indentation => { - indentations.pop(); - indentations.push(true); - } - _ => { - indentations.pop(); - indentations.push(false); - } + (SortField::Date, SortOrder::Asc) => { + let ma = &mailbox.collection[a]; + let mb = &mailbox.collection[b]; + ma.date().cmp(&mb.date()) } - if container.has_sibling() { - indentations.pop(); - indentations.push(true); + (SortField::Subject, SortOrder::Desc) => { + let ma = &mailbox.collection[a]; + let mb = &mailbox.collection[b]; + ma.subject().cmp(&mb.subject()) } - let envelope: &Envelope = &mailbox.collection[container.message().unwrap()]; - let fg_color = if !envelope.is_seen() { - Color::Byte(0) - } else { - Color::Default - }; - let bg_color = if !envelope.is_seen() { - Color::Byte(251) - } else if thread_idx % 2 == 0 { - Color::Byte(236) - } else { - Color::Default - }; - let (x, _) = write_string_to_grid( - &PlainListing::make_thread_entry( - envelope, - idx, - indentation, - container, - &indentations, - len, - // context.accounts[self.cursor_pos.0].backend.operation(envelope.hash()) - ), - &mut self.content, - fg_color, - bg_color, - ((0, idx), (MAX_COLS - 1, idx)), - false, - ); - for x in x..MAX_COLS { - self.content[(x, idx)].set_ch(' '); - self.content[(x, idx)].set_bg(bg_color); + (SortField::Subject, SortOrder::Asc) => { + let ma = &mailbox.collection[a]; + let mb = &mailbox.collection[b]; + mb.subject().cmp(&ma.subject()) } + }); + let envelope: &Envelope = &mailbox.collection[&self.local_collection[idx]]; - match iter.peek() { - Some(&x) if containers[x].indentation() > indentation => { - indentations.push(false); - } - Some(&x) if containers[x].indentation() < indentation => { - for _ in 0..(indentation - containers[x].indentation()) { - indentations.pop(); - } - } - _ => {} - } - idx += 1; - } - } else { - // Populate `CellBuffer` with every entry. - let mut idx = 0; - for y in 0..=self.length { - if idx >= self.length { - /* No more entries left, so fill the rest of the area with empty space */ - clear_area(&mut self.content, ((0, y), (MAX_COLS - 1, self.length))); - break; - } - /* Write an entire line for each envelope entry. */ - self.local_collection = (0..mailbox.collection.len()).collect(); - let sort = self.sort; - self.local_collection.sort_by(|a, b| match sort { - (SortField::Date, SortOrder::Desc) => { - let ma = &mailbox.collection[*a]; - let mb = &mailbox.collection[*b]; - mb.date().cmp(&ma.date()) - } - (SortField::Date, SortOrder::Asc) => { - let ma = &mailbox.collection[*a]; - let mb = &mailbox.collection[*b]; - ma.date().cmp(&mb.date()) - } - (SortField::Subject, SortOrder::Desc) => { - let ma = &mailbox.collection[*a]; - let mb = &mailbox.collection[*b]; - ma.subject().cmp(&mb.subject()) - } - (SortField::Subject, SortOrder::Asc) => { - let ma = &mailbox.collection[*a]; - let mb = &mailbox.collection[*b]; - mb.subject().cmp(&ma.subject()) - } - }); - let envelope: &Envelope = &mailbox.collection[self.local_collection[idx]]; - - let fg_color = if !envelope.is_seen() { - Color::Byte(0) - } else { - Color::Default - }; - let bg_color = if !envelope.is_seen() { - Color::Byte(251) - } else if idx % 2 == 0 { - Color::Byte(236) - } else { - Color::Default - }; - let (x, y) = write_string_to_grid( - &PlainListing::make_entry_string(envelope, idx), - &mut self.content, - fg_color, - bg_color, - ((0, y), (MAX_COLS - 1, y)), - false, - ); - - for x in x..MAX_COLS { - self.content[(x, y)].set_ch(' '); - self.content[(x, y)].set_bg(bg_color); - } + let fg_color = if !envelope.is_seen() { + Color::Byte(0) + } else { + Color::Default + }; + let bg_color = if !envelope.is_seen() { + Color::Byte(251) + } else if idx % 2 == 0 { + Color::Byte(236) + } else { + Color::Default + }; + let (x, y) = write_string_to_grid( + &PlainListing::make_entry_string(envelope, idx), + &mut self.content, + fg_color, + bg_color, + ((0, y), (MAX_COLS - 1, y)), + false, + ); - idx += 1; + for x in x..MAX_COLS { + self.content[(x, y)].set_ch(' '); + self.content[(x, y)].set_bg(bg_color); } + + idx += 1; } } @@ -301,12 +205,7 @@ impl PlainListing { let mailbox = &context.accounts[self.cursor_pos.0][self.cursor_pos.1] .as_ref() .unwrap(); - let envelope: &Envelope = if threaded { - let i = mailbox.threaded_mail(idx); - &mailbox.collection[i] - } else { - &mailbox.collection[idx] - }; + let envelope: &Envelope = &mailbox.collection[&self.local_collection[idx]]; let fg_color = if !envelope.is_seen() { Color::Byte(0) @@ -336,12 +235,7 @@ impl PlainListing { let mailbox = &context.accounts[self.cursor_pos.0][self.cursor_pos.1] .as_ref() .unwrap(); - let envelope: &Envelope = if threaded { - let i = mailbox.threaded_mail(idx); - &mailbox.collection[i] - } else { - &mailbox.collection[idx] - }; + let envelope: &Envelope = &mailbox.collection[&self.local_collection[idx]]; let fg_color = if !envelope.is_seen() { Color::Byte(0) @@ -423,14 +317,15 @@ impl PlainListing { envelope: &Envelope, idx: usize, indent: usize, - container: &Container, + node_idx: usize, + nodes: &Threads, indentations: &[bool], idx_width: usize, //op: Box<BackendOp>, ) -> String { - let has_sibling = container.has_sibling(); - let has_parent = container.has_parent(); - let show_subject = container.show_subject(); + let has_sibling = nodes.has_sibling(node_idx); + let has_parent = nodes[node_idx].has_parent(); + let show_subject = nodes[node_idx].show_subject(); let mut s = format!( "{}{}{} ", @@ -525,12 +420,10 @@ impl Component for PlainListing { let account = &mut context.accounts[self.cursor_pos.0]; let (hash, is_seen) = { let mailbox = &mut account[self.cursor_pos.1].as_mut().unwrap(); - let envelope: &mut Envelope = if threaded { - let i = mailbox.threaded_mail(idx); - &mut mailbox.collection[i] - } else { - &mut mailbox.collection[self.local_collection[idx]] - }; + let envelope: &mut Envelope = &mut mailbox + .collection + .entry(self.local_collection[idx]) + .or_default(); (envelope.hash(), envelope.is_seen()) }; if !is_seen { @@ -539,12 +432,10 @@ impl Component for PlainListing { backend.operation(hash) }; let mailbox = &mut account[self.cursor_pos.1].as_mut().unwrap(); - let envelope: &mut Envelope = if threaded { - let i = mailbox.threaded_mail(idx); - &mut mailbox.collection[i] - } else { - &mut mailbox.collection[self.local_collection[idx]] - }; + let envelope: &mut Envelope = &mut mailbox + .collection + .entry(self.local_collection[idx]) + .or_default(); envelope.set_seen(op).unwrap(); true } else { @@ -598,11 +489,11 @@ impl Component for PlainListing { let account = &context.accounts[self.cursor_pos.0]; let mailbox = &account[self.cursor_pos.1].as_ref().unwrap(); let mut coordinates = self.cursor_pos; - coordinates.2 = if threaded { - mailbox.threaded_mail(self.cursor_pos.2) - } else { - self.local_collection[self.cursor_pos.2] - }; + let coordinates = ( + coordinates.0, + coordinates.1, + self.local_collection[self.cursor_pos.2], + ); self.view = Some(MailView::new(coordinates, None, None)); } self.view.as_mut().unwrap().draw( diff --git a/ui/src/components/mail/mod.rs b/ui/src/components/mail/mod.rs index 0c46a561..62f9243c 100644 --- a/ui/src/components/mail/mod.rs +++ b/ui/src/components/mail/mod.rs @@ -144,7 +144,7 @@ impl AccountMenu { .as_ref() .unwrap() .collection - .iter() + .values() .filter(|e| !e.is_seen()) .count(); s.insert_str( diff --git a/ui/src/components/mail/view/mod.rs b/ui/src/components/mail/view/mod.rs index 6d28e0a3..53e58537 100644 --- a/ui/src/components/mail/view/mod.rs +++ b/ui/src/components/mail/view/mod.rs @@ -61,7 +61,7 @@ impl ViewMode { /// menus #[derive(Debug, Default)] pub struct MailView { - coordinates: (usize, usize, usize), + coordinates: (usize, usize, EnvelopeHash), pager: Option<Pager>, subview: Option<Box<Component>>, dirty: bool, @@ -79,7 +79,7 @@ impl fmt::Display for MailView { impl MailView { pub fn new( - coordinates: (usize, usize, usize), + coordinates: (usize, usize, EnvelopeHash), pager: Option<Pager>, subview: Option<Box<Component>>, ) -> Self { @@ -217,7 +217,7 @@ impl Component for MailView { let mailbox = &mut accounts[self.coordinates.0][self.coordinates.1] .as_ref() .unwrap(); - let envelope: &Envelope = &mailbox.collection[self.coordinates.2]; + let envelope: &Envelope = &mailbox.collection[&self.coordinates.2]; if self.mode == ViewMode::Raw { clear_area(grid, area); @@ -302,7 +302,7 @@ impl Component for MailView { let mailbox = &context.accounts[mailbox_idx.0][mailbox_idx.1] .as_ref() .unwrap(); - let envelope: &Envelope = &mailbox.collection[mailbox_idx.2]; + let envelope: &Envelope = &mailbox.collection[&mailbox_idx.2]; let op = context.accounts[mailbox_idx.0] .backend .operation(envelope.hash()); @@ -419,7 +419,7 @@ impl Component for MailView { .as_ref() .unwrap(); - let envelope: &Envelope = &mailbox.collection[self.coordinates.2]; + let envelope: &Envelope = &mailbox.collection[&self.coordinates.2]; let op = context.accounts[self.coordinates.0] .backend .operation(envelope.hash()); @@ -514,7 +514,7 @@ impl Component for MailView { .as_ref() .unwrap(); - let envelope: &Envelope = &mailbox.collection[self.coordinates.2]; + let envelope: &Envelope = &mailbox.collection[&self.coordinates.2]; let finder = LinkFinder::new(); let op = context.accounts[self.coordinates.0] .backend diff --git a/ui/src/components/mail/view/thread.rs b/ui/src/components/mail/view/thread.rs index e434cd08..f04b1667 100644 --- a/ui/src/components/mail/view/thread.rs +++ b/ui/src/components/mail/view/thread.rs @@ -25,9 +25,9 @@ use std::cmp; #[derive(Debug, Clone)] struct ThreadEntry { index: (usize, usize, usize), - /// (indentation, container index, line number in listing) + /// (indentation, thread_node index, line number in listing) indentation: usize, - msg_idx: usize, + msg_idx: EnvelopeHash, } #[derive(Debug, Default)] @@ -47,7 +47,7 @@ pub struct ThreadView { impl ThreadView { /* - * coordinates: (account index, mailbox index, root set container index) + * coordinates: (account index, mailbox index, root set thread_node index) * expanded_idx: optional position of expanded entry when we render the threadview. Default * expanded message is the last one. * context: current context @@ -62,13 +62,13 @@ impl ThreadView { let mailbox = &context.accounts[coordinates.0][coordinates.1] .as_ref() .unwrap(); - let threads = &mailbox.threads; - let container = &threads.containers()[threads.root_set()[coordinates.2]]; + let threads = &mailbox.collection.threads; + let thread_node = &threads.thread_nodes()[threads.root_set()[coordinates.2]]; - if container.message().is_some() { + if thread_node.message().is_some() { stack.push((0, threads.root_set()[coordinates.2])); } else { - stack.push((1, container.first_child().unwrap())); + stack.push((1, thread_node.children()[0])); } let mut view = ThreadView { dirty: true, @@ -95,13 +95,9 @@ impl ThreadView { } _ => {} } - let container = &threads.containers()[idx]; - if let Some(i) = container.next_sibling() { - stack.push((ind, i)); - } - - if let Some(i) = container.first_child() { - stack.push((ind + 1, i)); + let thread_node = &threads.thread_nodes()[idx]; + for &c in thread_node.children().iter() { + stack.push((ind + 1, c)); } } if expanded_idx.is_none() { @@ -117,9 +113,9 @@ impl ThreadView { let mut highlight_reply_subjects: Vec<Option<usize>> = Vec::with_capacity(view.entries.len()); for e in &view.entries { - let envelope: &Envelope = &mailbox.collection[e.msg_idx]; - let container = &threads.containers()[e.index.1]; - let string = if container.show_subject() { + let envelope: &Envelope = &mailbox.collection[&e.msg_idx]; + let thread_node = &threads.thread_nodes()[e.index.1]; + let string = if thread_node.show_subject() { let subject = envelope.subject(); highlight_reply_subjects.push(Some(subject.len())); format!( @@ -198,11 +194,11 @@ impl ThreadView { let mailbox = &context.accounts[self.coordinates.0][self.coordinates.1] .as_ref() .unwrap(); - let container = &mailbox.threads.containers()[idx]; - let msg_idx = if let Some(i) = container.message() { + let thread_node = &mailbox.collection.threads.thread_nodes()[idx]; + let msg_idx = if let Some(i) = thread_node.message() { i } else { - mailbox.threads.containers()[container.first_child().unwrap()] + mailbox.collection.threads.thread_nodes()[thread_node.children()[0]] .message() .unwrap() }; @@ -316,16 +312,16 @@ impl ThreadView { let mailbox = &mut context.accounts[self.coordinates.0][self.coordinates.1] .as_ref() .unwrap(); - let threads = &mailbox.threads; - let container = &threads.containers()[threads.root_set()[self.coordinates.2]]; - let i = if let Some(i) = container.message() { + let threads = &mailbox.collection.threads; + let thread_node = &threads.thread_nodes()[threads.root_set()[self.coordinates.2]]; + let i = if let Some(i) = thread_node.message() { i } else { - threads.containers()[container.first_child().unwrap()] + threads.thread_nodes()[thread_node.children()[0]] .message() .unwrap() }; - let envelope: &Envelope = &mailbox.collection[i]; + let envelope: &Envelope = &mailbox.collection[&i]; let (x, y) = write_string_to_grid( &envelope.subject(), @@ -435,16 +431,16 @@ impl ThreadView { let mailbox = &mut context.accounts[self.coordinates.0][self.coordinates.1] .as_ref() .unwrap(); - let threads = &mailbox.threads; - let container = &threads.containers()[threads.root_set()[self.coordinates.2]]; - let i = if let Some(i) = container.message() { + let threads = &mailbox.collection.threads; + let thread_node = &threads.thread_nodes()[threads.root_set()[self.coordinates.2]]; + let i = if let Some(i) = thread_node.message() { i } else { - threads.containers()[container.first_child().unwrap()] + threads.thread_nodes()[thread_node.children()[0]] .message() .unwrap() }; - let envelope: &Envelope = &mailbox.collection[i]; + let envelope: &Envelope = &mailbox.collection[&i]; let (x, y) = write_string_to_grid( &envelope.subject(), diff --git a/ui/src/components/utilities.rs b/ui/src/components/utilities.rs index 620d3028..cd24635d 100644 --- a/ui/src/components/utilities.rs +++ b/ui/src/components/utilities.rs @@ -562,7 +562,7 @@ impl Component for StatusBar { self.mode, m.folder.name(), m.collection.len(), - m.collection.iter().filter(|e| !e.is_seen()).count() + m.collection.values().filter(|e| !e.is_seen()).count() ); self.dirty = true; } diff --git a/ui/src/state.rs b/ui/src/state.rs index 566d4d9c..1098925d 100644 --- a/ui/src/state.rs +++ b/ui/src/state.rs @@ -185,7 +185,7 @@ impl State { thread::Builder::new() .name("startup-thread".to_string()) .spawn(move || { - let dur = time::Duration::from_millis(100); + let dur = time::Duration::from_millis(800); loop { chan_select! { default => {}, |