Skip to main content

supercode_frontend_tui/terminal/notifications/
mod.rs

1// Derived from OpenAI Codex: codex-rs/tui/src/notifications/mod.rs
2// Pinned source: 8604689ec5e3437eb79802d8d72249b7722fbf5b
3// Copyright 2025 OpenAI
4// Licensed under the Apache License, Version 2.0.
5// Modified by the Supercode contributors; see docs/legal/codex-frontend-extraction.toml.
6
7//! Desktop notification selection from explicit terminal capabilities.
8
9mod bel;
10mod osc9;
11
12use std::io;
13
14use bel::BelBackend;
15use osc9::Osc9Backend;
16
17#[derive(Clone, Copy, Debug, Eq, PartialEq)]
18pub enum NotificationMethod {
19    Auto,
20    Osc9,
21    Bell,
22}
23
24#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
25pub struct NotificationCapabilities {
26    pub osc9: bool,
27    pub tmux_passthrough: bool,
28}
29
30#[derive(Debug)]
31pub enum DesktopNotificationBackend {
32    Osc9(Osc9Backend),
33    Bell(BelBackend),
34}
35
36impl DesktopNotificationBackend {
37    pub fn new(method: NotificationMethod, capabilities: NotificationCapabilities) -> Self {
38        match method {
39            NotificationMethod::Auto if capabilities.osc9 => {
40                Self::Osc9(Osc9Backend::new(capabilities.tmux_passthrough))
41            }
42            NotificationMethod::Osc9 => Self::Osc9(Osc9Backend::new(capabilities.tmux_passthrough)),
43            NotificationMethod::Auto | NotificationMethod::Bell => Self::Bell(BelBackend),
44        }
45    }
46
47    pub fn method(&self) -> NotificationMethod {
48        match self {
49            Self::Osc9(_) => NotificationMethod::Osc9,
50            Self::Bell(_) => NotificationMethod::Bell,
51        }
52    }
53
54    pub fn notify(&mut self, message: &str) -> io::Result<()> {
55        match self {
56            Self::Osc9(backend) => backend.notify(message),
57            Self::Bell(backend) => backend.notify(message),
58        }
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn auto_uses_osc9_only_when_the_runtime_reports_support() {
68        let osc9 = DesktopNotificationBackend::new(
69            NotificationMethod::Auto,
70            NotificationCapabilities {
71                osc9: true,
72                tmux_passthrough: true,
73            },
74        );
75        assert_eq!(osc9.method(), NotificationMethod::Osc9);
76
77        let bell = DesktopNotificationBackend::new(
78            NotificationMethod::Auto,
79            NotificationCapabilities::default(),
80        );
81        assert_eq!(bell.method(), NotificationMethod::Bell);
82    }
83
84    #[test]
85    fn explicit_methods_do_not_depend_on_terminal_detection() {
86        assert_eq!(
87            DesktopNotificationBackend::new(
88                NotificationMethod::Osc9,
89                NotificationCapabilities::default(),
90            )
91            .method(),
92            NotificationMethod::Osc9
93        );
94        assert_eq!(
95            DesktopNotificationBackend::new(
96                NotificationMethod::Bell,
97                NotificationCapabilities {
98                    osc9: true,
99                    tmux_passthrough: true,
100                },
101            )
102            .method(),
103            NotificationMethod::Bell
104        );
105    }
106}