ui/MailView: implement headers_sticky option

Kind of hacky, I don't like the way it is done but I'm willing to
compromise.
jmap
Manos Pitsidianakis 2019-11-24 20:38:30 +02:00
parent af365fa8d4
commit db197aaffe
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
2 changed files with 209 additions and 199 deletions

View File

@ -77,6 +77,9 @@ pub struct MailView {
dirty: bool,
mode: ViewMode,
expand_headers: bool,
headers_no: usize,
headers_cursor: usize,
force_draw_headers: bool,
cmd_buf: String,
id: ComponentId,
@ -116,6 +119,10 @@ impl MailView {
mode: ViewMode::Normal,
expand_headers: false,
headers_no: 5,
headers_cursor: 0,
force_draw_headers: false,
cmd_buf: String::with_capacity(4),
id: ComponentId::new_v4(),
}
@ -300,7 +307,7 @@ impl MailView {
impl Component for MailView {
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
if !self.is_dirty() {
if !self.is_dirty() && !self.force_draw_headers {
return;
}
let upper_left = upper_left!(area);
@ -344,93 +351,51 @@ impl Component for MailView {
context.dirty_areas.push_back(area);
get_y(upper_left) - 1
} else {
let (x, y) = write_string_to_grid(
&format!("Date: {}", envelope.date_as_str()),
let height_p = self.pager.size().1;
let height = height!(area) - self.headers_no - 1;
self.headers_no = 0;
let mut skip_header_ctr = self.headers_cursor;
let sticky = context.settings.pager.headers_sticky || height_p < height;
let (_, mut y) = upper_left;
macro_rules! print_header {
($($string:expr)+) => {
$({
if sticky || skip_header_ctr == 0 {
let (_x, _y) = write_string_to_grid(
&$string,
grid,
header_fg,
Color::Default,
Attr::Default,
area,
(set_y(upper_left, y), bottom_right),
Some(get_x(upper_left)),
);
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.field_from_to_string()),
grid,
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, y + 1), bottom_right),
Some(get_x(upper_left)),
);
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.field_to_to_string()),
grid,
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, y + 1), bottom_right),
Some(get_x(upper_left)),
);
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,
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, y + 1), bottom_right),
Some(get_x(upper_left)),
);
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, mut y) = write_string_to_grid(
&format!("Message-ID: <{}>", envelope.message_id_raw()),
grid,
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, y + 1), bottom_right),
Some(get_x(upper_left)),
);
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);
}
if self.expand_headers && envelope.in_reply_to().is_some() {
let (x, _y) = write_string_to_grid(
&format!("In-Reply-To: {}", envelope.in_reply_to_display().unwrap()),
grid,
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, y + 1), bottom_right),
Some(get_x(upper_left)),
);
for x in x..=get_x(bottom_right) {
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!(
y = _y + 1;
} else {
skip_header_ctr -= 1;
}
self.headers_no += 1;
})+
};
}
print_header!(
format!("Date: {}", envelope.date_as_str())
format!("From: {}", envelope.field_from_to_string())
format!("To: {}", envelope.field_to_to_string())
format!("Subject: {}", envelope.subject())
format!("Message-ID: <{}>", envelope.message_id_raw())
);
if self.expand_headers && envelope.in_reply_to().is_some() {
print_header!(
format!("In-Reply-To: {}", envelope.in_reply_to_display().unwrap())
format!(
"References: {}",
envelope
.references()
@ -438,20 +403,8 @@ impl Component for MailView {
.map(std::string::ToString::to_string)
.collect::<Vec<String>>()
.join(", ")
),
grid,
header_fg,
Color::Default,
Attr::Default,
(set_y(upper_left, _y + 1), bottom_right),
Some(get_x(upper_left)),
)
);
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);
}
y = _y;
}
if let Some(list_management::ListActions {
ref id,
@ -461,8 +414,8 @@ impl Component for MailView {
}) = list_management::ListActions::detect(&envelope)
{
let mut x = get_x(upper_left);
y += 1;
if let Some(id) = id {
if sticky || skip_header_ctr == 0 {
let (_x, _) = write_string_to_grid(
"List-ID: ",
grid,
@ -487,6 +440,9 @@ impl Component for MailView {
}
y = _y;
}
self.headers_no += 1;
}
if sticky || skip_header_ctr == 0 {
if archive.is_some() || post.is_some() || unsubscribe.is_some() {
let (_x, _y) = write_string_to_grid(
" Available actions: [ ",
@ -554,13 +510,33 @@ impl Component for MailView {
grid[(x, y)].set_bg(Color::Default);
grid[(x, y)].set_fg(Color::Default);
}
y += 1;
}
}
clear_area(grid, (set_y(upper_left, y + 1), set_y(bottom_right, y + 1)));
self.force_draw_headers = false;
clear_area(grid, (set_y(upper_left, y), set_y(bottom_right, y + 1)));
context
.dirty_areas
.push_back((upper_left, set_y(bottom_right, y + 1)));
.push_back((upper_left, set_y(bottom_right, y + 3)));
if !context.settings.pager.headers_sticky {
let height_p = self.pager.size().1;
let height = height!(area) - y - 1;
if self.pager.cursor_pos() >= self.headers_no {
get_y(upper_left)
} else if height_p > height && self.headers_cursor < self.headers_no + 1 {
y + 1
} else if self.headers_cursor == 0 {
y + 1
} else if height_p < height {
y + 1
} else {
get_y(upper_left)
}
} else {
y + 1
}
}
};
@ -632,12 +608,12 @@ impl Component for MailView {
match self.mode {
ViewMode::Subview if self.subview.is_some() => {
if let Some(s) = self.subview.as_mut() {
s.draw(grid, (set_y(upper_left, y + 1), bottom_right), context);
s.draw(grid, (set_y(upper_left, y), bottom_right), context);
}
}
_ => {
self.pager
.draw(grid, (set_y(upper_left, y + 1), bottom_right), context);
.draw(grid, (set_y(upper_left, y), bottom_right), context);
}
}
if let ViewMode::ContactSelector(ref mut s) = self.mode {
@ -647,6 +623,7 @@ impl Component for MailView {
}
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
let shortcuts = self.get_shortcuts(context);
match self.mode {
ViewMode::Subview => {
if let Some(s) = self.subview.as_mut() {
@ -676,11 +653,39 @@ impl Component for MailView {
return true;
}
}
_ => match event {
UIEvent::Input(ref k)
if k == shortcuts[Pager::DESCRIPTION]["scroll_up"]
&& !context.settings.pager.headers_sticky
&& self.headers_cursor <= self.headers_no =>
{
self.force_draw_headers = true;
if self.pager.cursor_pos() == 0 {
self.headers_cursor = self.headers_cursor.saturating_sub(1);
} else {
if self.pager.process_event(event, context) {
return true;
}
}
self.pager.set_dirty();
return true;
}
UIEvent::Input(ref k)
if k == shortcuts[Pager::DESCRIPTION]["scroll_down"]
&& !context.settings.pager.headers_sticky
&& self.headers_cursor < self.headers_no =>
{
self.force_draw_headers = true;
self.headers_cursor += 1;
self.pager.set_dirty();
return true;
}
_ => {
if self.pager.process_event(event, context) {
return true;
}
}
},
}
let shortcuts = &self.get_shortcuts(context)[MailView::DESCRIPTION];

View File

@ -303,7 +303,7 @@ impl fmt::Display for Pager {
}
impl Pager {
const DESCRIPTION: &'static str = "pager";
pub const DESCRIPTION: &'static str = "pager";
pub fn set_reflow(&mut self, new_val: Reflow) {
self.reflow = new_val;
}
@ -470,9 +470,14 @@ impl Pager {
}
}
}
pub fn cursor_pos(&self) -> usize {
self.cursor.1
}
pub fn size(&self) -> (usize, usize) {
(self.width, self.height)
}
}
impl Component for Pager {