ui: force refresh_mailbox etc on Mailbox{Delete,Create}

memfd
Manos Pitsidianakis 2020-02-06 01:51:20 +02:00
parent f5e694cf5a
commit 144eb62b76
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
6 changed files with 467 additions and 439 deletions

View File

@ -200,6 +200,9 @@ pub trait MailListingTrait: ListingTrait {
fn redraw_list(&mut self, _context: &Context, _items: Box<dyn Iterator<Item = ThreadHash>>) {
unimplemented!()
}
/// Use `force` when there have been changes in the mailbox or account lists in `context`
fn refresh_mailbox(&mut self, context: &mut Context, force: bool);
}
pub trait ListingTrait: Component {
@ -447,6 +450,20 @@ impl Component for Listing {
}
}
}
UIEvent::MailboxDelete((account_index, _folder_hash))
| UIEvent::MailboxCreate((account_index, _folder_hash)) => {
if self.cursor_pos.0 == *account_index {
self.cursor_pos.1 = std::cmp::min(
context.accounts[*account_index].len() - 1,
self.cursor_pos.1,
);
self.component
.set_coordinates((self.cursor_pos.0, self.cursor_pos.1));
self.component.refresh_mailbox(context, true);
self.set_dirty(true);
}
return true;
}
_ => {}
}

View File

