BlueGit

golden-age paperdoll-renderer

Files

paperdoll-renderer / src / notify.rs

notify.rs

notify.rs 2.5 KiB Download Raw
1//! Desktop notification when a render ends while the window is unfocused
2//! (Tim t1025u). Freedesktop notifications on Linux/BSD, a toast on Windows.
3
4/// How a single render or the Render Alles queue ended.
5#[derive(Clone, Debug, PartialEq, Eq)]
6pub enum RenderOutcome {
7 /// One render (or the whole Render Alles queue) finished; `text` is the
8 /// status line also shown in the window.
9 Done { ok: bool, text: String },
10}
11
12/// The toast to show, if any.
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct Toast {
15 pub summary: String,
16 pub body: String,
17}
18
19/// Decide whether to notify: only when the window is not focused.
20pub fn toast_for(outcome: &RenderOutcome, window_focused: bool) -> Option<Toast> {
21 if window_focused {
22 return None;
23 }
24 let RenderOutcome::Done { ok, text } = outcome;
25 let summary = if *ok {
26 crate::i18n::t("Render klaar")
27 } else {
28 crate::i18n::t("Render niet gelukt")
29 };
30 Some(Toast {
31 summary,
32 body: crate::i18n::t(text),
33 })
34}
35
36/// Show the toast on a short-lived thread; delivery errors are ignored.
37pub fn show(toast: Toast) {
38 let _ = std::thread::Builder::new()
39 .name("render-notification".into())
40 .spawn(move || {
41 let mut n = notify_rust::Notification::new();
42 n.summary(&["Paperdoll Renderer", &toast.summary].join(": "))
43 .body(&toast.body)
44 .appname("Paperdoll Renderer");
45 #[cfg(all(unix, not(target_os = "macos")))]
46 {
47 n.icon(crate::icon::APP_ID)
48 .hint(notify_rust::Hint::DesktopEntry(crate::icon::APP_ID.into()));
49 }
50 let _ = n.show();
51 });
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn focused_window_gets_no_toast() {
60 let o = RenderOutcome::Done {
61 ok: true,
62 text: "Batch opgeslagen: x".into(),
63 };
64 assert_eq!(toast_for(&o, true), None);
65 }
66
67 #[test]
68 fn unfocused_window_gets_one_toast_with_status() {
69 let o = RenderOutcome::Done {
70 ok: true,
71 text: "Batch opgeslagen: /p/out".into(),
72 };
73 let t = toast_for(&o, false).unwrap();
74 assert!(t.body.contains("/p/out"));
75 let f = toast_for(
76 &RenderOutcome::Done {
77 ok: false,
78 text: "boom".into(),
79 },
80 false,
81 )
82 .unwrap();
83 assert_ne!(t.summary, f.summary);
84 }
85}