1use std::sync::atomic::{AtomicBool, Ordering};
8
9static ENABLED: AtomicBool = AtomicBool::new(true);
12
13pub fn set_enabled(enabled: bool) {
15 ENABLED.store(enabled, Ordering::Relaxed);
16 log::debug!("Notifications enabled: {}", enabled);
17}
18
19pub fn send_sync_summary(succeeded: usize, failed: usize) {
23 if succeeded == 0 && failed == 0 {
24 return;
25 }
26 let title = "Sync complete".to_string();
27 let processed = succeeded.saturating_add(failed);
28 let body = if failed == 0 {
29 format!("All {} file(s) processed. Idle.", processed)
30 } else {
31 format!(
32 "All {} file(s) processed. Idle. {} failed and will be retried.",
33 processed, failed
34 )
35 };
36 send_gio(&title, &body, "sync-complete");
37}
38
39pub fn send_connectivity_lost() {
41 send_gio(
42 "Mimick: Connection lost",
43 "Could not reach the Immich server. Uploads will resume automatically when connectivity is restored.",
44 "connectivity-lost",
45 );
46}
47
48fn send_gio(title: &str, body: &str, notification_id: &str) {
56 if !ENABLED.load(Ordering::Relaxed) {
57 log::debug!("Notifications disabled; suppressing: {}", title);
58 return;
59 }
60
61 let title = title.to_string();
62 let body = body.to_string();
63 let id = notification_id.to_string();
64
65 glib::idle_add_once(move || {
66 use gtk::prelude::ApplicationExt;
67
68 let Some(app) = gtk::gio::Application::default() else {
69 log::debug!("No default GIO application; skipping notification.");
70 return;
71 };
72
73 let notification = gtk::gio::Notification::new(&title);
74 notification.set_body(Some(&body));
75
76 let icon = gtk::gio::ThemedIcon::new("dev.nicx.mimick");
77 notification.set_icon(&icon);
78
79 app.send_notification(Some(&id), ¬ification);
80 log::debug!("Notification sent via GIO: {} - {}", title, body);
81 });
82}