summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2018-07-23 15:40:13 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2019-06-10 19:40:24 +0300
commitd0e6bc24f4664ed2d50cb40bc83c81c7914b409b (patch)
tree6b700873cb313cbbc0ac424b50fee516ca85ecf2 /ui
parentbae613ec54b8e5b28adb1a631f92ff09f7c76009 (diff)
Add url mode in MailView and open command
for #13 TODO: - bounds check with statusbar message - color in [X] markers
Diffstat (limited to 'ui')
-rw-r--r--ui/Cargo.toml2
-rw-r--r--ui/src/components/mail/view.rs102
-rw-r--r--ui/src/components/utilities.rs17
-rw-r--r--ui/src/lib.rs1
4 files changed, 103 insertions, 19 deletions
diff --git a/ui/Cargo.toml b/ui/Cargo.toml
index d9c862fa..72ec77e1 100644
--- a/ui/Cargo.toml
+++ b/ui/Cargo.toml
@@ -12,3 +12,5 @@ notify = "4.0.1"
notify-rust = "^3"
nom = "3.2.0"
chan-signal = "0.3.1"
+
+linkify = "0.3.1"
diff --git a/ui/src/components/mail/view.rs b/ui/src/components/mail/view.rs
index 746fb8d3..b8a43ffa 100644
--- a/ui/src/components/mail/view.rs
+++ b/ui/src/components/mail/view.rs
@@ -1,6 +1,16 @@
use super::*;
+use linkify::{LinkFinder, Link};
+use std::process::{Command, Stdio};
+#[derive(PartialEq, Debug)]
+enum ViewMode {
+ Normal,
+ Url,
+ Attachment,
+ Raw,
+}
+
/// Contains an Envelope view, with sticky headers, a pager for the body, and subviews for more
/// menus
pub struct MailView {
@@ -8,6 +18,9 @@ pub struct MailView {
pager: Option<Pager>,
subview: Option<Box<MailView>>,
dirty: bool,
+ mode: ViewMode,
+
+ cmd_buf: String,
}
impl MailView {
@@ -18,6 +31,9 @@ impl MailView {
pager: pager,
subview: subview,
dirty: true,
+ mode: ViewMode::Normal,
+
+ cmd_buf: String::with_capacity(4),
}
}
}
@@ -40,11 +56,11 @@ impl Component for MailView {
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);
+ 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);
@@ -99,18 +115,88 @@ impl Component for MailView {
context.dirty_areas.push_back((upper_left, set_y(bottom_right, y+1)));
(envelope_idx, y + 1)
};
+
if self.dirty {
+ let text = {
+ let mailbox_idx = self.coordinates; // coordinates are mailbox idxs
+ let mailbox = &mut context.accounts[mailbox_idx.0][mailbox_idx.1].as_ref().unwrap().as_ref().unwrap();
+ let envelope : &Envelope = &mailbox.collection[envelope_idx];
+ let mut text = match self.mode {
+ ViewMode::Url => {
+ let finder = LinkFinder::new();
+ let mut t = envelope.body().text().to_string();
+ for (lidx, l) in finder.links(&envelope.body().text()).enumerate() {
+ t.insert_str(l.start()+(lidx*3), &format!("[{}]", lidx));
+ }
+ t
+ },
+ _ => envelope.body().text().to_string(),
+ };
+ if envelope.body().count_attachments() > 1 {
+ text = envelope.body().attachments().iter().enumerate().fold(text, |mut s, (idx, a)| { s.push_str(&format!("[{}] {}\n\n", idx, a)); s });
+ }
+ text
+ };
+ let cursor_pos = self.pager.as_mut().map(|p| p.cursor_pos());
// TODO: pass string instead of envelope
- self.pager = Some(Pager::from_envelope((self.coordinates.0, self.coordinates.1), envelope_idx, context));
+ self.pager = Some(Pager::from_string(text, context, cursor_pos));
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) {
+ match event.event_type {
+ UIEventType::Input(Key::Char(c)) if c >= '0' && c <= '9' => { //TODO:this should be an Action
+ match self.mode {
+ ViewMode::Url => { self.cmd_buf.push(c);
+ eprintln!("buf is {}", self.cmd_buf);
+ return; },
+ _ => {},
+ }
+ },
+ UIEventType::Input(Key::Char('g')) if self.cmd_buf.len() > 0 && self.mode == ViewMode::Url => { //TODO:this should be an Action
+
+ let lidx = self.cmd_buf.parse::<usize>().unwrap();
+ self.cmd_buf.clear();
+ let url = {
+ 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 finder = LinkFinder::new();
+ let mut t = envelope.body().text().to_string();
+ let links: Vec<Link> = finder.links(&t).collect();
+ links[lidx].as_str().to_string()
+ };
+
+
+ let open_url = Command::new("xdg-open")
+ .arg(url)
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .spawn()
+ .expect("Failed to start xdg_open");
+
+ },
+ UIEventType::Input(Key::Char('u')) => { //TODO:this should be an Action
+ match self.mode {
+ ViewMode::Normal => { self.mode = ViewMode::Url },
+ ViewMode::Url => { self.mode = ViewMode::Normal },
+ _ => {},
+ }
+ self.dirty = true;
+ },
+ _ => {},
+ }
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);
@@ -119,6 +205,6 @@ impl Component for MailView {
}
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)
+ self.subview.as_ref().map(|p| p.is_dirty()).unwrap_or(false)
}
}
diff --git a/ui/src/components/utilities.rs b/ui/src/components/utilities.rs
index 71965425..2d14adfc 100644
--- a/ui/src/components/utilities.rs
+++ b/ui/src/components/utilities.rs
@@ -47,7 +47,6 @@ impl Component for HSplit {
let _ = self.bottom.component.draw(grid,
((get_x(upper_left), get_y(upper_left) + mid), bottom_right),
context);
- grid[bottom_right].set_ch('b');
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) {
self.top.rcv_event(event, context);
@@ -143,14 +142,10 @@ pub struct Pager {
content: CellBuffer,
}
-// TODO: Make a `new` method that is content agnostic.
impl Pager {
- pub fn from_envelope(mailbox_idx: (usize, usize), envelope_idx: usize, context: &mut Context) -> Self {
- let mailbox = &mut context.accounts[mailbox_idx.0][mailbox_idx.1].as_ref().unwrap().as_ref().unwrap();
- let envelope : &Envelope = &mailbox.collection[envelope_idx];
+ pub fn from_string(mut text: String, context: &mut Context, cursor_pos: Option<usize>) -> Self {
let pager_filter: Option<&String> = context.settings.pager.filter.as_ref();
//let format_flowed: bool = context.settings.pager.format_flowed;
- let mut text = envelope.body().text();
if let Some(bin) = pager_filter {
use std::io::Write;
use std::process::{Command, Stdio};
@@ -168,10 +163,7 @@ impl Pager {
text = String::from_utf8_lossy(&filter_child.wait_with_output().expect("Failed to wait on filter").stdout).to_string();
}
- let mut text = text.to_string();
- if envelope.body().count_attachments() > 1 {
- text = envelope.body().attachments().iter().enumerate().fold(text, |mut s, (idx, a)| { s.push_str(&format!("[{}] {}\n\n", idx, a)); s });
- }
+
let lines: Vec<&str> = text.trim().split('\n').collect();
let height = lines.len() + 1;
let width = lines.iter().map(|l| l.len()).max().unwrap_or(0);
@@ -179,7 +171,7 @@ impl Pager {
//interpret_format_flowed(&text);
Pager::print_string(&mut content, &text);
Pager {
- cursor_pos: 0,
+ cursor_pos: cursor_pos.unwrap_or(0),
height: height,
width: width,
dirty: true,
@@ -214,6 +206,9 @@ impl Pager {
}
}
}
+ pub fn cursor_pos(&self) -> usize {
+ self.cursor_pos
+ }
}
impl Component for Pager {
diff --git a/ui/src/lib.rs b/ui/src/lib.rs
index 79ad174f..93a25bee 100644
--- a/ui/src/lib.rs
+++ b/ui/src/lib.rs
@@ -45,6 +45,7 @@ extern crate notify_rust;
#[macro_use]
extern crate chan;
extern crate chan_signal;
+extern crate linkify;
use melib::*;
use std::io::{Write, };