mirror of
https://git.meli.delivery/meli/meli
synced 2024-10-30 21:20:34 +00:00
types: Change UIEvent::Notification structure
Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
This commit is contained in:
parent
458258e1aa
commit
3495ffd61b
@ -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!(
|
||||
UIEvent::Notification {
|
||||
title: Some(
|
||||
format!(
|
||||
"{}: could not create mailbox {}",
|
||||
&self.name, path
|
||||
)),
|
||||
err.to_string(),
|
||||
Some(crate::types::NotificationType::Error(err.kind)),
|
||||
)
|
||||
.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!(
|
||||
UIEvent::Notification {
|
||||
title: Some(
|
||||
format!(
|
||||
"{}: could not set mailbox permissions",
|
||||
&self.name
|
||||
)),
|
||||
err.to_string(),
|
||||
Some(crate::types::NotificationType::Error(err.kind)),
|
||||
)
|
||||
.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!(
|
||||
UIEvent::Notification {
|
||||
title: Some(
|
||||
format!(
|
||||
"{}: mailbox permissions set successfully",
|
||||
&self.name
|
||||
)),
|
||||
String::new(),
|
||||
Some(crate::types::NotificationType::Info),
|
||||
)
|
||||
.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!(
|
||||
UIEvent::Notification {
|
||||
title: Some(
|
||||
format!(
|
||||
"{}: could not set mailbox subscription",
|
||||
&self.name
|
||||
)),
|
||||
err.to_string(),
|
||||
Some(crate::types::NotificationType::Error(err.kind)),
|
||||
)
|
||||
.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!(
|
||||
UIEvent::Notification {
|
||||
title: 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),
|
||||
)
|
||||
.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),
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -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 \
|
||||
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!(
|
||||
context.replies.push_back(UIEvent::Notification {
|
||||
title: Some(
|
||||
format!(
|
||||
"could not add attachment: {}",
|
||||
String::from_utf8_lossy(path)
|
||||
)),
|
||||
err.to_string(),
|
||||
Some(NotificationType::Error(
|
||||
)
|
||||
.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),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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)), });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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) => {
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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, *};
|
||||
|
Loading…
Reference in New Issue
Block a user