Re-enable conversations listing style

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
pull/319/head
Manos Pitsidianakis 2023-12-04 16:22:53 +02:00
parent 031d0f7dc7
commit c751b2e845
Signed by: Manos Pitsidianakis
GPG Key ID: 7729C7707F7E09D0
2 changed files with 122 additions and 143 deletions

View File

@ -230,8 +230,8 @@ impl<T> RowsState<T> {
}
}
//mod conversations;
//pub use self::conversations::*;
mod conversations;
pub use self::conversations::*;
mod compact;
pub use self::compact::*;
@ -927,7 +927,7 @@ pub trait ListingTrait: Component {
#[derive(Debug)]
pub enum ListingComponent {
Compact(Box<CompactListing>),
//Conversations(Box<ConversationsListing>),
Conversations(Box<ConversationsListing>),
Offline(Box<OfflineListing>),
Plain(Box<PlainListing>),
Threaded(Box<ThreadListing>),
@ -940,7 +940,7 @@ impl std::ops::Deref for ListingComponent {
fn deref(&self) -> &Self::Target {
match &self {
Compact(ref l) => l.as_ref(),
//Conversations(ref l) => l.as_ref(),
Conversations(ref l) => l.as_ref(),
Offline(ref l) => l.as_ref(),
Plain(ref l) => l.as_ref(),
Threaded(ref l) => l.as_ref(),
@ -952,7 +952,7 @@ impl std::ops::DerefMut for ListingComponent {
fn deref_mut(&mut self) -> &mut (dyn MailListingTrait + 'static) {
match self {
Compact(l) => l.as_mut(),
//Conversations(l) => l.as_mut(),
Conversations(l) => l.as_mut(),
Offline(l) => l.as_mut(),
Plain(l) => l.as_mut(),
Threaded(l) => l.as_mut(),
@ -964,7 +964,7 @@ impl ListingComponent {
fn id(&self) -> ComponentId {
match self {
Compact(l) => l.as_component().id(),
//Conversations(l) => l.as_component().id(),
Conversations(l) => l.as_component().id(),
Offline(l) => l.as_component().id(),
Plain(l) => l.as_component().id(),
Threaded(l) => l.as_component().id(),
@ -1041,7 +1041,7 @@ impl std::fmt::Display for Listing {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self.component {
Compact(ref l) => write!(f, "{}", l),
//Conversations(ref l) => write!(f, "{}", l),
Conversations(ref l) => write!(f, "{}", l),
Offline(ref l) => write!(f, "{}", l),
Plain(ref l) => write!(f, "{}", l),
Threaded(ref l) => write!(f, "{}", l),
@ -2458,7 +2458,7 @@ impl Component for Listing {
self.component.id(),
match &self.component {
Compact(l) => l.as_component(),
//Conversations(l) => l.as_component(),
Conversations(l) => l.as_component(),
Offline(l) => l.as_component(),
Plain(l) => l.as_component(),
Threaded(l) => l.as_component(),
@ -2474,7 +2474,7 @@ impl Component for Listing {
self.component.id(),
match &mut self.component {
Compact(l) => l.as_component_mut(),
//Conversations(l) => l.as_component_mut(),
Conversations(l) => l.as_component_mut(),
Offline(l) => l.as_component_mut(),
Plain(l) => l.as_component_mut(),
Threaded(l) => l.as_component_mut(),
@ -3124,7 +3124,7 @@ impl Listing {
fn set_index_style(&mut self, new_style: IndexStyle, context: &mut Context) {
let old = match new_style {
IndexStyle::Conversations | IndexStyle::Plain => {
IndexStyle::Plain => {
if matches!(self.component, Plain(_)) {
return;
}
@ -3153,17 +3153,17 @@ impl Listing {
&mut self.component,
Compact(CompactListing::new(self.id, coordinates)),
)
} //IndexStyle::Conversations => {
// return;
// //if matches!(self.component, Conversations(_)) {
// // return;
// //}
// //let coordinates = self.component.coordinates();
// //std::mem::replace(
// // &mut self.component,
// // Conversations(ConversationsListing::new(self.id,
// // coordinates)),
//}
}
IndexStyle::Conversations => {
if matches!(self.component, Conversations(_)) {
return;
}
let coordinates = self.component.coordinates();
std::mem::replace(
&mut self.component,
Conversations(ConversationsListing::new(self.id, coordinates)),
)
}
};
if let MenuEntryCursor::Mailbox(idx) = self.cursor_pos.menu {
if let Some(mbox_entry) = self.accounts[self.cursor_pos.account].entries.get_mut(idx) {

View File

@ -22,7 +22,7 @@
use std::{collections::BTreeMap, iter::FromIterator};
use indexmap::IndexSet;
use melib::{SortField, SortOrder, TagHash, Threads};
use melib::{Address, SortField, SortOrder, TagHash, Threads};
use super::*;
use crate::{components::PageMovement, jobs::JoinHandle};
@ -460,11 +460,8 @@ impl ListingTrait for ConversationsListing {
{
self.refresh_mailbox(context, false);
}
let upper_left = area.upper_left();
let bottom_right = area.bottom_right();
if let Err(message) = self.error.as_ref() {
grid.clear_area(area, self.color_cache.theme_default);
grid.write_string(
message,
self.color_cache.theme_default.fg,
@ -476,7 +473,7 @@ impl ListingTrait for ConversationsListing {
context.dirty_areas.push_back(area);
return;
}
let rows = (get_y(bottom_right) - get_y(upper_left) + 1) / 3;
let rows = area.height() / 3;
if rows == 0 {
return;
}
@ -519,8 +516,8 @@ impl ListingTrait for ConversationsListing {
let top_idx = page_no * rows;
/* If cursor position has changed, remove the highlight from the previous
* position and apply it in the new one. */
// If cursor position has changed, remove the highlight from the previous
// position and apply it in the new one.
if self.cursor_pos.2 != self.new_cursor_pos.2 && prev_page_no == page_no {
let old_cursor_pos = self.cursor_pos;
self.cursor_pos = self.new_cursor_pos;
@ -544,12 +541,12 @@ impl ListingTrait for ConversationsListing {
}
grid.clear_area(area, self.color_cache.theme_default);
/* Page_no has changed, so draw new page */
// Page_no has changed, so draw new page
self.draw_rows(grid, area, context, top_idx);
self.highlight_line(
grid,
area.skip_rows(3 * (self.cursor_pos.2 % rows)).take_rows(2),
area.skip_rows(3 * (self.cursor_pos.2 % rows)).take_rows(3),
self.cursor_pos.2,
context,
);
@ -639,10 +636,9 @@ impl ListingTrait for ConversationsListing {
match new_value {
Focus::None => {
self.dirty = true;
/* If self.rows.row_updates is not empty and we exit a thread, the row_update
* events will be performed but the list will not be drawn.
* So force a draw in any case.
*/
// If self.rows.row_updates is not empty and we exit a thread, the row_update
// events will be performed but the list will not be drawn. So force a draw in
// any case.
self.force_draw = true;
}
Focus::Entry => {
@ -797,7 +793,7 @@ impl ConversationsListing {
if thread.has_attachments() { "📎" } else { "" },
if thread.snoozed() { "💤" } else { "" }
)),
from: FromString(address_list!((from) as comma_sep_list)),
from: FromString(Address::display_name_slice(from).to_string()),
tags: TagString(tags_string, colors),
}
}
@ -885,6 +881,7 @@ impl ConversationsListing {
if !context.accounts[&self.cursor_pos.0].contains_key(*root_env_hash) {
continue;
}
let area = area.skip_rows(3 * (idx - top_idx)).take_rows(3);
let thread = threads.thread_ref(*thread_hash);
let row_attr = row_attr!(
@ -893,17 +890,20 @@ impl ConversationsListing {
self.cursor_pos.2 == idx,
self.rows.is_thread_selected(*thread_hash)
);
/* draw flags */
let (x, _) = grid.write_string(
// draw flags
let (mut x, _) = grid.write_string(
&strings.flag,
row_attr.fg,
row_attr.bg,
row_attr.attrs,
area.skip_rows(idx),
area,
None,
);
for c in grid.row_iter(area, x..(x + 3), idx) {
grid[c].set_bg(row_attr.bg);
if !strings.flag.is_empty() {
for c in grid.row_iter(area, x..(x + 3), 0) {
grid[c].set_bg(row_attr.bg);
}
x += 3;
}
let subject_attr = row_attr!(
subject,
@ -912,53 +912,50 @@ impl ConversationsListing {
self.cursor_pos.2 == idx,
self.rows.is_thread_selected(*thread_hash)
);
/* draw subject */
let (mut x, subject_overflowed) = grid.write_string(
// draw subject
let (x_, subject_overflowed) = grid.write_string(
&strings.subject,
subject_attr.fg,
subject_attr.bg,
subject_attr.attrs,
area.skip(idx, x),
area.skip_cols(x),
None,
);
x += x_;
let mut subject_overflowed = subject_overflowed > 0;
for (t, &color) in strings.tags.split_whitespace().zip(strings.tags.1.iter()) {
if subject_overflowed {
break;
};
let area = area.skip_cols(x).take_cols(t.grapheme_width() + 2);
let color = color.unwrap_or(self.color_cache.tag_default.bg);
let (_x, _y) = grid.write_string(
t,
self.color_cache.tag_default.fg,
color,
self.color_cache.tag_default.attrs,
area.skip(idx, x + 1),
area.skip_cols(1),
None,
);
if _y > 0 {
subject_overflowed = true;
break;
}
grid[set_x(upper_left, x)].set_bg(color);
if _x <= get_x(bottom_right) {
grid[set_x(upper_left, _x)].set_bg(color).set_keep_bg(true);
}
for x in (x + 1).._x {
grid[set_x(upper_left, x)]
for c in grid.row_iter(area, 0..area.width(), 0) {
grid[c]
.set_keep_fg(true)
.set_keep_bg(true);
.set_bg(color)
.set_keep_bg(true)
.set_attrs(self.color_cache.tag_default.attrs);
}
grid[set_x(upper_left, x)].set_keep_bg(true);
x = _x + 1;
x += _x + 2;
}
if !subject_overflowed {
for x in x..get_x(bottom_right) {
grid[set_x(upper_left, x)]
.set_ch(' ')
.set_fg(row_attr.fg)
.set_bg(row_attr.bg);
for c in grid.row_iter(area, x..area.width(), 0) {
grid[c].set_ch(' ').set_fg(row_attr.fg).set_bg(row_attr.bg);
}
}
// Next line, draw date
let date_attr = row_attr!(
date,
self.color_cache,
@ -966,25 +963,21 @@ impl ConversationsListing {
self.cursor_pos.2 == idx,
self.rows.is_thread_selected(*thread_hash)
);
upper_left.1 += 1;
if upper_left.1 >= bottom_right.1 {
return;
}
/* Next line, draw date */
let (x, _) = grid.write_string(
&strings.date,
date_attr.fg,
date_attr.bg,
date_attr.attrs,
(upper_left, bottom_right),
None,
);
for x in x..(x + 4) {
grid[set_x(upper_left, x)]
.set_ch('▁')
.set_fg(row_attr.fg)
.set_bg(row_attr.bg);
x = 0;
x += grid
.write_string(
&strings.date,
date_attr.fg,
date_attr.bg,
date_attr.attrs,
area.skip(x, 1),
None,
)
.0;
for c in grid.row_iter(area, x..(x + 4), 1) {
grid[c].set_ch('▁').set_fg(row_attr.fg).set_bg(row_attr.bg);
}
x += 4;
let from_attr = row_attr!(
from,
self.color_cache,
@ -992,25 +985,20 @@ impl ConversationsListing {
self.cursor_pos.2 == idx,
self.rows.is_thread_selected(*thread_hash)
);
/* draw from */
let (x, _) = grid.write_string(
&strings.from,
from_attr.fg,
from_attr.bg,
from_attr.attrs,
(set_x(upper_left, x + 4), bottom_right),
None,
);
// draw from
x += grid
.write_string(
&strings.from,
from_attr.fg,
from_attr.bg,
from_attr.attrs,
area.skip(x, 1),
None,
)
.0;
for x in x..get_x(bottom_right) {
grid[set_x(upper_left, x)]
.set_ch('▁')
.set_fg(row_attr.fg)
.set_bg(row_attr.bg);
}
upper_left.1 += 2;
if upper_left.1 >= bottom_right.1 {
return;
for c in grid.row_iter(area, x..area.width(), 1) {
grid[c].set_ch('▁').set_fg(row_attr.fg).set_bg(row_attr.bg);
}
}
}
@ -1027,7 +1015,6 @@ impl Component for ConversationsListing {
return;
}
let (upper_left, bottom_right) = area;
{
let mut area = area;
@ -1042,24 +1029,18 @@ impl Component for ConversationsListing {
self.color_cache.theme_default.bg,
self.color_cache.theme_default.attrs,
area,
Some(get_x(upper_left)),
Some(0),
);
for c in grid.row_iter(area, x..(get_x(bottom_right) + 1), y) {
for c in grid.row_iter(area, x..area.width(), y) {
grid[c] = Cell::default();
}
grid.clear_area(
((x, y), set_y(bottom_right, y)),
self.color_cache.theme_default,
);
context
.dirty_areas
.push_back((upper_left, set_y(bottom_right, y + 1)));
grid.clear_area(area.skip(x, y), self.color_cache.theme_default);
context.dirty_areas.push_back(area.nth_row(0));
area = (set_y(upper_left, y + 1), bottom_right);
area = area.skip_rows(1);
}
let (upper_left, bottom_right) = area;
let rows = (get_y(bottom_right) - get_y(upper_left) + 1) / 3;
let rows = area.height() / 3;
if let Some(modifier) = self.modifier_command.take() {
if let Some(mvm) = self.movement.as_ref() {
match mvm {
@ -1231,8 +1212,7 @@ impl Component for ConversationsListing {
}
if !self.rows.row_updates.is_empty() {
/* certain rows need to be updated (eg an unseen message was just set seen)
*/
// certain rows need to be updated (eg an unseen message was just set seen)
while let Some(row) = self.rows.row_updates.pop() {
self.update_line(context, row);
let row: usize = self.rows.env_order[&row];
@ -1240,23 +1220,20 @@ impl Component for ConversationsListing {
let page_no = (self.cursor_pos.2).wrapping_div(rows);
let top_idx = page_no * rows;
/* Update row only if it's currently visible */
// Update row only if it's currently visible
if row >= top_idx && row < top_idx + rows {
let area = (
set_y(upper_left, get_y(upper_left) + (3 * (row % rows))),
set_y(bottom_right, get_y(upper_left) + (3 * (row % rows) + 2)),
);
let area = area.skip_rows(3 * (row % rows)).take_rows(3);
self.highlight_line(grid, area, row, context);
context.dirty_areas.push_back(area);
}
}
if self.force_draw {
/* Draw the entire list */
// Draw the entire list
self.draw_list(grid, area, context);
self.force_draw = false;
}
} else {
/* Draw the entire list */
// Draw the entire list
self.draw_list(grid, area, context);
}
}
@ -1267,14 +1244,8 @@ impl Component for ConversationsListing {
return;
}
let entry_area = (
set_x(upper_left, get_x(upper_left) + area.width() / 3 + 2),
bottom_right,
);
let gap_area = (
pos_dec(entry_area.upper_left(), (1, 0)),
entry_area.bottom_right(),
);
let entry_area = area.skip_cols(1 + area.width() / 3);
let gap_area = area.nth_col(area.width() / 3);
grid.clear_area(gap_area, self.color_cache.theme_default);
context.dirty_areas.push_back(gap_area);
self.view_area = entry_area.into();
@ -1415,23 +1386,21 @@ impl Component for ConversationsListing {
return true;
}
Action::Listing(ToggleThreadSnooze) if !self.unfocused() => {
/*
if let Some(thread) = self.get_thread_under_cursor(self.cursor_pos.2) {
let account = &mut context.accounts[&self.cursor_pos.0];
account
.collection
.threads
.write()
.unwrap()
.entry(self.cursor_pos.1)
.and_modify(|threads| {
let is_snoozed = threads.thread_ref(thread).snoozed();
threads.thread_ref_mut(thread).set_snoozed(!is_snoozed);
});
self.rows.row_updates.push(thread);
self.refresh_mailbox(context, false);
}
*/
//if let Some(thread) = self.get_thread_under_cursor(self.cursor_pos.2) {
// let account = &mut context.accounts[&self.cursor_pos.0];
// account
// .collection
// .threads
// .write()
// .unwrap()
// .entry(self.cursor_pos.1)
// .and_modify(|threads| {
// let is_snoozed = threads.thread_ref(thread).snoozed();
// threads.thread_ref_mut(thread).set_snoozed(!is_snoozed);
// });
// self.rows.row_updates.push(thread);
// self.refresh_mailbox(context, false);
//}
return true;
}
_ => {}
@ -1476,7 +1445,12 @@ impl Component for ConversationsListing {
self.search_job = Some((filter_term.to_string(), handle));
}
Err(err) => {
context.replies.push_back(UIEvent::Notification { title: Some("Could not perform search".into()), source: None, body: err.to_string().into(), kind: Some(crate::types::NotificationType::Error(err.kind)), });
context.replies.push_back(UIEvent::Notification {
title: Some("Could not perform search".into()),
source: None,
body: err.to_string().into(),
kind: Some(crate::types::NotificationType::Error(err.kind)),
});
}
};
self.set_dirty(true);
@ -1518,7 +1492,12 @@ impl Component for ConversationsListing {
Ok(None) => { /* something happened, perhaps a worker thread panicked */ }
Ok(Some(Ok(results))) => self.filter(filter_term, results, context),
Ok(Some(Err(err))) => {
context.replies.push_back(UIEvent::Notification { title: Some("Could not perform search".into()), source: None, body: err.to_string().into(), kind: Some(crate::types::NotificationType::Error(err.kind)), });
context.replies.push_back(UIEvent::Notification {
title: Some("Could not perform search".into()),
source: None,
body: err.to_string().into(),
kind: Some(crate::types::NotificationType::Error(err.kind)),
});
}
}
self.set_dirty(true);