Add MailListingTrait

Inheriting ListingTrait
async
Manos Pitsidianakis 2019-12-01 16:04:57 +02:00
parent 6cf73b4238
commit 8e27b86453
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
4 changed files with 185 additions and 267 deletions

View File

@ -46,6 +46,77 @@ struct AccountMenuEntry {
index: usize,
}
pub trait MailListingTrait: ListingTrait {
fn perform_action(
&mut self,
context: &mut Context,
thread_hash: ThreadHash,
a: &ListingAction,
) {
let account = &mut context.accounts[self.coordinates().0];
let mut envs_to_set: StackVec<EnvelopeHash> = StackVec::new();
let folder_hash = account[self.coordinates().1].unwrap().folder.hash();
{
let mut stack = StackVec::new();
stack.push(thread_hash);
while let Some(thread_iter) = stack.pop() {
{
let threads = account.collection.threads.get_mut(&folder_hash).unwrap();
threads
.thread_nodes
.entry(thread_iter)
.and_modify(|t| t.set_has_unseen(false));
}
let threads = &account.collection.threads[&folder_hash];
if let Some(env_hash) = threads[&thread_iter].message() {
if !account.contains_key(env_hash) {
/* The envelope has been renamed or removed, so wait for the appropriate event to
* arrive */
continue;
}
envs_to_set.push(env_hash);
}
for c in 0..threads[&thread_iter].children().len() {
let c = threads[&thread_iter].children()[c];
stack.push(c);
}
}
}
for env_hash in envs_to_set {
let op = account.operation(env_hash);
let mut envelope: EnvelopeRefMut = account.collection.get_env_mut(env_hash);
match a {
ListingAction::SetSeen => {
if let Err(e) = envelope.set_seen(op) {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
));
}
self.row_updates().push(thread_hash);
}
ListingAction::SetUnseen => {
if let Err(e) = envelope.set_unseen(op) {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
));
}
}
ListingAction::Delete => {
/* do nothing */
continue;
}
_ => unreachable!(),
}
self.row_updates().push(thread_hash);
drop(envelope);
}
}
fn row_updates(&mut self) -> &mut StackVec<ThreadHash>;
fn update_line(&mut self, context: &Context, thread_hash: ThreadHash);
}
pub trait ListingTrait: Component {
fn coordinates(&self) -> (usize, usize);
fn set_coordinates(&mut self, _: (usize, usize));

View File

@ -74,6 +74,76 @@ pub struct CompactListing {
id: ComponentId,
}
impl MailListingTrait for CompactListing {
fn row_updates(&mut self) -> &mut StackVec<ThreadHash> {
&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) => {}
}
}
}
}
impl ListingTrait for CompactListing {
fn coordinates(&self) -> (usize, usize) {
(self.new_cursor_pos.0, self.new_cursor_pos.1)
@ -888,136 +958,6 @@ impl CompactListing {
self.filtered_selection[cursor]
}
}
fn perform_action(
&mut self,
context: &mut Context,
thread_hash: ThreadHash,
a: &ListingAction,
) {
let account = &mut context.accounts[self.cursor_pos.0];
let mut envs_to_set: StackVec<EnvelopeHash> = StackVec::new();
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
{
let mut stack = StackVec::new();
stack.push(thread_hash);
while let Some(thread_iter) = stack.pop() {
{
let threads = account.collection.threads.get_mut(&folder_hash).unwrap();
threads
.thread_nodes
.entry(thread_iter)
.and_modify(|t| t.set_has_unseen(false));
}
let threads = &account.collection.threads[&folder_hash];
if let Some(env_hash) = threads[&thread_iter].message() {
if !account.contains_key(env_hash) {
/* The envelope has been renamed or removed, so wait for the appropriate event to
* arrive */
continue;
}
envs_to_set.push(env_hash);
}
for c in 0..threads[&thread_iter].children().len() {
let c = threads[&thread_iter].children()[c];
stack.push(c);
}
}
}
for env_hash in envs_to_set {
let op = account.operation(env_hash);
let mut envelope: EnvelopeRefMut = account.collection.get_env_mut(env_hash);
match a {
ListingAction::SetSeen => {
if let Err(e) = envelope.set_seen(op) {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
));
}
self.row_updates.push(thread_hash);
}
ListingAction::SetUnseen => {
if let Err(e) = envelope.set_unseen(op) {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
));
}
}
ListingAction::Delete => {
/* do nothing */
continue;
}
_ => unreachable!(),
}
self.row_updates.push(thread_hash);
let has_attachments = envelope.has_attachments();
drop(envelope);
let threads = &account.collection.threads[&folder_hash];
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 min_width = (
self.data_columns.columns[0].size().0,
self.data_columns.columns[1].size().0,
self.data_columns.columns[2].size().0,
self.data_columns.columns[3].size().0,
self.data_columns.columns[4].size().0,
);
for x in 0..min_width.0 {
self.data_columns.columns[0][(x, idx)].set_fg(fg_color);
self.data_columns.columns[0][(x, idx)].set_bg(bg_color);
}
for x in 0..min_width.1 {
self.data_columns.columns[1][(x, idx)].set_fg(fg_color);
self.data_columns.columns[1][(x, idx)].set_bg(bg_color);
}
for x in 0..min_width.2 {
self.data_columns.columns[2][(x, idx)].set_fg(fg_color);
self.data_columns.columns[2][(x, idx)].set_bg(bg_color);
}
for x in 0..min_width.3 {
self.data_columns.columns[3][(x, idx)].set_fg(fg_color);
self.data_columns.columns[3][(x, idx)].set_bg(bg_color);
}
for x in 0..min_width.4 {
self.data_columns.columns[4][(x, idx)].set_fg(fg_color);
self.data_columns.columns[4][(x, idx)].set_bg(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) => {}
}
}
}
}
impl Component for CompactListing {
@ -1053,44 +993,8 @@ impl Component for CompactListing {
if !self.row_updates.is_empty() {
let (upper_left, bottom_right) = area;
while let Some(row) = self.row_updates.pop() {
self.update_line(context, row);
let row: usize = self.order[&row];
let i = self.get_thread_under_cursor(row, context);
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[&i];
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 if self.selection[&i] {
Color::Byte(210)
} else if row % 2 == 0 {
if context.settings.terminal.theme == "light" {
Color::Byte(252)
} else {
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, row), (column_width - 1, row)),
fg_color,
bg_color,
);
}
let rows = get_y(bottom_right) - get_y(upper_left) + 1;
let page_no = (self.new_cursor_pos.2).wrapping_div(rows);

View File

@ -106,6 +106,48 @@ pub struct ConversationsListing {
id: ComponentId,
}
impl MailListingTrait for ConversationsListing {
fn row_updates(&mut self) -> &mut StackVec<ThreadHash> {
&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)
} else {
Color::Default
};
let bg_color = if thread_node.has_unseen() {
Color::Byte(251)
} else {
Color::Default
};
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,
);
}
}
impl ListingTrait for ConversationsListing {
fn coordinates(&self) -> (usize, usize) {
(self.new_cursor_pos.0, self.new_cursor_pos.1)
@ -898,70 +940,6 @@ impl ConversationsListing {
self.filtered_selection[cursor]
}
}
fn perform_action(
&mut self,
context: &mut Context,
thread_hash: ThreadHash,
a: &ListingAction,
) {
let account = &mut context.accounts[self.cursor_pos.0];
let mut envs_to_set: StackVec<EnvelopeHash> = StackVec::new();
{
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
let mut stack = StackVec::new();
stack.push(thread_hash);
while let Some(thread_iter) = stack.pop() {
{
let threads = account.collection.threads.get_mut(&folder_hash).unwrap();
threads
.thread_nodes
.entry(thread_iter)
.and_modify(|t| t.set_has_unseen(false));
}
let threads = &account.collection.threads[&folder_hash];
if let Some(env_hash) = threads[&thread_iter].message() {
if !account.contains_key(env_hash) {
/* The envelope has been renamed or removed, so wait for the appropriate event to
* arrive */
continue;
}
envs_to_set.push(env_hash);
}
for c in 0..threads[&thread_iter].children().len() {
let c = threads[&thread_iter].children()[c];
stack.push(c);
}
}
}
for env_hash in envs_to_set {
let hash = account.collection.get_env(env_hash).hash();
let op = account.operation(hash);
let mut envelope: EnvelopeRefMut = account.collection.get_env_mut(env_hash);
match a {
ListingAction::SetSeen => {
if let Err(e) = envelope.set_seen(op) {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
));
}
}
ListingAction::SetUnseen => {
if let Err(e) = envelope.set_unseen(op) {
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
));
}
}
ListingAction::Delete => {
/* do nothing */
continue;
}
_ => unreachable!(),
}
self.row_updates.push(thread_hash);
}
}
}
impl Component for ConversationsListing {
@ -1016,43 +994,10 @@ impl Component for ConversationsListing {
/* certain rows need to be updated (eg an unseen message was just set seen)
* */
let (upper_left, bottom_right) = area;
let width = self.content.size().0;
while let Some(row) = self.row_updates.pop() {
self.update_line(context, row);
let row: usize = self.order[&row];
let i = self.get_thread_under_cursor(row, context);
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[&i];
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
};
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 rows = (get_y(bottom_right) - get_y(upper_left) + 1) / 3;
let page_no = (self.cursor_pos.2).wrapping_div(rows);

View File

@ -1005,8 +1005,6 @@ pub fn clear_area(grid: &mut CellBuffer, area: Area) {
if !is_valid_area!(area) {
return;
}
let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area);
for row in grid.bounds_iter(area) {
for c in row {
grid[c] = Cell::default();