@ -100,6 +100,93 @@ impl MailListingTrait for CompactListing {
.cloned();
SmallVec::from_iter(iter.into_iter())
}
/// Fill the `self.data_columns` `CellBuffers` with the contents of the account folder the user has
/// chosen.
fn refresh_mailbox(&mut self, context: &mut Context, force: bool) {
self.dirty = true;
let old_cursor_pos = self.cursor_pos;
if !(self.cursor_pos.0 == self.new_cursor_pos.0
&& self.cursor_pos.1 == self.new_cursor_pos.1)
{
self.cursor_pos.2 = 0;
self.new_cursor_pos.2 = 0;
}
self.cursor_pos.1 = self.new_cursor_pos.1;
self.cursor_pos.0 = self.new_cursor_pos.0;
self.folder_hash = if let Some(h) = context.accounts[self.cursor_pos.0]
.folders_order
.get(self.cursor_pos.1)
{
*h
} else {
self.cursor_pos.1 = old_cursor_pos.1;
self.dirty = false;
return;
};
self.color_cache = ColorCache {
unseen: crate::conf::value(context, "mail.listing.compact.unseen"),
highlighted: crate::conf::value(context, "mail.listing.compact.highlighted"),
even: crate::conf::value(context, "mail.listing.compact.even"),
odd: crate::conf::value(context, "mail.listing.compact.odd"),
selected: crate::conf::value(context, "mail.listing.compact.selected"),
attachment_flag: crate::conf::value(context, "mail.listing.attachment_flag"),
thread_snooze_flag: crate::conf::value(context, "mail.listing.thread_snooze_flag"),
..self.color_cache
};
if std::env::var("NO_COLOR").is_ok()
&& (context.settings.terminal.use_color.is_false()
|| context.settings.terminal.use_color.is_internal())
{
self.color_cache.highlighted.attrs |= Attr::Reverse;
}
// Get mailbox as a reference.
//
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
Ok(()) => {}
Err(_) => {
let message: String =
context.accounts[self.cursor_pos.0][self.folder_hash].to_string();
self.data_columns.columns[0] =
CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
self.length = 0;
write_string_to_grid(
message.as_str(),
&mut self.data_columns.columns[0],
Color::Default,
Color::Default,
Attr::Default,
((0, 0), (MAX_COLS - 1, 0)),
None,
);
return;
}
}
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.folder_hash];
self.all_threads.clear();
let mut roots = threads.roots();
threads.group_inner_sort_by(
&mut roots,
self.sort,
&context.accounts[self.cursor_pos.0].collection.envelopes,
);
self.redraw_list(
context,
Box::new(roots.into_iter()) as Box<dyn Iterator<Item = ThreadHash>>,
);
if !force && old_cursor_pos == self.new_cursor_pos {
self.view.update(context);
} else if self.unfocused {
let thread = self.get_thread_under_cursor(self.cursor_pos.2);
self.view = ThreadView::new(self.new_cursor_pos, thread, None, context);
}
}
}
impl ListingTrait for CompactListing {
@ -110,6 +197,7 @@ impl ListingTrait for CompactListing {
fn set_coordinates(&mut self, coordinates: (usize, usize)) {
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
self.unfocused = false;
self.view = ThreadView::default();
self.filtered_selection.clear();
self.filtered_order.clear();
self.filter_term.clear();
@ -190,7 +278,7 @@ impl ListingTrait for CompactListing {
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
if self.cursor_pos.1 != self.new_cursor_pos.1 || self.cursor_pos.0 != self.new_cursor_pos.0
{
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
}
let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area);
@ -624,93 +712,6 @@ impl CompactListing {
}
}
/// Fill the `self.data_columns` `CellBuffers` with the contents of the account folder the user has
/// chosen.
fn refresh_mailbox(&mut self, context: &mut Context) {
self.dirty = true;
let old_cursor_pos = self.cursor_pos;
if !(self.cursor_pos.0 == self.new_cursor_pos.0
&& self.cursor_pos.1 == self.new_cursor_pos.1)
{
self.cursor_pos.2 = 0;
self.new_cursor_pos.2 = 0;
}
self.cursor_pos.1 = self.new_cursor_pos.1;
self.cursor_pos.0 = self.new_cursor_pos.0;
self.folder_hash = if let Some(h) = context.accounts[self.cursor_pos.0]
.folders_order
.get(self.cursor_pos.1)
{
*h
} else {
self.cursor_pos.1 = old_cursor_pos.1;
self.dirty = false;
return;
};
self.color_cache = ColorCache {
unseen: crate::conf::value(context, "mail.listing.compact.unseen"),
highlighted: crate::conf::value(context, "mail.listing.compact.highlighted"),
even: crate::conf::value(context, "mail.listing.compact.even"),
odd: crate::conf::value(context, "mail.listing.compact.odd"),
selected: crate::conf::value(context, "mail.listing.compact.selected"),
attachment_flag: crate::conf::value(context, "mail.listing.attachment_flag"),
thread_snooze_flag: crate::conf::value(context, "mail.listing.thread_snooze_flag"),
..self.color_cache
};
if std::env::var("NO_COLOR").is_ok()
&& (context.settings.terminal.use_color.is_false()
|| context.settings.terminal.use_color.is_internal())
{
self.color_cache.highlighted.attrs |= Attr::Reverse;
}
// Get mailbox as a reference.
//
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
Ok(()) => {}
Err(_) => {
let message: String =
context.accounts[self.cursor_pos.0][self.folder_hash].to_string();
self.data_columns.columns[0] =
CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
self.length = 0;
write_string_to_grid(
message.as_str(),
&mut self.data_columns.columns[0],
Color::Default,
Color::Default,
Attr::Default,
((0, 0), (MAX_COLS - 1, 0)),
None,
);
return;
}
}
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.folder_hash];
self.all_threads.clear();
let mut roots = threads.roots();
threads.group_inner_sort_by(
&mut roots,
self.sort,
&context.accounts[self.cursor_pos.0].collection.envelopes,
);
self.redraw_list(
context,
Box::new(roots.into_iter()) as Box<dyn Iterator<Item = ThreadHash>>,
);
if old_cursor_pos == self.new_cursor_pos {
self.view.update(context);
} else if self.unfocused {
let thread = self.get_thread_under_cursor(self.cursor_pos.2);
self.view = ThreadView::new(self.new_cursor_pos, thread, None, context);
}
}
fn redraw_list(&mut self, context: &Context, items: Box<dyn Iterator<Item = ThreadHash>>) {
let account = &context.accounts[self.cursor_pos.0];
let mailbox = &account[self.cursor_pos.1].unwrap();
@ -1244,7 +1245,7 @@ impl Component for CompactListing {
// FIXME: perform sort
self.dirty = true;
} else {
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
}
return true;
}
@ -1266,7 +1267,7 @@ impl Component for CompactListing {
threads.thread_ref_mut(thread).set_snoozed(!is_snoozed);
});
self.row_updates.push(thread);
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
return true;
}
@ -1280,11 +1281,11 @@ impl Component for CompactListing {
UIEvent::MailboxUpdate((ref idxa, ref idxf))
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
{
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
self.set_dirty(true);
}
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
self.set_dirty(true);
}
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
@ -1316,7 +1317,7 @@ impl Component for CompactListing {
}
UIEvent::Input(Key::Esc) if !self.unfocused && !self.filter_term.is_empty() => {
self.set_coordinates((self.new_cursor_pos.0, self.new_cursor_pos.1));
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
self.set_dirty(true);
return true;
}
@ -1331,7 +1332,7 @@ impl Component for CompactListing {
}
self.filtered_selection.clear();
self.new_cursor_pos.1 = *idx;
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
return true;
}
Action::Listing(Filter(ref filter_term)) if !self.unfocused => {

View File

@ -79,6 +79,100 @@ impl MailListingTrait for ConversationsListing {
.cloned();
SmallVec::from_iter(iter.into_iter())
}
/// Fill the `self.data_columns` `CellBuffers` with the contents of the account folder the user has
/// chosen.
fn refresh_mailbox(&mut self, context: &mut Context, force: bool) {
self.dirty = true;
let old_folder_hash = self.folder_hash;
let old_cursor_pos = self.cursor_pos;
if !(self.cursor_pos.0 == self.new_cursor_pos.0
&& self.cursor_pos.1 == self.new_cursor_pos.1)
{
self.cursor_pos.2 = 0;
self.new_cursor_pos.2 = 0;
}
self.cursor_pos.1 = self.new_cursor_pos.1;
self.cursor_pos.0 = self.new_cursor_pos.0;
self.folder_hash = if let Some(h) = context.accounts[self.cursor_pos.0]
.folders_order
.get(self.cursor_pos.1)
{
*h
} else {
self.cursor_pos.1 = old_cursor_pos.1;
self.dirty = false;
return;
};
self.color_cache = ColorCache {
theme_default: crate::conf::value(context, "mail.listing.conversations"),
subject: crate::conf::value(context, "mail.listing.conversations.subject"),
from: crate::conf::value(context, "mail.listing.conversations.from"),
date: crate::conf::value(context, "mail.listing.conversations.date"),
padding: crate::conf::value(context, "mail.listing.conversations.padding"),
unseen: crate::conf::value(context, "mail.listing.conversations.unseen"),
unseen_padding: crate::conf::value(
context,
"mail.listing.conversations.unseen_padding",
),
highlighted: crate::conf::value(context, "mail.listing.conversations.highlighted"),
attachment_flag: crate::conf::value(context, "mail.listing.attachment_flag"),
thread_snooze_flag: crate::conf::value(context, "mail.listing.thread_snooze_flag"),
..self.color_cache
};
if std::env::var("NO_COLOR").is_ok()
&& (context.settings.terminal.use_color.is_false()
|| context.settings.terminal.use_color.is_internal())
{
self.color_cache.highlighted.attrs |= Attr::Reverse;
}
// Get mailbox as a reference.
//
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
Ok(()) => {}
Err(_) => {
let message: String =
context.accounts[self.cursor_pos.0][self.folder_hash].to_string();
self.content =
CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
self.length = 0;
write_string_to_grid(
message.as_str(),
&mut self.content,
Color::Default,
Color::Default,
Attr::Default,
((0, 0), (message.len() - 1, 0)),
None,
);
return;
}
}
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.folder_hash];
self.all_threads.clear();
let mut roots = threads.roots();
threads.group_inner_sort_by(
&mut roots,
self.sort,
&context.accounts[self.cursor_pos.0].collection.envelopes,
);
self.redraw_list(
context,
Box::new(roots.into_iter()) as Box<dyn Iterator<Item = ThreadHash>>,
);
if !force && old_cursor_pos == self.new_cursor_pos && old_folder_hash == self.folder_hash {
self.view.update(context);
} else if self.unfocused {
let thread_group = self.get_thread_under_cursor(self.cursor_pos.2);
self.view = ThreadView::new(self.new_cursor_pos, thread_group, None, context);
}
}
}
impl ListingTrait for ConversationsListing {
@ -87,8 +181,10 @@ impl ListingTrait for ConversationsListing {
}
fn set_coordinates(&mut self, coordinates: (usize, usize)) {
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
self.unfocused = false;
self.view = ThreadView::default();
self.filtered_selection.clear();
self.filtered_order.clear();
self.filter_term.clear();
@ -183,7 +279,7 @@ impl ListingTrait for ConversationsListing {
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
if self.cursor_pos.1 != self.new_cursor_pos.1 || self.cursor_pos.0 != self.new_cursor_pos.0
{
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
}
let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area);
@ -550,99 +646,6 @@ impl ConversationsListing {
}
}
/// Fill the `self.data_columns` `CellBuffers` with the contents of the account folder the user has
/// chosen.
fn refresh_mailbox(&mut self, context: &mut Context) {
self.dirty = true;
let old_cursor_pos = self.cursor_pos;
if !(self.cursor_pos.0 == self.new_cursor_pos.0
&& self.cursor_pos.1 == self.new_cursor_pos.1)
{
self.cursor_pos.2 = 0;
self.new_cursor_pos.2 = 0;
}
self.cursor_pos.1 = self.new_cursor_pos.1;
self.cursor_pos.0 = self.new_cursor_pos.0;
self.folder_hash = if let Some(h) = context.accounts[self.cursor_pos.0]
.folders_order
.get(self.cursor_pos.1)
{
*h
} else {
self.cursor_pos.1 = old_cursor_pos.1;
self.dirty = false;
return;
};
self.color_cache = ColorCache {
theme_default: crate::conf::value(context, "mail.listing.conversations"),
subject: crate::conf::value(context, "mail.listing.conversations.subject"),
from: crate::conf::value(context, "mail.listing.conversations.from"),
date: crate::conf::value(context, "mail.listing.conversations.date"),
padding: crate::conf::value(context, "mail.listing.conversations.padding"),
unseen: crate::conf::value(context, "mail.listing.conversations.unseen"),
unseen_padding: crate::conf::value(
context,
"mail.listing.conversations.unseen_padding",
),
highlighted: crate::conf::value(context, "mail.listing.conversations.highlighted"),
attachment_flag: crate::conf::value(context, "mail.listing.attachment_flag"),
thread_snooze_flag: crate::conf::value(context, "mail.listing.thread_snooze_flag"),
..self.color_cache
};
if std::env::var("NO_COLOR").is_ok()
&& (context.settings.terminal.use_color.is_false()
|| context.settings.terminal.use_color.is_internal())
{
self.color_cache.highlighted.attrs |= Attr::Reverse;
}
// Get mailbox as a reference.
//
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
Ok(()) => {}
Err(_) => {
let message: String =
context.accounts[self.cursor_pos.0][self.folder_hash].to_string();
self.content =
CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
self.length = 0;
write_string_to_grid(
message.as_str(),
&mut self.content,
Color::Default,
Color::Default,
Attr::Default,
((0, 0), (message.len() - 1, 0)),
None,
);
return;
}
}
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&self.folder_hash];
self.all_threads.clear();
let mut roots = threads.roots();
threads.group_inner_sort_by(
&mut roots,
self.sort,
&context.accounts[self.cursor_pos.0].collection.envelopes,
);
self.redraw_list(
context,
Box::new(roots.into_iter()) as Box<dyn Iterator<Item = ThreadHash>>,
);
if old_cursor_pos == self.new_cursor_pos {
self.view.update(context);
} else if self.unfocused {
let thread_group = self.get_thread_under_cursor(self.cursor_pos.2);
self.view = ThreadView::new(self.new_cursor_pos, thread_group, None, context);
}
}
fn redraw_list(&mut self, context: &Context, items: Box<dyn Iterator<Item = ThreadHash>>) {
let account = &context.accounts[self.cursor_pos.0];
let mailbox = &account[self.cursor_pos.1].unwrap();
@ -1206,7 +1209,7 @@ impl Component for ConversationsListing {
// let threads = &account.collection.threads[&self.folder_hash];
// threads.vec_inner_sort_by(&mut self.filtered_selection, self.sort, &account.collection);
//} else {
// self.refresh_mailbox(context);
// self.refresh_mailbox(context, false);
//}
return true;
}
@ -1225,7 +1228,7 @@ impl Component for ConversationsListing {
);
self.dirty = true;
} else {
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
}
*/
return true;
@ -1242,7 +1245,7 @@ impl Component for ConversationsListing {
threads.thread_ref_mut(thread).set_snoozed(!is_snoozed);
});
self.row_updates.push(thread);
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
return true;
}
_ => {}
@ -1254,11 +1257,11 @@ impl Component for ConversationsListing {
UIEvent::MailboxUpdate((ref idxa, ref idxf))
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
{
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
self.set_dirty(true);
}
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
self.set_dirty(true);
}
UIEvent::ChangeMode(UIMode::Normal) => {
@ -1277,7 +1280,7 @@ impl Component for ConversationsListing {
return true;
}
self.set_coordinates((self.new_cursor_pos.0, *idx));
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
return true;
}
@ -1292,7 +1295,7 @@ impl Component for ConversationsListing {
if !self.unfocused && !&self.filter_term.is_empty() =>
{
self.set_coordinates((self.new_cursor_pos.0, self.new_cursor_pos.1));
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
self.force_draw = false;
self.set_dirty(true);
return true;

View File

@ -101,6 +101,100 @@ impl MailListingTrait for PlainListing {
}
*/
}
/// Fill the `self.data_columns` `CellBuffers` with the contents of the account folder the user has
/// chosen.
fn refresh_mailbox(&mut self, context: &mut Context, force: bool) {
self.dirty = true;
let old_cursor_pos = self.cursor_pos;
if !(self.cursor_pos.0 == self.new_cursor_pos.0
&& self.cursor_pos.1 == self.new_cursor_pos.1)
{
self.cursor_pos.2 = 0;
self.new_cursor_pos.2 = 0;
}
self.cursor_pos.1 = self.new_cursor_pos.1;
self.cursor_pos.0 = self.new_cursor_pos.0;
self.folder_hash = if let Some(h) = context.accounts[self.cursor_pos.0]
.folders_order
.get(self.cursor_pos.1)
{
*h
} else {
self.cursor_pos.1 = old_cursor_pos.1;
self.dirty = false;
return;
};
self.color_cache = ColorCache {
unseen: crate::conf::value(context, "mail.listing.plain.unseen"),
highlighted: crate::conf::value(context, "mail.listing.plain.highlighted"),
even: crate::conf::value(context, "mail.listing.plain.even"),
odd: crate::conf::value(context, "mail.listing.plain.odd"),
selected: crate::conf::value(context, "mail.listing.plain.selected"),
attachment_flag: crate::conf::value(context, "mail.listing.attachment_flag"),
thread_snooze_flag: crate::conf::value(context, "mail.listing.thread_snooze_flag"),
..self.color_cache
};
if std::env::var("NO_COLOR").is_ok()
&& (context.settings.terminal.use_color.is_false()
|| context.settings.terminal.use_color.is_internal())
{
self.color_cache.highlighted.attrs |= Attr::Reverse;
}
// Get mailbox as a reference.
//
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
Ok(()) => {}
Err(_) => {
let message: String =
context.accounts[self.cursor_pos.0][self.folder_hash].to_string();
self.data_columns.columns[0] =
CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
self.length = 0;
write_string_to_grid(
message.as_str(),
&mut self.data_columns.columns[0],
Color::Default,
Color::Default,
Attr::Default,
((0, 0), (MAX_COLS - 1, 0)),
None,
);
return;
}
}
self.local_collection = context.accounts[self.cursor_pos.0][self.folder_hash]
.unwrap()
.envelopes
.iter()
.cloned()
.collect();
let env_lck = context.accounts[self.cursor_pos.0]
.collection
.envelopes
.read()
.unwrap();
self.thread_node_hashes = context.accounts[self.cursor_pos.0][self.folder_hash]
.unwrap()
.envelopes
.iter()
.map(|h| (*h, env_lck[h].thread()))
.collect();
drop(env_lck);
self.redraw_list(context);
if self.length > 0 {
let env_hash = self.get_env_under_cursor(self.cursor_pos.2, context);
let temp = (self.new_cursor_pos.0, self.new_cursor_pos.1, env_hash);
if !force && old_cursor_pos == self.new_cursor_pos {
self.view.update(temp);
} else if self.unfocused {
self.view = MailView::new(temp, None, None);
}
}
}
}
impl ListingTrait for PlainListing {
@ -111,6 +205,7 @@ impl ListingTrait for PlainListing {
fn set_coordinates(&mut self, coordinates: (usize, usize)) {
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
self.unfocused = false;
self.view = MailView::default();
self.filtered_selection.clear();
self.filtered_order.clear();
self.filter_term.clear();
@ -189,7 +284,7 @@ impl ListingTrait for PlainListing {
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
if self.cursor_pos.1 != self.new_cursor_pos.1 || self.cursor_pos.0 != self.new_cursor_pos.0
{
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
}
let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area);
@ -563,100 +658,6 @@ impl PlainListing {
}
}
/// Fill the `self.data_columns` `CellBuffers` with the contents of the account folder the user has
/// chosen.
fn refresh_mailbox(&mut self, context: &mut Context) {
self.dirty = true;
let old_cursor_pos = self.cursor_pos;
if !(self.cursor_pos.0 == self.new_cursor_pos.0
&& self.cursor_pos.1 == self.new_cursor_pos.1)
{
self.cursor_pos.2 = 0;
self.new_cursor_pos.2 = 0;
}
self.cursor_pos.1 = self.new_cursor_pos.1;
self.cursor_pos.0 = self.new_cursor_pos.0;
self.folder_hash = if let Some(h) = context.accounts[self.cursor_pos.0]
.folders_order
.get(self.cursor_pos.1)
{
*h
} else {
self.cursor_pos.1 = old_cursor_pos.1;
self.dirty = false;
return;
};
self.color_cache = ColorCache {
unseen: crate::conf::value(context, "mail.listing.plain.unseen"),
highlighted: crate::conf::value(context, "mail.listing.plain.highlighted"),
even: crate::conf::value(context, "mail.listing.plain.even"),
odd: crate::conf::value(context, "mail.listing.plain.odd"),
selected: crate::conf::value(context, "mail.listing.plain.selected"),
attachment_flag: crate::conf::value(context, "mail.listing.attachment_flag"),
thread_snooze_flag: crate::conf::value(context, "mail.listing.thread_snooze_flag"),
..self.color_cache
};
if std::env::var("NO_COLOR").is_ok()
&& (context.settings.terminal.use_color.is_false()
|| context.settings.terminal.use_color.is_internal())
{
self.color_cache.highlighted.attrs |= Attr::Reverse;
}
// Get mailbox as a reference.
//
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
Ok(()) => {}
Err(_) => {
let message: String =
context.accounts[self.cursor_pos.0][self.folder_hash].to_string();
self.data_columns.columns[0] =
CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
self.length = 0;
write_string_to_grid(
message.as_str(),
&mut self.data_columns.columns[0],
Color::Default,
Color::Default,
Attr::Default,
((0, 0), (MAX_COLS - 1, 0)),
None,
);
return;
}
}
self.local_collection = context.accounts[self.cursor_pos.0][self.folder_hash]
.unwrap()
.envelopes
.iter()
.cloned()
.collect();
let env_lck = context.accounts[self.cursor_pos.0]
.collection
.envelopes
.read()
.unwrap();
self.thread_node_hashes = context.accounts[self.cursor_pos.0][self.folder_hash]
.unwrap()
.envelopes
.iter()
.map(|h| (*h, env_lck[h].thread()))
.collect();
drop(env_lck);
self.redraw_list(context);
if self.length > 0 {
let env_hash = self.get_env_under_cursor(self.cursor_pos.2, context);
let temp = (self.new_cursor_pos.0, self.new_cursor_pos.1, env_hash);
if old_cursor_pos == self.new_cursor_pos {
self.view.update(temp);
} else if self.unfocused {
self.view = MailView::new(temp, None, None);
}
}
}
fn redraw_list(&mut self, context: &Context) {
let account = &context.accounts[self.cursor_pos.0];
let mailbox = &account[self.cursor_pos.1].unwrap();
@ -1084,7 +1085,7 @@ impl Component for PlainListing {
// let threads = &account.collection.threads[&self.folder_hash];
// threads.vec_inner_sort_by(&mut self.filtered_selection, self.sort, &account.collection);
//} else {
// self.refresh_mailbox(context);
// self.refresh_mailbox(contex, falset);
//}
return true;
}
@ -1134,11 +1135,11 @@ impl Component for PlainListing {
UIEvent::MailboxUpdate((ref idxa, ref idxf))
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
{
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
self.set_dirty(true);
}
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
self.set_dirty(true);
}
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
@ -1179,7 +1180,7 @@ impl Component for PlainListing {
UIEvent::Input(Key::Esc) if !self.unfocused && !self.filter_term.is_empty() => {
self.set_coordinates((self.new_cursor_pos.0, self.new_cursor_pos.1));
self.set_dirty(true);
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
return true;
}
UIEvent::Action(ref action) => match action {
@ -1193,7 +1194,7 @@ impl Component for PlainListing {
}
self.filtered_selection.clear();
self.new_cursor_pos.1 = *idx;
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
return true;
}
Action::Listing(Filter(ref filter_term)) if !self.unfocused => {

View File

@ -58,6 +58,145 @@ impl MailListingTrait for ThreadListing {
fn get_focused_items(&self, _context: &Context) -> SmallVec<[ThreadHash; 8]> {
SmallVec::new()
}
/// Fill the `self.content` `CellBuffer` with the contents of the account folder the user has
/// chosen.
fn refresh_mailbox(&mut self, context: &mut Context, _force: bool) {
self.dirty = true;
if !(self.cursor_pos.0 == self.new_cursor_pos.0
&& self.cursor_pos.1 == self.new_cursor_pos.1)
{
self.cursor_pos.2 = 0;
self.new_cursor_pos.2 = 0;
}
self.cursor_pos.1 = self.new_cursor_pos.1;
self.cursor_pos.0 = self.new_cursor_pos.0;
self.folder_hash = if let Some(h) = context.accounts[self.cursor_pos.0]
.folders_order
.get(self.cursor_pos.1)
{
*h
} else {
return;
};
// Get mailbox as a reference.
//
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
Ok(_) => {}
Err(_) => {
let message: String =
context.accounts[self.cursor_pos.0][self.folder_hash].to_string();
self.content = CellBuffer::new(message.len(), 1, Cell::with_char(' '));
self.length = 0;
write_string_to_grid(
message.as_str(),
&mut self.content,
Color::Default,
Color::Default,
Attr::Default,
((0, 0), (MAX_COLS - 1, 0)),
None,
);
return;
}
}
let account = &context.accounts[self.cursor_pos.0];
let mailbox = account[self.cursor_pos.1].unwrap();
let threads = &account.collection.threads[&mailbox.folder.hash()];
self.length = threads.len();
self.locations.clear();
if self.length == 0 {
let message = format!("Folder `{}` is empty.", mailbox.folder.name());
self.content = CellBuffer::new(message.len(), 1, Cell::with_char(' '));
write_string_to_grid(
&message,
&mut self.content,
Color::Default,
Color::Default,
Attr::Default,
((0, 0), (message.len() - 1, 0)),
None,
);
return;
}
self.content = CellBuffer::new(MAX_COLS, self.length + 1, Cell::with_char(' '));
let mut indentations: Vec<bool> = Vec::with_capacity(6);
let mut thread_idx = 0; // needed for alternate thread colors
/* Draw threaded view. */
threads.sort_by(self.sort, self.subsort, &account.collection.envelopes);
let thread_nodes: &FnvHashMap<ThreadNodeHash, ThreadNode> = &threads.thread_nodes();
let mut iter = threads.threads_iter().peekable();
/* This is just a desugared for loop so that we can use .peek() */
let mut idx = 0;
while let Some((indentation, thread_node_hash, has_sibling)) = iter.next() {
let thread_node = &thread_nodes[&thread_node_hash];
if indentation == 0 {
thread_idx += 1;
}
if thread_node.has_message() {
let envelope: EnvelopeRef =
account.collection.get_env(thread_node.message().unwrap());
self.locations.push(envelope.hash());
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(
&ThreadListing::make_thread_entry(
&envelope,
idx,
indentation,
thread_node_hash,
threads,
&indentations,
has_sibling,
),
&mut self.content,
fg_color,
bg_color,
Attr::Default,
((0, idx), (MAX_COLS - 1, idx)),
None,
);
for x in x..MAX_COLS {
self.content[(x, idx)].set_ch(' ');
self.content[(x, idx)].set_bg(bg_color);
}
idx += 1;
} else {
continue;
}
match iter.peek() {
Some((x, _, _)) if *x > indentation => {
if has_sibling {
indentations.push(true);
} else {
indentations.push(false);
}
}
Some((x, _, _)) if *x < indentation => {
for _ in 0..(indentation - *x) {
indentations.pop();
}
}
_ => {}
}
}
}
}
impl ListingTrait for ThreadListing {
@ -67,6 +206,7 @@ impl ListingTrait for ThreadListing {
fn set_coordinates(&mut self, coordinates: (usize, usize)) {
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
self.unfocused = false;
self.view = None;
self.locations.clear();
self.row_updates.clear();
self.initialised = false;
@ -74,7 +214,7 @@ impl ListingTrait for ThreadListing {
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
if self.cursor_pos.1 != self.new_cursor_pos.1 || self.cursor_pos.0 != self.new_cursor_pos.0
{
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
}
let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area);
@ -254,144 +394,6 @@ impl ThreadListing {
id: ComponentId::new_v4(),
}
}
/// Fill the `self.content` `CellBuffer` with the contents of the account folder the user has
/// chosen.
fn refresh_mailbox(&mut self, context: &mut Context) {
self.dirty = true;
if !(self.cursor_pos.0 == self.new_cursor_pos.0
&& self.cursor_pos.1 == self.new_cursor_pos.1)
{
self.cursor_pos.2 = 0;
self.new_cursor_pos.2 = 0;
}
self.cursor_pos.1 = self.new_cursor_pos.1;
self.cursor_pos.0 = self.new_cursor_pos.0;
self.folder_hash = if let Some(h) = context.accounts[self.cursor_pos.0]
.folders_order
.get(self.cursor_pos.1)
{
*h
} else {
return;
};
// Get mailbox as a reference.
//
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
Ok(_) => {}
Err(_) => {
let message: String =
context.accounts[self.cursor_pos.0][self.folder_hash].to_string();
self.content = CellBuffer::new(message.len(), 1, Cell::with_char(' '));
self.length = 0;
write_string_to_grid(
message.as_str(),
&mut self.content,
Color::Default,
Color::Default,
Attr::Default,
((0, 0), (MAX_COLS - 1, 0)),
None,
);
return;
}
}
let account = &context.accounts[self.cursor_pos.0];
let mailbox = account[self.cursor_pos.1].unwrap();
let threads = &account.collection.threads[&mailbox.folder.hash()];
self.length = threads.len();
self.locations.clear();
if self.length == 0 {
let message = format!("Folder `{}` is empty.", mailbox.folder.name());
self.content = CellBuffer::new(message.len(), 1, Cell::with_char(' '));
write_string_to_grid(
&message,
&mut self.content,
Color::Default,
Color::Default,
Attr::Default,
((0, 0), (message.len() - 1, 0)),
None,
);
return;
}
self.content = CellBuffer::new(MAX_COLS, self.length + 1, Cell::with_char(' '));
let mut indentations: Vec<bool> = Vec::with_capacity(6);
let mut thread_idx = 0; // needed for alternate thread colors
/* Draw threaded view. */
threads.sort_by(self.sort, self.subsort, &account.collection.envelopes);
let thread_nodes: &FnvHashMap<ThreadNodeHash, ThreadNode> = &threads.thread_nodes();
let mut iter = threads.threads_iter().peekable();
/* This is just a desugared for loop so that we can use .peek() */
let mut idx = 0;
while let Some((indentation, thread_node_hash, has_sibling)) = iter.next() {
let thread_node = &thread_nodes[&thread_node_hash];
if indentation == 0 {
thread_idx += 1;
}
if thread_node.has_message() {
let envelope: EnvelopeRef =
account.collection.get_env(thread_node.message().unwrap());
self.locations.push(envelope.hash());
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(
&ThreadListing::make_thread_entry(
&envelope,
idx,
indentation,
thread_node_hash,
threads,
&indentations,
has_sibling,
),
&mut self.content,
fg_color,
bg_color,
Attr::Default,
((0, idx), (MAX_COLS - 1, idx)),
None,
);
for x in x..MAX_COLS {
self.content[(x, idx)].set_ch(' ');
self.content[(x, idx)].set_bg(bg_color);
}
idx += 1;
} else {
continue;
}
match iter.peek() {
Some((x, _, _)) if *x > indentation => {
if has_sibling {
indentations.push(true);
} else {
indentations.push(false);
}
}
Some((x, _, _)) if *x < indentation => {
for _ in 0..(indentation - *x) {
indentations.pop();
}
}
_ => {}
}
}
}
fn highlight_line_self(&mut self, idx: usize, context: &Context) {
let mailbox = if context.accounts[self.cursor_pos.0][self.cursor_pos.1].is_available() {
@ -624,11 +626,11 @@ impl Component for ThreadListing {
UIEvent::MailboxUpdate((ref idxa, ref idxf))
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
{
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
self.set_dirty(true);
}
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
self.set_dirty(true);
}
UIEvent::ChangeMode(UIMode::Normal) => {
@ -641,21 +643,21 @@ impl Component for ThreadListing {
Action::ViewMailbox(idx_m) => {
self.new_cursor_pos.1 = *idx_m;
self.dirty = true;
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
return true;
}
Action::SubSort(field, order) => {
debug!("SubSort {:?} , {:?}", field, order);
self.subsort = (*field, *order);
self.dirty = true;
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
return true;
}
Action::Sort(field, order) => {
debug!("Sort {:?} , {:?}", field, order);
self.sort = (*field, *order);
self.dirty = true;
self.refresh_mailbox(context);
self.refresh_mailbox(context, false);
return true;
}
_ => {}

View File

@ -166,6 +166,10 @@ impl ThreadView {
let mailbox = &account[self.coordinates.1].unwrap();
let threads = &account.collection.threads[&mailbox.folder.hash()];
if !threads.groups.contains_key(&self.thread_group) {
return;
}
let thread_iter = threads.thread_group_iter(self.thread_group);
self.entries.clear();
for (line, (ind, thread_node_hash)) in thread_iter.enumerate() {