synpad 0.1.0

A full-featured Matrix chat client built with Dioxus
use crate::persistence::app_state as prefs;

/// Show a desktop notification for a new message.
///
/// Uses the OS-native notification system. On Windows this uses the toast
/// notification API, on macOS the Notification Center, on Linux libnotify.
pub async fn show_desktop_notification(
    room_name: &str,
    sender_name: &str,
    message_body: &str,
    _room_id: &str,
) {
    // Check if desktop notifications are enabled
    let enabled = match prefs::load_preferences().await {
        Ok(p) => p.desktop_notifications,
        Err(_) => true,
    };
    if !enabled {
        return;
    }

    let show_preview = match prefs::load_preferences().await {
        Ok(p) => p.show_message_preview,
        Err(_) => true,
    };

    let title = format!("{sender_name} in {room_name}");
    let body = if show_preview {
        truncate_notification_body(message_body, 200)
    } else {
        "New message".to_string()
    };

    // Use OS notification API
    #[cfg(target_os = "windows")]
    {
        show_windows_notification(&title, &body);
    }

    #[cfg(target_os = "macos")]
    {
        show_macos_notification(&title, &body);
    }

    #[cfg(target_os = "linux")]
    {
        show_linux_notification(&title, &body);
    }

    #[cfg(target_family = "wasm")]
    {
        show_web_notification(&title, &body);
    }
}

/// Truncate notification body to a maximum length.
fn truncate_notification_body(body: &str, max_len: usize) -> String {
    if body.len() <= max_len {
        body.to_string()
    } else {
        format!("{}...", &body[..max_len])
    }
}

/// Show notification on Windows using PowerShell toast notification.
#[cfg(target_os = "windows")]
fn show_windows_notification(title: &str, body: &str) {
    // Use a simple approach with std::process::Command
    let script = format!(
        "[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('Netrix').Show($toast)",
        title.replace('\'', "''"),
        body.replace('\'', "''")
    );
    let _ = std::process::Command::new("powershell")
        .args(["-WindowStyle", "Hidden", "-Command", &script])
        .spawn();
}

/// Show notification on macOS using osascript.
#[cfg(target_os = "macos")]
fn show_macos_notification(title: &str, body: &str) {
    let script = format!(
        "display notification \"{}\" with title \"{}\"",
        body.replace('"', "\\\""),
        title.replace('"', "\\\"")
    );
    let _ = std::process::Command::new("osascript")
        .args(["-e", &script])
        .spawn();
}

/// Show notification on Linux using notify-send.
#[cfg(target_os = "linux")]
fn show_linux_notification(title: &str, body: &str) {
    let _ = std::process::Command::new("notify-send")
        .args(["-a", "Netrix", title, body])
        .spawn();
}

/// Show notification on Web using the Notification API.
#[cfg(target_family = "wasm")]
fn show_web_notification(title: &str, body: &str) {
    // Web notifications would use web_sys::Notification
    tracing::debug!("Web notification: {title} - {body}");
}

/// Check if a message body matches any notification keywords.
pub fn matches_keywords(body: &str, keywords: &[String]) -> bool {
    let body_lower = body.to_lowercase();
    keywords.iter().any(|kw| body_lower.contains(&kw.to_lowercase()))
}

/// Play a notification sound.
pub fn play_notification_sound() {
    // On desktop, we could use rodio or a system beep
    // For now, log it
    tracing::debug!("Notification sound requested");
}