From 9b4b6051f1b7efd6067e39d3b4fb76efb724a600 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Tue, 26 Mar 2019 15:26:09 +0200 Subject: [PATCH] ui: use any email as composing template with edit command concerns #38 --- melib/src/error.rs | 7 +++++++ melib/src/mailbox/email.rs | 5 +++++ melib/src/mailbox/email/compose.rs | 19 ++++++++++++++++++ ui/src/components/mail/compose.rs | 17 ++++++++++++++++ ui/src/components/mail/view/thread.rs | 29 +++++++++++++++++++++++++++ ui/src/components/utilities.rs | 6 ++++++ ui/src/execute/actions.rs | 1 + 7 files changed, 84 insertions(+) diff --git a/melib/src/error.rs b/melib/src/error.rs index 432325cea..ce4d27ddb 100644 --- a/melib/src/error.rs +++ b/melib/src/error.rs @@ -29,6 +29,7 @@ use std::fmt; use std::io; use std::result; use std::string; +use std::str; use nom; @@ -90,6 +91,12 @@ impl From for MeliError { } } +impl From for MeliError { + #[inline] + fn from(kind: str::Utf8Error) -> MeliError { + MeliError::new(format!("{:?}", kind)) + } +} //use std::option; //impl From for MeliError { // #[inline] diff --git a/melib/src/mailbox/email.rs b/melib/src/mailbox/email.rs index 2f0e582e8..fb5f8b9eb 100644 --- a/melib/src/mailbox/email.rs +++ b/melib/src/mailbox/email.rs @@ -557,6 +557,11 @@ impl Envelope { } builder.build() } + pub fn headers<'a>(&self, bytes: &'a [u8]) -> Result> { + let ret = parser::headers(bytes).to_full_result()?; + let len = ret.len(); + ret.into_iter().try_fold(Vec::with_capacity(len), |mut acc, (a, b)| Ok({acc.push((std::str::from_utf8(a)?, std::str::from_utf8(b)?)); acc })) + } pub fn body(&self, mut operation: Box) -> Attachment { let file = operation.as_bytes(); self.body_bytes(file.unwrap()) diff --git a/melib/src/mailbox/email/compose.rs b/melib/src/mailbox/email/compose.rs index cad33e5c6..be34f8976 100644 --- a/melib/src/mailbox/email/compose.rs +++ b/melib/src/mailbox/email/compose.rs @@ -1,4 +1,5 @@ use super::*; +use mailbox::backends::BackendOp; use chrono::{DateTime, Local}; use data_encoding::BASE64_MIME; use std::str; @@ -93,6 +94,23 @@ impl str::FromStr for Draft { } impl Draft { + pub fn edit(envelope: &Envelope, mut op: Box) -> Self { + + let mut ret = Draft::default(); + //TODO: Inform user if error + { + let bytes = op.as_bytes().unwrap_or(&[]); + for (h, v) in envelope.headers(bytes).unwrap_or_else(|_| Vec::new()) { + ret.header_order.push(h.into()); + ret.headers_mut() + .insert(h.into(), v.into()); + } + } + + ret.body = envelope.body(op).text(); + + ret + } pub fn new_reply(envelope: &Envelope, bytes: &[u8]) -> Self { let mut ret = Draft::default(); ret.headers_mut().insert( @@ -128,6 +146,7 @@ impl Draft { let mut ret = String::with_capacity(reply_body.len() + lines.len()); for l in lines { ret.push('>'); + ret.push(' '); ret.push_str(l.trim()); ret.push('\n'); } diff --git a/ui/src/components/mail/compose.rs b/ui/src/components/mail/compose.rs index d7cc97ad3..1125ae1f1 100644 --- a/ui/src/components/mail/compose.rs +++ b/ui/src/components/mail/compose.rs @@ -117,6 +117,23 @@ impl Composer { * msg: index of message we reply to in thread_nodes * context: current context */ + pub fn edit(coordinates: (usize, usize, usize), msg: usize, context: &Context) -> Self { + let mailbox = &context.accounts[coordinates.0][coordinates.1] + .as_ref() + .unwrap(); + let threads = &mailbox.collection.threads; + let thread_nodes = &threads.thread_nodes(); + let mut ret = Composer::default(); + let message = &mailbox.collection[&thread_nodes[msg].message().unwrap()]; + let op = context.accounts[coordinates.0] + .backend + .operation(message.hash(), mailbox.folder.hash()); + + ret.draft = Draft::edit(message, op); + + ret.account_cursor = coordinates.0; + ret + } pub fn with_context(coordinates: (usize, usize, usize), msg: usize, context: &Context) -> Self { let mailbox = &context.accounts[coordinates.0][coordinates.1] .as_ref() diff --git a/ui/src/components/mail/view/thread.rs b/ui/src/components/mail/view/thread.rs index c56a63eaa..58690ca9f 100644 --- a/ui/src/components/mail/view/thread.rs +++ b/ui/src/components/mail/view/thread.rs @@ -555,6 +555,35 @@ impl Component for ThreadView { }); return true; } + UIEventType::Input(Key::Char('e')) => { + { + let mailbox = &context.accounts[self.coordinates.0][self.coordinates.1] + .as_ref() + .unwrap(); + let threads = &mailbox.collection.threads; + let thread_node = &threads.thread_nodes()[threads.root_set(self.coordinates.2)]; + let i = if let Some(i) = thread_node.message() { + i + } else { + threads.thread_nodes()[thread_node.children()[0]] + .message() + .unwrap() + }; + let envelope: &Envelope = &mailbox.collection[&i]; + let op = context.accounts[self.coordinates.0] + .backend + .operation(envelope.hash(), mailbox.folder.hash()); + eprintln!("sending action edit for {}, {}", envelope.message_id(), op.description()); + } + context.replies.push_back(UIEvent { + id: 0, + event_type: UIEventType::Action(Tab(Edit( + self.coordinates, + self.entries[self.expanded_pos].index.1, + ))), + }); + return true; + } UIEventType::Input(Key::Up) => { if self.cursor_pos > 0 { self.new_cursor_pos = self.new_cursor_pos.saturating_sub(1); diff --git a/ui/src/components/utilities.rs b/ui/src/components/utilities.rs index 647110ad0..aaa06cede 100644 --- a/ui/src/components/utilities.rs +++ b/ui/src/components/utilities.rs @@ -980,6 +980,12 @@ impl Component for Tabbed { self.children[self.cursor_pos].set_dirty(); return true; } + UIEventType::Action(Tab(Edit(coordinates, msg))) => { + self.add_component(Box::new(Composer::edit(coordinates, msg, context))); + self.cursor_pos = self.children.len() - 1; + self.children[self.cursor_pos].set_dirty(); + return true; + } UIEventType::Action(Tab(TabOpen(ref mut e))) if e.is_some() => { self.add_component(e.take().unwrap()); self.cursor_pos = self.children.len() - 1; diff --git a/ui/src/execute/actions.rs b/ui/src/execute/actions.rs index ba4409035..a0113c62c 100644 --- a/ui/src/execute/actions.rs +++ b/ui/src/execute/actions.rs @@ -42,6 +42,7 @@ pub enum TabAction { NewDraft, Reply((usize, usize, usize), usize), // thread coordinates (account, mailbox, root_set idx) and message idx Close, + Edit((usize, usize, usize), usize), // thread coordinates (account, mailbox, root_set idx) and message idx Kill(Uuid), }