refactor + broken battery

This commit is contained in:
Jiří Maxmilián Stříbrný 2026-03-20 20:29:34 +01:00
parent 58166358ba
commit 93857e2f18
15 changed files with 598 additions and 2440 deletions

94
src/widgets/battery.rs Normal file
View file

@ -0,0 +1,94 @@
use crate::widget::{Message, PanelWidget};
use iced::Element;
use iced::Subscription;
use iced::Task;
use iced::futures::SinkExt;
use iced::futures::StreamExt;
use iced::widget::text;
use std::time::Duration;
#[zbus::proxy(
interface = "org.freedesktop.UPower.Device",
default_service = "org.freedesktop.UPower",
default_path = "/org/freedesktop/UPower/devices/DisplayDevice"
)]
trait UPowerDevice {
#[zbus(property)]
fn percentage(&self) -> zbus::Result<f64>;
}
pub struct BatteryWidget {
capacity: Option<f64>,
}
impl BatteryWidget {
pub fn new() -> Self {
Self { capacity: None }
}
}
impl PanelWidget for BatteryWidget {
fn update(&mut self, message: &Message) -> Task<Message> {
if let Message::Battery(capacity) = message {
self.capacity = *capacity;
}
Task::none()
}
fn subscribe(&self) -> Subscription<Message> {
Subscription::run(|| {
iced::stream::channel(16, async |mut tx| {
loop {
let Ok(conn) = zbus::Connection::system().await else {
tokio::time::sleep(Duration::from_secs(5)).await;
continue;
};
let Ok(proxy) = UPowerDeviceProxy::new(&conn).await else {
tokio::time::sleep(Duration::from_secs(5)).await;
continue;
};
if let Ok(pct) = proxy.percentage().await {
tx.send(Message::Battery(Some(pct))).await.ok();
}
let mut changes = proxy.receive_percentage_changed().await;
while let Some(change) = changes.next().await {
if let Ok(pct) = change.get().await {
tx.send(Message::Battery(Some(pct))).await.ok();
}
}
tx.send(Message::Battery(None)).await.ok();
}
})
})
}
fn view(&self, _id: iced::window::Id) -> Element<'_, Message> {
match self.capacity {
Some(cap) => text!("{} {}", cap, Self::icon(cap)),
None => text!("󰂃"),
}
.into()
}
}
impl BatteryWidget {
fn icon(capacity: f64) -> &'static str {
match capacity {
0f64..6f64 => "󰂎",
6f64..11f64 => "󰁺",
11f64..21f64 => "󰁻",
21f64..31f64 => "󰁼",
31f64..41f64 => "󰁽",
41f64..51f64 => "󰁾",
51f64..61f64 => "󰁿",
61f64..71f64 => "󰂀",
71f64..81f64 => "󰂁",
81f64..91f64 => "󰂂",
91f64..=100f64 => "󰁹",
_ => "󰂃",
}
}
}

35
src/widgets/clock.rs Normal file
View file

@ -0,0 +1,35 @@
use crate::widget::{Message, PanelWidget};
use iced::Task;
use std::time::Duration;
pub struct ClockWidget {
current_time: chrono::DateTime<chrono::Local>,
}
impl ClockWidget {
pub fn new() -> Self {
Self {
current_time: chrono::Local::now(),
}
}
}
impl PanelWidget for ClockWidget {
fn update(&mut self, message: &Message) -> Task<Message> {
let Message::Time = message else {
return Task::none();
};
self.current_time = chrono::Local::now();
Task::none()
}
fn subscribe(&self) -> iced::Subscription<Message> {
iced::time::every(Duration::from_secs(1)).map(|_| Message::Time)
}
fn view(&self, _id: iced::window::Id) -> iced::Element<'_, Message> {
let formatted_time = self.current_time.format("%H:%M");
iced::widget::text!("{}", formatted_time).into()
}
}

3
src/widgets/mod.rs Normal file
View file

@ -0,0 +1,3 @@
pub mod battery;
pub mod clock;
pub mod spacer;

25
src/widgets/spacer.rs Normal file
View file

@ -0,0 +1,25 @@
use crate::widget::PanelWidget;
pub struct Spacer {
space: iced::Length,
}
impl Spacer {
pub fn new(space: iced::Length) -> Self {
Self { space }
}
}
impl PanelWidget for Spacer {
fn update(&mut self, _message: &crate::widget::Message) -> iced::Task<crate::widget::Message> {
iced::Task::none()
}
fn subscribe(&self) -> iced::Subscription<crate::widget::Message> {
iced::Subscription::none()
}
fn view(&self, _id: iced::window::Id) -> iced::Element<'_, crate::widget::Message> {
iced::widget::space().width(self.space).into()
}
}