types: Change UIEvent::Notification structure

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
pull/312/head
Manos Pitsidianakis 2023-11-26 20:36:02 +02:00
parent 458258e1aa
commit 3495ffd61b
Signed by: Manos Pitsidianakis
GPG Key ID: 7729C7707F7E09D0
17 changed files with 603 additions and 479 deletions

View File

@ -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),
},
));
}
}

View File

@ -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::<Vec<_>>()
{
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),
});
}
}
}

View File

@ -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)),
});
}
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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)),
});
}
}
}

View File

@ -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;

View File

@ -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 {

View File

@ -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)), });
}
}
}

View File

@ -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()

View File

@ -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::<SmallVec<[&str; 16]>>();
@ -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) => {

View File

@ -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 {

View File

@ -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>, String, Option<NotificationType>),
Notification {
title: Option<Cow<'static, str>>,
source: Option<Error>,
body: Cow<'static, str>,
kind: Option<NotificationType>,
},
Action(Action),
StatusEvent(StatusEvent),
MailboxUpdate((AccountHash, MailboxHash)), // (account_idx, mailbox_idx)

View File

@ -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));

View File

@ -19,7 +19,6 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use futures::executor::block_on;
use meli::*;
use melib::{imap::managesieve::ManageSieveConnection, Result, *};