diff --git a/cosmic-applet-battery/src/app.rs b/cosmic-applet-battery/src/app.rs index fe225096..1dcda59f 100644 --- a/cosmic-applet-battery/src/app.rs +++ b/cosmic-applet-battery/src/app.rs @@ -392,31 +392,28 @@ impl Application for CosmicBatteryApplet { Subscription::batch(vec![ self.applet_helper.theme_subscription(0).map(Message::Theme), device_subscription(0).map( - |( - _, - DeviceDbusEvent::Update { - icon_name, - percent, - time_to_empty, - }, - )| Message::Update { + |DeviceDbusEvent::Update { + icon_name, + percent, + time_to_empty, + }| Message::Update { icon_name, percent, time_to_empty, }, ), kbd_backlight_subscription(0).map(|event| match event { - (_, KeyboardBacklightUpdate::Update(b)) => Message::UpdateKbdBrightness(b), - (_, KeyboardBacklightUpdate::Init(tx, b)) => Message::InitKbdBacklight(tx, b), + KeyboardBacklightUpdate::Update(b) => Message::UpdateKbdBrightness(b), + KeyboardBacklightUpdate::Init(tx, b) => Message::InitKbdBacklight(tx, b), }), screen_backlight_subscription(0).map(|e| match e { - (_, ScreenBacklightUpdate::Update(b)) => Message::UpdateScreenBrightness(b), - (_, ScreenBacklightUpdate::Init(tx, b)) => Message::InitScreenBacklight(tx, b), + ScreenBacklightUpdate::Update(b) => Message::UpdateScreenBrightness(b), + ScreenBacklightUpdate::Init(tx, b) => Message::InitScreenBacklight(tx, b), }), power_profile_subscription(0).map(|event| match event { - (_, PowerProfileUpdate::Update { profile }) => Message::Profile(profile), - (_, PowerProfileUpdate::Init(tx, p)) => Message::InitProfile(p, tx), - (_, PowerProfileUpdate::Error(e)) => Message::Errored(e), // TODO: handle error + PowerProfileUpdate::Update { profile } => Message::Profile(profile), + PowerProfileUpdate::Init(tx, p) => Message::InitProfile(p, tx), + PowerProfileUpdate::Error(e) => Message::Errored(e), // TODO: handle error }), self.timeline .as_subscription() diff --git a/cosmic-applet-battery/src/backlight.rs b/cosmic-applet-battery/src/backlight.rs index 64fe65d1..9d5a8232 100644 --- a/cosmic-applet-battery/src/backlight.rs +++ b/cosmic-applet-battery/src/backlight.rs @@ -11,8 +11,7 @@ use std::{ str::{self, FromStr}, }; -use cosmic::iced; -use iced::subscription; +use cosmic::iced::{self, futures::SinkExt, subscription}; use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}; const BACKLIGHT_SYSDIR: &str = "/sys/class/backlight"; @@ -77,21 +76,14 @@ pub async fn backlight() -> io::Result> { pub fn screen_backlight_subscription( id: I, -) -> iced::Subscription<(I, ScreenBacklightUpdate)> { - subscription::unfold(id, State::Ready, move |state| start_listening_loop(id, state)) -} +) -> iced::Subscription { + subscription::channel(id, 50, move |mut output| async move { + let mut state = State::Ready; -async fn start_listening_loop( - id: I, - mut state: State, -) -> ((I, ScreenBacklightUpdate), State) { - loop { - let (update, new_state) = start_listening(id, state).await; - state = new_state; - if let Some(update) = update { - return (update, state); + loop { + state = start_listening(state, &mut output).await; } - } + }) } pub enum State { @@ -104,46 +96,43 @@ pub enum State { Finished, } -async fn start_listening( - id: I, +async fn start_listening( state: State, -) -> (Option<(I, ScreenBacklightUpdate)>, State) { + output: &mut futures::channel::mpsc::Sender, +) -> State { match state { State::Ready => { let conn = match zbus::Connection::system().await { Ok(conn) => conn, - Err(_) => return (None, State::Finished), + Err(_) => return State::Finished, }; let screen_proxy = match LogindSessionProxy::builder(&conn).build().await { Ok(p) => p, - Err(_) => return (None, State::Finished), + Err(_) => return State::Finished, }; let backlight = match backlight().await { Ok(Some(b)) => b, - _ => return (None, State::Finished), + _ => return State::Finished, }; let (tx, rx) = unbounded_channel(); let b = (backlight.brightness().await.unwrap_or_default() as f64 / backlight.max_brightness().await.unwrap_or(1) as f64) .clamp(0., 1.); - ( - Some((id, ScreenBacklightUpdate::Init(tx, b))), - State::Waiting(backlight, screen_proxy, rx), - ) + _ = output.send(ScreenBacklightUpdate::Init(tx, b)).await; + + State::Waiting(backlight, screen_proxy, rx) } State::Waiting(backlight, proxy, mut rx) => match rx.recv().await { Some(req) => match req { ScreenBacklightRequest::Get => { - let msg = if let Some(max_brightness) = backlight.max_brightness().await { + if let Some(max_brightness) = backlight.max_brightness().await { let value = (backlight.brightness().await.unwrap_or_default() as f64 / max_brightness as f64) .clamp(0., 1.); - Some((id, ScreenBacklightUpdate::Update(value))) - } else { - None - }; - (msg, State::Waiting(backlight, proxy, rx)) + _ = output.send(ScreenBacklightUpdate::Update(value)).await; + } + State::Waiting(backlight, proxy, rx) } ScreenBacklightRequest::Set(value) => { if let Some(max_brightness) = backlight.max_brightness().await { @@ -151,10 +140,10 @@ async fn start_listening( let value = value.round() as u32; let _ = backlight.set_brightness(&proxy, value).await; } - (None, State::Waiting(backlight, proxy, rx)) + State::Waiting(backlight, proxy, rx) } }, - None => (None, State::Finished), + None => State::Finished, }, State::Finished => iced::futures::future::pending().await, } diff --git a/cosmic-applet-battery/src/power_daemon.rs b/cosmic-applet-battery/src/power_daemon.rs index bfc7f950..bbf65daa 100644 --- a/cosmic-applet-battery/src/power_daemon.rs +++ b/cosmic-applet-battery/src/power_daemon.rs @@ -18,8 +18,7 @@ //! //! …consequently `zbus-xmlgen` did not generate code for the above interfaces. -use cosmic::iced; -use cosmic::iced::subscription; +use cosmic::iced::{self, futures::SinkExt, subscription}; use std::fmt::Debug; use std::hash::Hash; use tokio::sync::mpsc::UnboundedReceiver; @@ -113,9 +112,13 @@ pub async fn set_power_profile(daemon: PowerDaemonProxy<'_>, power: Power) -> Re pub fn power_profile_subscription( id: I, -) -> iced::Subscription<(I, PowerProfileUpdate)> { - subscription::unfold(id, State::Ready, move |state| { - start_listening_loop(id, state) +) -> iced::Subscription { + subscription::channel(id, 50, move |mut output| async move { + let mut state = State::Ready; + + loop { + state = start_listening(state, &mut output).await; + } }) } @@ -126,25 +129,18 @@ pub enum State { Finished, } -async fn start_listening_loop( - id: I, - mut state: State, -) -> ((I, PowerProfileUpdate), State) { - loop { - let (update, new_state) = start_listening(id, state).await; - state = new_state; - if let Some(update) = update { - return (update, state); - } - } -} - -async fn start_listening(id: I, state: State) -> (Option<(I, PowerProfileUpdate)>, State) { +async fn start_listening( + state: State, + output: &mut futures::channel::mpsc::Sender, +) -> State { match state { State::Ready => { let conn = match Connection::system().await.map_err(|e| e.to_string()) { Ok(conn) => conn, - Err(e) => return (Some((id, PowerProfileUpdate::Error(e))), State::Finished), + Err(e) => { + _ = output.send(PowerProfileUpdate::Error(e)).await; + return State::Finished; + } }; let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); @@ -154,10 +150,9 @@ async fn start_listening(id: I, state: State) -> (Option<(I, PowerProfi { Ok(p) => p, Err(e) => { - return ( - Some((id, PowerProfileUpdate::Error(e))), - State::Waiting(conn, rx), - ) + _ = output.send(PowerProfileUpdate::Error(e)).await; + + return State::Waiting(conn, rx); } }; let profile = match get_power_profile(power_proxy) @@ -166,17 +161,12 @@ async fn start_listening(id: I, state: State) -> (Option<(I, PowerProfi { Ok(p) => p, Err(e) => { - return ( - Some((id, PowerProfileUpdate::Error(e))), - State::Waiting(conn, rx), - ) + _ = output.send(PowerProfileUpdate::Error(e)).await; + return State::Waiting(conn, rx); } }; - - ( - Some((id, PowerProfileUpdate::Init(profile, tx))), - State::Waiting(conn, rx), - ) + _ = output.send(PowerProfileUpdate::Init(profile, tx)).await; + State::Waiting(conn, rx) } State::Waiting(conn, mut rx) => { let power_proxy = match PowerDaemonProxy::new(&conn) @@ -185,32 +175,24 @@ async fn start_listening(id: I, state: State) -> (Option<(I, PowerProfi { Ok(p) => p, Err(e) => { - return ( - Some((id, PowerProfileUpdate::Error(e))), - State::Waiting(conn, rx), - ) + _ = output.send(PowerProfileUpdate::Error(e)).await; + return State::Waiting(conn, rx); } }; match rx.recv().await { Some(PowerProfileRequest::Get) => { if let Ok(profile) = get_power_profile(power_proxy).await { - ( - Some((id, PowerProfileUpdate::Update { profile })), - State::Waiting(conn, rx), - ) - } else { - (None, State::Waiting(conn, rx)) + _ = output.send(PowerProfileUpdate::Update { profile }).await; } + State::Waiting(conn, rx) } Some(PowerProfileRequest::Set(profile)) => { let _ = set_power_profile(power_proxy, profile).await; - ( - Some((id, PowerProfileUpdate::Update { profile })), - State::Waiting(conn, rx), - ) + _ = output.send(PowerProfileUpdate::Update { profile }).await; + State::Waiting(conn, rx) } - None => (None, State::Finished), + None => State::Finished, } } State::Finished => iced::futures::future::pending().await, diff --git a/cosmic-applet-battery/src/upower_device.rs b/cosmic-applet-battery/src/upower_device.rs index 0b721f44..48ceaa96 100644 --- a/cosmic-applet-battery/src/upower_device.rs +++ b/cosmic-applet-battery/src/upower_device.rs @@ -3,9 +3,12 @@ //! This code was generated by `zbus-xmlgen` `2.0.1` from DBus introspection data. //! Source: `Interface '/org/freedesktop/UPower/devices/DisplayDevice' from service 'org.freedesktop.UPower' on system bus`. -use cosmic::iced::{self, subscription}; +use cosmic::iced::{ + self, + futures::{SinkExt, StreamExt}, + subscription, +}; -use futures::StreamExt; use std::{fmt::Debug, hash::Hash}; use zbus::dbus_proxy; @@ -152,8 +155,14 @@ trait Device { pub fn device_subscription( id: I, -) -> iced::Subscription<(I, DeviceDbusEvent)> { - subscription::unfold(id, State::Ready, move |state| start_listening_loop(id, state)) +) -> iced::Subscription { + subscription::channel(id, 50, move |mut output| async move { + let mut state = State::Ready; + + loop { + state = start_listening(state, &mut output).await; + } + }) } #[derive(Debug)] @@ -174,45 +183,32 @@ async fn display_device() -> zbus::Result> { .await } -async fn start_listening_loop( - id: I, - mut state: State, -) -> ((I, DeviceDbusEvent), State) { - loop { - let (update, new_state) = start_listening(id, state).await; - state = new_state; - if let Some(update) = update { - return (update, state); - } - } -} - -async fn start_listening(id: I, state: State) -> (Option<(I, DeviceDbusEvent)>, State) { +async fn start_listening( + state: State, + output: &mut futures::channel::mpsc::Sender, +) -> State { match state { State::Ready => { if let Ok(device) = display_device().await { - return ( - Some(( - id, - DeviceDbusEvent::Update { - icon_name: device - .cached_icon_name() - .unwrap_or_default() - .unwrap_or_default(), - percent: device - .cached_percentage() - .unwrap_or_default() - .unwrap_or_default(), - time_to_empty: device - .cached_time_to_empty() - .unwrap_or_default() - .unwrap_or_default(), - }, - )), - State::Waiting(device), - ); + _ = output + .send(DeviceDbusEvent::Update { + icon_name: device + .cached_icon_name() + .unwrap_or_default() + .unwrap_or_default(), + percent: device + .cached_percentage() + .unwrap_or_default() + .unwrap_or_default(), + time_to_empty: device + .cached_time_to_empty() + .unwrap_or_default() + .unwrap_or_default(), + }) + .await; + return State::Waiting(device); } - (None, State::Finished) + State::Finished } State::Waiting(device) => { let mut stream = futures::stream_select!( @@ -221,10 +217,9 @@ async fn start_listening(id: I, state: State) -> (Option<(I, DeviceDbus device.receive_time_to_empty_changed().await.map(|_| ()), ); match stream.next().await { - Some(_) => ( - Some(( - id, - DeviceDbusEvent::Update { + Some(_) => { + _ = output + .send(DeviceDbusEvent::Update { icon_name: device .cached_icon_name() .unwrap_or_default() @@ -237,11 +232,12 @@ async fn start_listening(id: I, state: State) -> (Option<(I, DeviceDbus .cached_time_to_empty() .unwrap_or_default() .unwrap_or_default(), - }, - )), - State::Waiting(device), - ), - None => (None, State::Finished), + }) + .await; + + State::Waiting(device) + } + None => State::Finished, } } State::Finished => iced::futures::future::pending().await, diff --git a/cosmic-applet-battery/src/upower_kbdbacklight.rs b/cosmic-applet-battery/src/upower_kbdbacklight.rs index 04088d33..13c5fdb8 100644 --- a/cosmic-applet-battery/src/upower_kbdbacklight.rs +++ b/cosmic-applet-battery/src/upower_kbdbacklight.rs @@ -3,8 +3,7 @@ //! This code was generated by `zbus-xmlgen` `2.0.1` from DBus introspection data. //! Source: `Interface '/org/freedesktop/UPower/KbdBacklight' from service 'org.freedesktop.UPower' on system bus`. -use cosmic::iced; -use iced::subscription; +use cosmic::iced::{self, futures::SinkExt, subscription}; use std::{fmt::Debug, hash::Hash}; use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}; use zbus::dbus_proxy; @@ -35,21 +34,14 @@ trait KbdBacklight { pub fn kbd_backlight_subscription( id: I, -) -> iced::Subscription<(I, KeyboardBacklightUpdate)> { - subscription::unfold(id, State::Ready, move |state| start_listening_loop(id, state)) -} +) -> iced::Subscription { + subscription::channel(id, 50, move |mut output| async move { + let mut state = State::Ready; -async fn start_listening_loop( - id: I, - mut state: State, -) -> ((I, KeyboardBacklightUpdate), State) { - loop { - let (update, new_state) = start_listening(id, state).await; - state = new_state; - if let Some(update) = update { - return (update, state); + loop { + state = start_listening(state, &mut output).await; } - } + }) } #[derive(Debug)] @@ -62,38 +54,35 @@ pub enum State { Finished, } -async fn start_listening( - id: I, +async fn start_listening( state: State, -) -> (Option<(I, KeyboardBacklightUpdate)>, State) { + output: &mut futures::channel::mpsc::Sender, +) -> State { match state { State::Ready => { let conn = match zbus::Connection::system().await { Ok(conn) => conn, - Err(_) => return (None, State::Finished), + Err(_) => return State::Finished, }; let kbd_proxy = match KbdBacklightProxy::builder(&conn).build().await { Ok(p) => p, - Err(_) => return (None, State::Finished), + Err(_) => return State::Finished, }; let (tx, rx) = unbounded_channel(); let b = kbd_proxy.get_brightness().await.unwrap_or_default() as f64 / kbd_proxy.get_max_brightness().await.unwrap_or(1) as f64; - ( - Some((id, KeyboardBacklightUpdate::Init(tx, b))), - State::Waiting(kbd_proxy, rx), - ) + _ = output.send(KeyboardBacklightUpdate::Init(tx, b)).await; + + State::Waiting(kbd_proxy, rx) } State::Waiting(proxy, mut rx) => match rx.recv().await { Some(req) => match req { KeyboardBacklightRequest::Get => { let b = proxy.get_brightness().await.unwrap_or_default() as f64 / proxy.get_max_brightness().await.unwrap_or(1) as f64; - ( - Some((id, KeyboardBacklightUpdate::Update(b))), - State::Waiting(proxy, rx), - ) + _ = output.send(KeyboardBacklightUpdate::Update(b)).await; + State::Waiting(proxy, rx) } KeyboardBacklightRequest::Set(value) => { if let Ok(max_brightness) = proxy.get_max_brightness().await { @@ -102,10 +91,10 @@ async fn start_listening( let _ = proxy.set_brightness(value).await; } - (None, State::Waiting(proxy, rx)) + State::Waiting(proxy, rx) } }, - None => (None, State::Finished), + None => State::Finished, }, State::Finished => iced::futures::future::pending().await, }