parent
6cf73b4238
commit
8e27b86453
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue