listing/compact: move flags to subject column
Flags (attachment, unseen, etc) being their own column overcomplicated code, so just prepend them to subject column.pull/144/head
parent
64b62352d0
commit
ad2a10478e
|
@ -28,6 +28,24 @@ use std::collections::{HashMap, HashSet};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
// TODO: emoji_text_presentation_selector should be printed along with the chars before it but not
|
||||||
|
// as a separate Cell
|
||||||
|
//macro_rules! emoji_text_presentation_selector {
|
||||||
|
// () => {
|
||||||
|
// "\u{FE0E}"
|
||||||
|
// };
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//pub const DEFAULT_ATTACHMENT_FLAG: &str = concat!("📎", emoji_text_presentation_selector!());
|
||||||
|
//pub const DEFAULT_SELECTED_FLAG: &str = concat!("☑️", emoji_text_presentation_selector!());
|
||||||
|
//pub const DEFAULT_UNSEEN_FLAG: &str = concat!("●", emoji_text_presentation_selector!());
|
||||||
|
//pub const DEFAULT_SNOOZED_FLAG: &str = concat!("💤", emoji_text_presentation_selector!());
|
||||||
|
|
||||||
|
pub const DEFAULT_ATTACHMENT_FLAG: &str = "📎";
|
||||||
|
pub const DEFAULT_SELECTED_FLAG: &str = "☑️";
|
||||||
|
pub const DEFAULT_UNSEEN_FLAG: &str = "●";
|
||||||
|
pub const DEFAULT_SNOOZED_FLAG: &str = "💤";
|
||||||
|
|
||||||
mod conversations;
|
mod conversations;
|
||||||
pub use self::conversations::*;
|
pub use self::conversations::*;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,44 @@ use std::cmp;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
macro_rules! digits_of_num {
|
||||||
|
($num:expr) => {{
|
||||||
|
const GUESS: [usize; 65] = [
|
||||||
|
1, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8,
|
||||||
|
8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15,
|
||||||
|
15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19,
|
||||||
|
];
|
||||||
|
const TENS: [usize; 20] = [
|
||||||
|
1,
|
||||||
|
10,
|
||||||
|
100,
|
||||||
|
1000,
|
||||||
|
10000,
|
||||||
|
100000,
|
||||||
|
1000000,
|
||||||
|
10000000,
|
||||||
|
100000000,
|
||||||
|
1000000000,
|
||||||
|
10000000000,
|
||||||
|
100000000000,
|
||||||
|
1000000000000,
|
||||||
|
10000000000000,
|
||||||
|
100000000000000,
|
||||||
|
1000000000000000,
|
||||||
|
10000000000000000,
|
||||||
|
100000000000000000,
|
||||||
|
1000000000000000000,
|
||||||
|
10000000000000000000,
|
||||||
|
];
|
||||||
|
const SIZE_IN_BITS: usize = std::mem::size_of::<usize>() * 8;
|
||||||
|
|
||||||
|
let leading_zeros = $num.leading_zeros() as usize;
|
||||||
|
let base_two_digits: usize = SIZE_IN_BITS - leading_zeros;
|
||||||
|
let x = GUESS[base_two_digits];
|
||||||
|
x + if $num >= TENS[x] { 1 } else { 0 }
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! address_list {
|
macro_rules! address_list {
|
||||||
(($name:expr) as comma_sep_list) => {{
|
(($name:expr) as comma_sep_list) => {{
|
||||||
let mut ret: String =
|
let mut ret: String =
|
||||||
|
@ -118,12 +156,6 @@ macro_rules! row_attr {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! emoji_text_presentation_selector {
|
|
||||||
() => {
|
|
||||||
"\u{FE0E}"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A list of all mail (`Envelope`s) in a `Mailbox`. On `\n` it opens the `Envelope` content in a
|
/// A list of all mail (`Envelope`s) in a `Mailbox`. On `\n` it opens the `Envelope` content in a
|
||||||
/// `ThreadView`.
|
/// `ThreadView`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -286,19 +318,17 @@ impl MailListingTrait for CompactListing {
|
||||||
self.order.clear();
|
self.order.clear();
|
||||||
self.length = 0;
|
self.length = 0;
|
||||||
let mut rows = Vec::with_capacity(1024);
|
let mut rows = Vec::with_capacity(1024);
|
||||||
let mut min_width = (0, 0, 0, 0, 0);
|
let mut min_width = (0, 0, 0, 0);
|
||||||
let mut row_widths: (
|
let mut row_widths: (
|
||||||
SmallVec<[u8; 1024]>,
|
SmallVec<[u8; 1024]>,
|
||||||
SmallVec<[u8; 1024]>,
|
SmallVec<[u8; 1024]>,
|
||||||
SmallVec<[u8; 1024]>,
|
SmallVec<[u8; 1024]>,
|
||||||
SmallVec<[u8; 1024]>,
|
SmallVec<[u8; 1024]>,
|
||||||
SmallVec<[u8; 1024]>,
|
|
||||||
) = (
|
) = (
|
||||||
SmallVec::new(),
|
SmallVec::new(),
|
||||||
SmallVec::new(),
|
SmallVec::new(),
|
||||||
SmallVec::new(),
|
SmallVec::new(),
|
||||||
SmallVec::new(),
|
SmallVec::new(),
|
||||||
SmallVec::new(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
'items_for_loop: for thread in items {
|
'items_for_loop: for thread in items {
|
||||||
|
@ -348,38 +378,48 @@ impl MailListingTrait for CompactListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
let entry_strings = self.make_entry_string(&root_envelope, context, &threads, thread);
|
let entry_strings = self.make_entry_string(&root_envelope, context, &threads, thread);
|
||||||
|
row_widths
|
||||||
|
.0
|
||||||
|
.push(digits_of_num!(self.length).try_into().unwrap_or(255));
|
||||||
|
/* date */
|
||||||
row_widths.1.push(
|
row_widths.1.push(
|
||||||
entry_strings
|
entry_strings
|
||||||
.date
|
.date
|
||||||
.grapheme_width()
|
.grapheme_width()
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or(255),
|
.unwrap_or(255),
|
||||||
); /* date */
|
);
|
||||||
|
/* from */
|
||||||
row_widths.2.push(
|
row_widths.2.push(
|
||||||
entry_strings
|
entry_strings
|
||||||
.from
|
.from
|
||||||
.grapheme_width()
|
.grapheme_width()
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or(255),
|
.unwrap_or(255),
|
||||||
); /* from */
|
);
|
||||||
|
/* subject */
|
||||||
row_widths.3.push(
|
row_widths.3.push(
|
||||||
entry_strings
|
(entry_strings
|
||||||
.flag
|
.flag
|
||||||
.grapheme_width()
|
.grapheme_width()
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or(255),
|
.unwrap_or(255)
|
||||||
); /* flags */
|
+ 1
|
||||||
row_widths.4.push(
|
+ entry_strings.subject.grapheme_width()
|
||||||
(entry_strings.subject.grapheme_width() + 1 + entry_strings.tags.grapheme_width())
|
+ 1
|
||||||
.try_into()
|
+ entry_strings.tags.grapheme_width())
|
||||||
.unwrap_or(255),
|
.try_into()
|
||||||
|
.unwrap_or(255),
|
||||||
);
|
);
|
||||||
min_width.1 = cmp::max(min_width.1, entry_strings.date.grapheme_width()); /* date */
|
min_width.1 = cmp::max(min_width.1, entry_strings.date.grapheme_width()); /* date */
|
||||||
min_width.2 = cmp::max(min_width.2, entry_strings.from.grapheme_width()); /* from */
|
min_width.2 = cmp::max(min_width.2, entry_strings.from.grapheme_width()); /* from */
|
||||||
min_width.3 = cmp::max(min_width.3, entry_strings.flag.grapheme_width()); /* flags */
|
min_width.3 = cmp::max(
|
||||||
min_width.4 = cmp::max(
|
min_width.3,
|
||||||
min_width.4,
|
entry_strings.flag.grapheme_width()
|
||||||
entry_strings.subject.grapheme_width() + 1 + entry_strings.tags.grapheme_width(),
|
+ 1
|
||||||
|
+ entry_strings.subject.grapheme_width()
|
||||||
|
+ 1
|
||||||
|
+ entry_strings.tags.grapheme_width(),
|
||||||
); /* subject */
|
); /* subject */
|
||||||
rows.push(((self.length, (thread, root_env_hash)), entry_strings));
|
rows.push(((self.length, (thread, root_env_hash)), entry_strings));
|
||||||
self.all_threads.insert(thread);
|
self.all_threads.insert(thread);
|
||||||
|
@ -394,21 +434,20 @@ impl MailListingTrait for CompactListing {
|
||||||
/* index column */
|
/* index column */
|
||||||
self.data_columns.columns[0] =
|
self.data_columns.columns[0] =
|
||||||
CellBuffer::new_with_context(min_width.0, rows.len(), None, context);
|
CellBuffer::new_with_context(min_width.0, rows.len(), None, context);
|
||||||
|
self.data_columns.segment_tree[0] = row_widths.0.into();
|
||||||
|
|
||||||
/* date column */
|
/* date column */
|
||||||
self.data_columns.columns[1] =
|
self.data_columns.columns[1] =
|
||||||
CellBuffer::new_with_context(min_width.1, rows.len(), None, context);
|
CellBuffer::new_with_context(min_width.1, rows.len(), None, context);
|
||||||
|
self.data_columns.segment_tree[1] = row_widths.1.into();
|
||||||
/* from column */
|
/* from column */
|
||||||
self.data_columns.columns[2] =
|
self.data_columns.columns[2] =
|
||||||
CellBuffer::new_with_context(min_width.2, rows.len(), None, context);
|
CellBuffer::new_with_context(min_width.2, rows.len(), None, context);
|
||||||
self.data_columns.segment_tree[2] = row_widths.2.into();
|
self.data_columns.segment_tree[2] = row_widths.2.into();
|
||||||
/* flags column */
|
/* subject column */
|
||||||
self.data_columns.columns[3] =
|
self.data_columns.columns[3] =
|
||||||
CellBuffer::new_with_context(min_width.3, rows.len(), None, context);
|
CellBuffer::new_with_context(min_width.3, rows.len(), None, context);
|
||||||
/* subject column */
|
self.data_columns.segment_tree[3] = row_widths.3.into();
|
||||||
self.data_columns.columns[4] =
|
|
||||||
CellBuffer::new_with_context(min_width.4, rows.len(), None, context);
|
|
||||||
self.data_columns.segment_tree[4] = row_widths.4.into();
|
|
||||||
|
|
||||||
self.rows = rows;
|
self.rows = rows;
|
||||||
self.rows_drawn = SegmentTree::from(
|
self.rows_drawn = SegmentTree::from(
|
||||||
|
@ -494,10 +533,16 @@ impl ListingTrait for CompactListing {
|
||||||
(set_x(upper_left, x), bottom_right),
|
(set_x(upper_left, x), bottom_right),
|
||||||
(
|
(
|
||||||
(0, idx),
|
(0, idx),
|
||||||
pos_dec(self.data_columns.columns[3].size(), (1, 1)),
|
pos_dec(
|
||||||
|
(
|
||||||
|
self.data_columns.widths[3],
|
||||||
|
self.data_columns.columns[3].size().1,
|
||||||
|
),
|
||||||
|
(1, 1),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
for c in grid.row_iter(x..(self.data_columns.widths[3] + x), get_y(upper_left)) {
|
for c in grid.row_iter(x..(get_x(bottom_right) + 1), get_y(upper_left)) {
|
||||||
grid[c].set_bg(row_attr.bg).set_attrs(row_attr.attrs);
|
grid[c].set_bg(row_attr.bg).set_attrs(row_attr.attrs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -602,40 +647,35 @@ impl ListingTrait for CompactListing {
|
||||||
self.data_columns.widths[0] = self.data_columns.columns[0].size().0;
|
self.data_columns.widths[0] = self.data_columns.columns[0].size().0;
|
||||||
self.data_columns.widths[1] = self.data_columns.columns[1].size().0; /* date*/
|
self.data_columns.widths[1] = self.data_columns.columns[1].size().0; /* date*/
|
||||||
self.data_columns.widths[2] = self.data_columns.columns[2].size().0; /* from */
|
self.data_columns.widths[2] = self.data_columns.columns[2].size().0; /* from */
|
||||||
self.data_columns.widths[3] = self.data_columns.columns[3].size().0; /* flags */
|
self.data_columns.widths[3] = self.data_columns.columns[3].size().0; /* subject */
|
||||||
self.data_columns.widths[4] = self.data_columns.columns[4].size().0; /* subject */
|
|
||||||
|
|
||||||
let min_col_width = std::cmp::min(
|
let min_col_width = std::cmp::min(
|
||||||
15,
|
15,
|
||||||
std::cmp::min(self.data_columns.widths[4], self.data_columns.widths[2]),
|
std::cmp::min(self.data_columns.widths[3], self.data_columns.widths[2]),
|
||||||
);
|
);
|
||||||
if self.data_columns.widths[0] + self.data_columns.widths[1] + 3 * min_col_width + 8 > width
|
if self.data_columns.widths[0] + self.data_columns.widths[1] + 2 * min_col_width + 4 > width
|
||||||
{
|
{
|
||||||
let remainder = width
|
let remainder = width
|
||||||
.saturating_sub(self.data_columns.widths[0])
|
.saturating_sub(self.data_columns.widths[0])
|
||||||
.saturating_sub(self.data_columns.widths[1])
|
.saturating_sub(self.data_columns.widths[1])
|
||||||
.saturating_sub(4);
|
.saturating_sub(2 * 2);
|
||||||
self.data_columns.widths[2] = remainder / 6;
|
self.data_columns.widths[2] = remainder / 6;
|
||||||
self.data_columns.widths[4] =
|
|
||||||
((2 * remainder) / 3).saturating_sub(self.data_columns.widths[3]);
|
|
||||||
} else {
|
} else {
|
||||||
let remainder = width
|
let remainder = width
|
||||||
.saturating_sub(self.data_columns.widths[0])
|
.saturating_sub(self.data_columns.widths[0])
|
||||||
.saturating_sub(self.data_columns.widths[1])
|
.saturating_sub(self.data_columns.widths[1])
|
||||||
.saturating_sub(8);
|
.saturating_sub(3 * 2);
|
||||||
if min_col_width + self.data_columns.widths[4] > remainder {
|
if min_col_width + self.data_columns.widths[3] > remainder {
|
||||||
self.data_columns.widths[4] =
|
|
||||||
remainder.saturating_sub(min_col_width + self.data_columns.widths[3]);
|
|
||||||
self.data_columns.widths[2] = min_col_width;
|
self.data_columns.widths[2] = min_col_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for &i in &[2, 4] {
|
for i in 0..3 {
|
||||||
/* Set From and Subject column widths to their maximum value width in the range
|
/* Set column widths to their maximum value width in the range
|
||||||
* [top_idx, top_idx + rows]. By using a segment tree the query is O(logn), which is
|
* [top_idx, top_idx + rows]. By using a segment tree the query is O(logn), which is
|
||||||
* great!
|
* great!
|
||||||
*/
|
*/
|
||||||
self.data_columns.widths[i] =
|
self.data_columns.widths[i] =
|
||||||
self.data_columns.segment_tree[i].get_max(top_idx, top_idx + rows) as usize;
|
self.data_columns.segment_tree[i].get_max(top_idx, top_idx + rows - 1) as usize;
|
||||||
}
|
}
|
||||||
if self.data_columns.widths.iter().sum::<usize>() > width {
|
if self.data_columns.widths.iter().sum::<usize>() > width {
|
||||||
let diff = self.data_columns.widths.iter().sum::<usize>() - width;
|
let diff = self.data_columns.widths.iter().sum::<usize>() - width;
|
||||||
|
@ -646,40 +686,30 @@ impl ListingTrait for CompactListing {
|
||||||
15,
|
15,
|
||||||
self.data_columns.widths[2].saturating_sub((2 * diff) / 3),
|
self.data_columns.widths[2].saturating_sub((2 * diff) / 3),
|
||||||
);
|
);
|
||||||
self.data_columns.widths[4] = std::cmp::max(
|
|
||||||
15,
|
|
||||||
self.data_columns.widths[4].saturating_sub(diff / 3 + diff % 3),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clear_area(grid, area, self.color_cache.theme_default);
|
clear_area(grid, area, self.color_cache.theme_default);
|
||||||
/* Page_no has changed, so draw new page */
|
/* Page_no has changed, so draw new page */
|
||||||
let mut x = get_x(upper_left);
|
let mut x = get_x(upper_left);
|
||||||
let mut flag_x = 0;
|
let mut flag_x = 0;
|
||||||
for i in 0..self.data_columns.columns.len() {
|
for i in 0..4 {
|
||||||
let column_width = self.data_columns.columns[i].size().0;
|
let column_width = self.data_columns.widths[i];
|
||||||
if i == 3 {
|
if i == 3 {
|
||||||
flag_x = x;
|
flag_x = x;
|
||||||
}
|
}
|
||||||
if self.data_columns.widths[i] == 0 {
|
if column_width == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
copy_area(
|
copy_area(
|
||||||
grid,
|
grid,
|
||||||
&self.data_columns.columns[i],
|
&self.data_columns.columns[i],
|
||||||
(
|
(set_x(upper_left, x), bottom_right),
|
||||||
set_x(upper_left, x),
|
|
||||||
set_x(
|
|
||||||
bottom_right,
|
|
||||||
std::cmp::min(get_x(bottom_right), x + (self.data_columns.widths[i])),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
(0, top_idx),
|
(0, top_idx),
|
||||||
(column_width.saturating_sub(1), self.length - 1),
|
(column_width.saturating_sub(1), self.length - 1),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
x += self.data_columns.widths[i] + 2; // + SEPARATOR
|
x += column_width + 2; // + SEPARATOR
|
||||||
if x > get_x(bottom_right) {
|
if x > get_x(bottom_right) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -705,26 +735,9 @@ impl ListingTrait for CompactListing {
|
||||||
row_attr.fg,
|
row_attr.fg,
|
||||||
row_attr.bg,
|
row_attr.bg,
|
||||||
);
|
);
|
||||||
for x in flag_x
|
for x in flag_x..get_x(bottom_right) {
|
||||||
..std::cmp::min(
|
|
||||||
get_x(bottom_right),
|
|
||||||
flag_x + 2 + self.data_columns.widths[3],
|
|
||||||
)
|
|
||||||
{
|
|
||||||
grid[(x, get_y(upper_left) + r)].set_bg(row_attr.bg);
|
grid[(x, get_y(upper_left) + r)].set_bg(row_attr.bg);
|
||||||
}
|
}
|
||||||
change_colors(
|
|
||||||
grid,
|
|
||||||
(
|
|
||||||
(
|
|
||||||
flag_x + 2 + self.data_columns.widths[3],
|
|
||||||
get_y(upper_left) + r,
|
|
||||||
),
|
|
||||||
(get_x(bottom_right), get_y(upper_left) + r),
|
|
||||||
),
|
|
||||||
row_attr.fg,
|
|
||||||
row_attr.bg,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.highlight_line(
|
self.highlight_line(
|
||||||
|
@ -740,10 +753,7 @@ impl ListingTrait for CompactListing {
|
||||||
if top_idx + rows > self.length {
|
if top_idx + rows > self.length {
|
||||||
clear_area(
|
clear_area(
|
||||||
grid,
|
grid,
|
||||||
(
|
(pos_inc(upper_left, (0, rows)), bottom_right),
|
||||||
pos_inc(upper_left, (0, self.length - top_idx)),
|
|
||||||
bottom_right,
|
|
||||||
),
|
|
||||||
self.color_cache.theme_default,
|
self.color_cache.theme_default,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -946,44 +956,8 @@ impl CompactListing {
|
||||||
SubjectString(subject)
|
SubjectString(subject)
|
||||||
},
|
},
|
||||||
flag: FlagString(format!(
|
flag: FlagString(format!(
|
||||||
"{}{}{}{}",
|
"{selected}{snoozed}{unseen}{attachments}{whitespace}",
|
||||||
if thread.has_attachments() {
|
selected = if self.selection.get(&hash).cloned().unwrap_or(false) {
|
||||||
mailbox_settings!(
|
|
||||||
context[self.cursor_pos.0][&self.cursor_pos.1]
|
|
||||||
.listing
|
|
||||||
.attachment_flag
|
|
||||||
)
|
|
||||||
.as_ref()
|
|
||||||
.map(|s| s.as_str())
|
|
||||||
.unwrap_or(concat!("📎", emoji_text_presentation_selector!()))
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
},
|
|
||||||
if thread.snoozed() {
|
|
||||||
mailbox_settings!(
|
|
||||||
context[self.cursor_pos.0][&self.cursor_pos.1]
|
|
||||||
.listing
|
|
||||||
.thread_snoozed_flag
|
|
||||||
)
|
|
||||||
.as_ref()
|
|
||||||
.map(|s| s.as_str())
|
|
||||||
.unwrap_or(concat!("💤", emoji_text_presentation_selector!()))
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
},
|
|
||||||
if thread.unseen() > 0 {
|
|
||||||
mailbox_settings!(
|
|
||||||
context[self.cursor_pos.0][&self.cursor_pos.1]
|
|
||||||
.listing
|
|
||||||
.unseen_flag
|
|
||||||
)
|
|
||||||
.as_ref()
|
|
||||||
.map(|s| s.as_str())
|
|
||||||
.unwrap_or("●")
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
},
|
|
||||||
if self.selection.get(&hash).cloned().unwrap_or(false) {
|
|
||||||
mailbox_settings!(
|
mailbox_settings!(
|
||||||
context[self.cursor_pos.0][&self.cursor_pos.1]
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
.listing
|
.listing
|
||||||
|
@ -991,7 +965,52 @@ impl CompactListing {
|
||||||
)
|
)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| s.as_str())
|
.map(|s| s.as_str())
|
||||||
.unwrap_or(concat!("☑️", emoji_text_presentation_selector!()))
|
.unwrap_or(super::DEFAULT_SELECTED_FLAG)
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
},
|
||||||
|
snoozed = if thread.snoozed() {
|
||||||
|
mailbox_settings!(
|
||||||
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
|
.listing
|
||||||
|
.thread_snoozed_flag
|
||||||
|
)
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(super::DEFAULT_SNOOZED_FLAG)
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
},
|
||||||
|
unseen = if thread.unseen() > 0 {
|
||||||
|
mailbox_settings!(
|
||||||
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
|
.listing
|
||||||
|
.unseen_flag
|
||||||
|
)
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(super::DEFAULT_UNSEEN_FLAG)
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
},
|
||||||
|
attachments = if thread.has_attachments() {
|
||||||
|
mailbox_settings!(
|
||||||
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
|
.listing
|
||||||
|
.attachment_flag
|
||||||
|
)
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(super::DEFAULT_ATTACHMENT_FLAG)
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
},
|
||||||
|
whitespace = if self.selection.get(&hash).cloned().unwrap_or(false)
|
||||||
|
|| thread.unseen() > 0
|
||||||
|
|| thread.snoozed()
|
||||||
|
|| thread.has_attachments()
|
||||||
|
{
|
||||||
|
" "
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
},
|
},
|
||||||
|
@ -1022,6 +1041,44 @@ impl CompactListing {
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
let thread = threads.thread_ref(thread_hash);
|
let thread = threads.thread_ref(thread_hash);
|
||||||
let thread_node_hash = threads.thread_group_iter(thread_hash).next().unwrap().1;
|
let thread_node_hash = threads.thread_group_iter(thread_hash).next().unwrap().1;
|
||||||
|
|
||||||
|
let selected_flag_len = mailbox_settings!(
|
||||||
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
|
.listing
|
||||||
|
.selected_flag
|
||||||
|
)
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(super::DEFAULT_SELECTED_FLAG)
|
||||||
|
.grapheme_width();
|
||||||
|
let thread_snoozed_flag_len = mailbox_settings!(
|
||||||
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
|
.listing
|
||||||
|
.thread_snoozed_flag
|
||||||
|
)
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(super::DEFAULT_SNOOZED_FLAG)
|
||||||
|
.grapheme_width();
|
||||||
|
let unseen_flag_len = mailbox_settings!(
|
||||||
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
|
.listing
|
||||||
|
.unseen_flag
|
||||||
|
)
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(super::DEFAULT_UNSEEN_FLAG)
|
||||||
|
.grapheme_width();
|
||||||
|
let attachment_flag_len = mailbox_settings!(
|
||||||
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
|
.listing
|
||||||
|
.attachment_flag
|
||||||
|
)
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(super::DEFAULT_ATTACHMENT_FLAG)
|
||||||
|
.grapheme_width();
|
||||||
|
|
||||||
if let Some(env_hash) = threads.thread_nodes()[&thread_node_hash].message() {
|
if let Some(env_hash) = threads.thread_nodes()[&thread_node_hash].message() {
|
||||||
if !account.contains_key(env_hash) {
|
if !account.contains_key(env_hash) {
|
||||||
/* The envelope has been renamed or removed, so wait for the appropriate event to
|
/* The envelope has been renamed or removed, so wait for the appropriate event to
|
||||||
|
@ -1045,7 +1102,6 @@ impl CompactListing {
|
||||||
columns[1].size().0,
|
columns[1].size().0,
|
||||||
columns[2].size().0,
|
columns[2].size().0,
|
||||||
columns[3].size().0,
|
columns[3].size().0,
|
||||||
columns[4].size().0,
|
|
||||||
);
|
);
|
||||||
let (x, _) = write_string_to_grid(
|
let (x, _) = write_string_to_grid(
|
||||||
&idx.to_string(),
|
&idx.to_string(),
|
||||||
|
@ -1057,7 +1113,7 @@ impl CompactListing {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
for c in columns[0].row_iter(x..min_width.0, idx) {
|
for c in columns[0].row_iter(x..min_width.0, idx) {
|
||||||
columns[0][c].set_bg(row_attr.bg);
|
columns[0][c].set_bg(row_attr.bg).set_ch(' ');
|
||||||
}
|
}
|
||||||
let (x, _) = write_string_to_grid(
|
let (x, _) = write_string_to_grid(
|
||||||
&strings.date,
|
&strings.date,
|
||||||
|
@ -1069,7 +1125,7 @@ impl CompactListing {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
for c in columns[1].row_iter(x..min_width.1, idx) {
|
for c in columns[1].row_iter(x..min_width.1, idx) {
|
||||||
columns[1][c].set_bg(row_attr.bg);
|
columns[1][c].set_bg(row_attr.bg).set_ch(' ');
|
||||||
}
|
}
|
||||||
let (x, _) = write_string_to_grid(
|
let (x, _) = write_string_to_grid(
|
||||||
&strings.from,
|
&strings.from,
|
||||||
|
@ -1081,7 +1137,7 @@ impl CompactListing {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
for c in columns[2].row_iter(x..min_width.2, idx) {
|
for c in columns[2].row_iter(x..min_width.2, idx) {
|
||||||
columns[2][c].set_bg(row_attr.bg);
|
columns[2][c].set_bg(row_attr.bg).set_ch(' ');
|
||||||
}
|
}
|
||||||
let (x, _) = write_string_to_grid(
|
let (x, _) = write_string_to_grid(
|
||||||
&strings.flag,
|
&strings.flag,
|
||||||
|
@ -1092,66 +1148,70 @@ impl CompactListing {
|
||||||
((0, idx), (min_width.3, idx)),
|
((0, idx), (min_width.3, idx)),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
for c in columns[3].row_iter(x..min_width.3, idx) {
|
|
||||||
columns[3][c].set_bg(row_attr.bg);
|
|
||||||
}
|
|
||||||
let (x, _) = write_string_to_grid(
|
let (x, _) = write_string_to_grid(
|
||||||
&strings.subject,
|
&strings.subject,
|
||||||
&mut columns[4],
|
&mut columns[3],
|
||||||
row_attr.fg,
|
row_attr.fg,
|
||||||
row_attr.bg,
|
row_attr.bg,
|
||||||
row_attr.attrs,
|
row_attr.attrs,
|
||||||
((0, idx), (min_width.4, idx)),
|
((x, idx), (min_width.3, idx)),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
columns[3][(x, idx)].set_bg(row_attr.bg).set_ch(' ');
|
||||||
let x = {
|
let x = {
|
||||||
let mut x = x + 1;
|
let mut x = x + 1;
|
||||||
for (t, &color) in strings.tags.split_whitespace().zip(strings.tags.1.iter()) {
|
for (t, &color) in strings.tags.split_whitespace().zip(strings.tags.1.iter()) {
|
||||||
let color = color.unwrap_or(self.color_cache.tag_default.bg);
|
let color = color.unwrap_or(self.color_cache.tag_default.bg);
|
||||||
let (_x, _) = write_string_to_grid(
|
let (_x, _) = write_string_to_grid(
|
||||||
t,
|
t,
|
||||||
&mut columns[4],
|
&mut columns[3],
|
||||||
self.color_cache.tag_default.fg,
|
self.color_cache.tag_default.fg,
|
||||||
color,
|
color,
|
||||||
self.color_cache.tag_default.attrs,
|
self.color_cache.tag_default.attrs,
|
||||||
((x + 1, idx), (min_width.4, idx)),
|
((x + 1, idx), (min_width.3, idx)),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
for c in columns[4].row_iter(x..(x + 1), idx) {
|
for c in columns[3].row_iter(x..(x + 1), idx) {
|
||||||
columns[4][c].set_bg(color);
|
columns[3][c].set_bg(color);
|
||||||
}
|
}
|
||||||
for c in columns[4].row_iter(_x..(_x + 1), idx) {
|
for c in columns[3].row_iter(_x..(_x + 1), idx) {
|
||||||
columns[4][c].set_bg(color).set_keep_bg(true);
|
columns[3][c].set_bg(color).set_keep_bg(true);
|
||||||
}
|
}
|
||||||
for c in columns[4].row_iter((x + 1)..(_x + 1), idx) {
|
for c in columns[3].row_iter((x + 1)..(_x + 1), idx) {
|
||||||
columns[4][c]
|
columns[3][c]
|
||||||
.set_keep_fg(true)
|
.set_keep_fg(true)
|
||||||
.set_keep_bg(true)
|
.set_keep_bg(true)
|
||||||
.set_keep_attrs(true);
|
.set_keep_attrs(true);
|
||||||
}
|
}
|
||||||
for c in columns[4].row_iter(x..(x + 1), idx) {
|
for c in columns[3].row_iter(x..(x + 1), idx) {
|
||||||
columns[4][c].set_keep_bg(true);
|
columns[3][c].set_keep_bg(true);
|
||||||
}
|
}
|
||||||
x = _x + 1;
|
x = _x + 1;
|
||||||
|
columns[3][(x, idx)].set_bg(row_attr.bg).set_ch(' ');
|
||||||
}
|
}
|
||||||
x
|
x
|
||||||
};
|
};
|
||||||
for c in columns[4].row_iter(x..min_width.4, idx) {
|
for c in columns[3].row_iter(x..min_width.3, idx) {
|
||||||
columns[4][c].set_ch(' ');
|
columns[3][c].set_ch(' ').set_bg(row_attr.bg);
|
||||||
columns[4][c].set_bg(row_attr.bg);
|
|
||||||
}
|
}
|
||||||
match (thread.snoozed(), thread.has_attachments()) {
|
/* Set fg color for flags */
|
||||||
(true, true) => {
|
let mut x = 0;
|
||||||
columns[3][(0, idx)].set_fg(self.color_cache.attachment_flag.fg);
|
if self.selection.get(&thread_hash).cloned().unwrap_or(false) {
|
||||||
columns[3][(2, idx)].set_fg(self.color_cache.thread_snooze_flag.fg);
|
x += selected_flag_len;
|
||||||
|
}
|
||||||
|
if thread.snoozed() {
|
||||||
|
for x in x..(x + thread_snoozed_flag_len) {
|
||||||
|
columns[3][(x, idx)].set_fg(self.color_cache.thread_snooze_flag.fg);
|
||||||
}
|
}
|
||||||
(true, false) => {
|
x += thread_snoozed_flag_len;
|
||||||
columns[3][(0, idx)].set_fg(self.color_cache.thread_snooze_flag.fg);
|
}
|
||||||
|
if thread.unseen() > 0 {
|
||||||
|
x += unseen_flag_len;
|
||||||
|
}
|
||||||
|
if thread.has_attachments() {
|
||||||
|
for x in x..(x + attachment_flag_len) {
|
||||||
|
columns[3][(x, idx)].set_fg(self.color_cache.attachment_flag.fg);
|
||||||
}
|
}
|
||||||
(false, true) => {
|
|
||||||
columns[3][(0, idx)].set_fg(self.color_cache.attachment_flag.fg);
|
|
||||||
}
|
|
||||||
(false, false) => {}
|
|
||||||
}
|
}
|
||||||
*self.rows.get_mut(idx).unwrap() = ((idx, (thread_hash, env_hash)), strings);
|
*self.rows.get_mut(idx).unwrap() = ((idx, (thread_hash, env_hash)), strings);
|
||||||
self.rows_drawn.update(idx, 1);
|
self.rows_drawn.update(idx, 1);
|
||||||
|
@ -1176,12 +1236,48 @@ impl CompactListing {
|
||||||
self.data_columns.columns[1].size().0,
|
self.data_columns.columns[1].size().0,
|
||||||
self.data_columns.columns[2].size().0,
|
self.data_columns.columns[2].size().0,
|
||||||
self.data_columns.columns[3].size().0,
|
self.data_columns.columns[3].size().0,
|
||||||
self.data_columns.columns[4].size().0,
|
|
||||||
);
|
);
|
||||||
let account = &context.accounts[&self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
|
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
|
|
||||||
|
let selected_flag_len = mailbox_settings!(
|
||||||
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
|
.listing
|
||||||
|
.selected_flag
|
||||||
|
)
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(super::DEFAULT_SELECTED_FLAG)
|
||||||
|
.grapheme_width();
|
||||||
|
let thread_snoozed_flag_len = mailbox_settings!(
|
||||||
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
|
.listing
|
||||||
|
.thread_snoozed_flag
|
||||||
|
)
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(super::DEFAULT_SNOOZED_FLAG)
|
||||||
|
.grapheme_width();
|
||||||
|
let unseen_flag_len = mailbox_settings!(
|
||||||
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
|
.listing
|
||||||
|
.unseen_flag
|
||||||
|
)
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(super::DEFAULT_UNSEEN_FLAG)
|
||||||
|
.grapheme_width();
|
||||||
|
let attachment_flag_len = mailbox_settings!(
|
||||||
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
|
.listing
|
||||||
|
.attachment_flag
|
||||||
|
)
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(super::DEFAULT_ATTACHMENT_FLAG)
|
||||||
|
.grapheme_width();
|
||||||
|
|
||||||
for ((idx, (thread_hash, root_env_hash)), strings) in
|
for ((idx, (thread_hash, root_env_hash)), strings) in
|
||||||
self.rows.iter().skip(start).take(end - start + 1)
|
self.rows.iter().skip(start).take(end - start + 1)
|
||||||
{
|
{
|
||||||
|
@ -1265,26 +1361,21 @@ impl CompactListing {
|
||||||
((0, idx), (min_width.3, idx)),
|
((0, idx), (min_width.3, idx)),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
for x in x..min_width.3 {
|
|
||||||
self.data_columns.columns[3][(x, idx)]
|
|
||||||
.set_bg(row_attr.bg)
|
|
||||||
.set_attrs(row_attr.attrs);
|
|
||||||
}
|
|
||||||
let (x, _) = write_string_to_grid(
|
let (x, _) = write_string_to_grid(
|
||||||
&strings.subject,
|
&strings.subject,
|
||||||
&mut self.data_columns.columns[4],
|
&mut self.data_columns.columns[3],
|
||||||
row_attr.fg,
|
row_attr.fg,
|
||||||
row_attr.bg,
|
row_attr.bg,
|
||||||
row_attr.attrs,
|
row_attr.attrs,
|
||||||
((0, idx), (min_width.4, idx)),
|
((x, idx), (min_width.3, idx)),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
#[cfg(feature = "regexp")]
|
#[cfg(feature = "regexp")]
|
||||||
{
|
{
|
||||||
for text_formatter in crate::conf::text_format_regexps(context, "listing.subject") {
|
for text_formatter in crate::conf::text_format_regexps(context, "listing.subject") {
|
||||||
let t = self.data_columns.columns[4].insert_tag(text_formatter.tag);
|
let t = self.data_columns.columns[3].insert_tag(text_formatter.tag);
|
||||||
for (start, end) in text_formatter.regexp.find_iter(strings.subject.as_str()) {
|
for (start, end) in text_formatter.regexp.find_iter(strings.subject.as_str()) {
|
||||||
self.data_columns.columns[4].set_tag(t, (start, idx), (end, idx));
|
self.data_columns.columns[3].set_tag(t, (start, idx), (end, idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1294,52 +1385,56 @@ impl CompactListing {
|
||||||
let color = color.unwrap_or(self.color_cache.tag_default.bg);
|
let color = color.unwrap_or(self.color_cache.tag_default.bg);
|
||||||
let (_x, _) = write_string_to_grid(
|
let (_x, _) = write_string_to_grid(
|
||||||
t,
|
t,
|
||||||
&mut self.data_columns.columns[4],
|
&mut self.data_columns.columns[3],
|
||||||
self.color_cache.tag_default.fg,
|
self.color_cache.tag_default.fg,
|
||||||
color,
|
color,
|
||||||
self.color_cache.tag_default.attrs,
|
self.color_cache.tag_default.attrs,
|
||||||
((x + 1, idx), (min_width.4, idx)),
|
((x + 1, idx), (min_width.3, idx)),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
self.data_columns.columns[4][(x, idx)].set_bg(color);
|
self.data_columns.columns[3][(x, idx)].set_bg(color);
|
||||||
if _x < min_width.4 {
|
if _x < min_width.3 {
|
||||||
self.data_columns.columns[4][(_x, idx)]
|
self.data_columns.columns[3][(_x, idx)]
|
||||||
.set_bg(color)
|
.set_bg(color)
|
||||||
.set_keep_bg(true);
|
.set_keep_bg(true);
|
||||||
}
|
}
|
||||||
for x in (x + 1).._x {
|
for x in (x + 1).._x {
|
||||||
self.data_columns.columns[4][(x, idx)]
|
self.data_columns.columns[3][(x, idx)]
|
||||||
.set_keep_fg(true)
|
.set_keep_fg(true)
|
||||||
.set_keep_bg(true)
|
.set_keep_bg(true)
|
||||||
.set_keep_attrs(true);
|
.set_keep_attrs(true);
|
||||||
}
|
}
|
||||||
self.data_columns.columns[4][(x, idx)].set_keep_bg(true);
|
self.data_columns.columns[3][(x, idx)].set_keep_bg(true);
|
||||||
x = _x + 1;
|
x = _x + 1;
|
||||||
}
|
}
|
||||||
x
|
x
|
||||||
};
|
};
|
||||||
for x in x..min_width.4 {
|
for x in x..min_width.3 {
|
||||||
self.data_columns.columns[4][(x, idx)]
|
self.data_columns.columns[3][(x, idx)]
|
||||||
.set_ch(' ')
|
.set_ch(' ')
|
||||||
.set_bg(row_attr.bg)
|
.set_bg(row_attr.bg)
|
||||||
.set_attrs(row_attr.attrs);
|
.set_attrs(row_attr.attrs);
|
||||||
}
|
}
|
||||||
match (thread.snoozed(), thread.has_attachments()) {
|
/* Set fg color for flags */
|
||||||
(true, true) => {
|
let mut x = 0;
|
||||||
self.data_columns.columns[3][(0, idx)]
|
if self.selection.get(&thread_hash).cloned().unwrap_or(false) {
|
||||||
.set_fg(self.color_cache.attachment_flag.fg);
|
x += selected_flag_len;
|
||||||
self.data_columns.columns[3][(2, idx)]
|
}
|
||||||
|
if thread.snoozed() {
|
||||||
|
for x in x..(x + thread_snoozed_flag_len) {
|
||||||
|
self.data_columns.columns[3][(x, idx)]
|
||||||
.set_fg(self.color_cache.thread_snooze_flag.fg);
|
.set_fg(self.color_cache.thread_snooze_flag.fg);
|
||||||
}
|
}
|
||||||
(true, false) => {
|
x += thread_snoozed_flag_len;
|
||||||
self.data_columns.columns[3][(0, idx)]
|
}
|
||||||
.set_fg(self.color_cache.thread_snooze_flag.fg);
|
if thread.unseen() > 0 {
|
||||||
}
|
x += unseen_flag_len;
|
||||||
(false, true) => {
|
}
|
||||||
self.data_columns.columns[3][(0, idx)]
|
if thread.has_attachments() {
|
||||||
|
for x in x..(x + attachment_flag_len) {
|
||||||
|
self.data_columns.columns[3][(x, idx)]
|
||||||
.set_fg(self.color_cache.attachment_flag.fg);
|
.set_fg(self.color_cache.attachment_flag.fg);
|
||||||
}
|
}
|
||||||
(false, false) => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue