From 53e924eb33446f9434c4d2c59d54be19ef505b85 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Tue, 25 Aug 2020 15:39:43 +0300 Subject: [PATCH] Add edit envelope action back as async --- src/command/actions.rs | 6 +- src/components/contacts/contact_list.rs | 4 +- src/components/mail/listing.rs | 5 +- src/components/mail/view.rs | 73 ++++++++++++++++++++++--- src/components/utilities.rs | 46 ---------------- src/conf/accounts.rs | 9 +++ src/state.rs | 5 ++ src/types.rs | 9 +++ 8 files changed, 96 insertions(+), 61 deletions(-) diff --git a/src/command/actions.rs b/src/command/actions.rs index 3a6d6a90f..d3cf72836 100644 --- a/src/command/actions.rs +++ b/src/command/actions.rs @@ -24,9 +24,7 @@ */ use crate::components::Component; -use melib::backends::AccountHash; pub use melib::thread::{SortField, SortOrder}; -use melib::{Draft, EnvelopeHash}; extern crate uuid; use uuid::Uuid; @@ -58,11 +56,9 @@ pub enum ListingAction { #[derive(Debug)] pub enum TabAction { - New(Option>), - NewDraft(AccountHash, Option), Close, - Edit(AccountHash, EnvelopeHash), // account_position, envelope hash Kill(Uuid), + New(Option>), } #[derive(Debug)] diff --git a/src/components/contacts/contact_list.rs b/src/components/contacts/contact_list.rs index ce5e41a8b..baeb43942 100644 --- a/src/components/contacts/contact_list.rs +++ b/src/components/contacts/contact_list.rs @@ -642,9 +642,11 @@ impl Component for ContactList { let mut draft: Draft = Draft::default(); *draft.headers_mut().get_mut("To").unwrap() = format!("{} <{}>", &card.name(), &card.email()); + let mut composer = Composer::new(account_hash, context); + composer.set_draft(draft); context .replies - .push_back(UIEvent::Action(Tab(NewDraft(account_hash, Some(draft))))); + .push_back(UIEvent::Action(Tab(New(Some(Box::new(composer)))))); return true; } diff --git a/src/components/mail/listing.rs b/src/components/mail/listing.rs index d4795ebf9..aae81f855 100644 --- a/src/components/mail/listing.rs +++ b/src/components/mail/listing.rs @@ -286,6 +286,7 @@ pub trait MailListingTrait: ListingTrait { name: "message copying".into(), handle, channel, + on_finish: None, }, ); } @@ -323,6 +324,7 @@ pub trait MailListingTrait: ListingTrait { name: "message moving".into(), handle, channel, + on_finish: None, }, ); } @@ -1099,9 +1101,10 @@ impl Component for Listing { if shortcut!(k == shortcuts[Listing::DESCRIPTION]["new_mail"]) => { let account_hash = context.accounts[self.cursor_pos.0].hash(); + let composer = Composer::new(account_hash, context); context .replies - .push_back(UIEvent::Action(Tab(NewDraft(account_hash, None)))); + .push_back(UIEvent::Action(Tab(New(Some(Box::new(composer)))))); return true; } UIEvent::StartupCheck(_) => { diff --git a/src/components/mail/view.rs b/src/components/mail/view.rs index f39301a3c..e58b05e92 100644 --- a/src/components/mail/view.rs +++ b/src/components/mail/view.rs @@ -1137,10 +1137,66 @@ impl Component for MailView { UIEvent::Input(ref key) if shortcut!(key == shortcuts[MailView::DESCRIPTION]["edit"]) => { - context.replies.push_back(UIEvent::Action(Tab(Edit( - self.coordinates.0, - self.coordinates.2, - )))); + let account_hash = self.coordinates.0; + let env_hash = self.coordinates.2; + let (sender, mut receiver) = crate::jobs::oneshot::channel(); + let operation = context.accounts[&account_hash].operation(env_hash); + let bytes_job = async move { + let _ = sender.send(operation?.as_bytes()?.await); + Ok(()) + }; + let (channel, handle, job_id) = if context.accounts[&account_hash] + .backend_capabilities + .is_async + { + context.accounts[&account_hash] + .job_executor + .spawn_specialized(bytes_job) + } else { + context.accounts[&account_hash] + .job_executor + .spawn_blocking(bytes_job) + }; + context.accounts[&account_hash].insert_job( + job_id, + crate::conf::accounts::JobRequest::Generic { + name: "fetch envelope".into(), + handle, + channel, + on_finish: Some(CallbackFn(Box::new(move |context: &mut Context| { + let result = receiver.try_recv().unwrap().unwrap(); + match result.and_then(|bytes| { + Composer::edit(account_hash, env_hash, &bytes, context) + }) { + Ok(composer) => { + context.replies.push_back(UIEvent::Action(Tab(New(Some( + Box::new(composer), + ))))); + } + Err(err) => { + let err_string = format!( + "Failed to open envelope {}: {}", + context.accounts[&account_hash] + .collection + .envelopes + .read() + .unwrap() + .get(&env_hash) + .map(|env| env.message_id_display()) + .unwrap_or_else(|| "Not found".into()), + err.to_string() + ); + log(&err_string, ERROR); + context.replies.push_back(UIEvent::Notification( + Some("Failed to open e-mail".to_string()), + err_string, + Some(NotificationType::ERROR), + )); + } + } + }))), + }, + ); return true; } UIEvent::Input(ref key) @@ -1538,10 +1594,11 @@ impl Component for MailView { { if let Ok(mailto) = Mailto::try_from(list_post_addr) { let draft: Draft = mailto.into(); - context.replies.push_back(UIEvent::Action(Tab(NewDraft( - self.coordinates.0, - Some(draft), - )))); + let mut composer = Composer::new(self.coordinates.0, context); + composer.set_draft(draft); + context.replies.push_back(UIEvent::Action(Tab(New(Some( + Box::new(composer), + ))))); failure = false; } } diff --git a/src/components/utilities.rs b/src/components/utilities.rs index be1b8a520..31d640a93 100644 --- a/src/components/utilities.rs +++ b/src/components/utilities.rs @@ -1662,52 +1662,6 @@ impl Component for Tabbed { self.dirty = true; return true; } - UIEvent::Action(Tab(NewDraft(account_hash, ref draft))) => { - let mut composer = Composer::new(*account_hash, context); - if let Some(draft) = draft { - composer.set_draft(draft.clone()); - } - self.add_component(Box::new(composer)); - self.cursor_pos = self.children.len() - 1; - self.children[self.cursor_pos].set_dirty(true); - let mut children_maps = self.children[self.cursor_pos].get_shortcuts(context); - children_maps.extend(self.get_shortcuts(context)); - self.help_curr_views = children_maps; - return true; - } - UIEvent::Action(Tab(Edit(_, _))) => { - /* FIXME - let composer = match Composer::edit(*account_hash, *msg, context) { - Ok(c) => c, - Err(e) => { - context.replies.push_back(UIEvent::Notification( - Some("Failed to open e-mail".to_string()), - e.to_string(), - Some(NotificationType::ERROR), - )); - log( - format!( - "Failed to open envelope {}: {}", - context.accounts[&*account_hash] - .collection - .get_env(*msg) - .message_id_display(), - e.to_string() - ), - ERROR, - ); - return true; - } - }; - self.add_component(Box::new(composer)); - self.cursor_pos = self.children.len() - 1; - self.children[self.cursor_pos].set_dirty(true); - let mut children_maps = self.children[self.cursor_pos].get_shortcuts(context); - children_maps.extend(self.get_shortcuts(context)); - self.help_curr_views = children_maps; - */ - return true; - } UIEvent::Action(Tab(New(ref mut e))) if e.is_some() => { self.add_component(e.take().unwrap()); self.cursor_pos = self.children.len() - 1; diff --git a/src/conf/accounts.rs b/src/conf/accounts.rs index 29e7973e7..0ef57e01a 100644 --- a/src/conf/accounts.rs +++ b/src/conf/accounts.rs @@ -176,6 +176,7 @@ pub enum JobRequest { name: Cow<'static, str>, handle: JoinHandle, channel: JobChannel<()>, + on_finish: Option, }, IsOnline(JoinHandle, oneshot::Receiver>), Refresh(MailboxHash, JoinHandle, oneshot::Receiver>), @@ -1796,6 +1797,7 @@ impl Account { ref name, ref mut channel, handle: _, + ref mut on_finish, } => { let r = channel.try_recv().unwrap(); match r { @@ -1819,6 +1821,13 @@ impl Account { } None => {} } + if on_finish.is_some() { + self.sender + .send(ThreadEvent::UIEvent(UIEvent::Callback( + on_finish.take().unwrap(), + ))) + .unwrap(); + } self.sender .send(ThreadEvent::UIEvent(UIEvent::StatusEvent( StatusEvent::JobFinished(*job_id), diff --git a/src/state.rs b/src/state.rs index bf584e0f9..54341b6eb 100644 --- a/src/state.rs +++ b/src/state.rs @@ -888,6 +888,7 @@ impl State { name: "Message index rebuild".into(), handle, channel, + on_finish: None, }, ); self.context.replies.push_back(UIEvent::Notification( @@ -1089,6 +1090,10 @@ impl State { return; } } + UIEvent::Callback(callback_fn) => { + (callback_fn.0)(&mut self.context); + return; + } UIEvent::GlobalUIDialog(dialog) => { self.overlay.push(dialog); return; diff --git a/src/types.rs b/src/types.rs index a3fa8873f..3807f1fde 100644 --- a/src/types.rs +++ b/src/types.rs @@ -126,10 +126,19 @@ pub enum UIEvent { Contacts(ContactEvent), Compose(ComposeEvent), FinishedUIDialog(ComponentId, UIMessage), + Callback(CallbackFn), GlobalUIDialog(Box), Timer(u8), } +pub struct CallbackFn(pub Box () + Send + 'static>); + +impl core::fmt::Debug for CallbackFn { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(fmt, "CallbackFn") + } +} + impl From for UIEvent { fn from(event: RefreshEvent) -> Self { UIEvent::RefreshEvent(Box::new(event))