mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-07-03 03:31:03 +02:00
refactor(tray): complete client rewrite
This commit is contained in:
parent
c7b6ee8bc0
commit
004ea76da5
9 changed files with 193 additions and 246 deletions
|
@ -1,3 +1,4 @@
|
|||
use crate::Ironbar;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cfg(feature = "clipboard")]
|
||||
|
@ -9,7 +10,7 @@ pub mod music;
|
|||
#[cfg(feature = "notifications")]
|
||||
pub mod swaync;
|
||||
#[cfg(feature = "tray")]
|
||||
pub mod system_tray;
|
||||
pub mod tray;
|
||||
#[cfg(feature = "upower")]
|
||||
pub mod upower;
|
||||
#[cfg(feature = "volume")]
|
||||
|
@ -30,7 +31,7 @@ pub struct Clients {
|
|||
#[cfg(feature = "notifications")]
|
||||
notifications: Option<Arc<swaync::Client>>,
|
||||
#[cfg(feature = "tray")]
|
||||
tray: Option<Arc<system_tray::TrayEventReceiver>>,
|
||||
tray: Option<Arc<tray::Client>>,
|
||||
#[cfg(feature = "upower")]
|
||||
upower: Option<Arc<zbus::fdo::PropertiesProxy<'static>>>,
|
||||
#[cfg(feature = "volume")]
|
||||
|
@ -85,11 +86,17 @@ impl Clients {
|
|||
}
|
||||
|
||||
#[cfg(feature = "tray")]
|
||||
pub fn tray(&mut self) -> Arc<system_tray::TrayEventReceiver> {
|
||||
pub fn tray(&mut self) -> Arc<tray::Client> {
|
||||
// TODO: Error handling here isn't great - should throw a user-friendly error
|
||||
self.tray
|
||||
.get_or_insert_with(|| {
|
||||
Arc::new(crate::await_sync(async {
|
||||
system_tray::create_client().await
|
||||
let service_name =
|
||||
format!("{}-{}", env!("CARGO_CRATE_NAME"), Ironbar::unique_id());
|
||||
|
||||
tray::Client::new(&service_name)
|
||||
.await
|
||||
.expect("to be able to start client")
|
||||
}))
|
||||
})
|
||||
.clone()
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
use crate::{arc_mut, lock, register_client, send, spawn, Ironbar};
|
||||
use color_eyre::Report;
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use system_tray::message::menu::TrayMenu;
|
||||
use system_tray::message::tray::StatusNotifierItem;
|
||||
use system_tray::message::{NotifierItemCommand, NotifierItemMessage};
|
||||
use system_tray::StatusNotifierWatcher;
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use tracing::{debug, error, trace};
|
||||
|
||||
type Tray = BTreeMap<String, (Box<StatusNotifierItem>, Option<TrayMenu>)>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TrayEventReceiver {
|
||||
tx: mpsc::Sender<NotifierItemCommand>,
|
||||
b_tx: broadcast::Sender<NotifierItemMessage>,
|
||||
_b_rx: broadcast::Receiver<NotifierItemMessage>,
|
||||
|
||||
tray: Arc<Mutex<Tray>>,
|
||||
}
|
||||
|
||||
impl TrayEventReceiver {
|
||||
async fn new() -> system_tray::error::Result<Self> {
|
||||
let id = format!("ironbar-{}", Ironbar::unique_id());
|
||||
|
||||
let (tx, rx) = mpsc::channel(16);
|
||||
let (b_tx, b_rx) = broadcast::channel(64);
|
||||
|
||||
let tray = StatusNotifierWatcher::new(rx).await?;
|
||||
let mut host = Box::pin(tray.create_notifier_host(&id)).await?;
|
||||
|
||||
let tray = arc_mut!(BTreeMap::new());
|
||||
|
||||
{
|
||||
let b_tx = b_tx.clone();
|
||||
let tray = tray.clone();
|
||||
|
||||
spawn(async move {
|
||||
while let Ok(message) = host.recv().await {
|
||||
trace!("Received message: {message:?}");
|
||||
|
||||
send!(b_tx, message.clone());
|
||||
let mut tray = lock!(tray);
|
||||
match message {
|
||||
NotifierItemMessage::Update {
|
||||
address,
|
||||
item,
|
||||
menu,
|
||||
} => {
|
||||
debug!("Adding/updating item with address '{address}'");
|
||||
tray.insert(address, (item, menu));
|
||||
}
|
||||
NotifierItemMessage::Remove { address } => {
|
||||
debug!("Removing item with address '{address}'");
|
||||
tray.remove(&address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok::<(), broadcast::error::SendError<NotifierItemMessage>>(())
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
tx,
|
||||
b_tx,
|
||||
_b_rx: b_rx,
|
||||
tray,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn subscribe(
|
||||
&self,
|
||||
) -> (
|
||||
mpsc::Sender<NotifierItemCommand>,
|
||||
broadcast::Receiver<NotifierItemMessage>,
|
||||
) {
|
||||
let tx = self.tx.clone();
|
||||
let b_rx = self.b_tx.subscribe();
|
||||
|
||||
let tray = lock!(self.tray).clone();
|
||||
for (address, (item, menu)) in tray {
|
||||
let update = NotifierItemMessage::Update {
|
||||
address,
|
||||
item,
|
||||
menu,
|
||||
};
|
||||
send!(self.b_tx, update);
|
||||
}
|
||||
|
||||
(tx, b_rx)
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to create a new `TrayEventReceiver` instance,
|
||||
/// retrying a maximum of 10 times before panicking the thread.
|
||||
pub async fn create_client() -> TrayEventReceiver {
|
||||
const MAX_RETRIES: i32 = 10;
|
||||
|
||||
// sometimes this can fail
|
||||
let mut retries = 0;
|
||||
|
||||
let value = loop {
|
||||
retries += 1;
|
||||
|
||||
let tray = Box::pin(TrayEventReceiver::new()).await;
|
||||
|
||||
match tray {
|
||||
Ok(tray) => break Some(tray),
|
||||
Err(err) => error!(
|
||||
"{:?}",
|
||||
Report::new(err).wrap_err(format!(
|
||||
"Failed to create StatusNotifierWatcher (attempt {retries})"
|
||||
))
|
||||
),
|
||||
}
|
||||
|
||||
if retries == MAX_RETRIES {
|
||||
break None;
|
||||
}
|
||||
};
|
||||
|
||||
value.expect("Failed to create StatusNotifierWatcher")
|
||||
}
|
||||
|
||||
register_client!(TrayEventReceiver, tray);
|
4
src/clients/tray.rs
Normal file
4
src/clients/tray.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
use crate::register_client;
|
||||
pub use system_tray::client::Client;
|
||||
|
||||
register_client!(Client, tray);
|
Loading…
Add table
Add a link
Reference in a new issue