2024-05-06 15:39:04 +02:00
|
|
|
// Copyright 2023 System76 <info@system76.com>
|
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
|
|
2023-06-30 16:27:45 -04:00
|
|
|
use cosmic::{
|
2024-10-30 22:51:08 -04:00
|
|
|
iced::{futures, stream},
|
2023-06-30 16:27:45 -04:00
|
|
|
iced_futures::Subscription,
|
|
|
|
|
};
|
2023-07-20 17:55:43 -04:00
|
|
|
use cosmic_notifications_util::Notification;
|
|
|
|
|
use std::{
|
|
|
|
|
collections::HashMap,
|
|
|
|
|
os::unix::io::{FromRawFd, RawFd},
|
|
|
|
|
};
|
|
|
|
|
|
2023-11-17 14:29:39 -05:00
|
|
|
use tracing::{error, trace};
|
2023-07-20 17:55:43 -04:00
|
|
|
use zbus::{
|
2024-05-16 21:29:28 -04:00
|
|
|
connection::Builder,
|
2023-07-20 17:55:43 -04:00
|
|
|
export::futures_util::{SinkExt, StreamExt},
|
2024-05-16 21:29:28 -04:00
|
|
|
proxy,
|
2023-07-01 02:01:47 -04:00
|
|
|
};
|
2023-06-30 16:27:45 -04:00
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub enum State {
|
2024-01-18 22:13:05 -05:00
|
|
|
WaitingForNotificationEvent(u8),
|
2023-06-30 16:27:45 -04:00
|
|
|
Finished,
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-18 21:02:35 -05:00
|
|
|
pub fn notifications(proxy: NotificationsAppletProxy<'static>) -> Subscription<Notification> {
|
2023-06-30 16:27:45 -04:00
|
|
|
struct SomeWorker;
|
|
|
|
|
|
2024-10-30 22:51:08 -04:00
|
|
|
Subscription::run_with_id(
|
2023-06-30 16:27:45 -04:00
|
|
|
std::any::TypeId::of::<SomeWorker>(),
|
2024-10-30 22:51:08 -04:00
|
|
|
stream::channel(50, |mut output| async move {
|
2024-01-18 22:13:05 -05:00
|
|
|
let mut state = State::WaitingForNotificationEvent(0);
|
2023-06-30 16:27:45 -04:00
|
|
|
|
|
|
|
|
loop {
|
|
|
|
|
match &mut state {
|
2024-01-18 22:13:05 -05:00
|
|
|
State::WaitingForNotificationEvent(mut fail_count) => {
|
2023-11-17 14:29:39 -05:00
|
|
|
trace!("Waiting for notification events...");
|
2023-07-20 17:55:43 -04:00
|
|
|
let mut signal = match proxy.receive_notify().await {
|
|
|
|
|
Ok(s) => s,
|
2023-06-30 16:27:45 -04:00
|
|
|
Err(err) => {
|
2023-07-20 17:55:43 -04:00
|
|
|
error!(
|
|
|
|
|
"failed to get a stream of signals for notifications. {}",
|
|
|
|
|
err
|
|
|
|
|
);
|
2023-11-17 14:29:39 -05:00
|
|
|
fail_count = fail_count.saturating_add(1);
|
|
|
|
|
if fail_count > 5 {
|
|
|
|
|
error!("Failed to receive notification events");
|
|
|
|
|
state = State::Finished;
|
|
|
|
|
} else {
|
|
|
|
|
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
|
|
|
|
};
|
2023-06-30 16:27:45 -04:00
|
|
|
continue;
|
|
|
|
|
}
|
2023-07-20 17:55:43 -04:00
|
|
|
};
|
|
|
|
|
while let Some(msg) = signal.next().await {
|
|
|
|
|
let Some(args) = msg.args().into_iter().next() else {
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
let notification = Notification::new(
|
|
|
|
|
args.app_name,
|
|
|
|
|
args.id,
|
|
|
|
|
args.app_icon,
|
|
|
|
|
args.summary,
|
|
|
|
|
args.body,
|
|
|
|
|
args.actions,
|
|
|
|
|
args.hints,
|
|
|
|
|
args.expire_timeout,
|
|
|
|
|
);
|
|
|
|
|
_ = output.send(notification).await;
|
2023-06-30 16:27:45 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
State::Finished => {
|
|
|
|
|
let () = futures::future::pending().await;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-30 22:51:08 -04:00
|
|
|
}),
|
2023-06-30 16:27:45 -04:00
|
|
|
)
|
2023-07-01 02:01:47 -04:00
|
|
|
}
|
2023-07-20 17:55:43 -04:00
|
|
|
|
2024-05-16 21:29:28 -04:00
|
|
|
#[proxy(
|
2023-07-20 17:55:43 -04:00
|
|
|
default_service = "com.system76.NotificationsApplet",
|
|
|
|
|
interface = "com.system76.NotificationsApplet",
|
|
|
|
|
default_path = "/com/system76/NotificationsApplet"
|
|
|
|
|
)]
|
|
|
|
|
trait NotificationsApplet {
|
2024-05-16 21:29:28 -04:00
|
|
|
#[zbus(signal)]
|
2023-07-20 17:55:43 -04:00
|
|
|
fn notify(
|
|
|
|
|
&self,
|
|
|
|
|
app_name: &str,
|
|
|
|
|
id: u32,
|
|
|
|
|
app_icon: &str,
|
|
|
|
|
summary: &str,
|
|
|
|
|
body: &str,
|
|
|
|
|
actions: Vec<&str>,
|
|
|
|
|
hints: HashMap<&str, zbus::zvariant::Value<'_>>,
|
|
|
|
|
expire_timeout: i32,
|
|
|
|
|
) -> zbus::Result<()>;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-18 21:02:35 -05:00
|
|
|
pub async fn get_proxy() -> anyhow::Result<NotificationsAppletProxy<'static>> {
|
2023-07-20 17:55:43 -04:00
|
|
|
let raw_fd = std::env::var("COSMIC_NOTIFICATIONS")?;
|
|
|
|
|
let raw_fd = raw_fd.parse::<RawFd>()?;
|
2024-01-18 22:13:05 -05:00
|
|
|
tracing::info!("Connecting to notifications daemon on fd {}", raw_fd);
|
2023-07-20 17:55:43 -04:00
|
|
|
|
|
|
|
|
let stream = unsafe { std::os::unix::net::UnixStream::from_raw_fd(raw_fd) };
|
|
|
|
|
stream.set_nonblocking(true)?;
|
|
|
|
|
let stream = tokio::net::UnixStream::from_std(stream)?;
|
2024-05-16 21:29:28 -04:00
|
|
|
let conn = Builder::socket(stream).p2p().build().await?;
|
2023-11-17 14:29:39 -05:00
|
|
|
trace!("Applet connection created");
|
2023-07-20 17:55:43 -04:00
|
|
|
let proxy = NotificationsAppletProxy::new(&conn).await?;
|
|
|
|
|
|
|
|
|
|
Ok(proxy)
|
|
|
|
|
}
|