From 3495ffd61b5888f8538304ecb6e441819b373bdc Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sun, 26 Nov 2023 20:36:02 +0200 Subject: [PATCH] types: Change UIEvent::Notification structure Signed-off-by: Manos Pitsidianakis --- meli/src/accounts.rs | 280 ++++++++++++---------- meli/src/mail/compose.rs | 306 ++++++++++++++----------- meli/src/mail/listing.rs | 44 ++-- meli/src/mail/listing/compact.rs | 44 ++-- meli/src/mail/listing/conversations.rs | 12 +- meli/src/mail/listing/plain.rs | 44 ++-- meli/src/mail/listing/thread.rs | 12 +- meli/src/mail/view.rs | 22 +- meli/src/mail/view/envelope.rs | 100 ++++---- meli/src/mail/view/html.rs | 28 +-- meli/src/mailbox_management.rs | 12 +- meli/src/notifications.rs | 22 +- meli/src/state.rs | 74 +++--- meli/src/svg.rs | 11 +- meli/src/types.rs | 8 +- tools/src/embedded.rs | 62 ++--- tools/src/managesieve.rs | 1 - 17 files changed, 603 insertions(+), 479 deletions(-) diff --git a/meli/src/accounts.rs b/meli/src/accounts.rs index a1152624..011fd3a0 100644 --- a/meli/src/accounts.rs +++ b/meli/src/accounts.rs @@ -932,16 +932,18 @@ impl Account { return Some(UIEvent::MailboxUpdate((self.hash, mailbox_hash))); } - return Some(Notification( - Some(format!("new e-mail from: {}", from)), - format!( + return Some(Notification { + title: Some(format!("new e-mail from: {}", from).into()), + body: format!( "{}\n{} {}", subject, self.name, self.mailbox_entries[&mailbox_hash].name() - ), - Some(crate::types::NotificationType::NewMail), - )); + ) + .into(), + source: None, + kind: Some(crate::types::NotificationType::NewMail), + }); } RefreshEventKind::Remove(env_hash) => { if !self.collection.contains_key(&env_hash) { @@ -987,21 +989,13 @@ impl Account { let j = self.active_jobs.remove(&job_id); drop(j); } - /* - context - .1 - .send(ThreadEvent::UIEvent(UIEvent::Notification( - Some(format!("{} watcher exited with error", &self.name)), - e.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - ))); - */ self.watch(); - return Some(Notification( - Some("Account watch failed".into()), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + return Some(Notification { + title: Some("Account watch failed".into()), + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + source: Some(err), + }); } RefreshEventKind::MailboxCreate(_new_mailbox) => {} RefreshEventKind::MailboxDelete(_mailbox_hash) => {} @@ -1699,11 +1693,14 @@ impl Account { if let Err(err) = mailboxes.and_then(|mailboxes| self.init(mailboxes)) { if err.kind.is_authentication() { self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!("{}: authentication error", &self.name)), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - ), + UIEvent::Notification { + title: Some( + format!("{}: authentication error", &self.name).into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }, )); self.is_online.set_err(err); self.main_loop_handler.send(ThreadEvent::UIEvent( @@ -1771,11 +1768,14 @@ impl Account { .job_executor .set_job_success(job_id, false); self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!("{}: could not fetch mailbox", &self.name)), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - ), + UIEvent::Notification { + title: Some( + format!("{}: could not fetch mailbox", &self.name).into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }, )); self.mailbox_entries .entry(mailbox_hash) @@ -1895,11 +1895,12 @@ impl Account { .job_executor .set_job_success(job_id, false); self.main_loop_handler - .send(ThreadEvent::UIEvent(UIEvent::Notification( - Some(format!("{}: could not set flag", &self.name)), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - ))); + .send(ThreadEvent::UIEvent(UIEvent::Notification { + title: Some(format!("{}: could not set flag", &self.name).into()), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + })); } Ok(Some(Ok(()))) => { for env_hash in env_hashes.iter() { @@ -1972,15 +1973,20 @@ impl Account { file.path().display() ); self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!("{}: could not save message", &self.name)), - format!( + UIEvent::Notification { + title: Some( + format!("{}: could not save message", &self.name) + .into(), + ), + source: None, + body: format!( "Message was stored in {} so that you can restore it \ manually.", file.path().display() - ), - Some(crate::types::NotificationType::Info), - ), + ) + .into(), + kind: Some(crate::types::NotificationType::Info), + }, )); } Err(err) => log::error!("Could not save message: {err}"), @@ -1994,11 +2000,12 @@ impl Account { .job_executor .set_job_success(job_id, false); self.main_loop_handler - .send(ThreadEvent::UIEvent(UIEvent::Notification( - Some("Could not send message".to_string()), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - ))); + .send(ThreadEvent::UIEvent(UIEvent::Notification { + title: Some("Could not send message".into()), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + })); } } JobRequest::DeleteMessages { ref mut handle, .. } => { @@ -2007,11 +2014,14 @@ impl Account { .job_executor .set_job_success(job_id, false); self.main_loop_handler - .send(ThreadEvent::UIEvent(UIEvent::Notification( - Some(format!("{}: could not delete message", &self.name)), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - ))); + .send(ThreadEvent::UIEvent(UIEvent::Notification { + title: Some( + format!("{}: could not delete message", &self.name).into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + })); } } JobRequest::CreateMailbox { @@ -2026,14 +2036,18 @@ impl Account { .job_executor .set_job_success(job_id, false); self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!( - "{}: could not create mailbox {}", - &self.name, path - )), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - ), + UIEvent::Notification { + title: Some( + format!( + "{}: could not create mailbox {}", + &self.name, path + ) + .into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }, )); } Ok((mailbox_hash, mut mailboxes)) => { @@ -2114,11 +2128,14 @@ impl Account { .job_executor .set_job_success(job_id, false); self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!("{}: could not delete mailbox", &self.name)), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - ), + UIEvent::Notification { + title: Some( + format!("{}: could not delete mailbox", &self.name).into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }, )); } Ok(Some(Ok(mut mailboxes))) => { @@ -2167,11 +2184,15 @@ impl Account { // [ref:FIXME] remove from settings as well self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!("{}: mailbox deleted successfully", &self.name)), - String::new(), - Some(crate::types::NotificationType::Info), - ), + UIEvent::Notification { + title: Some( + format!("{}: mailbox deleted successfully", &self.name) + .into(), + ), + source: None, + body: "".into(), + kind: Some(crate::types::NotificationType::Info), + }, )); } } @@ -2186,26 +2207,34 @@ impl Account { .job_executor .set_job_success(job_id, false); self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!( - "{}: could not set mailbox permissions", - &self.name - )), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - ), + UIEvent::Notification { + title: Some( + format!( + "{}: could not set mailbox permissions", + &self.name + ) + .into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }, )); } Ok(Some(Ok(_))) => { self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!( - "{}: mailbox permissions set successfully", - &self.name - )), - String::new(), - Some(crate::types::NotificationType::Info), - ), + UIEvent::Notification { + title: Some( + format!( + "{}: mailbox permissions set successfully", + &self.name + ) + .into(), + ), + source: None, + body: "".into(), + kind: Some(crate::types::NotificationType::Info), + }, )); } } @@ -2223,14 +2252,18 @@ impl Account { .job_executor .set_job_success(job_id, false); self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!( - "{}: could not set mailbox subscription", - &self.name - )), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - ), + UIEvent::Notification { + title: Some( + format!( + "{}: could not set mailbox subscription", + &self.name + ) + .into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }, )); } Ok(Some(Ok(()))) if self.mailbox_entries.contains_key(mailbox_hash) => { @@ -2243,16 +2276,20 @@ impl Account { let _ = m.ref_mailbox.set_is_subscribed(*new_value); }); self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!( - "{}: `{}` has been {}subscribed.", - &self.name, - self.mailbox_entries[mailbox_hash].name(), - if *new_value { "" } else { "un" } - )), - String::new(), - Some(crate::types::NotificationType::Info), - ), + UIEvent::Notification { + title: Some( + format!( + "{}: `{}` has been {}subscribed.", + &self.name, + self.mailbox_entries[mailbox_hash].name(), + if *new_value { "" } else { "un" } + ) + .into(), + ), + source: None, + body: "".into(), + kind: Some(crate::types::NotificationType::Info), + }, )); } Ok(Some(Ok(()))) => {} @@ -2269,11 +2306,14 @@ impl Account { .set_job_success(job_id, false); // [ref:TODO]: relaunch watch job with ratelimit for failure self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!("{}: watch thread failed", &self.name)), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - ), + UIEvent::Notification { + title: Some( + format!("{}: watch thread failed", &self.name).into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }, )); } } @@ -2290,21 +2330,25 @@ impl Account { .job_executor .set_job_success(job_id, false); self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!("{}: {} failed", &self.name, name,)), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - ), + UIEvent::Notification { + title: Some(format!("{}: {} failed", &self.name, name,).into()), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }, )); } Ok(Some(Ok(()))) if on_finish.is_none() => { if log_level <= LogLevel::INFO { self.main_loop_handler.send(ThreadEvent::UIEvent( - UIEvent::Notification( - Some(format!("{}: {} succeeded", &self.name, name,)), - String::new(), - Some(crate::types::NotificationType::Info), - ), + UIEvent::Notification { + title: Some( + format!("{}: {} succeeded", &self.name, name,).into(), + ), + source: None, + body: "".into(), + kind: Some(crate::types::NotificationType::Info), + }, )); } } diff --git a/meli/src/mail/compose.rs b/meli/src/mail/compose.rs index 686deff4..2b8eff01 100644 --- a/meli/src/mail/compose.rs +++ b/meli/src/mail/compose.rs @@ -843,11 +843,14 @@ To: {} true } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not parse draft headers correctly.".to_string()), - format!("{err}\nThe invalid text has been set as the body of your draft",), - Some(NotificationType::Error(melib::error::ErrorKind::None)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Could not parse draft headers correctly.".into()), + source: None, + body: + format!("{err}\nThe invalid text has been set as the body of your draft",) + .into(), + kind: Some(NotificationType::Error(melib::error::ErrorKind::None)), + }); self.has_changes = true; false } @@ -1209,11 +1212,12 @@ impl Component for Composer { ); } Err(err) => { - context.replies.push_back(UIEvent::Notification( - None, - err.to_string(), - Some(NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(err.kind)), + }); save_draft( self.draft.clone().finalise().unwrap().as_bytes(), context, @@ -1355,11 +1359,12 @@ impl Component for Composer { }) { Err(err) | Ok(Some(Err(err))) => { self.mode = ViewMode::Edit; - context.replies.push_back(UIEvent::Notification( - None, - err.to_string(), - Some(NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(err.kind)), + }); self.set_dirty(true); } Ok(None) | Ok(Some(Ok(()))) => { @@ -1482,11 +1487,12 @@ impl Component for Composer { }) .collect::>() { - context.replies.push_back(UIEvent::Notification( - None, - err.to_string(), - None, - )); + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: err.to_string().into(), + kind: None, + }); } } self.mode = ViewMode::Send(UIConfirmationDialog::new( @@ -1529,16 +1535,17 @@ impl Component for Composer { drop(embedded_guard); let embedded_pty = self.embedded_pty.take(); if exit_code != 0 { - context.replies.push_back(UIEvent::Notification( - None, - format!( - "Subprocess has exited with exit code {}", - exit_code - ), - Some(NotificationType::Error( + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: format!( + "Subprocess has exited with exit code {exit_code}", + ) + .into(), + kind: Some(NotificationType::Error( melib::error::ErrorKind::External, )), - )); + }); } else if let Some(EmbeddedPty { running: true, file, @@ -1608,13 +1615,15 @@ impl Component for Composer { } Ok(WaitStatus::Signaled(_, signal, _)) => { drop(embedded_guard); - context.replies.push_back(UIEvent::Notification( - None, - format!("Subprocess was killed by {} signal", signal), - Some(NotificationType::Error( + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: format!("Subprocess was killed by {signal} signal") + .into(), + kind: Some(NotificationType::Error( melib::error::ErrorKind::External, )), - )); + }); self.initialized = false; self.embedded_pty = None; self.mode = ViewMode::Edit; @@ -1623,13 +1632,14 @@ impl Component for Composer { .push_back(UIEvent::ChangeMode(UIMode::Normal)); } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("Embedded editor crashed.".to_string()), - format!("Subprocess has exited with reason {}", &err), - Some(NotificationType::Error( + context.replies.push_back(UIEvent::Notification { + title: Some("Embedded editor crashed.".into()), + source: None, + body: format!("Subprocess has exited with reason {err}").into(), + kind: Some(NotificationType::Error( melib::error::ErrorKind::External, )), - )); + }); drop(embedded_guard); self.initialized = false; self.embedded_pty = None; @@ -1674,11 +1684,12 @@ impl Component for Composer { self.mode = ViewMode::SelectEncryptKey(false, widget); } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not list keys.".to_string()), - format!("libgpgme error: {}", &err), - Some(NotificationType::Error(melib::error::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Could not list keys.".into()), + source: None, + body: format!("libgpgme error: {err}").into(), + kind: Some(NotificationType::Error(melib::error::ErrorKind::External)), + }); } } self.set_dirty(true); @@ -1714,11 +1725,12 @@ impl Component for Composer { self.mode = ViewMode::SelectEncryptKey(true, widget); } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not list keys.".to_string()), - format!("libgpgme error: {}", &err), - Some(NotificationType::Error(melib::error::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Could not list keys.".into()), + source: None, + body: format!("libgpgme error: {err}").into(), + kind: Some(NotificationType::Error(melib::error::ErrorKind::External)), + }); } } self.set_dirty(true); @@ -1775,11 +1787,12 @@ impl Component for Composer { guard.terminate(); self.update_from_file(file, context); } - context.replies.push_back(UIEvent::Notification( - None, - "Subprocess was killed by SIGTERM signal".to_string(), - Some(NotificationType::Error(melib::error::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: "Subprocess was killed by SIGTERM signal".into(), + kind: Some(NotificationType::Error(melib::error::ErrorKind::External)), + }); self.initialized = false; self.mode = ViewMode::Edit; context @@ -1800,13 +1813,15 @@ impl Component for Composer { } else { match std::env::var("EDITOR") { Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some(err.to_string()), - "$EDITOR is not set. You can change an envvar's value with setenv \ - or set composing.editor_command setting in your configuration." - .to_string(), - Some(NotificationType::Error(melib::error::ErrorKind::None)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some(err.to_string().into()), + source: None, + body: "$EDITOR is not set. You can change an envvar's value with \ + setenv or set composing.editor_command setting in your \ + configuration." + .into(), + kind: Some(NotificationType::Error(melib::error::ErrorKind::None)), + }); self.set_dirty(true); return true; } @@ -1829,11 +1844,12 @@ impl Component for Composer { ) { Ok(f) => f, Err(err) => { - context.replies.push_back(UIEvent::Notification( - None, - err.to_string(), - Some(NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(err.kind)), + }); self.set_dirty(true); return true; } @@ -1866,11 +1882,16 @@ impl Component for Composer { self.mode = ViewMode::EmbeddedPty; } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some(format!("Failed to create pseudoterminal: {}", err)), - err.to_string(), - Some(NotificationType::Error(melib::error::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some( + format!("Failed to create pseudoterminal: {}", err).into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error( + melib::error::ErrorKind::External, + )), + }); } } self.set_dirty(true); @@ -1896,11 +1917,12 @@ impl Component for Composer { let _ = child.wait(); } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some(format!("Failed to execute {}: {}", editor, err)), - err.to_string(), - Some(NotificationType::Error(melib::error::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some(format!("Failed to execute {}: {}", editor, err).into()), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(melib::error::ErrorKind::External)), + }); context.replies.push_back(UIEvent::Fork(ForkType::Finished)); context.restore_input(); self.set_dirty(true); @@ -1918,13 +1940,15 @@ impl Component for Composer { self.has_changes = has_changes; } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not parse draft headers correctly.".to_string()), - format!( + context.replies.push_back(UIEvent::Notification { + title: Some("Could not parse draft headers correctly.".into()), + source: None, + body: format!( "{err}\nThe invalid text has been set as the body of your draft", - ), - Some(NotificationType::Error(melib::error::ErrorKind::None)), - )); + ) + .into(), + kind: Some(NotificationType::Error(melib::error::ErrorKind::None)), + }); self.has_changes = true; } } @@ -1935,11 +1959,12 @@ impl Component for Composer { UIEvent::Action(ref a) => match a { Action::Compose(ComposeAction::AddAttachmentPipe(ref command)) => { if command.is_empty() { - context.replies.push_back(UIEvent::Notification( - None, - format!("pipe command value is invalid: {}", command), - Some(NotificationType::Error(melib::error::ErrorKind::None)), - )); + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: format!("pipe command value is invalid: {command}").into(), + kind: Some(NotificationType::Error(melib::error::ErrorKind::None)), + }); return false; } match File::create_temp_file(&[], None, None, None, true) @@ -1969,13 +1994,14 @@ impl Component for Composer { match melib::email::compose::attachment_from_file(&f.path()) { Ok(a) => a, Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("could not add attachment".to_string()), - err.to_string(), - Some(NotificationType::Error( + context.replies.push_back(UIEvent::Notification { + title: Some("could not add attachment".into()), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error( melib::error::ErrorKind::None, )), - )); + }); self.set_dirty(true); return true; } @@ -1986,11 +2012,15 @@ impl Component for Composer { return true; } Err(err) => { - context.replies.push_back(UIEvent::Notification( - None, - format!("could not execute pipe command {}: {}", command, &err), - Some(NotificationType::Error(melib::error::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: format!("could not execute pipe command {command}: {err}") + .into(), + kind: Some(NotificationType::Error( + melib::error::ErrorKind::External, + )), + }); self.set_dirty(true); return true; } @@ -2000,11 +2030,12 @@ impl Component for Composer { let attachment = match melib::email::compose::attachment_from_file(path) { Ok(a) => a, Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("could not add attachment".to_string()), - err.to_string(), - Some(NotificationType::Error(melib::error::ErrorKind::None)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("could not add attachment".into()), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(melib::error::ErrorKind::None)), + }); self.set_dirty(true); return true; } @@ -2022,13 +2053,14 @@ impl Component for Composer { { cmd.as_str() } else { - context.replies.push_back(UIEvent::Notification( - None, - "You haven't defined any command to launch in \ - [terminal.file_picker_command]." + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: "You haven't defined any command to launch in \ + [terminal.file_picker_command]." .into(), - Some(NotificationType::Error(melib::error::ErrorKind::None)), - )); + kind: Some(NotificationType::Error(melib::error::ErrorKind::None)), + }); self.set_dirty(true); return true; }; @@ -2057,27 +2089,36 @@ impl Component for Composer { self.has_changes = true; } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some(format!( - "could not add attachment: {}", - String::from_utf8_lossy(path) - )), - err.to_string(), - Some(NotificationType::Error( + context.replies.push_back(UIEvent::Notification { + title: Some( + format!( + "could not add attachment: {}", + String::from_utf8_lossy(path) + ) + .into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error( melib::error::ErrorKind::None, )), - )); + }); } }; } } Err(err) => { let command = command.to_string(); - context.replies.push_back(UIEvent::Notification( - Some(format!("Failed to execute {}: {}", command, err)), - err.to_string(), - Some(NotificationType::Error(melib::error::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some( + format!("Failed to execute {}: {}", command, err).into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error( + melib::error::ErrorKind::External, + )), + }); context.restore_input(); self.set_dirty(true); return true; @@ -2409,21 +2450,24 @@ pub fn save_draft( kind, .. }) => { - context.replies.push_back(UIEvent::Notification( - details.map(|s| s.into()), - summary.to_string(), - Some(NotificationType::Error(kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: details, + source: None, + body: summary, + kind: Some(NotificationType::Error(kind)), + }); } Ok(mailbox_hash) => { - context.replies.push_back(UIEvent::Notification( - Some("Message saved".into()), - format!( + context.replies.push_back(UIEvent::Notification { + title: Some("Message saved".into()), + source: None, + body: format!( "Message saved in `{}`", &context.accounts[&account_hash].mailbox_entries[&mailbox_hash].name - ), - Some(NotificationType::Info), - )); + ) + .into(), + kind: Some(NotificationType::Info), + }); } } } diff --git a/meli/src/mail/listing.rs b/meli/src/mail/listing.rs index e043c29e..0566de6e 100644 --- a/meli/src/mail/listing.rs +++ b/meli/src/mail/listing.rs @@ -780,21 +780,24 @@ pub trait MailListingTrait: ListingTrait { handle, on_finish: Some(CallbackFn(Box::new(move |context: &mut Context| { context.replies.push_back(match receiver.try_recv() { - Err(_) | Ok(None) => UIEvent::Notification( - Some("Could not export mbox".to_string()), - "Job was canceled.".to_string(), - Some(NotificationType::Info), - ), - Ok(Some(Err(err))) => UIEvent::Notification( - Some("Could not export mbox".to_string()), - err.to_string(), - Some(NotificationType::Error(err.kind)), - ), - Ok(Some(Ok(path))) => UIEvent::Notification( - Some("Succesfully exported mbox".to_string()), - format!("Wrote to file {}", path.display()), - Some(NotificationType::Info), - ), + Err(_) | Ok(None) => UIEvent::Notification { + title: Some("Could not export mbox".into()), + source: None, + body: "Job was canceled.".into(), + kind: Some(NotificationType::Info), + }, + Ok(Some(Err(err))) => UIEvent::Notification { + title: Some("Could not export mbox".into()), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(err.kind)), + }, + Ok(Some(Ok(path))) => UIEvent::Notification { + title: Some("Succesfully exported mbox".into()), + source: None, + body: format!("Wrote to file {}", path.display()).into(), + kind: Some(NotificationType::Info), + }, }); }))), log_level: LogLevel::INFO, @@ -1827,11 +1830,12 @@ impl Component for Listing { if let MenuEntryCursor::Mailbox(idx) = self.cursor_pos.menu { if let Some(&mailbox_hash) = account.mailboxes_order.get(idx) { if let Err(err) = account.refresh(mailbox_hash) { - context.replies.push_back(UIEvent::Notification( - Some("Could not refresh.".to_string()), - err.to_string(), - Some(NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Could not refresh.".into()), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(err.kind)), + }); } } } diff --git a/meli/src/mail/listing/compact.rs b/meli/src/mail/listing/compact.rs index de52565f..d0f10c0a 100644 --- a/meli/src/mail/listing/compact.rs +++ b/meli/src/mail/listing/compact.rs @@ -1563,11 +1563,12 @@ impl CompactListing { search_term, &err ); log::error!("{}", message); - context.replies.push_back(UIEvent::Notification( - Some("Could not perform search".to_string()), - message, - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Could not perform search".into()), + source: None, + body: message.into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }); } } } @@ -2033,11 +2034,12 @@ impl Component for CompactListing { self.search_job = Some((filter_term.to_string(), handle)); } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not perform search".to_string()), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Could not perform search".into()), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }); } }; self.set_dirty(true); @@ -2061,11 +2063,12 @@ impl Component for CompactListing { } } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not perform search".to_string()), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Could not perform search".into()), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }); } }; self.set_dirty(true); @@ -2084,11 +2087,12 @@ impl Component for CompactListing { Ok(None) => { /* something happened, perhaps a worker thread panicked */ } Ok(Some(Ok(results))) => self.filter(filter_term, results, context), Ok(Some(Err(err))) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not perform search".to_string()), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Could not perform search".into()), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }); } } self.set_dirty(true); diff --git a/meli/src/mail/listing/conversations.rs b/meli/src/mail/listing/conversations.rs index 7f560002..5fd604f6 100644 --- a/meli/src/mail/listing/conversations.rs +++ b/meli/src/mail/listing/conversations.rs @@ -1476,11 +1476,7 @@ impl Component for ConversationsListing { self.search_job = Some((filter_term.to_string(), handle)); } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not perform search".to_string()), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { title: Some("Could not perform search".into()), source: None, body: err.to_string().into(), kind: Some(crate::types::NotificationType::Error(err.kind)), }); } }; self.set_dirty(true); @@ -1522,11 +1518,7 @@ impl Component for ConversationsListing { Ok(None) => { /* something happened, perhaps a worker thread panicked */ } Ok(Some(Ok(results))) => self.filter(filter_term, results, context), Ok(Some(Err(err))) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not perform search".to_string()), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { title: Some("Could not perform search".into()), source: None, body: err.to_string().into(), kind: Some(crate::types::NotificationType::Error(err.kind)), }); } } self.set_dirty(true); diff --git a/meli/src/mail/listing/plain.rs b/meli/src/mail/listing/plain.rs index f2633ca0..17d6faeb 100644 --- a/meli/src/mail/listing/plain.rs +++ b/meli/src/mail/listing/plain.rs @@ -1313,11 +1313,12 @@ impl PlainListing { search_term, &err ); log::error!("{}", message); - context.replies.push_back(UIEvent::Notification( - Some("Could not perform search".to_string()), - message, - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Could not perform search".into()), + source: None, + body: message.into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }); } } } @@ -1756,11 +1757,12 @@ impl Component for PlainListing { self.search_job = Some((filter_term.to_string(), handle)); } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not perform search".to_string()), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Could not perform search".into()), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }); } }; self.set_dirty(true); @@ -1784,11 +1786,12 @@ impl Component for PlainListing { } } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not perform search".to_string()), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Could not perform search".into()), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }); } }; self.set_dirty(true); @@ -1807,11 +1810,12 @@ impl Component for PlainListing { Ok(None) => { /* something happened, perhaps a worker thread panicked */ } Ok(Some(Ok(results))) => self.filter(filter_term, results, context), Ok(Some(Err(err))) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not perform search".to_string()), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Could not perform search".into()), + source: None, + body: err.to_string().into(), + kind: Some(crate::types::NotificationType::Error(err.kind)), + }); } } self.set_dirty(true); diff --git a/meli/src/mail/listing/thread.rs b/meli/src/mail/listing/thread.rs index 0337d8ab..5cbd2134 100644 --- a/meli/src/mail/listing/thread.rs +++ b/meli/src/mail/listing/thread.rs @@ -1613,11 +1613,7 @@ impl Component for ThreadListing { self.search_job = Some((filter_term.to_string(), handle)); } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not perform search".to_string()), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { title: Some("Could not perform search".into()), source: None, body: err.to_string().into(), kind: Some(crate::types::NotificationType::Error(err.kind)), }); } }; self.set_dirty(true); @@ -1638,11 +1634,7 @@ impl Component for ThreadListing { Ok(None) => { /* something happened, perhaps a worker thread panicked */ } Ok(Some(Ok(results))) => self.filter(filter_term, results, context), Ok(Some(Err(err))) => { - context.replies.push_back(UIEvent::Notification( - Some("Could not perform search".to_string()), - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { title: Some("Could not perform search".into()), source: None, body: err.to_string().into(), kind: Some(crate::types::NotificationType::Error(err.kind)), }); } } self.set_dirty(true); diff --git a/meli/src/mail/view.rs b/meli/src/mail/view.rs index 39677c42..5fec9b77 100644 --- a/meli/src/mail/view.rs +++ b/meli/src/mail/view.rs @@ -327,11 +327,12 @@ impl Component for MailView { } else if let MailViewState::Error { ref err } = self.state { grid.clear_area(area, self.theme_default); context.dirty_areas.push_back(area); - context.replies.push_back(UIEvent::Notification( - Some("Failed to open e-mail".to_string()), - err.to_string(), - Some(NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Failed to open e-mail".into()), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(err.kind)), + }); log::error!("Failed to open envelope: {err}"); self.init_futures(context); return; @@ -575,11 +576,12 @@ impl Component for MailView { err ); log::error!("{err_string}"); - context.replies.push_back(UIEvent::Notification( - Some("Failed to open e-mail".to_string()), - err_string, - Some(NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Failed to open e-mail".into()), + source: None, + body: err_string.into(), + kind: Some(NotificationType::Error(err.kind)), + }); } } } diff --git a/meli/src/mail/view/envelope.rs b/meli/src/mail/view/envelope.rs index 9af9c489..a1a08cd7 100644 --- a/meli/src/mail/view/envelope.rs +++ b/meli/src/mail/view/envelope.rs @@ -144,14 +144,15 @@ impl EnvelopeView { }); match command_obj { Err(err) => { - main_loop_handler.send(ThreadEvent::UIEvent(UIEvent::Notification( - Some(format!( - "Failed to start html filter process: {}", - filter_invocation, - )), - err.to_string(), - Some(NotificationType::Error(melib::ErrorKind::External)), - ))); + main_loop_handler.send(ThreadEvent::UIEvent(UIEvent::Notification { + title: Some( + format!("Failed to start html filter process: {}", filter_invocation,) + .into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(melib::ErrorKind::External)), + })); // [ref:FIXME]: add `v` configurable shortcut let comment = Some(format!( "Failed to start html filter process: `{}`. Press `v` to open in web \ @@ -1385,20 +1386,24 @@ impl Component for EnvelopeView { } match save_attachment(&path, &self.mail.bytes) { Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some(format!("Failed to create file at {}", path.display())), - err.to_string(), - Some(NotificationType::Error(melib::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some( + format!("Failed to create file at {}", path.display()).into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(melib::ErrorKind::External)), + }); log::error!("Failed to create file at {}: {err}", path.display()); return true; } Ok(()) => { - context.replies.push_back(UIEvent::Notification( - None, - format!("Saved at {}", &path.display()), - Some(NotificationType::Info), - )); + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: format!("Saved at {}", &path.display()).into(), + kind: Some(NotificationType::Info), + }); } } @@ -1423,19 +1428,23 @@ impl Component for EnvelopeView { } match save_attachment(&path, &u.decode(Default::default())) { Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some(format!("Failed to create file at {}", path.display())), - err.to_string(), - Some(NotificationType::Error(melib::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some( + format!("Failed to create file at {}", path.display()).into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(melib::ErrorKind::External)), + }); log::error!("Failed to create file at {}: {err}", path.display()); } Ok(()) => { - context.replies.push_back(UIEvent::Notification( - None, - format!("Saved at {}", path.display()), - Some(NotificationType::Info), - )); + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: format!("Saved at {}", path.display()).into(), + kind: Some(NotificationType::Info), + }); } } } else if a_i == 0 { @@ -1448,20 +1457,24 @@ impl Component for EnvelopeView { } match save_attachment(&path, &self.mail.bytes) { Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some(format!("Failed to create file at {}", path.display())), - err.to_string(), - Some(NotificationType::Error(melib::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some( + format!("Failed to create file at {}", path.display()).into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(melib::ErrorKind::External)), + }); log::error!("Failed to create file at {}: {err}", path.display()); return true; } Ok(()) => { - context.replies.push_back(UIEvent::Notification( - None, - format!("Saved at {}", &path.display()), - Some(NotificationType::Info), - )); + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: format!("Saved at {}", &path.display()).into(), + kind: Some(NotificationType::Info), + }); } } @@ -1651,11 +1664,12 @@ impl Component for EnvelopeView { context.children.push(child); } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some(format!("Failed to launch {:?}", url_launcher)), - err.to_string(), - Some(NotificationType::Error(melib::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some(format!("Failed to launch {:?}", url_launcher).into()), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(melib::ErrorKind::External)), + }); } } return true; diff --git a/meli/src/mail/view/html.rs b/meli/src/mail/view/html.rs index f6854666..be8a09c3 100644 --- a/meli/src/mail/view/html.rs +++ b/meli/src/mail/view/html.rs @@ -61,14 +61,15 @@ impl HtmlView { .spawn(); match command_obj { Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some(format!( - "Failed to start html filter process: {}", - filter_invocation, - )), - err.to_string(), - Some(NotificationType::Error(melib::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some( + format!("Failed to start html filter process: {}", filter_invocation,) + .into(), + ), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(melib::ErrorKind::External)), + }); String::from_utf8_lossy(&bytes).to_string() } Ok(mut html_filter) => { @@ -108,11 +109,12 @@ impl HtmlView { display_text } else { - context.replies.push_back(UIEvent::Notification( - Some("Failed to find any application to use as html filter".to_string()), - String::new(), - Some(NotificationType::Error(melib::error::ErrorKind::None)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Failed to find any application to use as html filter".into()), + source: None, + body: "".into(), + kind: Some(NotificationType::Error(melib::error::ErrorKind::None)), + }); String::from_utf8_lossy(&bytes).to_string() }; if body.count_attachments() > 1 { diff --git a/meli/src/mailbox_management.rs b/meli/src/mailbox_management.rs index 93fbaf40..14e4a861 100644 --- a/meli/src/mailbox_management.rs +++ b/meli/src/mailbox_management.rs @@ -373,11 +373,7 @@ impl Component for MailboxManager { .to_string(), )) { - context.replies.push_back(UIEvent::Notification( - None, - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { title: None, source: None, body: err.to_string().into(), kind: Some(crate::types::NotificationType::Error(err.kind)), }); } } MailboxAction::Unsubscribe => { @@ -389,11 +385,7 @@ impl Component for MailboxManager { .to_string(), )) { - context.replies.push_back(UIEvent::Notification( - None, - err.to_string(), - Some(crate::types::NotificationType::Error(err.kind)), - )); + context.replies.push_back(UIEvent::Notification { title: None, source: None, body: err.to_string().into(), kind: Some(crate::types::NotificationType::Error(err.kind)), }); } } } diff --git a/meli/src/notifications.rs b/meli/src/notifications.rs index 11163471..4dbad419 100644 --- a/meli/src/notifications.rs +++ b/meli/src/notifications.rs @@ -68,7 +68,13 @@ mod dbus { return false; } - if let UIEvent::Notification(ref title, ref body, ref kind) = event { + if let UIEvent::Notification { + ref title, + source: _, + ref body, + ref kind, + } = event + { if !self.rate_limit.tick() { return false; } @@ -77,7 +83,7 @@ mod dbus { let mut notification = notify_rust::Notification::new(); notification .appname("meli") - .summary(title.as_ref().map(String::as_str).unwrap_or("meli")) + .summary(title.as_ref().map(<_>::as_ref).unwrap_or("meli")) .body(&escape_str(body)); match *kind { Some(NotificationType::NewMail) => { @@ -191,7 +197,13 @@ impl Component for NotificationCommand { fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {} fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { - if let UIEvent::Notification(ref title, ref body, ref kind) = event { + if let UIEvent::Notification { + ref title, + source: _, + ref body, + ref kind, + } = event + { if context.settings.notifications.enable { if *kind == Some(NotificationType::NewMail) { if let Some(ref path) = context.settings.notifications.xbiff_file_path { @@ -211,8 +223,8 @@ impl Component for NotificationCommand { if let Some(ref bin) = script { match Command::new(bin) .arg(&kind.map(|k| k.to_string()).unwrap_or_default()) - .arg(title.as_ref().map(String::as_str).unwrap_or("meli")) - .arg(body) + .arg(title.as_ref().map(<_>::as_ref).unwrap_or("meli")) + .arg(body.as_ref()) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn() diff --git a/meli/src/state.rs b/meli/src/state.rs index 2dfa9af2..7aac8c12 100644 --- a/meli/src/state.rs +++ b/meli/src/state.rs @@ -491,7 +491,7 @@ impl State { } = &mut *self.context; if let Some(notification) = accounts[&account_hash].reload(event, mailbox_hash) { - if let UIEvent::Notification(_, _, _) = notification { + if matches!(notification, UIEvent::Notification { .. }) { self.rcv_event(UIEvent::MailboxUpdate((account_hash, mailbox_hash))); } self.rcv_event(notification); @@ -775,11 +775,12 @@ impl State { { a } else { - self.context.replies.push_back(UIEvent::Notification( - None, - format!("Account {} was not found.", account_name), - Some(NotificationType::Error(ErrorKind::None)), - )); + self.context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: format!("Account {account_name} was not found.").into(), + kind: Some(NotificationType::Error(ErrorKind::None)), + }); return; }; if *self.context.accounts[account_index] @@ -788,14 +789,15 @@ impl State { .search_backend() != crate::conf::SearchBackend::Sqlite3 { - self.context.replies.push_back(UIEvent::Notification( - None, - format!( - "Account {} doesn't have an sqlite3 search backend.", - account_name - ), - Some(NotificationType::Error(ErrorKind::None)), - )); + self.context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: format!( + "Account {account_name} doesn't have an sqlite3 search backend.", + ) + .into(), + kind: Some(NotificationType::Error(ErrorKind::None)), + }); return; } match crate::sqlite3::index(&mut self.context, account_index) { @@ -814,29 +816,32 @@ impl State { log_level: LogLevel::INFO, }, ); - self.context.replies.push_back(UIEvent::Notification( - None, - "Message index rebuild started.".to_string(), - Some(NotificationType::Info), - )); + self.context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: "Message index rebuild started.".into(), + kind: Some(NotificationType::Info), + }); } Err(err) => { - self.context.replies.push_back(UIEvent::Notification( - Some("Message index rebuild failed".to_string()), - err.to_string(), - Some(NotificationType::Error(err.kind)), - )); + self.context.replies.push_back(UIEvent::Notification { + title: Some("Message index rebuild failed".into()), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(err.kind)), + }); } } } #[cfg(not(feature = "sqlite3"))] AccountAction(_, ReIndex) => { - self.context.replies.push_back(UIEvent::Notification( - None, - "Message index rebuild failed: meli is not built with sqlite3 support." + self.context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: "Message index rebuild failed: meli is not built with sqlite3 support." .to_string(), - Some(NotificationType::Error(ErrorKind::None)), - )); + kind: Some(NotificationType::Error(ErrorKind::None)), + }); } AccountAction(ref account_name, PrintAccountSetting(ref setting)) => { let path = setting.split('.').collect::>(); @@ -855,11 +860,12 @@ impl State { ), )); } else { - self.context.replies.push_back(UIEvent::Notification( - None, - format!("Account {} was not found.", account_name), - Some(NotificationType::Error(ErrorKind::None)), - )); + self.context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: format!("Account {account_name} was not found.").into(), + kind: Some(NotificationType::Error(ErrorKind::None)), + }); } } PrintSetting(ref setting) => { diff --git a/meli/src/svg.rs b/meli/src/svg.rs index 1c31d39e..423216e8 100644 --- a/meli/src/svg.rs +++ b/meli/src/svg.rs @@ -424,11 +424,12 @@ impl Component for SVGScreenshotFilter { .unwrap() .write_all(&res) .unwrap(); - context.replies.push_back(UIEvent::Notification( - Some("Screenshot saved".into()), - format!("Screenshot saved to {}", filename), - None, - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Screenshot saved".into()), + source: None, + body: format!("Screenshot saved to {filename}").into(), + kind: None, + }); } fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool { if let UIEvent::Input(Key::F(6)) = event { diff --git a/meli/src/types.rs b/meli/src/types.rs index b9d14a9e..183e170a 100644 --- a/meli/src/types.rs +++ b/meli/src/types.rs @@ -41,6 +41,7 @@ use std::{borrow::Cow, sync::Arc}; pub use helpers::*; use melib::{ backends::{AccountHash, BackendEvent, MailboxHash}, + error::Error, EnvelopeHash, RefreshEvent, ThreadHash, }; use nix::unistd::Pid; @@ -137,7 +138,12 @@ pub enum UIEvent { ChangeMailbox(usize), ChangeMode(UIMode), Command(String), - Notification(Option, String, Option), + Notification { + title: Option>, + source: Option, + body: Cow<'static, str>, + kind: Option, + }, Action(Action), StatusEvent(StatusEvent), MailboxUpdate((AccountHash, MailboxHash)), // (account_idx, mailbox_idx) diff --git a/tools/src/embedded.rs b/tools/src/embedded.rs index 340319eb..8a0c7e5c 100644 --- a/tools/src/embedded.rs +++ b/tools/src/embedded.rs @@ -185,11 +185,12 @@ impl Component for EmbeddedContainer { ))); } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some(format!("Failed to create pseudoterminal: {}", err)), - err.to_string(), - Some(NotificationType::Error(melib::error::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: Some("Failed to create pseudoterminal".into()), + source: None, + body: err.to_string().into(), + kind: Some(NotificationType::Error(melib::error::ErrorKind::External)), + }); } } } @@ -225,16 +226,17 @@ impl Component for EmbeddedContainer { drop(embedded_pty_guard); _ = self.embedded_pty.take(); if exit_code != 0 { - context.replies.push_back(UIEvent::Notification( - None, - format!( - "Subprocess has exited with exit code {}", - exit_code - ), - Some(NotificationType::Error( + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: format!( + "Subprocess has exited with exit code {exit_code}", + ) + .into(), + kind: Some(NotificationType::Error( melib::error::ErrorKind::External, )), - )); + }); } self.set_dirty(true); context @@ -281,26 +283,29 @@ impl Component for EmbeddedContainer { } Ok(WaitStatus::Signaled(_, signal, _)) => { drop(embedded_pty_guard); - context.replies.push_back(UIEvent::Notification( - None, - format!("Subprocess was killed by {} signal", signal), - Some(NotificationType::Error( + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: format!("Subprocess was killed by {signal} signal") + .into(), + kind: Some(NotificationType::Error( melib::error::ErrorKind::External, )), - )); + }); self.embedded_pty = None; context .replies .push_back(UIEvent::ChangeMode(UIMode::Normal)); } Err(err) => { - context.replies.push_back(UIEvent::Notification( - Some("Embedded editor crashed.".to_string()), - format!("Subprocess has exited with reason {}", &err), - Some(NotificationType::Error( + context.replies.push_back(UIEvent::Notification { + title: Some("Embedded editor crashed.".into()), + source: None, + body: format!("Subprocess has exited with reason {err}").into(), + kind: Some(NotificationType::Error( melib::error::ErrorKind::External, )), - )); + }); drop(embedded_pty_guard); self.embedded_pty = None; context @@ -348,11 +353,12 @@ impl Component for EmbeddedContainer { } _ => {} } - context.replies.push_back(UIEvent::Notification( - None, - "Subprocess was killed by SIGTERM signal".to_string(), - Some(NotificationType::Error(melib::error::ErrorKind::External)), - )); + context.replies.push_back(UIEvent::Notification { + title: None, + source: None, + body: "Subprocess was killed by SIGTERM signal".into(), + kind: Some(NotificationType::Error(melib::error::ErrorKind::External)), + }); context .replies .push_back(UIEvent::ChangeMode(UIMode::Normal)); diff --git a/tools/src/managesieve.rs b/tools/src/managesieve.rs index eb684278..2dfa0fc2 100644 --- a/tools/src/managesieve.rs +++ b/tools/src/managesieve.rs @@ -19,7 +19,6 @@ * along with meli. If not, see . */ - use futures::executor::block_on; use meli::*; use melib::{imap::managesieve::ManageSieveConnection, Result, *};