aboutsummaryrefslogtreecommitdiff
path: root/src/client/notifications.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/notifications.rs')
-rw-r--r--src/client/notifications.rs102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/client/notifications.rs b/src/client/notifications.rs
new file mode 100644
index 00000000..7c97742e
--- /dev/null
+++ b/src/client/notifications.rs
@@ -0,0 +1,102 @@
+use std::io;
+
+use tracing::{debug, warn};
+
+use crate::protocol::NotifyKind;
+
+use super::shell;
+
+pub(super) fn handle_shell_notification_effects(
+ effects: Vec<shell::ClientShellNotificationEffect>,
+ sound_config: &crate::config::SoundConfig,
+) {
+ for effect in effects {
+ match effect {
+ shell::ClientShellNotificationEffect::Sound { sound, agent } => {
+ let agent = agent.as_deref().and_then(crate::detect::parse_agent_label);
+ if sound_config.allows(agent) {
+ crate::sound::play(sound, sound_config);
+ }
+ }
+ shell::ClientShellNotificationEffect::Terminal { title, body } => {
+ if let Err(err) = crate::terminal_notify::show_notification(&title, body.as_deref())
+ {
+ warn!(err = %err, "failed to emit terminal notification");
+ }
+ }
+ shell::ClientShellNotificationEffect::System { title, body } => {
+ if let Err(err) =
+ crate::platform::show_desktop_notification(&title, body.as_deref())
+ {
+ warn!(err = %err, "failed to emit system notification");
+ }
+ }
+ }
+ }
+}
+
+pub(super) fn handle_notify(
+ kind: NotifyKind,
+ message: &str,
+ body: Option<&str>,
+ sound_config: &crate::config::SoundConfig,
+) {
+ handle_notify_with_notifiers(
+ kind,
+ message,
+ body,
+ sound_config,
+ crate::terminal_notify::show_notification,
+ crate::platform::show_desktop_notification,
+ );
+}
+
+pub(super) fn handle_notify_with_notifiers(
+ kind: NotifyKind,
+ message: &str,
+ body: Option<&str>,
+ sound_config: &crate::config::SoundConfig,
+ mut show_terminal_notification: impl FnMut(&str, Option<&str>) -> io::Result<bool>,
+ mut show_system_notification: impl FnMut(&str, Option<&str>) -> io::Result<bool>,
+) {
+ match kind {
+ NotifyKind::Sound => {
+ let Some(sound) = sound_from_notify_message(message) else {
+ warn!(
+ message = message,
+ "received unknown sound notification from server"
+ );
+ return;
+ };
+ if sound_config.enabled {
+ crate::sound::play(sound, sound_config);
+ }
+ }
+ NotifyKind::Toast => {
+ debug!(
+ message = message,
+ "received terminal toast notification from server"
+ );
+ if let Err(err) = show_terminal_notification(message, body) {
+ warn!(err = %err, "failed to emit terminal notification");
+ }
+ }
+ NotifyKind::SystemToast => {
+ debug!(
+ message = message,
+ "received system toast notification from server"
+ );
+ if let Err(err) = show_system_notification(message, body) {
+ warn!(err = %err, "failed to emit system notification");
+ }
+ }
+ }
+}
+
+pub(super) fn sound_from_notify_message(message: &str) -> Option<crate::sound::Sound> {
+ match message {
+ "agent done" => Some(crate::sound::Sound::Done),
+ "agent attention" => Some(crate::sound::Sound::Request),
+ _ => None,
+ }
+}