Create MailView to replace pager in MailListing
parent
7ed707a309
commit
dcb1fe6c3a
|
@ -18,9 +18,9 @@ pub struct MailListing {
|
||||||
content: CellBuffer,
|
content: CellBuffer,
|
||||||
/// If we must redraw on next redraw event
|
/// If we must redraw on next redraw event
|
||||||
dirty: bool,
|
dirty: bool,
|
||||||
/// If `self.pager` exists or not.
|
/// If `self.view` exists or not.
|
||||||
unfocused: bool,
|
unfocused: bool,
|
||||||
pager: Option<Pager>,
|
view: Option<MailView>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MailListing {
|
impl MailListing {
|
||||||
|
@ -39,7 +39,7 @@ impl MailListing {
|
||||||
content: content,
|
content: content,
|
||||||
dirty: true,
|
dirty: true,
|
||||||
unfocused: false,
|
unfocused: false,
|
||||||
pager: None,
|
view: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Fill the `self.content` `CellBuffer` with the contents of the account folder the user has
|
/// Fill the `self.content` `CellBuffer` with the contents of the account folder the user has
|
||||||
|
@ -126,7 +126,7 @@ impl MailListing {
|
||||||
} else {
|
} else {
|
||||||
Color::Default
|
Color::Default
|
||||||
};
|
};
|
||||||
let (x, y) = write_string_to_grid(&MailListing::make_thread_entry(envelope, idx, indentation, container, &indentations, len),
|
let (x, _) = write_string_to_grid(&MailListing::make_thread_entry(envelope, idx, indentation, container, &indentations, len),
|
||||||
&mut content,
|
&mut content,
|
||||||
fg_color,
|
fg_color,
|
||||||
bg_color,
|
bg_color,
|
||||||
|
@ -272,23 +272,6 @@ impl MailListing {
|
||||||
context.dirty_areas.push_back(area);
|
context.dirty_areas.push_back(area);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a pager for the `Envelope` currently under the cursor.
|
|
||||||
fn draw_mail_view(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
|
||||||
{
|
|
||||||
let envelope_idx: usize = {
|
|
||||||
let threaded = context.accounts[self.cursor_pos.0].runtime_settings.threaded;
|
|
||||||
let mailbox = &mut context.accounts[self.cursor_pos.0][self.cursor_pos.1].as_ref().unwrap().as_ref().unwrap();
|
|
||||||
if threaded {
|
|
||||||
mailbox.threaded_mail(self.cursor_pos.2)
|
|
||||||
} else {
|
|
||||||
self.cursor_pos.2
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.pager = Some(Pager::from_envelope((self.cursor_pos.0, self.cursor_pos.1), envelope_idx, context));
|
|
||||||
}
|
|
||||||
self.pager.as_mut().map(|p| p.draw(grid, area, context));
|
|
||||||
}
|
|
||||||
fn make_thread_entry(envelope: &Envelope, idx: usize, indent: usize,
|
fn make_thread_entry(envelope: &Envelope, idx: usize, indent: usize,
|
||||||
container: &Container, indentations: &Vec<bool>, idx_width: usize) -> String {
|
container: &Container, indentations: &Vec<bool>, idx_width: usize) -> String {
|
||||||
let has_sibling = container.has_sibling();
|
let has_sibling = container.has_sibling();
|
||||||
|
@ -341,7 +324,6 @@ impl MailListing {
|
||||||
format!("{} days ago{}", n / (24*60*60), " ".repeat(9))
|
format!("{} days ago{}", n / (24*60*60), " ".repeat(9))
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let date = envelope.datetime();
|
|
||||||
envelope.datetime().format("%Y-%m-%d %H:%M:%S").to_string()
|
envelope.datetime().format("%Y-%m-%d %H:%M:%S").to_string()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -358,9 +340,7 @@ impl Component for MailListing {
|
||||||
}
|
}
|
||||||
self.dirty = false;
|
self.dirty = false;
|
||||||
/* Draw the entire list */
|
/* Draw the entire list */
|
||||||
self.draw_list(grid,
|
self.draw_list(grid, area, context);
|
||||||
area,
|
|
||||||
context);
|
|
||||||
} else {
|
} else {
|
||||||
let upper_left = upper_left!(area);
|
let upper_left = upper_left!(area);
|
||||||
let bottom_right = bottom_right!(area);
|
let bottom_right = bottom_right!(area);
|
||||||
|
@ -371,7 +351,7 @@ impl Component for MailListing {
|
||||||
|
|
||||||
/* Render the mail body in a pager, basically copy what HSplit does */
|
/* Render the mail body in a pager, basically copy what HSplit does */
|
||||||
let total_rows = get_y(bottom_right) - get_y(upper_left);
|
let total_rows = get_y(bottom_right) - get_y(upper_left);
|
||||||
let pager_ratio = context.settings.pager.pager_ratio;
|
let pager_ratio = context.runtime_settings.pager.pager_ratio;
|
||||||
let bottom_entity_rows = (pager_ratio*total_rows )/100;
|
let bottom_entity_rows = (pager_ratio*total_rows )/100;
|
||||||
|
|
||||||
if bottom_entity_rows > total_rows {
|
if bottom_entity_rows > total_rows {
|
||||||
|
@ -398,99 +378,17 @@ impl Component for MailListing {
|
||||||
for i in get_x(upper_left)..=get_x(bottom_right) {
|
for i in get_x(upper_left)..=get_x(bottom_right) {
|
||||||
grid[(i, mid)].set_ch('─');
|
grid[(i, mid)].set_ch('─');
|
||||||
}
|
}
|
||||||
|
context.dirty_areas.push_back((set_y(upper_left, mid), set_y(bottom_right, mid)));
|
||||||
}
|
}
|
||||||
// TODO: Make headers view configurable
|
// TODO: Make headers view configurable
|
||||||
|
|
||||||
/* Draw header */
|
|
||||||
let y =
|
|
||||||
{
|
|
||||||
let threaded = context.accounts[self.cursor_pos.0].runtime_settings.threaded;
|
|
||||||
let mailbox = &mut context.accounts[self.cursor_pos.0][self.cursor_pos.1].as_ref().unwrap().as_ref().unwrap();
|
|
||||||
let envelope: &Envelope = if threaded {
|
|
||||||
let i = mailbox.threaded_mail(self.cursor_pos.2);
|
|
||||||
&mailbox.collection[i]
|
|
||||||
} else {
|
|
||||||
&mailbox.collection[self.cursor_pos.2]
|
|
||||||
};
|
|
||||||
|
|
||||||
let (x,y) = write_string_to_grid(&format!("Date: {}", envelope.date_as_str()),
|
|
||||||
grid,
|
|
||||||
Color::Byte(33),
|
|
||||||
Color::Default,
|
|
||||||
(set_y(upper_left, mid+1), bottom_right),
|
|
||||||
true);
|
|
||||||
for x in x..=get_x(bottom_right) {
|
|
||||||
grid[(x, y)].set_ch(' ');
|
|
||||||
grid[(x, y)].set_bg(Color::Default);
|
|
||||||
grid[(x, y)].set_fg(Color::Default);
|
|
||||||
}
|
|
||||||
let (x,y) = write_string_to_grid(&format!("From: {}", envelope.from()),
|
|
||||||
grid,
|
|
||||||
Color::Byte(33),
|
|
||||||
Color::Default,
|
|
||||||
(set_y(upper_left, y+1), bottom_right),
|
|
||||||
true);
|
|
||||||
for x in x..=get_x(bottom_right) {
|
|
||||||
grid[(x, y)].set_ch(' ');
|
|
||||||
grid[(x, y)].set_bg(Color::Default);
|
|
||||||
grid[(x, y)].set_fg(Color::Default);
|
|
||||||
}
|
|
||||||
let (x,y) = write_string_to_grid(&format!("To: {}", envelope.to()),
|
|
||||||
grid,
|
|
||||||
Color::Byte(33),
|
|
||||||
Color::Default,
|
|
||||||
(set_y(upper_left, y+1), bottom_right),
|
|
||||||
true);
|
|
||||||
for x in x..=get_x(bottom_right) {
|
|
||||||
grid[(x, y)].set_ch(' ');
|
|
||||||
grid[(x, y)].set_bg(Color::Default);
|
|
||||||
grid[(x, y)].set_fg(Color::Default);
|
|
||||||
}
|
|
||||||
let (x,y) = write_string_to_grid(&format!("Subject: {}", envelope.subject()),
|
|
||||||
grid,
|
|
||||||
Color::Byte(33),
|
|
||||||
Color::Default,
|
|
||||||
(set_y(upper_left, y+1), bottom_right),
|
|
||||||
true);
|
|
||||||
for x in x..=get_x(bottom_right) {
|
|
||||||
grid[(x, y)].set_ch(' ');
|
|
||||||
grid[(x, y)].set_bg(Color::Default);
|
|
||||||
grid[(x, y)].set_fg(Color::Default);
|
|
||||||
}
|
|
||||||
let (x, y) = write_string_to_grid(&format!("Message-ID: {}", envelope.message_id_raw()),
|
|
||||||
grid,
|
|
||||||
Color::Byte(33),
|
|
||||||
Color::Default,
|
|
||||||
(set_y(upper_left, y+1), bottom_right),
|
|
||||||
true);
|
|
||||||
for x in x..=get_x(bottom_right) {
|
|
||||||
grid[(x, y)].set_ch(' ');
|
|
||||||
grid[(x, y)].set_bg(Color::Default);
|
|
||||||
grid[(x, y)].set_fg(Color::Default);
|
|
||||||
}
|
|
||||||
clear_area(grid,
|
|
||||||
(set_y(upper_left, y+1), set_y(bottom_right, y+2)));
|
|
||||||
context.dirty_areas.push_back((set_y(upper_left, mid), set_y(bottom_right, y+1)));
|
|
||||||
y + 2
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
if !self.dirty {
|
if !self.dirty {
|
||||||
if let Some(ref mut p) = self.pager {
|
self.view.as_mut().map(|v| v.draw(grid, (set_y(upper_left, mid + 1), bottom_right), context));
|
||||||
p.draw(grid,
|
|
||||||
((get_x(upper_left), y), bottom_right),
|
|
||||||
context);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
self.view = Some(MailView::new(self.cursor_pos, None, None));
|
||||||
|
self.view.as_mut().map(|v| v.draw(grid, (set_y(upper_left, mid + 1), bottom_right), context));
|
||||||
self.dirty = false;
|
self.dirty = false;
|
||||||
|
|
||||||
/* Draw body */
|
|
||||||
self.draw_mail_view(grid,
|
|
||||||
((get_x(upper_left), y), bottom_right),
|
|
||||||
context);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn process_event(&mut self, event: &UIEvent, context: &mut Context) {
|
fn process_event(&mut self, event: &UIEvent, context: &mut Context) {
|
||||||
|
@ -561,7 +459,7 @@ impl Component for MailListing {
|
||||||
UIEventType::Input(Key::Esc) | UIEventType::Input(Key::Char('i')) if self.unfocused == true => {
|
UIEventType::Input(Key::Esc) | UIEventType::Input(Key::Char('i')) if self.unfocused == true => {
|
||||||
self.unfocused = false;
|
self.unfocused = false;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
self.pager = None;
|
self.view = None;
|
||||||
|
|
||||||
},
|
},
|
||||||
UIEventType::Input(Key::Char(k @ 'J')) | UIEventType::Input(Key::Char(k @ 'K')) => {
|
UIEventType::Input(Key::Char(k @ 'J')) | UIEventType::Input(Key::Char(k @ 'K')) => {
|
||||||
|
@ -617,7 +515,7 @@ impl Component for MailListing {
|
||||||
},
|
},
|
||||||
UIEventType::RefreshMailbox(_) => {
|
UIEventType::RefreshMailbox(_) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
self.pager = None;
|
self.view = None;
|
||||||
},
|
},
|
||||||
UIEventType::ChangeMode(UIMode::Normal) => {
|
UIEventType::ChangeMode(UIMode::Normal) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
@ -640,11 +538,11 @@ impl Component for MailListing {
|
||||||
_ => {
|
_ => {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if let Some(ref mut p) = self.pager {
|
if let Some(ref mut v) = self.view {
|
||||||
p.process_event(event, context);
|
v.process_event(event, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn is_dirty(&self) -> bool {
|
fn is_dirty(&self) -> bool {
|
||||||
self.dirty || self.pager.as_ref().map(|p| p.is_dirty()).unwrap_or(false)
|
self.dirty || self.view.as_ref().map(|p| p.is_dirty()).unwrap_or(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub mod listing;
|
pub mod listing;
|
||||||
|
pub mod view;
|
||||||
pub use listing::*;
|
pub use listing::*;
|
||||||
|
pub use view::*;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct MailView {
|
||||||
|
coordinates: (usize, usize, usize),
|
||||||
|
pager: Option<Pager>,
|
||||||
|
subview: Option<Box<MailView>>,
|
||||||
|
dirty: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MailView {
|
||||||
|
pub fn new(coordinates: (usize, usize, usize), pager: Option<Pager>, subview: Option<Box<MailView>>) -> Self {
|
||||||
|
|
||||||
|
MailView {
|
||||||
|
coordinates: coordinates,
|
||||||
|
pager: pager,
|
||||||
|
subview: subview,
|
||||||
|
dirty: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Component for MailView {
|
||||||
|
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||||
|
let upper_left = upper_left!(area);
|
||||||
|
let bottom_right = bottom_right!(area);
|
||||||
|
|
||||||
|
let (envelope_idx, y): (usize, usize) = {
|
||||||
|
let threaded = context.accounts[self.coordinates.0].runtime_settings.threaded;
|
||||||
|
let mailbox = &mut context.accounts[self.coordinates.0][self.coordinates.1].as_ref().unwrap().as_ref().unwrap();
|
||||||
|
let envelope_idx: usize = if threaded {
|
||||||
|
mailbox.threaded_mail(self.coordinates.2)
|
||||||
|
} else {
|
||||||
|
self.coordinates.2
|
||||||
|
};
|
||||||
|
|
||||||
|
let envelope: &Envelope = &mailbox.collection[envelope_idx];
|
||||||
|
|
||||||
|
let (x,y) = write_string_to_grid(&format!("Date: {}", envelope.date_as_str()),
|
||||||
|
grid,
|
||||||
|
Color::Byte(33),
|
||||||
|
Color::Default,
|
||||||
|
area,
|
||||||
|
true);
|
||||||
|
for x in x..=get_x(bottom_right) {
|
||||||
|
grid[(x, y)].set_ch(' ');
|
||||||
|
grid[(x, y)].set_bg(Color::Default);
|
||||||
|
grid[(x, y)].set_fg(Color::Default);
|
||||||
|
}
|
||||||
|
let (x,y) = write_string_to_grid(&format!("From: {}", envelope.from()),
|
||||||
|
grid,
|
||||||
|
Color::Byte(33),
|
||||||
|
Color::Default,
|
||||||
|
(set_y(upper_left, y+1), bottom_right),
|
||||||
|
true);
|
||||||
|
for x in x..=get_x(bottom_right) {
|
||||||
|
grid[(x, y)].set_ch(' ');
|
||||||
|
grid[(x, y)].set_bg(Color::Default);
|
||||||
|
grid[(x, y)].set_fg(Color::Default);
|
||||||
|
}
|
||||||
|
let (x,y) = write_string_to_grid(&format!("To: {}", envelope.to()),
|
||||||
|
grid,
|
||||||
|
Color::Byte(33),
|
||||||
|
Color::Default,
|
||||||
|
(set_y(upper_left, y+1), bottom_right),
|
||||||
|
true);
|
||||||
|
for x in x..=get_x(bottom_right) {
|
||||||
|
grid[(x, y)].set_ch(' ');
|
||||||
|
grid[(x, y)].set_bg(Color::Default);
|
||||||
|
grid[(x, y)].set_fg(Color::Default);
|
||||||
|
}
|
||||||
|
let (x,y) = write_string_to_grid(&format!("Subject: {}", envelope.subject()),
|
||||||
|
grid,
|
||||||
|
Color::Byte(33),
|
||||||
|
Color::Default,
|
||||||
|
(set_y(upper_left, y+1), bottom_right),
|
||||||
|
true);
|
||||||
|
for x in x..=get_x(bottom_right) {
|
||||||
|
grid[(x, y)].set_ch(' ');
|
||||||
|
grid[(x, y)].set_bg(Color::Default);
|
||||||
|
grid[(x, y)].set_fg(Color::Default);
|
||||||
|
}
|
||||||
|
let (x, y) = write_string_to_grid(&format!("Message-ID: {}", envelope.message_id_raw()),
|
||||||
|
grid,
|
||||||
|
Color::Byte(33),
|
||||||
|
Color::Default,
|
||||||
|
(set_y(upper_left, y+1), bottom_right),
|
||||||
|
true);
|
||||||
|
for x in x..=get_x(bottom_right) {
|
||||||
|
grid[(x, y)].set_ch(' ');
|
||||||
|
grid[(x, y)].set_bg(Color::Default);
|
||||||
|
grid[(x, y)].set_fg(Color::Default);
|
||||||
|
}
|
||||||
|
clear_area(grid,
|
||||||
|
(set_y(upper_left, y+1), set_y(bottom_right, y+2)));
|
||||||
|
context.dirty_areas.push_back((upper_left, set_y(bottom_right, y+1)));
|
||||||
|
(envelope_idx, y + 1)
|
||||||
|
};
|
||||||
|
if self.dirty {
|
||||||
|
self.pager = Some(Pager::from_envelope((self.coordinates.0, self.coordinates.1), envelope_idx, context));
|
||||||
|
self.dirty = false;
|
||||||
|
}
|
||||||
|
self.pager.as_mut().map(|p| p.draw(grid, (set_y(upper_left, y + 1),bottom_right), context));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_event(&mut self, event: &UIEvent, context: &mut Context) {
|
||||||
|
if let Some(ref mut sub) = self.subview {
|
||||||
|
sub.process_event(event, context);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if let Some(ref mut p) = self.pager {
|
||||||
|
p.process_event(event, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn is_dirty(&self) -> bool {
|
||||||
|
self.dirty || self.pager.as_ref().map(|p| p.is_dirty()).unwrap_or(false) ||
|
||||||
|
self.subview.as_ref().map(|p| p.is_dirty()).unwrap_or(false)
|
||||||
|
}
|
||||||
|
}
|
|
@ -172,7 +172,7 @@ impl Pager {
|
||||||
let mut text = text.to_string();
|
let mut text = text.to_string();
|
||||||
if envelope.body().count_attachments() > 1 {
|
if envelope.body().count_attachments() > 1 {
|
||||||
eprintln!("text was {}", text);
|
eprintln!("text was {}", text);
|
||||||
text = envelope.body().attachments().iter().fold(text, |mut s, a| { s.push_str(&format!("{}\n", a)); s });
|
text = envelope.body().attachments().iter().enumerate().fold(text, |mut s, (idx, a)| { s.push_str(&format!("[{}] {}\n\n", idx, a)); s });
|
||||||
eprintln!("text is {}", text);
|
eprintln!("text is {}", text);
|
||||||
}
|
}
|
||||||
let mut lines: Vec<&str> = text.trim().split('\n').collect();
|
let mut lines: Vec<&str> = text.trim().split('\n').collect();
|
||||||
|
@ -208,7 +208,6 @@ impl Pager {
|
||||||
let width = lines.iter().map(|l| l.len()).max().unwrap_or(0);
|
let width = lines.iter().map(|l| l.len()).max().unwrap_or(0);
|
||||||
if width > 0 {
|
if width > 0 {
|
||||||
for (i, l) in lines.iter().enumerate() {
|
for (i, l) in lines.iter().enumerate() {
|
||||||
eprintln!("line: {:?}", l);
|
|
||||||
write_string_to_grid(l,
|
write_string_to_grid(l,
|
||||||
content,
|
content,
|
||||||
Color::Default,
|
Color::Default,
|
||||||
|
@ -235,11 +234,10 @@ impl Component for Pager {
|
||||||
if self.height == 0 || self.height == self.cursor_pos || self.width == 0 {
|
if self.height == 0 || self.height == self.cursor_pos || self.width == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
eprintln!("drawing");
|
||||||
|
|
||||||
clear_area(grid,
|
clear_area(grid,
|
||||||
(upper_left, bottom_right));
|
(upper_left, bottom_right));
|
||||||
context.dirty_areas.push_back((upper_left, bottom_right));
|
|
||||||
|
|
||||||
//let pager_context: usize = context.settings.pager.pager_context;
|
//let pager_context: usize = context.settings.pager.pager_context;
|
||||||
//let pager_stop: bool = context.settings.pager.pager_stop;
|
//let pager_stop: bool = context.settings.pager.pager_stop;
|
||||||
//let rows = y(bottom_right) - y(upper_left);
|
//let rows = y(bottom_right) - y(upper_left);
|
||||||
|
@ -248,6 +246,7 @@ impl Component for Pager {
|
||||||
context.dirty_areas.push_back(area);
|
context.dirty_areas.push_back(area);
|
||||||
}
|
}
|
||||||
fn process_event(&mut self, event: &UIEvent, _context: &mut Context) {
|
fn process_event(&mut self, event: &UIEvent, _context: &mut Context) {
|
||||||
|
eprintln!("pager got {:?}", event);
|
||||||
match event.event_type {
|
match event.event_type {
|
||||||
UIEventType::Input(Key::Char('k')) => {
|
UIEventType::Input(Key::Char('k')) => {
|
||||||
if self.cursor_pos > 0 {
|
if self.cursor_pos > 0 {
|
||||||
|
|
Loading…
Reference in New Issue