Add delete, copy actions for envelopes

async
Manos Pitsidianakis 2020-03-01 17:47:23 +02:00
parent 2a9059f9b4
commit 6c76db2063
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
6 changed files with 101 additions and 2 deletions

View File

@ -287,6 +287,9 @@ pub trait MailBackend: ::std::fmt::Debug + Send + Sync {
fn operation(&self, hash: EnvelopeHash) -> Box<dyn BackendOp>;
fn save(&self, bytes: &[u8], mailbox: &str, flags: Option<Flag>) -> Result<()>;
fn delete(&self, env_hash: EnvelopeHash) -> Result<()> {
Err(MeliError::new("Unimplemented."))
}
fn tags(&self) -> Option<Arc<RwLock<BTreeMap<u64, String>>>> {
None
}

View File

@ -954,6 +954,64 @@ impl Component for Composer {
}
UIEvent::Action(ref a) => {
match a {
Action::Compose(ComposeAction::AddAttachmentPipe(ref cmd)) => {
let parts = split_command!(cmd);
if parts.is_empty() {
context.replies.push_back(UIEvent::Notification(
None,
format!("pipe cmd value is invalid: {}", cmd),
Some(NotificationType::ERROR),
));
return false;
}
let (cmd, args) = (parts[0], &parts[1..]);
let f = create_temp_file(&[], None, None, true);
match std::process::Command::new(cmd)
.args(args)
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::from(f.file()))
.spawn()
{
Ok(child) => {
let out = child
.wait_with_output()
.expect("failed to launch cmd")
.stdout;
let mut attachment =
match melib::email::attachment_from_file(f.path()) {
Ok(a) => a,
Err(e) => {
context.replies.push_back(UIEvent::Notification(
Some("could not add attachment".to_string()),
e.to_string(),
Some(NotificationType::ERROR),
));
self.dirty = true;
return true;
}
};
if let Ok(mime_type) = query_mime_info(f.path()) {
match attachment.content_type {
ContentType::Other { ref mut tag, .. } => {
*tag = mime_type;
}
_ => {}
}
}
self.draft.attachments_mut().push(attachment);
self.dirty = true;
return true;
}
Err(err) => {
context.replies.push_back(UIEvent::Notification(
None,
format!("could not execute pipe cmd: {}", cmd),
Some(NotificationType::ERROR),
));
return true;
}
}
}
Action::Compose(ComposeAction::AddAttachment(ref path)) => {
let mut attachment = match melib::email::attachment_from_file(path) {
Ok(a) => a,

View File

@ -146,7 +146,7 @@ pub trait MailListingTrait: ListingTrait {
);
}
for env_hash in envs_to_set {
let op = account.operation(env_hash);
let mut op = account.operation(env_hash);
let mut envelope: EnvelopeRefMut = account.collection.get_env_mut(env_hash);
match a {
ListingAction::SetSeen => {
@ -164,7 +164,30 @@ pub trait MailListingTrait: ListingTrait {
}
}
ListingAction::Delete => {
/* do nothing */
drop(envelope);
if let Err(err) = account.delete(env_hash) {
context.replies.push_back(UIEvent::Notification(
Some("Could not delete.".to_string()),
err.to_string(),
Some(NotificationType::ERROR),
));
return;
}
continue;
}
ListingAction::CopyTo(ref mailbox_path) => {
drop(envelope);
if let Err(err) = op
.as_bytes()
.and_then(|bytes| account.save(bytes, mailbox_path, None))
{
context.replies.push_back(UIEvent::Notification(
Some("Could not copy.".to_string()),
err.to_string(),
Some(NotificationType::ERROR),
));
return;
}
continue;
}
ListingAction::Tag(Remove(ref tag_str)) => {

View File

@ -876,6 +876,16 @@ impl Account {
self.backend.write().unwrap().save(bytes, mailbox, flags)
}
pub fn delete(&self, env_hash: EnvelopeHash) -> Result<()> {
if self.settings.account.read_only() {
return Err(MeliError::new(format!(
"Account {} is read-only.",
self.name.as_str()
)));
}
self.backend.write().unwrap().delete(env_hash)
}
pub fn contains_key(&self, h: EnvelopeHash) -> bool {
self.collection.contains_key(&h)
}

View File

@ -79,6 +79,10 @@ define_commands!([
| map!(ws!(tag!("unseen")), |_| Listing(SetUnseen))
)
) | map!(preceded!(tag!("delete"), eof!()), |_| Listing(Delete))
| do_parse!(tag!("copyto")
>> is_a!(" ")
>> path: quoted_argument
>> ({ Listing(CopyTo(path.to_string())) }))
)
); )
},

View File

@ -46,6 +46,7 @@ pub enum ListingAction {
Search(String),
SetSeen,
SetUnseen,
CopyTo(MailboxPath),
Delete,
OpenInNewTab,
Tag(TagAction),