summaryrefslogtreecommitdiffstats
path: root/ui/src/components
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2019-12-01 22:28:50 +0200
committerManos Pitsidianakis <el13635@mail.ntua.gr>2019-12-07 20:47:59 +0200
commitf632bc4c08b7a9d4630b34c446863f2126716316 (patch)
treeaf2b5b1ef46c55b5b25aee039d172cc12a439383 /ui/src/components
parentc6f1fa9be03616a66d3fadc1fdd439125c0b4702 (diff)
ui: update rows on TagAdd/TagRemove
Except for threadlisting
Diffstat (limited to 'ui/src/components')
-rw-r--r--ui/src/components/mail/listing.rs15
-rw-r--r--ui/src/components/mail/listing/compact.rs289
-rw-r--r--ui/src/components/mail/listing/conversations.rs257
-rw-r--r--ui/src/components/mail/listing/plain.rs43
-rw-r--r--ui/src/components/mail/listing/thread.rs4
5 files changed, 428 insertions, 180 deletions
diff --git a/ui/src/components/mail/listing.rs b/ui/src/components/mail/listing.rs
index cd1d5f64..ad53231a 100644
--- a/ui/src/components/mail/listing.rs
+++ b/ui/src/components/mail/listing.rs
@@ -92,7 +92,6 @@ pub trait MailListingTrait: ListingTrait {
StatusEvent::DisplayMessage(e.to_string()),
));
}
- self.row_updates().push(thread_hash);
}
ListingAction::SetUnseen => {
if let Err(e) = envelope.set_unseen(op) {
@@ -153,8 +152,7 @@ pub trait MailListingTrait: ListingTrait {
}
fn row_updates(&mut self) -> &mut StackVec<ThreadHash>;
-
- fn update_line(&mut self, context: &Context, thread_hash: ThreadHash);
+ fn get_focused_items(&self, _context: &Context) -> StackVec<ThreadHash>;
}
pub trait ListingTrait: Component {
@@ -508,6 +506,17 @@ impl Component for Listing {
self.component.set_style(IndexStyle::Conversations);
return true;
}
+ Action::Listing(a @ ListingAction::SetSeen)
+ | Action::Listing(a @ ListingAction::SetUnseen)
+ | Action::Listing(a @ ListingAction::Delete)
+ | Action::Listing(a @ ListingAction::Tag(_)) => {
+ let focused = self.component.get_focused_items(context);
+ for i in focused {
+ self.component.perform_action(context, i, a);
+ }
+ self.component.set_dirty();
+ return true;
+ }
_ => {}
},
UIEvent::RefreshMailbox((idxa, folder_hash)) => {
diff --git a/ui/src/components/mail/listing/compact.rs b/ui/src/components/mail/listing/compact.rs
index 15a86a0a..c9f24c1d 100644
--- a/ui/src/components/mail/listing/compact.rs
+++ b/ui/src/components/mail/listing/compact.rs
@@ -79,68 +79,23 @@ impl MailListingTrait for CompactListing {
&mut self.row_updates
}
- fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
- let account = &context.accounts[self.cursor_pos.0];
- let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
- let threads = &account.collection.threads[&folder_hash];
- if let Some(env_hash) = threads[&thread_hash].message() {
- if !account.contains_key(env_hash) {
- /* The envelope has been renamed or removed, so wait for the appropriate event to
- * arrive */
- return;
- }
- let envelope: EnvelopeRef = account.collection.get_env(env_hash);
- let has_attachments = envelope.has_attachments();
- drop(envelope);
- let fg_color = if threads[&thread_hash].has_unseen() {
- Color::Byte(0)
- } else {
- Color::Default
- };
- let idx = self.order[&thread_hash];
- let bg_color = if context.settings.terminal.theme == "light" {
- if threads[&thread_hash].has_unseen() {
- Color::Byte(251)
- } else if idx % 2 == 0 {
- Color::Byte(252)
- } else {
- Color::Default
- }
- } else {
- if threads[&thread_hash].has_unseen() {
- Color::Byte(253)
- } else if idx % 2 == 0 {
- Color::Byte(236)
- } else {
- Color::Default
- }
- };
- for i in 0..self.data_columns.columns.len() {
- let column_width = self.data_columns.columns[i].size().0;
- if column_width == 0 {
- continue;
- }
- change_colors(
- &mut self.data_columns.columns[i],
- ((0, idx), (column_width - 1, idx)),
- fg_color,
- bg_color,
- );
- }
- match (threads.is_snoozed(thread_hash), has_attachments) {
- (true, true) => {
- self.data_columns.columns[3][(0, idx)].set_fg(Color::Byte(103));
- self.data_columns.columns[3][(2, idx)].set_fg(Color::Red);
- }
- (true, false) => {
- self.data_columns.columns[3][(0, idx)].set_fg(Color::Red);
- }
- (false, true) => {
- self.data_columns.columns[3][(0, idx)].set_fg(Color::Byte(103));
- }
- (false, false) => {}
- }
- }
+ fn get_focused_items(&self, context: &Context) -> StackVec<ThreadHash> {
+ let is_selection_empty = self.selection.values().cloned().any(std::convert::identity);
+ let i = [self.get_thread_under_cursor(self.cursor_pos.2, context)];
+ let cursor_iter;
+ let sel_iter = if is_selection_empty {
+ cursor_iter = None;
+ Some(self.selection.iter().filter(|(_, v)| **v).map(|(k, _)| k))
+ } else {
+ cursor_iter = Some(i.iter());
+ None
+ };
+ let iter = sel_iter
+ .into_iter()
+ .flatten()
+ .chain(cursor_iter.into_iter().flatten())
+ .cloned();
+ StackVec::from_iter(iter.into_iter())
}
}
@@ -564,7 +519,7 @@ impl CompactListing {
}
fn make_entry_string(
&self,
- e: EnvelopeRef,
+ e: &Envelope,
context: &Context,
thread_node: &ThreadNode,
is_snoozed: bool,
@@ -592,10 +547,16 @@ impl CompactListing {
tags.push(' ');
tags.push_str(tags_lck.get(t).as_ref().unwrap());
tags.push(' ');
- if let Some(&c) = context.settings.tags.colors.get(t) {
+ if let Some(&c) = folder
+ .conf_override
+ .tags
+ .as_ref()
+ .map(|s| s.colors.get(t))
+ .unwrap_or(None)
+ {
colors.push(c);
} else {
- colors.push(8);
+ colors.push(Color::Byte(8));
}
}
if !tags.is_empty() {
@@ -732,7 +693,7 @@ impl CompactListing {
context.accounts[self.cursor_pos.0].collection.get_env(i);
let entry_strings = self.make_entry_string(
- root_envelope,
+ &root_envelope,
context,
thread_node,
threads.is_snoozed(root_idx),
@@ -885,14 +846,14 @@ impl CompactListing {
t,
&mut self.data_columns.columns[4],
Color::White,
- Color::Byte(color),
+ color,
Attr::Bold,
((x + 1, idx), (min_width.4, idx)),
None,
);
- self.data_columns.columns[4][(x, idx)].set_bg(Color::Byte(color));
+ self.data_columns.columns[4][(x, idx)].set_bg(color);
if _x < min_width.4 {
- self.data_columns.columns[4][(_x, idx)].set_bg(Color::Byte(color));
+ self.data_columns.columns[4][(_x, idx)].set_bg(color);
self.data_columns.columns[4][(_x, idx)].set_keep_bg(true);
}
for x in (x + 1).._x {
@@ -905,6 +866,7 @@ impl CompactListing {
x
};
for x in x..min_width.4 {
+ self.data_columns.columns[4][(x, idx)].set_ch(' ');
self.data_columns.columns[4][(x, idx)].set_bg(bg_color);
}
match (
@@ -958,6 +920,163 @@ impl CompactListing {
self.filtered_selection[cursor]
}
}
+
+ fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
+ let account = &context.accounts[self.cursor_pos.0];
+ let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
+ let threads = &account.collection.threads[&folder_hash];
+ if let Some(env_hash) = threads[&thread_hash].message() {
+ if !account.contains_key(env_hash) {
+ /* The envelope has been renamed or removed, so wait for the appropriate event to
+ * arrive */
+ return;
+ }
+ let envelope: EnvelopeRef = account.collection.get_env(env_hash);
+ let has_attachments = envelope.has_attachments();
+ let fg_color = if threads[&thread_hash].has_unseen() {
+ Color::Byte(0)
+ } else {
+ Color::Default
+ };
+ let idx = self.order[&thread_hash];
+ let bg_color = if context.settings.terminal.theme == "light" {
+ if threads[&thread_hash].has_unseen() {
+ Color::Byte(251)
+ } else if idx % 2 == 0 {
+ Color::Byte(252)
+ } else {
+ Color::Default
+ }
+ } else {
+ if threads[&thread_hash].has_unseen() {
+ Color::Byte(253)
+ } else if idx % 2 == 0 {
+ Color::Byte(236)
+ } else {
+ Color::Default
+ }
+ };
+ let strings = self.make_entry_string(
+ &envelope,
+ context,
+ &threads[&thread_hash],
+ threads.is_snoozed(thread_hash),
+ );
+ drop(envelope);
+ let columns = &mut self.data_columns.columns;
+ let min_width = (
+ columns[0].size().0,
+ columns[1].size().0,
+ columns[2].size().0,
+ columns[3].size().0,
+ columns[4].size().0,
+ );
+ let (x, _) = write_string_to_grid(
+ &idx.to_string(),
+ &mut columns[0],
+ fg_color,
+ bg_color,
+ Attr::Default,
+ ((0, idx), (min_width.0, idx)),
+ None,
+ );
+ for c in columns[0].row_iter((x, min_width.0.saturating_sub(1)), idx) {
+ columns[0][c].set_bg(bg_color);
+ }
+ let (x, _) = write_string_to_grid(
+ &strings.date,
+ &mut columns[1],
+ fg_color,
+ bg_color,
+ Attr::Default,
+ ((0, idx), (min_width.1.saturating_sub(1), idx)),
+ None,
+ );
+ for c in columns[1].row_iter((x, min_width.1.saturating_sub(1)), idx) {
+ columns[1][c].set_bg(bg_color);
+ }
+ let (x, _) = write_string_to_grid(
+ &strings.from,
+ &mut columns[2],
+ fg_color,
+ bg_color,
+ Attr::Default,
+ ((0, idx), (min_width.2, idx)),
+ None,
+ );
+ for c in columns[2].row_iter((x, min_width.2.saturating_sub(1)), idx) {
+ columns[2][c].set_bg(bg_color);
+ }
+ let (x, _) = write_string_to_grid(
+ &strings.flag,
+ &mut columns[3],
+ fg_color,
+ bg_color,
+ Attr::Default,
+ ((0, idx), (min_width.3, idx)),
+ None,
+ );
+ for c in columns[3].row_iter((x, min_width.3.saturating_sub(1)), idx) {
+ columns[3][c].set_bg(bg_color);
+ }
+ let (x, _) = write_string_to_grid(
+ &strings.subject,
+ &mut columns[4],
+ fg_color,
+ bg_color,
+ Attr::Default,
+ ((0, idx), (min_width.4, idx)),
+ None,
+ );
+ let x = {
+ let mut x = x + 1;
+ for (t, &color) in strings.tags.split_whitespace().zip(strings.tags.1.iter()) {
+ let (_x, _) = write_string_to_grid(
+ t,
+ &mut columns[4],
+ Color::White,
+ color,
+ Attr::Bold,
+ ((x + 1, idx), (min_width.4, idx)),
+ None,
+ );
+ for c in columns[4].row_iter((x, x), idx) {
+ columns[4][c].set_bg(color);
+ }
+ for c in columns[4].row_iter((_x, _x), idx) {
+ columns[4][c].set_bg(color);
+ columns[4][c].set_keep_bg(true);
+ }
+ for c in columns[4].row_iter((x + 1, _x), idx) {
+ columns[4][c].set_keep_fg(true);
+ columns[4][c].set_keep_bg(true);
+ }
+ for c in columns[4].row_iter((x, x), idx) {
+ columns[4][c].set_keep_bg(true);
+ }
+ x = _x + 1;
+ }
+ x
+ };
+ for c in columns[4].row_iter((x, min_width.4.saturating_sub(1)), idx) {
+ columns[4][c].set_ch(' ');
+ columns[4][c].set_bg(bg_color);
+ }
+ match (threads.is_snoozed(thread_hash), has_attachments) {
+ (true, true) => {
+ columns[3][(0, idx)].set_fg(Color::Byte(103));
+ columns[3][(2, idx)].set_fg(Color::Red);
+ }
+ (true, false) => {
+ columns[3][(0, idx)].set_fg(Color::Red);
+ }
+ (false, true) => {
+ columns[3][(0, idx)].set_fg(Color::Byte(103));
+ }
+ (false, false) => {}
+ }
+ }
+ }
}
impl Component for CompactListing {
@@ -1132,38 +1251,6 @@ impl Component for CompactListing {
self.refresh_mailbox(context);
return true;
}
- Action::Listing(a @ ListingAction::SetSeen)
- | Action::Listing(a @ ListingAction::SetUnseen)
- | Action::Listing(a @ ListingAction::Delete)
- | Action::Listing(a @ ListingAction::Tag(_))
- if !self.unfocused =>
- {
- let is_selection_empty =
- self.selection.values().cloned().any(std::convert::identity);
- let i = [self.get_thread_under_cursor(self.cursor_pos.2, context)];
- let cursor_iter;
- let sel_iter = if is_selection_empty {
- cursor_iter = None;
- Some(self.selection.iter().filter(|(_, v)| **v).map(|(k, _)| k))
- } else {
- cursor_iter = Some(i.iter());
- None
- };
- let iter = sel_iter
- .into_iter()
- .flatten()
- .chain(cursor_iter.into_iter().flatten())
- .cloned();
- let stack = StackVec::from_iter(iter.into_iter());
- for i in stack {
- self.perform_action(context, i, a);
- }
- self.dirty = true;
- for v in self.selection.values_mut() {
- *v = false;
- }
- return true;
- }
_ => {}
},
diff --git a/ui/src/components/mail/listing/conversations.rs b/ui/src/components/mail/listing/conversations.rs
index 7de6631e..b8019871 100644
--- a/ui/src/components/mail/listing/conversations.rs
+++ b/ui/src/components/mail/listing/conversations.rs
@@ -73,7 +73,7 @@ column_str!(struct DateString(String));
column_str!(struct FromString(String));
column_str!(struct SubjectString(String));
column_str!(struct FlagString(String));
-column_str!(struct TagString(String, StackVec<u8>));
+column_str!(struct TagString(String, StackVec<Color>));
/// A list of all mail (`Envelope`s) in a `Mailbox`. On `\n` it opens the `Envelope` content in a
/// `ThreadView`.
@@ -111,43 +111,26 @@ impl MailListingTrait for ConversationsListing {
&mut self.row_updates
}
- fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
- let account = &context.accounts[self.cursor_pos.0];
- let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
- let threads = &account.collection.threads[&folder_hash];
- let thread_node = &threads.thread_nodes[&thread_hash];
- let row: usize = self.order[&thread_hash];
- let width = self.content.size().0;
-
- let fg_color = if thread_node.has_unseen() {
- Color::Byte(0)
+ fn get_focused_items(&self, context: &Context) -> StackVec<ThreadHash> {
+ let is_selection_empty = self.selection.values().cloned().any(std::convert::identity);
+ let i = [self.get_thread_under_cursor(self.cursor_pos.2, context)];
+ let cursor_iter;
+ let sel_iter = if is_selection_empty {
+ cursor_iter = None;
+ Some(self.selection.iter().filter(|(_, v)| **v).map(|(k, _)| k))
} else {
- Color::Default
- };
- let bg_color = if thread_node.has_unseen() {
- Color::Byte(251)
- } else {
- Color::Default
+ cursor_iter = Some(i.iter());
+ None
};
- change_colors(
- &mut self.content,
- ((0, 3 * row), (width - 1, 3 * row + 1)),
- fg_color,
- bg_color,
- );
- let padding_fg = if context.settings.terminal.theme == "light" {
- Color::Byte(254)
- } else {
- Color::Byte(235)
- };
- change_colors(
- &mut self.content,
- ((0, 3 * row + 2), (width - 1, 3 * row + 2)),
- padding_fg,
- bg_color,
- );
+ let iter = sel_iter
+ .into_iter()
+ .flatten()
+ .chain(cursor_iter.into_iter().flatten())
+ .cloned();
+ StackVec::from_iter(iter.into_iter())
}
}
+
impl ListingTrait for ConversationsListing {
fn coordinates(&self) -> (usize, usize) {
(self.new_cursor_pos.0, self.new_cursor_pos.1)
@@ -559,10 +542,16 @@ impl ConversationsListing {
tags.push(' ');
tags.push_str(tags_lck.get(t).as_ref().unwrap());
tags.push(' ');
- if let Some(&c) = context.settings.tags.colors.get(t) {
+ if let Some(&c) = folder
+ .conf_override
+ .tags
+ .as_ref()
+ .map(|s| s.colors.get(t))
+ .unwrap_or(None)
+ {
colors.push(c);
} else {
- colors.push(8);
+ colors.push(Color::Byte(8));
}
}
if !tags.is_empty() {
@@ -830,14 +819,14 @@ impl ConversationsListing {
t,
&mut self.content,
Color::White,
- Color::Byte(color),
+ color,
Attr::Bold,
((x + 1, 3 * idx), (width - 1, 3 * idx)),
None,
);
- self.content[(x, 3 * idx)].set_bg(Color::Byte(color));
+ self.content[(x, 3 * idx)].set_bg(color);
if _x < width {
- self.content[(_x, 3 * idx)].set_bg(Color::Byte(color));
+ self.content[(_x, 3 * idx)].set_bg(color);
self.content[(_x, 3 * idx)].set_keep_bg(true);
}
for x in (x + 1).._x {
@@ -848,6 +837,7 @@ impl ConversationsListing {
x = _x + 1;
}
for x in x..width {
+ self.content[(x, 3 * idx)].set_ch(' ');
self.content[(x, 3 * idx)].set_bg(bg_color);
}
/* Next line, draw date */
@@ -940,6 +930,164 @@ impl ConversationsListing {
self.filtered_selection[cursor]
}
}
+
+ fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
+ let account = &context.accounts[self.cursor_pos.0];
+ let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
+ let threads = &account.collection.threads[&folder_hash];
+ let thread_node = &threads.thread_nodes[&thread_hash];
+ let idx: usize = self.order[&thread_hash];
+ let width = self.content.size().0;
+
+ let fg_color = if thread_node.has_unseen() {
+ Color::Byte(0)
+ } else {
+ Color::Default
+ };
+ let bg_color = if thread_node.has_unseen() {
+ Color::Byte(251)
+ } else {
+ Color::Default
+ };
+ let padding_fg = if context.settings.terminal.theme == "light" {
+ Color::Byte(254)
+ } else {
+ Color::Byte(235)
+ };
+ let mut from_address_list = Vec::new();
+ let mut from_address_set: std::collections::HashSet<Vec<u8>> =
+ std::collections::HashSet::new();
+ let mut stack = StackVec::new();
+ stack.push(thread_hash);
+ while let Some(h) = stack.pop() {
+ let env_hash = if let Some(h) = threads.thread_nodes()[&h].message() {
+ h
+ } else {
+ break;
+ };
+
+ let envelope: &EnvelopeRef = &context.accounts[self.cursor_pos.0]
+ .collection
+ .get_env(env_hash);
+ for addr in envelope.from().iter() {
+ if from_address_set.contains(addr.raw()) {
+ continue;
+ }
+ from_address_set.insert(addr.raw().to_vec());
+ from_address_list.push(addr.clone());
+ }
+ for c in threads.thread_nodes()[&h].children() {
+ stack.push(*c);
+ }
+ }
+ let env_hash = threads[&thread_hash].message().unwrap();
+ let envelope: EnvelopeRef = account.collection.get_env(env_hash);
+ let strings = self.make_entry_string(
+ &envelope,
+ context,
+ &from_address_list,
+ &threads[&thread_hash],
+ threads.is_snoozed(thread_hash),
+ );
+ drop(envelope);
+ /* draw flags */
+ let (x, _) = write_string_to_grid(
+ &strings.flag,
+ &mut self.content,
+ fg_color,
+ bg_color,
+ Attr::Default,
+ ((0, 3 * idx), (width - 1, 3 * idx)),
+ None,
+ );
+ for c in self.content.row_iter((x, x + 3), 3 * idx) {
+ self.content[c].set_bg(bg_color);
+ }
+ /* draw subject */
+ let (x, _) = write_string_to_grid(
+ &strings.subject,
+ &mut self.content,
+ fg_color,
+ bg_color,
+ Attr::Bold,
+ ((x, 3 * idx), (width - 1, 3 * idx)),
+ None,
+ );
+ let x = {
+ let mut x = x + 1;
+ for (t, &color) in strings.tags.split_whitespace().zip(strings.tags.1.iter()) {
+ let (_x, _) = write_string_to_grid(
+ t,
+ &mut self.content,
+ Color::White,
+ color,
+ Attr::Bold,
+ ((x + 1, 3 * idx), (width - 1, 3 * idx)),
+ None,
+ );
+ for c in self.content.row_iter((x, x), 3 * idx) {
+ self.content[c].set_bg(color);
+ }
+ for c in self.content.row_iter((_x, _x), 3 * idx) {
+ self.content[c].set_bg(color);
+ self.content[c].set_keep_bg(true);
+ }
+ for c in self.content.row_iter((x + 1, _x), 3 * idx) {
+ self.content[c].set_keep_fg(true);
+ self.content[c].set_keep_bg(true);
+ }
+ for c in self.content.row_iter((x, x), 3 * idx) {
+ self.content[c].set_keep_bg(true);
+ }
+ x = _x + 1;
+ }
+ x
+ };
+ for c in self.content.row_iter((x, width.saturating_sub(1)), 3 * idx) {
+ self.content[c].set_ch(' ');
+ self.content[c].set_bg(bg_color);
+ }
+ /* Next line, draw date */
+ let (x, _) = write_string_to_grid(
+ &strings.date,
+ &mut self.content,
+ fg_color,
+ bg_color,
+ Attr::Default,
+ ((0, 3 * idx + 1), (width - 1, 3 * idx + 1)),
+ None,
+ );
+ for c in self.content.row_iter((x, x + 4), 3 * idx + 1) {
+ self.content[c].set_ch('▁');
+ self.content[c].set_bg(bg_color);
+ }
+ /* draw from */
+ let (x, _) = write_string_to_grid(
+ &strings.from,
+ &mut self.content,
+ fg_color,
+ bg_color,
+ Attr::Default,
+ ((x + 4, 3 * idx + 1), (width - 1, 3 * idx + 1)),
+ None,
+ );
+
+ for c in self
+ .content
+ .row_iter((x, width.saturating_sub(1)), 3 * idx + 1)
+ {
+ self.content[c].set_ch('▁');
+ self.content[c].set_bg(bg_color);
+ }
+ for c in self
+ .content
+ .row_iter((0, width.saturating_sub(1)), 3 * idx + 2)
+ {
+ self.content[c].set_ch('▓');
+ self.content[c].set_fg(padding_fg);
+ self.content[c].set_bg(bg_color);
+ }
+ }
}
impl Component for ConversationsListing {
@@ -1191,37 +1339,6 @@ impl Component for ConversationsListing {
self.refresh_mailbox(context);
return true;
}
- Action::Listing(a @ ListingAction::SetSeen)
- | Action::Listing(a @ ListingAction::SetUnseen)
- | Action::Listing(a @ ListingAction::Delete)
- if !self.unfocused =>
- {
- let is_selection_empty =
- self.selection.values().cloned().any(std::convert::identity);
- let i = [self.get_thread_under_cursor(self.cursor_pos.2, context)];
- let cursor_iter;
- let sel_iter = if is_selection_empty {
- cursor_iter = None;
- Some(self.selection.iter().filter(|(_, v)| **v).map(|(k, _)| k))
- } else {
- cursor_iter = Some(i.iter());
- None
- };
- let iter = sel_iter
- .into_iter()
- .flatten()
- .chain(cursor_iter.into_iter().flatten())
- .cloned();
- let stack = StackVec::from_iter(iter.into_iter());
- for i in stack {
- self.perform_action(context, i, a);
- }
- self.dirty = true;
- for v in self.selection.values_mut() {
- *v = false;
- }
- return true;
- }
_ => {}
},
_ => {}
diff --git a/ui/src/components/mail/listing/plain.rs b/ui/src/components/mail/listing/plain.rs
index eb79c350..28f83284 100644
--- a/ui/src/components/mail/listing/plain.rs
+++ b/ui/src/components/mail/listing/plain.rs
@@ -62,6 +62,7 @@ pub struct PlainListing {
filtered_selection: Vec<EnvelopeHash>,
filtered_order: FnvHashMap<EnvelopeHash, usize>,
selection: FnvHashMap<EnvelopeHash, bool>,
+ thread_hashes: FnvHashMap<EnvelopeHash, ThreadHash>,
local_collection: Vec<EnvelopeHash>,
/// If we must redraw on next redraw event
dirty: bool,
@@ -81,7 +82,20 @@ impl MailListingTrait for PlainListing {
&mut self._row_updates
}
- fn update_line(&mut self, _context: &Context, _thread_hash: ThreadHash) {}
+ fn get_focused_items(&self, context: &Context) -> StackVec<ThreadHash> {
+ let is_selection_empty = self.selection.values().cloned().any(std::convert::identity);
+ if is_selection_empty {
+ self.selection
+ .iter()
+ .filter(|(_, v)| **v)
+ .map(|(k, _)| self.thread_hashes[k])
+ .collect()
+ } else {
+ let mut ret = StackVec::new();
+ ret.push(self.get_thread_under_cursor(self.cursor_pos.2, context));
+ ret
+ }
+ }
}
impl ListingTrait for PlainListing {
@@ -470,6 +484,7 @@ impl PlainListing {
subsort: (SortField::Date, SortOrder::Desc),
all_envelopes: fnv::FnvHashSet::default(),
local_collection: Vec::new(),
+ thread_hashes: FnvHashMap::default(),
order: FnvHashMap::default(),
filter_term: String::new(),
filtered_selection: Vec::new(),
@@ -520,7 +535,7 @@ impl PlainListing {
{
colors.push(c);
} else {
- colors.push(8);
+ colors.push(Color::Byte(8));
}
}
if !tags.is_empty() {
@@ -587,6 +602,18 @@ impl PlainListing {
.iter()
.cloned()
.collect();
+ let env_lck = context.accounts[self.cursor_pos.0]
+ .collection
+ .envelopes
+ .read()
+ .unwrap();
+ self.thread_hashes = context.accounts[self.cursor_pos.0][folder_hash]
+ .unwrap()
+ .envelopes
+ .iter()
+ .map(|h| (*h, env_lck[h].thread()))
+ .collect();
+ drop(env_lck);
self.redraw_list(context);
if self.length > 0 {
@@ -803,16 +830,16 @@ impl PlainListing {
t,
&mut columns[4],
Color::White,
- Color::Byte(color),
+ color,
Attr::Bold,
((x + 1, idx), (min_width.4, idx)),
None,
);
for c in columns[4].row_iter((x, x), idx) {
- columns[4][c].set_bg(Color::Byte(color));
+ columns[4][c].set_bg(color);
}
for c in columns[4].row_iter((_x, _x), idx) {
- columns[4][c].set_bg(Color::Byte(color));
+ columns[4][c].set_bg(color);
columns[4][c].set_keep_bg(true);
}
for c in columns[4].row_iter((x + 1, _x), idx) {
@@ -866,6 +893,12 @@ impl PlainListing {
}
}
+ fn get_thread_under_cursor(&self, cursor: usize, context: &Context) -> ThreadHash {
+ let account = &context.accounts[self.cursor_pos.0];
+ let env_hash = self.get_env_under_cursor(cursor, context);
+ account.collection.get_env(env_hash).thread()
+ }
+
fn format_date(envelope: &Envelope) -> String {
let d = std::time::UNIX_EPOCH + std::time::Duration::from_secs(envelope.date());
let now: std::time::Duration = std::time::SystemTime::now()
diff --git a/ui/src/components/mail/listing/thread.rs b/ui/src/components/mail/listing/thread.rs
index 5d005e6a..5312c93e 100644
--- a/ui/src/components/mail/listing/thread.rs
+++ b/ui/src/components/mail/listing/thread.rs
@@ -54,7 +54,9 @@ impl MailListingTrait for ThreadListing {
&mut self.row_updates
}
- fn update_line(&mut self, _context: &Context, _thread_hash: ThreadHash) {}
+ fn get_focused_items(&self, _context: &Context) -> StackVec<ThreadHash> {
+ StackVec::new()
+ }
}
impl ListingTrait for ThreadListing {