azalea_shell/service/dbus/notification/
mod.rs1pub mod service;
2
3use std::collections::HashMap;
4
5use azalea_service::StaticServiceManager;
6use tokio::sync::{broadcast, oneshot};
7
8#[derive(azalea_derive::StaticServiceManager)]
9pub struct Service {
10 notifications: HashMap<u32, service::Notification>,
11 conn: Option<zbus::Connection>,
12 rx: flume::Receiver<service::Event>,
13}
14
15pub struct Streams {}
16
17#[derive(Default, Clone)]
18pub struct Init {}
19
20#[derive(Clone, Debug)]
21pub enum Input {
22 Close,
23}
24
25pub enum Event {
26 Notifications(service::Event),
27}
28
29#[derive(Clone, Debug)]
30pub enum Output {
31 Notification(service::Notification),
32}
33
34impl azalea_service::Service for Service {
35 type Init = Init;
36 type Input = Input;
37 type Event = Event;
38 type Output = Output;
39
40 fn handler(init: Self::Init) -> azalea_service::ServiceManager<Self> {
41 azalea_service::ServiceManager::new(init, 16, 16)
42 }
43
44 async fn new(
45 _init: Self::Init,
46 _input: flume::Sender<Self::Input>,
47 _output_sender: broadcast::Sender<Self::Output>,
48 ) -> Self {
49 let (tx, rx) = flume::unbounded();
50 let (discovery_tx, discovery_rx) = oneshot::channel();
51
52 super::discovery::Service::send(super::discovery::Input::QueryServiceExists(
53 format!("org.freedesktop.StatusNotifierWatcher"),
54 discovery_tx,
55 ));
56
57 let conn = match discovery_rx.await {
58 Ok(true) => None,
59 Ok(false) => {
60 let notifications = service::Notifications::new(tx);
61
62 if let Ok(conn) = zbus::conn::Builder::session()
63 .and_then(|conn| conn.name("org.freedesktop.Notifications"))
64 .and_then(|conn| conn.serve_at("/org/freedesktop/Notifications", notifications))
65 .map(|conn| conn.build())
66 {
67 conn.await.ok()
68 } else {
69 azalea_log::warning!("There's already a notification server running!");
70 None
71 }
72 }
73 Err(e) => {
74 azalea_log::warning!("Failed to query for other notification servers: {e}");
75 None
76 }
77 };
78
79 Self {
80 notifications: Default::default(),
81 conn,
82 rx,
83 }
84 }
85
86 async fn message(
87 &mut self,
88 input: Self::Input,
89 _output_sender: &broadcast::Sender<Self::Output>,
90 ) {
91 match input {
92 Input::Close => todo!(),
93 }
94 }
95
96 async fn event_generator(&mut self) -> Self::Event {
97 loop {
98 if self.conn.is_none() {
99 tokio::time::sleep(std::time::Duration::from_secs(100)).await;
101 } else {
102 if let Ok(event) = self.rx.recv_async().await {
103 return Event::Notifications(event);
104 }
105 }
106 }
107 }
108
109 async fn event_handler(
110 &mut self,
111 event: Self::Event,
112 output_sender: &tokio::sync::broadcast::Sender<Self::Output>,
113 ) -> azalea_service::Result<()> {
114 match event {
115 Event::Notifications(event) => match event {
116 service::Event::Notify(notification) => {
117 self.notifications
118 .insert(notification.id, notification.clone());
119 drop(output_sender.send(Output::Notification(notification)))
120 }
121 },
122 }
123 Ok(())
124 }
125}