-
Notifications
You must be signed in to change notification settings - Fork 44
Expand file tree
/
Copy pathnotification.rs
More file actions
156 lines (129 loc) · 4.48 KB
/
Copy pathnotification.rs
File metadata and controls
156 lines (129 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//! Desktop notification utilities for the Cortex CLI.
//!
//! Provides cross-platform desktop notification functionality.
use anyhow::Result;
/// Notification urgency level.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum NotificationUrgency {
/// Low urgency (informational).
Low,
/// Normal urgency (default).
#[default]
Normal,
/// Critical urgency (errors, failures).
Critical,
}
/// Send a desktop notification.
///
/// Uses platform-specific notification mechanisms:
/// - macOS: AppleScript `display notification`
/// - Linux: `notify-send` command
/// - Windows: PowerShell Toast notifications
///
/// # Arguments
/// * `title` - The notification title
/// * `body` - The notification body text
/// * `urgency` - The urgency level (affects visual styling on some platforms)
///
/// # Returns
/// `Ok(())` on success (or silent failure if notifications unavailable).
pub fn send_notification(title: &str, body: &str, urgency: NotificationUrgency) -> Result<()> {
#[cfg(not(target_os = "linux"))]
let _ = urgency;
#[cfg(target_os = "macos")]
{
send_notification_macos(title, body)?;
}
#[cfg(target_os = "linux")]
{
send_notification_linux(title, body, urgency)?;
}
#[cfg(target_os = "windows")]
{
send_notification_windows(title, body)?;
}
Ok(())
}
/// Send a task completion notification.
///
/// Convenience function for notifying about task completion status.
///
/// # Arguments
/// * `session_id` - The session identifier (will be truncated for display)
/// * `success` - Whether the task completed successfully
pub fn send_task_notification(session_id: &str, success: bool) -> Result<()> {
let title = if success {
"Cortex Task Completed"
} else {
"Cortex Task Failed"
};
let short_id = &session_id[..8.min(session_id.len())];
let body = format!("Session: {}", short_id);
let urgency = if success {
NotificationUrgency::Normal
} else {
NotificationUrgency::Critical
};
send_notification(title, &body, urgency)
}
#[cfg(target_os = "macos")]
fn send_notification_macos(title: &str, body: &str) -> Result<()> {
use std::process::Command;
// Escape special characters for AppleScript
let title_escaped = title.replace('"', "\\\"");
let body_escaped = body.replace('"', "\\\"");
let script = format!(
r#"display notification "{}" with title "{}""#,
body_escaped, title_escaped
);
// Fire and forget - don't fail if notification fails
let _ = Command::new("osascript").args(["-e", &script]).output();
Ok(())
}
#[cfg(target_os = "linux")]
fn send_notification_linux(title: &str, body: &str, urgency: NotificationUrgency) -> Result<()> {
use std::process::Command;
let urgency_str = match urgency {
NotificationUrgency::Low => "low",
NotificationUrgency::Normal => "normal",
NotificationUrgency::Critical => "critical",
};
// Fire and forget
let _ = Command::new("notify-send")
.args(["--urgency", urgency_str, title, body])
.output();
Ok(())
}
#[cfg(target_os = "windows")]
fn send_notification_windows(title: &str, body: &str) -> Result<()> {
use std::process::Command;
// Escape special characters for PowerShell
let title_escaped = title.replace('"', "`\"");
let body_escaped = body.replace('"', "`\"");
let script = format!(
r#"
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
$template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02)
$textNodes = $template.GetElementsByTagName("text")
$textNodes.Item(0).AppendChild($template.CreateTextNode("{}")) | Out-Null
$textNodes.Item(1).AppendChild($template.CreateTextNode("{}")) | Out-Null
$toast = [Windows.UI.Notifications.ToastNotification]::new($template)
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Cortex").Show($toast)
"#,
title_escaped, body_escaped
);
// Fire and forget
let _ = Command::new("powershell")
.args(["-Command", &script])
.output();
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_notification_urgency_default() {
let urgency = NotificationUrgency::default();
assert_eq!(urgency, NotificationUrgency::Normal);
}
}