ui: force refresh_mailbox etc on Mailbox{Delete,Create}
parent
f5e694cf5a
commit
144eb62b76
|
@ -200,6 +200,9 @@ pub trait MailListingTrait: ListingTrait {
|
||||||
fn redraw_list(&mut self, _context: &Context, _items: Box<dyn Iterator<Item = ThreadHash>>) {
|
fn redraw_list(&mut self, _context: &Context, _items: Box<dyn Iterator<Item = ThreadHash>>) {
|
||||||
unimplemented!()
|
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 {
|
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;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,93 @@ impl MailListingTrait for CompactListing {
|
||||||
.cloned();
|
.cloned();
|
||||||
SmallVec::from_iter(iter.into_iter())
|
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 {
|
impl ListingTrait for CompactListing {
|
||||||
|
@ -110,6 +197,7 @@ impl ListingTrait for CompactListing {
|
||||||
fn set_coordinates(&mut self, coordinates: (usize, usize)) {
|
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.unfocused = false;
|
||||||
|
self.view = ThreadView::default();
|
||||||
self.filtered_selection.clear();
|
self.filtered_selection.clear();
|
||||||
self.filtered_order.clear();
|
self.filtered_order.clear();
|
||||||
self.filter_term.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) {
|
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
|
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 upper_left = upper_left!(area);
|
||||||
let bottom_right = bottom_right!(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>>) {
|
fn redraw_list(&mut self, context: &Context, items: Box<dyn Iterator<Item = ThreadHash>>) {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[self.cursor_pos.0];
|
||||||
let mailbox = &account[self.cursor_pos.1].unwrap();
|
let mailbox = &account[self.cursor_pos.1].unwrap();
|
||||||
|
@ -1244,7 +1245,7 @@ impl Component for CompactListing {
|
||||||
// FIXME: perform sort
|
// FIXME: perform sort
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
} else {
|
} else {
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1266,7 +1267,7 @@ impl Component for CompactListing {
|
||||||
threads.thread_ref_mut(thread).set_snoozed(!is_snoozed);
|
threads.thread_ref_mut(thread).set_snoozed(!is_snoozed);
|
||||||
});
|
});
|
||||||
self.row_updates.push(thread);
|
self.row_updates.push(thread);
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1280,11 +1281,11 @@ impl Component for CompactListing {
|
||||||
UIEvent::MailboxUpdate((ref idxa, ref idxf))
|
UIEvent::MailboxUpdate((ref idxa, ref idxf))
|
||||||
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
|
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
|
||||||
{
|
{
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
|
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
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() => {
|
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_coordinates((self.new_cursor_pos.0, self.new_cursor_pos.1));
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1331,7 +1332,7 @@ impl Component for CompactListing {
|
||||||
}
|
}
|
||||||
self.filtered_selection.clear();
|
self.filtered_selection.clear();
|
||||||
self.new_cursor_pos.1 = *idx;
|
self.new_cursor_pos.1 = *idx;
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Action::Listing(Filter(ref filter_term)) if !self.unfocused => {
|
Action::Listing(Filter(ref filter_term)) if !self.unfocused => {
|
||||||
|
|
|
@ -79,6 +79,100 @@ impl MailListingTrait for ConversationsListing {
|
||||||
.cloned();
|
.cloned();
|
||||||
SmallVec::from_iter(iter.into_iter())
|
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 {
|
impl ListingTrait for ConversationsListing {
|
||||||
|
@ -87,8 +181,10 @@ impl ListingTrait for ConversationsListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_coordinates(&mut self, coordinates: (usize, usize)) {
|
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.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||||
self.unfocused = false;
|
self.unfocused = false;
|
||||||
|
self.view = ThreadView::default();
|
||||||
self.filtered_selection.clear();
|
self.filtered_selection.clear();
|
||||||
self.filtered_order.clear();
|
self.filtered_order.clear();
|
||||||
self.filter_term.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) {
|
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
|
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 upper_left = upper_left!(area);
|
||||||
let bottom_right = bottom_right!(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>>) {
|
fn redraw_list(&mut self, context: &Context, items: Box<dyn Iterator<Item = ThreadHash>>) {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[self.cursor_pos.0];
|
||||||
let mailbox = &account[self.cursor_pos.1].unwrap();
|
let mailbox = &account[self.cursor_pos.1].unwrap();
|
||||||
|
@ -1206,7 +1209,7 @@ impl Component for ConversationsListing {
|
||||||
// let threads = &account.collection.threads[&self.folder_hash];
|
// let threads = &account.collection.threads[&self.folder_hash];
|
||||||
// threads.vec_inner_sort_by(&mut self.filtered_selection, self.sort, &account.collection);
|
// threads.vec_inner_sort_by(&mut self.filtered_selection, self.sort, &account.collection);
|
||||||
//} else {
|
//} else {
|
||||||
// self.refresh_mailbox(context);
|
// self.refresh_mailbox(context, false);
|
||||||
//}
|
//}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1225,7 +1228,7 @@ impl Component for ConversationsListing {
|
||||||
);
|
);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
} else {
|
} else {
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
return true;
|
return true;
|
||||||
|
@ -1242,7 +1245,7 @@ impl Component for ConversationsListing {
|
||||||
threads.thread_ref_mut(thread).set_snoozed(!is_snoozed);
|
threads.thread_ref_mut(thread).set_snoozed(!is_snoozed);
|
||||||
});
|
});
|
||||||
self.row_updates.push(thread);
|
self.row_updates.push(thread);
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -1254,11 +1257,11 @@ impl Component for ConversationsListing {
|
||||||
UIEvent::MailboxUpdate((ref idxa, ref idxf))
|
UIEvent::MailboxUpdate((ref idxa, ref idxf))
|
||||||
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
|
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
|
||||||
{
|
{
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
|
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::ChangeMode(UIMode::Normal) => {
|
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||||
|
@ -1277,7 +1280,7 @@ impl Component for ConversationsListing {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
self.set_coordinates((self.new_cursor_pos.0, *idx));
|
self.set_coordinates((self.new_cursor_pos.0, *idx));
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1292,7 +1295,7 @@ impl Component for ConversationsListing {
|
||||||
if !self.unfocused && !&self.filter_term.is_empty() =>
|
if !self.unfocused && !&self.filter_term.is_empty() =>
|
||||||
{
|
{
|
||||||
self.set_coordinates((self.new_cursor_pos.0, self.new_cursor_pos.1));
|
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.force_draw = false;
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -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 {
|
impl ListingTrait for PlainListing {
|
||||||
|
@ -111,6 +205,7 @@ impl ListingTrait for PlainListing {
|
||||||
fn set_coordinates(&mut self, coordinates: (usize, usize)) {
|
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.unfocused = false;
|
||||||
|
self.view = MailView::default();
|
||||||
self.filtered_selection.clear();
|
self.filtered_selection.clear();
|
||||||
self.filtered_order.clear();
|
self.filtered_order.clear();
|
||||||
self.filter_term.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) {
|
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
|
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 upper_left = upper_left!(area);
|
||||||
let bottom_right = bottom_right!(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) {
|
fn redraw_list(&mut self, context: &Context) {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[self.cursor_pos.0];
|
||||||
let mailbox = &account[self.cursor_pos.1].unwrap();
|
let mailbox = &account[self.cursor_pos.1].unwrap();
|
||||||
|
@ -1084,7 +1085,7 @@ impl Component for PlainListing {
|
||||||
// let threads = &account.collection.threads[&self.folder_hash];
|
// let threads = &account.collection.threads[&self.folder_hash];
|
||||||
// threads.vec_inner_sort_by(&mut self.filtered_selection, self.sort, &account.collection);
|
// threads.vec_inner_sort_by(&mut self.filtered_selection, self.sort, &account.collection);
|
||||||
//} else {
|
//} else {
|
||||||
// self.refresh_mailbox(context);
|
// self.refresh_mailbox(contex, falset);
|
||||||
//}
|
//}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1134,11 +1135,11 @@ impl Component for PlainListing {
|
||||||
UIEvent::MailboxUpdate((ref idxa, ref idxf))
|
UIEvent::MailboxUpdate((ref idxa, ref idxf))
|
||||||
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
|
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
|
||||||
{
|
{
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
|
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
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() => {
|
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_coordinates((self.new_cursor_pos.0, self.new_cursor_pos.1));
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEvent::Action(ref action) => match action {
|
UIEvent::Action(ref action) => match action {
|
||||||
|
@ -1193,7 +1194,7 @@ impl Component for PlainListing {
|
||||||
}
|
}
|
||||||
self.filtered_selection.clear();
|
self.filtered_selection.clear();
|
||||||
self.new_cursor_pos.1 = *idx;
|
self.new_cursor_pos.1 = *idx;
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Action::Listing(Filter(ref filter_term)) if !self.unfocused => {
|
Action::Listing(Filter(ref filter_term)) if !self.unfocused => {
|
||||||
|
|
|
@ -58,6 +58,145 @@ impl MailListingTrait for ThreadListing {
|
||||||
fn get_focused_items(&self, _context: &Context) -> SmallVec<[ThreadHash; 8]> {
|
fn get_focused_items(&self, _context: &Context) -> SmallVec<[ThreadHash; 8]> {
|
||||||
SmallVec::new()
|
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 {
|
impl ListingTrait for ThreadListing {
|
||||||
|
@ -67,6 +206,7 @@ impl ListingTrait for ThreadListing {
|
||||||
fn set_coordinates(&mut self, coordinates: (usize, usize)) {
|
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.unfocused = false;
|
||||||
|
self.view = None;
|
||||||
self.locations.clear();
|
self.locations.clear();
|
||||||
self.row_updates.clear();
|
self.row_updates.clear();
|
||||||
self.initialised = false;
|
self.initialised = false;
|
||||||
|
@ -74,7 +214,7 @@ impl ListingTrait for ThreadListing {
|
||||||
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
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
|
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 upper_left = upper_left!(area);
|
||||||
let bottom_right = bottom_right!(area);
|
let bottom_right = bottom_right!(area);
|
||||||
|
@ -254,144 +394,6 @@ impl ThreadListing {
|
||||||
id: ComponentId::new_v4(),
|
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) {
|
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() {
|
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))
|
UIEvent::MailboxUpdate((ref idxa, ref idxf))
|
||||||
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
|
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.folder_hash) =>
|
||||||
{
|
{
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
|
UIEvent::StartupCheck(ref f) if *f == self.folder_hash => {
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::ChangeMode(UIMode::Normal) => {
|
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||||
|
@ -641,21 +643,21 @@ impl Component for ThreadListing {
|
||||||
Action::ViewMailbox(idx_m) => {
|
Action::ViewMailbox(idx_m) => {
|
||||||
self.new_cursor_pos.1 = *idx_m;
|
self.new_cursor_pos.1 = *idx_m;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Action::SubSort(field, order) => {
|
Action::SubSort(field, order) => {
|
||||||
debug!("SubSort {:?} , {:?}", field, order);
|
debug!("SubSort {:?} , {:?}", field, order);
|
||||||
self.subsort = (*field, *order);
|
self.subsort = (*field, *order);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Action::Sort(field, order) => {
|
Action::Sort(field, order) => {
|
||||||
debug!("Sort {:?} , {:?}", field, order);
|
debug!("Sort {:?} , {:?}", field, order);
|
||||||
self.sort = (*field, *order);
|
self.sort = (*field, *order);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -166,6 +166,10 @@ impl ThreadView {
|
||||||
let mailbox = &account[self.coordinates.1].unwrap();
|
let mailbox = &account[self.coordinates.1].unwrap();
|
||||||
let threads = &account.collection.threads[&mailbox.folder.hash()];
|
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);
|
let thread_iter = threads.thread_group_iter(self.thread_group);
|
||||||
self.entries.clear();
|
self.entries.clear();
|
||||||
for (line, (ind, thread_node_hash)) in thread_iter.enumerate() {
|
for (line, (ind, thread_node_hash)) in thread_iter.enumerate() {
|
||||||
|
|
Loading…
Reference in New Issue