Fix ThreadView for new TUI API

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
pull/312/head
Manos Pitsidianakis 6 months ago
parent 1c1be7d6c9
commit 62b8465f2c
No known key found for this signature in database
GPG Key ID: 7729C7707F7E09D0

@ -30,7 +30,6 @@ use melib::{
use super::*; use super::*;
use crate::{ use crate::{
boundaries::*,
melib::text_processing::{TextProcessing, Truncate}, melib::text_processing::{TextProcessing, Truncate},
uuid::Uuid, uuid::Uuid,
}; };

@ -1347,7 +1347,6 @@ impl Component for Listing {
// Need to clear gap between sidebar and listing component, if any. // Need to clear gap between sidebar and listing component, if any.
self.dirty = true; self.dirty = true;
} }
self.set_dirty(matches!(new_value, Focus::EntryFullscreen));
} }
Some(ListingMessage::UpdateView) => { Some(ListingMessage::UpdateView) => {
self.view.set_dirty(true); self.view.set_dirty(true);

@ -21,7 +21,10 @@
use std::cmp; use std::cmp;
use melib::UnixTimestamp; use melib::{
utils::datetime::{timestamp_to_string, UnixTimestamp},
Address,
};
use super::*; use super::*;
use crate::components::PageMovement; use crate::components::PageMovement;
@ -60,7 +63,7 @@ pub struct ThreadView {
focus: ThreadViewFocus, focus: ThreadViewFocus,
entries: Vec<ThreadEntry>, entries: Vec<ThreadEntry>,
visible_entries: Vec<Vec<usize>>, visible_entries: Vec<Vec<usize>>,
indentation_colors: [ThemeAttribute; 6], //indentation_colors: [ThemeAttribute; 6],
use_color: bool, use_color: bool,
horizontal: Option<bool>, horizontal: Option<bool>,
movement: Option<PageMovement>, movement: Option<PageMovement>,
@ -70,13 +73,11 @@ pub struct ThreadView {
} }
impl ThreadView { impl ThreadView {
/* /// @coordinates: (account index, mailbox_hash, root set thread_node index)
* @coordinates: (account index, mailbox_hash, root set thread_node index) /// @expanded_hash: optional position of expanded entry when we render the
* @expanded_hash: optional position of expanded entry when we render the /// ThreadView.
* ThreadView. /// default: expanded message is the last one.
* default: expanded message is the last one. /// @context: current context
* @context: current context
*/
pub fn new( pub fn new(
coordinates: (AccountHash, MailboxHash, EnvelopeHash), coordinates: (AccountHash, MailboxHash, EnvelopeHash),
thread_group: ThreadHash, thread_group: ThreadHash,
@ -95,14 +96,14 @@ impl ThreadView {
new_cursor_pos: 0, new_cursor_pos: 0,
dirty: true, dirty: true,
id: ComponentId::default(), id: ComponentId::default(),
indentation_colors: [ //indentation_colors: [
crate::conf::value(context, "mail.view.thread.indentation.a"), // crate::conf::value(context, "mail.view.thread.indentation.a"),
crate::conf::value(context, "mail.view.thread.indentation.b"), // crate::conf::value(context, "mail.view.thread.indentation.b"),
crate::conf::value(context, "mail.view.thread.indentation.c"), // crate::conf::value(context, "mail.view.thread.indentation.c"),
crate::conf::value(context, "mail.view.thread.indentation.d"), // crate::conf::value(context, "mail.view.thread.indentation.d"),
crate::conf::value(context, "mail.view.thread.indentation.e"), // crate::conf::value(context, "mail.view.thread.indentation.e"),
crate::conf::value(context, "mail.view.thread.indentation.f"), // crate::conf::value(context, "mail.view.thread.indentation.f"),
], //],
use_color: context.settings.terminal.use_color(), use_color: context.settings.terminal.use_color(),
horizontal: None, horizontal: None,
..Default::default() ..Default::default()
@ -233,7 +234,7 @@ impl ThreadView {
total_entries.push((msg_hash, env_ref.timestamp)); total_entries.push((msg_hash, env_ref.timestamp));
}; };
} }
total_entries.sort_by_key(|e| std::cmp::Reverse(e.1)); total_entries.sort_by_key(|e| cmp::Reverse(e.1));
let tokens = f64::from(u32::try_from(total_entries.len()).unwrap_or(0)) * 0.29; let tokens = f64::from(u32::try_from(total_entries.len()).unwrap_or(0)) * 0.29;
let tokens = tokens.ceil() as usize; let tokens = tokens.ceil() as usize;
total_entries.truncate(tokens); total_entries.truncate(tokens);
@ -313,7 +314,7 @@ impl ThreadView {
self.expanded_pos = earliest_unread_entry + 1; self.expanded_pos = earliest_unread_entry + 1;
} }
let height = 2 * self.entries.len() + 1; let height = self.entries.len();
let mut width = 0; let mut width = 0;
let mut highlight_reply_subjects: Vec<Option<usize>> = let mut highlight_reply_subjects: Vec<Option<usize>> =
@ -323,35 +324,23 @@ impl ThreadView {
.collection .collection
.get_env(e.msg_hash); .get_env(e.msg_hash);
let thread_node = &threads.thread_nodes()[&e.index.1]; let thread_node = &threads.thread_nodes()[&e.index.1];
let string = if thread_node.show_subject() { let from = Address::display_name_slice(envelope.from());
let date = timestamp_to_string(envelope.date(), Some("%Y-%m-%d %H:%M\0"), true);
e.heading = if thread_node.show_subject() {
let subject = envelope.subject(); let subject = envelope.subject();
highlight_reply_subjects.push(Some(subject.grapheme_width())); highlight_reply_subjects.push(Some(subject.grapheme_width()));
format!( format!(
" {} - {} {}{}", "{date} {subject:`>indent$} {from}",
envelope.date_as_str(), indent = 2 * e.index.0 + subject.grapheme_width(),
envelope.field_from_to_string(),
envelope.subject(),
if envelope.has_attachments() {
" 📎"
} else {
""
},
) )
} else { } else {
highlight_reply_subjects.push(None); highlight_reply_subjects.push(None);
format!( format!(
" {} - {}{}", "{date} {from:`>indent$}",
envelope.date_as_str(), indent = 2 * e.index.0 + from.grapheme_width()
envelope.field_from_to_string(),
if envelope.has_attachments() {
" 📎"
} else {
""
},
) )
}; };
e.heading = string; width = width.max(e.heading.grapheme_width() + 1);
width = cmp::max(width, e.index.0 * 4 + e.heading.grapheme_width() + 2);
} }
if !self.content.resize_with_context(width, height, context) { if !self.content.resize_with_context(width, height, context) {
return; return;
@ -360,41 +349,11 @@ impl ThreadView {
let highlight_theme = crate::conf::value(context, "highlight"); let highlight_theme = crate::conf::value(context, "highlight");
if self.reversed { if self.reversed {
for (y, e) in self.entries.iter().rev().enumerate() { for (y, e) in self.entries.iter().rev().enumerate() {
/* Box character drawing stuff */
if y > 0
&& self
.content
.grid_mut()
.get_mut(e.index.0 * 4, 2 * y - 1)
.is_some()
{
let index = (e.index.0 * 4, 2 * y - 1);
if self.content.grid()[index].ch() == ' ' {
let mut ctr = 1;
while self
.content
.grid()
.get(e.index.0 * 4 + ctr, 2 * y - 1)
.is_some()
{
if self.content.grid()[(e.index.0 * 4 + ctr, 2 * y - 1)].ch() != ' ' {
break;
}
set_and_join_box(
self.content.grid_mut(),
(e.index.0 * 4 + ctr, 2 * y - 1),
BoxBoundary::Horizontal,
);
ctr += 1;
}
set_and_join_box(self.content.grid_mut(), index, BoxBoundary::Horizontal);
}
}
{ {
let area = self let area = self
.content .content
.area() .area()
.skip(e.index.0 * 4 + 1, 2 * y) .skip_rows(y)
.take(e.heading.grapheme_width() + 1, height - 1); .take(e.heading.grapheme_width() + 1, height - 1);
self.content.grid_mut().write_string( self.content.grid_mut().write_string(
&e.heading, &e.heading,
@ -413,89 +372,18 @@ impl ThreadView {
None, None,
); );
} }
if let Some(len) = highlight_reply_subjects[y] { if highlight_reply_subjects[y].is_some() {
let index = e.index.0 * 4 + 1 + e.heading.grapheme_width() - len; let area = self.content.area().skip_rows(y).take_rows(1);
//let area = ((index, 2 * y), (width - 2, 2 * y));
let area = self.content.area().skip(index, 2 * y).take_rows(1);
self.content.grid_mut().change_theme(area, highlight_theme); self.content.grid_mut().change_theme(area, highlight_theme);
} }
set_and_join_box(
self.content.grid_mut(),
(e.index.0 * 4, 2 * y),
BoxBoundary::Vertical,
);
set_and_join_box(
self.content.grid_mut(),
(e.index.0 * 4, 2 * y + 1),
BoxBoundary::Vertical,
);
for i in ((e.index.0 * 4) + 1)..width - 1 {
set_and_join_box(
self.content.grid_mut(),
(i, 2 * y + 1),
BoxBoundary::Horizontal,
);
}
set_and_join_box(
self.content.grid_mut(),
(width - 1, 2 * y),
BoxBoundary::Vertical,
);
set_and_join_box(
self.content.grid_mut(),
(width - 1, 2 * y + 1),
BoxBoundary::Vertical,
);
} }
} else { } else {
for (y, e) in self.entries.iter().enumerate() { for (y, e) in self.entries.iter().enumerate() {
/* Box character drawing stuff */
let mut x = 0;
for i in 0..e.index.0 {
let att =
self.indentation_colors[(i).wrapping_rem(self.indentation_colors.len())];
let area = self.content.area().skip(x, 2 * y).take(3, 1);
self.content.grid_mut().change_theme(area, att);
x += 4;
}
if y > 0
&& self
.content
.grid_mut()
.get_mut(e.index.0 * 4, 2 * y - 1)
.is_some()
{
let index = (e.index.0 * 4, 2 * y - 1);
if self.content.grid()[index].ch() == ' ' {
let mut ctr = 1;
self.content.grid_mut()[(e.index.0 * 4, 2 * y - 1)]
.set_bg(theme_default.bg);
while self
.content
.grid()
.get(e.index.0 * 4 + ctr, 2 * y - 1)
.is_some()
{
self.content.grid_mut()[(e.index.0 * 4 + ctr, 2 * y - 1)]
.set_bg(theme_default.bg);
if self.content.grid()[(e.index.0 * 4 + ctr, 2 * y - 1)].ch() != ' ' {
break;
}
set_and_join_box(
self.content.grid_mut(),
(e.index.0 * 4 + ctr, 2 * y - 1),
BoxBoundary::Horizontal,
);
ctr += 1;
}
set_and_join_box(self.content.grid_mut(), index, BoxBoundary::Horizontal);
}
}
{ {
let area = self let area = self
.content .content
.area() .area()
.skip(e.index.0 * 4 + 1, 2 * y) .skip_rows(y)
.take(e.heading.grapheme_width(), height - 1); .take(e.heading.grapheme_width(), height - 1);
self.content.grid_mut().write_string( self.content.grid_mut().write_string(
&e.heading, &e.heading,
@ -515,49 +403,9 @@ impl ThreadView {
); );
} }
if highlight_reply_subjects[y].is_some() { if highlight_reply_subjects[y].is_some() {
let index = e.index.0 * 4 + 1; let area = self.content.area().skip_rows(y).take(width - 2, y);
let area = self
.content
.area()
.skip(index, 2 * y)
.take(width - 2, 2 * y);
self.content.grid_mut().change_theme(area, highlight_theme); self.content.grid_mut().change_theme(area, highlight_theme);
} }
set_and_join_box(
self.content.grid_mut(),
(e.index.0 * 4, 2 * y),
BoxBoundary::Vertical,
);
set_and_join_box(
self.content.grid_mut(),
(e.index.0 * 4, 2 * y + 1),
BoxBoundary::Vertical,
);
for i in ((e.index.0 * 4) + 1)..width - 1 {
set_and_join_box(
self.content.grid_mut(),
(i, 2 * y + 1),
BoxBoundary::Horizontal,
);
}
set_and_join_box(
self.content.grid_mut(),
(width - 1, 2 * y),
BoxBoundary::Vertical,
);
set_and_join_box(
self.content.grid_mut(),
(width - 1, 2 * y + 1),
BoxBoundary::Vertical,
);
}
for y in 0..height - 1 {
set_and_join_box(
self.content.grid_mut(),
(width - 1, y),
BoxBoundary::Vertical,
);
} }
} }
self.visible_entries = vec![(0..self.entries.len()).collect()]; self.visible_entries = vec![(0..self.entries.len()).collect()];
@ -650,20 +498,11 @@ impl ThreadView {
let page_no = (self.new_cursor_pos).wrapping_div(rows); let page_no = (self.new_cursor_pos).wrapping_div(rows);
let top_idx = page_no * rows; let top_idx = page_no * rows;
/* returns the **line** of an entry in the ThreadView grid. */ // returns the **line** of an entry in the ThreadView grid.
let get_entry_area = |idx: usize, entries: &[ThreadEntry]| { let get_entry_area = |idx: usize| self.content.area().skip_rows(idx).take_rows(1);
let entries = &entries;
let visual_indentation = entries[idx].index.0 * 4;
self.content.area().skip(visual_indentation, 2 * idx).take(
visual_indentation + entries[idx].heading.grapheme_width() + 1,
2 * idx,
)
};
if self.dirty || (page_no != prev_page_no) { if self.dirty || (page_no != prev_page_no) {
if page_no != prev_page_no { grid.clear_area(area, crate::conf::value(context, "theme_default"));
grid.clear_area(area, crate::conf::value(context, "theme_default"));
}
let visibles: Vec<&usize> = let visibles: Vec<&usize> =
self.visible_entries.iter().flat_map(|v| v.iter()).collect(); self.visible_entries.iter().flat_map(|v| v.iter()).collect();
@ -675,25 +514,19 @@ impl ThreadView {
grid.copy_area( grid.copy_area(
self.content.grid(), self.content.grid(),
area.skip_rows(2 * visible_entry_counter), area.skip_rows(visible_entry_counter).take_rows(1),
self.content.area().nth_row(2 * idx), self.content.area().skip_rows(*idx).take_rows(1),
); );
} }
/* If cursor position has changed, remove the highlight from the previous // If cursor position has changed, remove the highlight from the previous
* position and apply it in the new one. */ // position and apply it in the new one.
self.cursor_pos = self.new_cursor_pos; self.cursor_pos = self.new_cursor_pos;
if self.cursor_pos + 1 > visibles.len() { if self.cursor_pos + 1 > visibles.len() {
self.cursor_pos = visibles.len().saturating_sub(1); self.cursor_pos = visibles.len().saturating_sub(1);
} }
let idx = *visibles[self.cursor_pos]; let idx = *visibles[self.cursor_pos];
let src_area = get_entry_area(idx, &self.entries); let src_area = get_entry_area(idx);
let visual_indentation = self.entries[idx].indentation * 4; let dest_area = area.skip_rows(self.cursor_pos - top_idx).take_rows(1);
let dest_area = area
.skip(visual_indentation, 2 * (self.cursor_pos - top_idx))
.take(
visual_indentation + self.entries[idx].heading.grapheme_width() + 1,
2 * (self.cursor_pos - top_idx),
);
self.highlight_line(grid, dest_area, src_area, idx, context); self.highlight_line(grid, dest_area, src_area, idx, context);
if rows < visibles.len() { if rows < visibles.len() {
@ -701,34 +534,28 @@ impl ThreadView {
grid, grid,
area.nth_col(area.width().saturating_sub(1)), area.nth_col(area.width().saturating_sub(1)),
context, context,
2 * self.cursor_pos, self.cursor_pos,
rows, rows,
2 * visibles.len() + 1, visibles.len(),
); );
} }
if 2 * top_idx + rows > 2 * visibles.len() + 1 { if top_idx + rows > visibles.len() {
grid.clear_area( grid.clear_area(
area.skip_rows(2 * (visibles.len() - top_idx) + 1), area.skip_rows(visibles.len() - top_idx),
crate::conf::value(context, "theme_default"), crate::conf::value(context, "theme_default"),
); );
} }
} else { } else {
let old_cursor_pos = self.cursor_pos; let old_cursor_pos = self.cursor_pos;
self.cursor_pos = self.new_cursor_pos; self.cursor_pos = self.new_cursor_pos;
/* If cursor position has changed, remove the highlight from the previous // If cursor position has changed, remove the highlight from the previous
* position and apply it in the new one. */ // position and apply it in the new one.
let visibles: Vec<&usize> = let visibles: Vec<&usize> =
self.visible_entries.iter().flat_map(|v| v.iter()).collect(); self.visible_entries.iter().flat_map(|v| v.iter()).collect();
for &idx in &[old_cursor_pos, self.cursor_pos] { for &idx in &[old_cursor_pos, self.cursor_pos] {
let entry_idx = *visibles[idx]; let entry_idx = *visibles[idx];
let src_area = get_entry_area(entry_idx, &self.entries); let src_area = get_entry_area(entry_idx);
let visual_indentation = self.entries[entry_idx].indentation * 4; let dest_area = area.skip_rows(visibles[..idx].len() - top_idx).take_rows(1);
let dest_area = area
.skip(visual_indentation, 2 * (visibles[..idx].len() - top_idx))
.take(
visual_indentation + self.entries[entry_idx].heading.grapheme_width() + 1,
2 * (visibles[..idx].len() - top_idx),
);
self.highlight_line(grid, dest_area, src_area, entry_idx, context); self.highlight_line(grid, dest_area, src_area, entry_idx, context);
if rows < visibles.len() { if rows < visibles.len() {
@ -736,9 +563,9 @@ impl ThreadView {
grid, grid,
area.nth_col(area.width().saturating_sub(1)), area.nth_col(area.width().saturating_sub(1)),
context, context,
2 * self.cursor_pos, self.cursor_pos,
rows, rows,
2 * visibles.len() + 1, visibles.len(),
); );
} }
} }
@ -750,11 +577,11 @@ impl ThreadView {
if self.entries.is_empty() { if self.entries.is_empty() {
return; return;
} }
let mid = area.width() / 2; //get_x(upper_left) + self.content.size().0; let mid = self.content.area().width().min(area.width() / 2);
let theme_default = crate::conf::value(context, "theme_default"); let theme_default = crate::conf::value(context, "theme_default");
/* First draw the thread subject on the first row */ // First draw the thread subject on the first row
let y = if self.dirty { if self.dirty {
grid.clear_area(area, theme_default); grid.clear_area(area, theme_default);
let account = &context.accounts[&self.coordinates.0]; let account = &context.accounts[&self.coordinates.0];
let threads = account.collection.get_threads(self.coordinates.1); let threads = account.collection.get_threads(self.coordinates.1);
@ -771,37 +598,25 @@ impl ThreadView {
let (_, y) = grid.write_string( let (_, y) = grid.write_string(
&envelope.subject(), &envelope.subject(),
crate::conf::value(context, "highlight").fg, theme_default.fg,
theme_default.bg, theme_default.bg,
theme_default.attrs, theme_default.attrs,
area, area,
Some(0), Some(0),
); );
context.dirty_areas.push_back(area); context.dirty_areas.push_back(area);
grid.clear_area(area.nth_col(mid), theme_default);
grid.clear_area(area.skip(mid, y + 1), theme_default); grid.clear_area(area.skip(mid, y + 1), theme_default);
y + 2
} else {
2
}; };
let area = area.skip_rows(2);
let (width, height) = self.content.area().size(); let (width, height) = self.content.area().size();
if height == 0 || width == 0 { if height == 0 || width == 0 {
return; return;
} }
for x in get_x(area.upper_left())..=get_x(area.bottom_right()) {
set_and_join_box(grid, (x, y - 1), BoxBoundary::Horizontal);
grid[(x, y - 1)]
.set_fg(theme_default.fg)
.set_bg(theme_default.bg);
}
match self.focus { match self.focus {
ThreadViewFocus::None => { ThreadViewFocus::None => {
self.draw_list( self.draw_list(grid, area.take_cols(mid.saturating_sub(1)), context);
grid,
area.skip_rows(y).take_cols(mid.saturating_sub(1)),
context,
);
self.entries[self.new_expanded_pos].mailview.draw( self.entries[self.new_expanded_pos].mailview.draw(
grid, grid,
area.skip_cols(mid + 1), area.skip_cols(mid + 1),
@ -809,8 +624,8 @@ impl ThreadView {
); );
} }
ThreadViewFocus::Thread => { ThreadViewFocus::Thread => {
grid.clear_area(area.skip(mid + 1, y - 1), theme_default); grid.clear_area(area.skip_cols(mid + 1), theme_default);
self.draw_list(grid, area.skip_rows(y), context); self.draw_list(grid, area, context);
} }
ThreadViewFocus::MailView => { ThreadViewFocus::MailView => {
self.entries[self.new_expanded_pos] self.entries[self.new_expanded_pos]
@ -818,164 +633,165 @@ impl ThreadView {
.draw(grid, area, context); .draw(grid, area, context);
} }
} }
context.dirty_areas.push_back(area);
} }
fn draw_horz(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { //fn draw_horz(&mut self, grid: &mut CellBuffer, area: Area, context: &mut
if self.entries.is_empty() { // Context) { if self.entries.is_empty() {
return; // return;
} // }
let upper_left = area.upper_left(); // let upper_left = area.upper_left();
let bottom_right = area.bottom_right(); // let bottom_right = area.bottom_right();
let total_rows = area.height(); // let total_rows = area.height();
let pager_ratio = *mailbox_settings!( // let pager_ratio = *mailbox_settings!(
context[self.coordinates.0][&self.coordinates.1] // context[self.coordinates.0][&self.coordinates.1]
.pager // .pager
.pager_ratio // .pager_ratio
); // );
let mut bottom_entity_rows = (pager_ratio * total_rows) / 100; // let mut bottom_entity_rows = (pager_ratio * total_rows) / 100;
if bottom_entity_rows > total_rows { // if bottom_entity_rows > total_rows {
bottom_entity_rows = total_rows.saturating_sub(1); // bottom_entity_rows = total_rows.saturating_sub(1);
} // }
let mut mid = get_y(upper_left) + total_rows - bottom_entity_rows; // let mut mid = get_y(upper_left) + total_rows - bottom_entity_rows;
if mid >= get_y(bottom_right) { // if mid >= get_y(bottom_right) {
mid = get_y(bottom_right) / 2; // mid = get_y(bottom_right) / 2;
} // }
let mid = mid; // let mid = mid;
let theme_default = crate::conf::value(context, "theme_default"); // let theme_default = crate::conf::value(context, "theme_default");
/* First draw the thread subject on the first row */ // // First draw the thread subject on the first row
let y = { // let y = {
grid.clear_area(area, theme_default); // grid.clear_area(area, theme_default);
let account = &context.accounts[&self.coordinates.0]; // let account = &context.accounts[&self.coordinates.0];
let threads = account.collection.get_threads(self.coordinates.1); // let threads = account.collection.get_threads(self.coordinates.1);
let thread_root = threads.thread_iter(self.thread_group).next().unwrap().1; // let thread_root =
let thread_node = &threads.thread_nodes()[&thread_root]; // threads.thread_iter(self.thread_group).next().unwrap().1; let
let i = thread_node.message().unwrap_or_else(|| { // thread_node = &threads.thread_nodes()[&thread_root]; let i =
let mut iter_ptr = thread_node.children()[0]; // thread_node.message().unwrap_or_else(|| { let mut iter_ptr =
while threads.thread_nodes()[&iter_ptr].message().is_none() { // thread_node.children()[0]; while
iter_ptr = threads.thread_nodes()[&iter_ptr].children()[0]; // threads.thread_nodes()[&iter_ptr].message().is_none() {
} // iter_ptr = threads.thread_nodes()[&iter_ptr].children()[0]; }
threads.thread_nodes()[&iter_ptr].message().unwrap() // threads.thread_nodes()[&iter_ptr].message().unwrap()
}); // });
let envelope: EnvelopeRef = account.collection.get_env(i); // let envelope: EnvelopeRef = account.collection.get_env(i);
let (x, y) = grid.write_string( // let (x, y) = grid.write_string(
&envelope.subject(), // &envelope.subject(),
theme_default.fg, // theme_default.fg,
theme_default.bg, // theme_default.bg,
theme_default.attrs, // theme_default.attrs,
area, // area,
Some(get_x(upper_left)), // Some(get_x(upper_left)),
); // );
for x in x..=get_x(bottom_right) { // for x in x..=get_x(bottom_right) {
grid[(x, y)] // grid[(x, y)]
.set_ch(' ') // .set_ch(' ')
.set_fg(theme_default.fg) // .set_fg(theme_default.fg)
.set_bg(theme_default.bg); // .set_bg(theme_default.bg);
} // }
context.dirty_areas.push_back(area); // context.dirty_areas.push_back(area);
y + 2 // y + 2
}; // };
for x in get_x(upper_left)..=get_x(bottom_right) { // for x in get_x(upper_left)..=get_x(bottom_right) {
set_and_join_box(grid, (x, y - 1), BoxBoundary::Horizontal); // set_and_join_box(grid, (x, y - 1), BoxBoundary::Horizontal);
grid[(x, y - 1)] // grid[(x, y - 1)]
.set_fg(theme_default.fg) // .set_fg(theme_default.fg)
.set_bg(theme_default.bg); // .set_bg(theme_default.bg);
} // }
let (width, height) = self.content.area().size(); // let (width, height) = self.content.area().size();
if height == 0 || height == self.cursor_pos || width == 0 { // if height == 0 || height == self.cursor_pos || width == 0 {
return; // return;
} // }
grid.clear_area(area.skip_rows(y).take_rows(mid + 1), theme_default); // grid.clear_area(area.skip_rows(y).take_rows(mid + 1), theme_default);
match self.focus { // match self.focus {
ThreadViewFocus::None => { // ThreadViewFocus::None => {
let area = area.skip_rows(y).take_rows(mid); // let area = area.skip_rows(y).take_rows(mid);
let rows = area.height() / 2; // let rows = area.height() / 2;
if rows == 0 { // if rows == 0 {
return; // return;
} // }
let page_no = (self.new_cursor_pos).wrapping_div(rows); // let page_no = (self.new_cursor_pos).wrapping_div(rows);
let top_idx = page_no * rows; // let top_idx = page_no * rows;
grid.copy_area( // grid.copy_area(
self.content.grid(), // self.content.grid(),
area, // area,
self.content.area().skip_rows(2 * top_idx), // self.content.area().skip_rows(top_idx),
); // );
context.dirty_areas.push_back(area); // context.dirty_areas.push_back(area);
} // }
ThreadViewFocus::Thread => { // ThreadViewFocus::Thread => {
let area = { // let area = {
let val = area.skip_rows(y); // let val = area.skip_rows(y);
if val.height() < 20 { // if val.height() < 20 {
area // area
} else { // } else {
val // val
} // }
}; // };
let rows = area.height() / 2; // let rows = area.height() / 2;
if rows == 0 { // if rows == 0 {
return; // return;
} // }
let page_no = (self.new_cursor_pos).wrapping_div(rows); // let page_no = (self.new_cursor_pos).wrapping_div(rows);
let top_idx = page_no * rows; // let top_idx = page_no * rows;
grid.copy_area( // grid.copy_area(
self.content.grid(), // self.content.grid(),
area, // area,
self.content.area().skip_rows(2 * top_idx), // self.content.area().skip_rows(top_idx),
); // );
context.dirty_areas.push_back(area); // context.dirty_areas.push_back(area);
} // }
ThreadViewFocus::MailView => { /* show only envelope */ } // ThreadViewFocus::MailView => { /* show only envelope */ }
} // }
match self.focus { // match self.focus {
ThreadViewFocus::None => { // ThreadViewFocus::None => {
{ // {
let area = { // let area = {
let val = area.skip_rows(mid); // let val = area.skip_rows(mid);
if val.height() < 20 { // if val.height() < 20 {
area // area
} else { // } else {
val // val
} // }
}; // };
context.dirty_areas.push_back(area); // context.dirty_areas.push_back(area);
for x in get_x(area.upper_left())..=get_x(area.bottom_right()) { // for x in get_x(area.upper_left())..=get_x(area.bottom_right())
set_and_join_box(grid, (x, mid), BoxBoundary::Horizontal); // { set_and_join_box(grid, (x, mid),
grid[(x, mid)] // BoxBoundary::Horizontal); grid[(x, mid)]
.set_fg(theme_default.fg) // .set_fg(theme_default.fg)
.set_bg(theme_default.bg); // .set_bg(theme_default.bg);
} // }
} // }
{ // {
let area = area.skip_rows(y).take_rows(mid - 1); // let area = area.skip_rows(y).take_rows(mid - 1);
self.draw_list(grid, area, context); // self.draw_list(grid, area, context);
} // }
let area = area.take_rows(mid); // let area = area.take_rows(mid);
self.entries[self.new_expanded_pos] // self.entries[self.new_expanded_pos]
.mailview // .mailview
.draw(grid, area, context); // .draw(grid, area, context);
} // }
ThreadViewFocus::Thread => { // ThreadViewFocus::Thread => {
self.dirty = true; // self.dirty = true;
self.draw_list(grid, area.skip_rows(y), context); // self.draw_list(grid, area.skip_rows(y), context);
} // }
ThreadViewFocus::MailView => { // ThreadViewFocus::MailView => {
self.entries[self.new_expanded_pos] // self.entries[self.new_expanded_pos]
.mailview // .mailview
.draw(grid, area, context); // .draw(grid, area, context);
} // }
} // }
} //}
fn recalc_visible_entries(&mut self) { fn recalc_visible_entries(&mut self) {
if self.entries.is_empty() { if self.entries.is_empty() {
@ -1059,16 +875,14 @@ impl std::fmt::Display for ThreadView {
impl Component for ThreadView { impl Component for ThreadView {
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
let total_cols = area.width();
if self.entries.is_empty() { if self.entries.is_empty() {
self.dirty = false; self.set_dirty(false);
return;
} }
if !self.is_dirty() { if !self.is_dirty() {
return; return;
} }
/* If user has selected another mail to view, change to it */ // If user has selected another mail to view, change to it
if self.new_expanded_pos != self.expanded_pos { if self.new_expanded_pos != self.expanded_pos {
self.expanded_pos = self.new_expanded_pos; self.expanded_pos = self.new_expanded_pos;
} }
@ -1077,20 +891,15 @@ impl Component for ThreadView {
self.entries[self.new_expanded_pos] self.entries[self.new_expanded_pos]
.mailview .mailview
.draw(grid, area, context); .draw(grid, area, context);
} else if self
.horizontal
.unwrap_or(total_cols >= self.content.area().width() + 74)
{
self.draw_horz(grid, area, context);
} else { } else {
self.draw_vert(grid, area, context); self.draw_vert(grid, area, context);
} }
self.dirty = false; self.set_dirty(false);
} }
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if let (UIEvent::Action(Listing(OpenInNewTab)), false) = (&event, self.entries.is_empty()) { if let (UIEvent::Action(Listing(OpenInNewTab)), false) = (&event, self.entries.is_empty()) {
/* Handle this before self.mailview does */ // Handle this before self.mailview does
let mut new_tab = Self::new( let mut new_tab = Self::new(
self.coordinates, self.coordinates,
self.thread_group, self.thread_group,
@ -1231,7 +1040,7 @@ impl Component for ThreadView {
{ {
let visible_entries: Vec<&usize> = let visible_entries: Vec<&usize> =
self.visible_entries.iter().flat_map(|v| v.iter()).collect(); self.visible_entries.iter().flat_map(|v| v.iter()).collect();
/* search_old_cursor_pos */ // search_old_cursor_pos
self.new_cursor_pos = self.new_cursor_pos =
(|entries: Vec<&usize>, x: usize| { (|entries: Vec<&usize>, x: usize| {
let mut low = 0; let mut low = 0;
@ -1315,10 +1124,8 @@ impl Component for ThreadView {
fn set_dirty(&mut self, value: bool) { fn set_dirty(&mut self, value: bool) {
self.dirty = value; self.dirty = value;
if !self.entries.is_empty() { if let Some(entry) = self.entries.get_mut(self.new_expanded_pos) {
self.entries[self.new_expanded_pos] entry.mailview.set_dirty(value);
.mailview
.set_dirty(value);
} }
} }

Loading…
Cancel
Save