Add HtmlView, bounds checking in pager scrolling and better attachment view
parent
befe00dea6
commit
8462d1aceb
|
@ -367,7 +367,7 @@ fn display_addr(input: &[u8]) -> IResult<&[u8], Address> {
|
|||
let mut flag = false;
|
||||
for (i, b) in input[0..].iter().enumerate() {
|
||||
if *b == b'<' {
|
||||
display_name.length = if i != 0 { i - 1 } else { 0 };
|
||||
display_name.length = i.saturating_sub(1); // if i != 0 { i - 1 } else { 0 };
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
|
@ -395,9 +395,9 @@ fn display_addr(input: &[u8]) -> IResult<&[u8], Address> {
|
|||
IResult::Error(e) => IResult::Error(e),
|
||||
IResult::Incomplete(i) => IResult::Incomplete(i),
|
||||
IResult::Done(rest, raw) => {
|
||||
display_name.length = raw.find(b"<").unwrap();
|
||||
address_spec.offset = display_name.length + 1;
|
||||
address_spec.length = raw.len() - display_name.length - 2;
|
||||
display_name.length = raw.find(b"<").unwrap().saturating_sub(1);
|
||||
address_spec.offset = display_name.length + 2;
|
||||
address_spec.length = raw.len().saturating_sub(display_name.length).saturating_sub(3);
|
||||
IResult::Done(
|
||||
rest,
|
||||
Address::Mailbox(MailboxAddress {
|
||||
|
|
|
@ -228,7 +228,6 @@ impl MailListing {
|
|||
}
|
||||
} else {
|
||||
// Populate `CellBuffer` with every entry.
|
||||
// TODO: Lazy load?
|
||||
let mut idx = 0;
|
||||
for y in 0..=self.length {
|
||||
if idx >= self.length {
|
||||
|
|
|
@ -25,27 +25,32 @@ use std::process::{Command, Stdio};
|
|||
|
||||
pub struct HtmlView {
|
||||
pager: Pager,
|
||||
bytes: Vec<u8>
|
||||
bytes: Vec<u8>,
|
||||
}
|
||||
|
||||
impl HtmlView {
|
||||
pub fn new(bytes: Vec<u8>) -> Self {
|
||||
let mut html_filter = Command::new("w3m")
|
||||
.args(&["-I", "utf-8", "-T", "text/html"])
|
||||
.args(&["-I", "utf-8", "-T", "text/html"])
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to start html filter process");
|
||||
html_filter.stdin.as_mut().unwrap().write_all(&bytes).expect("Failed to write to w3m stdin");
|
||||
let mut display_text = String::from("Text piped through `w3m`. Press `v` to open in web browser. \n\n");
|
||||
display_text.push_str(&String::from_utf8_lossy(&html_filter.wait_with_output().unwrap().stdout));
|
||||
html_filter
|
||||
.stdin
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.write_all(&bytes)
|
||||
.expect("Failed to write to w3m stdin");
|
||||
let mut display_text =
|
||||
String::from("Text piped through `w3m`. Press `v` to open in web browser. \n\n");
|
||||
display_text.push_str(&String::from_utf8_lossy(
|
||||
&html_filter.wait_with_output().unwrap().stdout,
|
||||
));
|
||||
|
||||
let buf = MailView::plain_text_to_buf(&display_text, true);
|
||||
let pager = Pager::from_buf(&buf, None);
|
||||
HtmlView {
|
||||
pager,
|
||||
bytes
|
||||
}
|
||||
HtmlView { pager, bytes }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,20 +71,19 @@ impl Component for HtmlView {
|
|||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap_or_else(|_| {
|
||||
panic!("Failed to start {}", binary.display())
|
||||
});
|
||||
.unwrap_or_else(|_| panic!("Failed to start {}", binary.display()));
|
||||
context.temp_files.push(p);
|
||||
} else {
|
||||
context.replies.push_back(UIEvent {
|
||||
id: 0,
|
||||
event_type: UIEventType::StatusNotification(format!(
|
||||
"Couldn't find a default application for html files.")),
|
||||
"Couldn't find a default application for html files."
|
||||
)),
|
||||
});
|
||||
}
|
||||
return;
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.pager.process_event(event, context);
|
||||
}
|
||||
|
|
|
@ -262,7 +262,7 @@ impl Component for MailView {
|
|||
grid[(x, y)].set_fg(Color::Default);
|
||||
}
|
||||
let (x, y) = write_string_to_grid(
|
||||
&format!("Message-ID: {}", envelope.message_id_raw()),
|
||||
&format!("Message-ID: <{}>", envelope.message_id_raw()),
|
||||
grid,
|
||||
Color::Byte(33),
|
||||
Color::Default,
|
||||
|
@ -313,8 +313,10 @@ impl Component for MailView {
|
|||
};
|
||||
self.dirty = false;
|
||||
}
|
||||
if let Some(s) = self.subview.as_mut() {
|
||||
s.draw(grid, (set_y(upper_left, y + 1), bottom_right), context);
|
||||
if self.mode == ViewMode::Subview {
|
||||
if let Some(s) = self.subview.as_mut() {
|
||||
s.draw(grid, (set_y(upper_left, y + 1), bottom_right), context);
|
||||
}
|
||||
} else if let Some(p) = self.pager.as_mut() {
|
||||
p.draw(grid, (set_y(upper_left, y + 1), bottom_right), context);
|
||||
}
|
||||
|
|
|
@ -277,6 +277,11 @@ impl Component for Pager {
|
|||
}
|
||||
|
||||
self.dirty = false;
|
||||
if self.cursor_pos > 0 && self.cursor_pos + 1 + height!(area) > self.height {
|
||||
self.cursor_pos = self.cursor_pos.saturating_sub(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if self.height == 0 || self.height == self.cursor_pos || self.width == 0 {
|
||||
return;
|
||||
}
|
||||
|
@ -303,7 +308,7 @@ impl Component for Pager {
|
|||
}
|
||||
}
|
||||
UIEventType::Input(Key::Char('j')) => {
|
||||
if self.height > 0 && self.cursor_pos < self.height - 1 {
|
||||
if self.height > 0 && self.cursor_pos + 1 < self.height {
|
||||
self.cursor_pos += 1;
|
||||
self.dirty = true;
|
||||
}
|
||||
|
|
|
@ -371,6 +371,7 @@ impl<W: Write> State<W> {
|
|||
return;
|
||||
}
|
||||
UIEventType::EditDraft(mut file) => {
|
||||
eprintln!("edit draft event");
|
||||
use std::io::Read;
|
||||
use std::process::{Command, Stdio};
|
||||
let mut output = Command::new("msmtp")
|
||||
|
@ -386,7 +387,6 @@ impl<W: Write> State<W> {
|
|||
|
||||
f.read_to_end(&mut buf).unwrap();
|
||||
in_pipe.write_all(&buf).unwrap();
|
||||
std::fs::remove_file(file.path()).unwrap();
|
||||
}
|
||||
output.wait_with_output().expect("Failed to read stdout");
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
use std;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::fs::OpenOptions;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -38,8 +39,9 @@ impl Drop for File {
|
|||
|
||||
impl File {
|
||||
pub fn file(&mut self) -> std::fs::File {
|
||||
std::fs::File::create(&self.path).unwrap()
|
||||
OpenOptions::new().read(true).write(true).create(true).open(&self.path).unwrap()
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &PathBuf {
|
||||
&self.path
|
||||
}
|
||||
|
|
|
@ -55,6 +55,22 @@ pub fn set_y(p: Pos, new_y: usize) -> Pos {
|
|||
/// ```
|
||||
pub type Area = (Pos, Pos);
|
||||
|
||||
/// Get an area's height
|
||||
///
|
||||
/// Example:
|
||||
/// ```
|
||||
/// use ui::position;
|
||||
///
|
||||
/// let new_area = ((0, 0), (1, 1));
|
||||
/// assert_eq!(height!(new_area), 1);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! height {
|
||||
($a:expr) => {
|
||||
(get_y(bottom_right!($a))).saturating_sub(get_y(upper_left!($a)))
|
||||
};
|
||||
}
|
||||
|
||||
/// Get the upper left Position of an area
|
||||
///
|
||||
/// Example:
|
||||
|
|
Loading…
Reference in New Issue