Inline some clones to make code more readable, add config, implement dimming -> locking -> sleeping into idle daemon, fix waiting on network thread, implement run menu with application launching and math evaluation,

This commit is contained in:
jmb05
2026-11-01 16:21:46 +01:00
parent 80b5cafb8c
commit a8fe99b345
14 changed files with 975 additions and 484 deletions

View File

@@ -78,14 +78,16 @@ pub fn build(
let media_tx = channels.media_tx().unwrap();
let changed_progr = Rc::new(Cell::new(false));
let changed_progr_clone = changed_progr.clone();
volume.connect_value_changed(move |slider, button, _| {
if !changed_progr_clone.get() {
let _ = media_tx.send(MediaCommand::Cmd(
slider.value() as u8,
button.is_active(),
false,
));
volume.connect_value_changed({
let changed_progr = changed_progr.clone();
move |slider, button, _| {
if !changed_progr.get() {
let _ = media_tx.send(MediaCommand::Cmd(
slider.value() as u8,
button.is_active(),
false,
));
}
}
});
let media_tx = channels.media_tx().unwrap();
@@ -189,7 +191,7 @@ pub fn build(
let network_button = Button::new();
network_button.add_css_class("network");
let network_button_content = gtk::Box::new(Orientation::Horizontal, 0);
let network_icon = Image::from_file("../../icons/disconnected.svg");
let network_icon = Image::from_file("icons/disconnected.svg");
network_icon.add_css_class("network-icon");
network_button_content.append(&network_icon);
let network_label = Label::new(None);
@@ -312,184 +314,188 @@ pub fn build(
ControlFlow::Continue
});
let media_rx = channels.take_media_rx().unwrap();
let br_rx = channels.take_br_rx().unwrap();
let net_rx = channels.take_net_rx().unwrap();
let stats_rx = channels.take_stats_rx().unwrap();
let netbird_rx = channels.take_netbird_rx().unwrap();
let idle_rx = channels.take_idle_rx().unwrap();
let monitor_clone = monitor.clone();
let br_tx = channels.br_tx().unwrap();
glib::timeout_add_local(Duration::from_millis(100), move || {
while let Ok(command) = media_rx.try_recv() {
if let MediaCommand::Cmd(vol, mute, bt) = command {
changed_progr.set(true);
volume.set_value(vol as f64);
changed_progr.set(false);
volume.show_scale(!mute);
volume.imp().button.set_active(mute);
if mute {
volume.imp().button.add_css_class("muted");
volume.imp().second_icon.add_child_css_class("muted");
volume
glib::timeout_add_local(Duration::from_millis(100), {
let media_rx = channels.take_media_rx().unwrap();
let br_rx = channels.take_br_rx().unwrap();
let net_rx = channels.take_net_rx().unwrap();
let stats_rx = channels.take_stats_rx().unwrap();
let netbird_rx = channels.take_netbird_rx().unwrap();
let idle_rx = channels.take_idle_rx().unwrap();
let monitor = monitor.clone();
let br_tx = channels.br_tx().unwrap();
move || {
while let Ok(command) = media_rx.try_recv() {
if let MediaCommand::Cmd(vol, mute, bt) = command {
changed_progr.set(true);
volume.set_value(vol as f64);
changed_progr.set(false);
volume.show_scale(!mute);
volume.imp().button.set_active(mute);
if mute {
volume.imp().button.add_css_class("muted");
volume.imp().second_icon.add_child_css_class("muted");
volume
.imp()
.main_icon
.set_icon_path("icons/volume-mute.svg");
} else {
volume.imp().button.remove_css_class("muted");
volume.imp().second_icon.remove_child_css_class("muted");
let idx = ((volume.value() / 100.0) * (VOLUME_ICON_PATHS.len() - 1) as f64
+ 0.5) as usize;
volume.imp().main_icon.set_icon_path(VOLUME_ICON_PATHS[idx]);
}
volume.imp().second_icon.set_visible(bt);
}
}
while let Ok(message) = br_rx.try_recv() {
if let BrightnessMessage::Value(mon, value, _) = message
&& monitor.eq(&mon)
{
brightness.set_value(value as f64);
let idx = ((value as f32 / 100.0) * (BRIGHTNESS_ICONS.len() - 1) as f32 + 0.5)
as usize;
brightness
.imp()
.main_icon
.set_icon_path("icons/volume-mute.svg");
} else {
volume.imp().button.remove_css_class("muted");
volume.imp().second_icon.remove_child_css_class("muted");
let idx = ((volume.value() / 100.0) * (VOLUME_ICON_PATHS.len() - 1) as f64
+ 0.5) as usize;
volume.imp().main_icon.set_icon_path(VOLUME_ICON_PATHS[idx]);
.set_font_icon(BRIGHTNESS_ICONS[idx]);
}
volume.imp().second_icon.set_visible(bt);
}
}
while let Ok(message) = br_rx.try_recv() {
if let BrightnessMessage::Value(mon, value, _) = message
&& monitor.eq(&mon)
{
brightness.set_value(value as f64);
let idx =
((value as f32 / 100.0) * (BRIGHTNESS_ICONS.len() - 1) as f32 + 0.5) as usize;
brightness
.imp()
.main_icon
.set_font_icon(BRIGHTNESS_ICONS[idx]);
}
}
while let Ok(state) = idle_rx.try_recv() {
match state {
IdleState::Dimmed => {
if !caffeine_button.has_css_class("idle") && monitor_valid {
let _ =
br_tx.send(BrightnessMessage::Value(monitor_clone.clone(), 20, true));
brightness.set_value(20.0);
while let Ok(state) = idle_rx.try_recv() {
match state {
IdleState::Dimmed => {
if !caffeine_button.has_css_class("idle") && monitor_valid {
let _ = br_tx.send(BrightnessMessage::Value(monitor.clone(), 20, true));
brightness.set_value(20.0);
}
caffeine_button.add_css_class("idle");
caffeine_button.remove_css_class("inhibit");
caffeine_button.remove_css_class("on");
}
caffeine_button.add_css_class("idle");
caffeine_button.remove_css_class("inhibit");
caffeine_button.remove_css_class("on");
}
other => {
caffeine_button.remove_css_class("idle");
caffeine_button.remove_css_class("inhibit");
caffeine_button.remove_css_class("on");
if monitor_valid {
let _ = br_tx.send(BrightnessMessage::Revert(monitor_clone.clone()));
}
match other {
IdleState::Caffeine => caffeine_button.add_css_class("on"),
IdleState::Inhibited => caffeine_button.add_css_class("inhibit"),
IdleState::Active => {}
_ => {}
other => {
caffeine_button.remove_css_class("idle");
if monitor_valid {
let _ = br_tx.send(BrightnessMessage::Revert(monitor.clone()));
}
match other {
IdleState::Caffeine(true) => caffeine_button.add_css_class("on"),
IdleState::Inhibited(true) => caffeine_button.add_css_class("inhibit"),
IdleState::Caffeine(false) => caffeine_button.remove_css_class("on"),
IdleState::Inhibited(false) => {
caffeine_button.remove_css_class("inhibit")
}
IdleState::Active => {}
_ => {}
}
}
}
}
}
while let Ok(result) = net_rx.try_recv() {
trace!(&LOGGER, "NetworkResult: {:?}", result);
match result {
NetworkState::ChangeNetwork(cfg) => {
match cfg {
Some(network) => {
match network.network_type {
NetworkType::Wifi => {
//let idx = ((20.0 / 100.0) * (WIFI_ICON_PATHS.len() - 1) as f32 + 0.5) as usize;
let idx = ((network.signal as f32 / 100.0)
* (WIFI_ICON_PATHS.len() - 1) as f32
+ 0.5)
as usize;
network_icon.set_from_file(Some(WIFI_ICON_PATHS[idx]));
network_label.set_label(&network.name);
network_label.set_visible(true);
}
NetworkType::Wired => {
network_icon.set_from_file(Some("icons/ethernet.svg"));
network_label.set_visible(false);
while let Ok(result) = net_rx.try_recv() {
trace!(&LOGGER, "NetworkResult: {:?}", result);
match result {
NetworkState::ChangeNetwork(cfg) => {
match cfg {
Some(network) => {
match network.network_type {
NetworkType::Wifi => {
//let idx = ((20.0 / 100.0) * (WIFI_ICON_PATHS.len() - 1) as f32 + 0.5) as usize;
let idx = ((network.signal as f32 / 100.0)
* (WIFI_ICON_PATHS.len() - 1) as f32
+ 0.5)
as usize;
network_icon.set_from_file(Some(WIFI_ICON_PATHS[idx]));
network_label.set_label(&network.name);
network_label.set_visible(true);
}
NetworkType::Wired => {
network_icon.set_from_file(Some("icons/ethernet.svg"));
network_label.set_visible(false);
}
}
}
}
None => {
network_icon.set_from_file(Some("icons/disconnected.svg"));
network_label.set_visible(false);
None => {
network_icon.set_from_file(Some("icons/disconnected.svg"));
network_label.set_visible(false);
}
}
}
NetworkState::VpnState { connected, profile } if profile.as_str() == "wg" => {
if connected {
wg_button.add_css_class("on");
} else {
wg_button.remove_css_class("on");
}
}
_ => {}
}
NetworkState::VpnState { connected, profile } if profile.as_str() == "wg" => {
if connected {
wg_button.add_css_class("on");
} else {
wg_button.remove_css_class("on");
}
while let Ok(tailscale_state) = netbird_rx.try_recv() {
match tailscale_state {
json_socket::State::Disconnected => {
netbird_button.remove_css_class("on");
netbird_button.remove_css_class("starting");
netbird_button.remove_css_class("unknown");
netbird_button.remove_css_class("login");
}
json_socket::State::Connecting => {
netbird_button.remove_css_class("on");
netbird_button.add_css_class("starting");
netbird_button.remove_css_class("unknown");
netbird_button.remove_css_class("login");
}
json_socket::State::Connected => {
netbird_button.add_css_class("on");
netbird_button.remove_css_class("starting");
netbird_button.remove_css_class("unknown");
netbird_button.remove_css_class("login");
}
json_socket::State::NeedsLogin => {
netbird_button.remove_css_class("on");
netbird_button.remove_css_class("starting");
netbird_button.remove_css_class("unknown");
netbird_button.add_css_class("login");
}
}
_ => {}
}
}
while let Ok(tailscale_state) = netbird_rx.try_recv() {
match tailscale_state {
json_socket::State::Disconnected => {
netbird_button.remove_css_class("on");
netbird_button.remove_css_class("starting");
netbird_button.remove_css_class("unknown");
netbird_button.remove_css_class("login");
}
json_socket::State::Connecting => {
netbird_button.remove_css_class("on");
netbird_button.add_css_class("starting");
netbird_button.remove_css_class("unknown");
netbird_button.remove_css_class("login");
}
json_socket::State::Connected => {
netbird_button.add_css_class("on");
netbird_button.remove_css_class("starting");
netbird_button.remove_css_class("unknown");
netbird_button.remove_css_class("login");
}
json_socket::State::NeedsLogin => {
netbird_button.remove_css_class("on");
netbird_button.remove_css_class("starting");
netbird_button.remove_css_class("unknown");
netbird_button.add_css_class("login");
}
if wg_button.has_css_class("on") || netbird_button.has_css_class("on") {
vpn_button.add_css_class("on");
vpn_button.remove_css_class("login");
} else if wg_button.has_css_class("login") || netbird_button.has_css_class("login") {
vpn_button.add_css_class("login");
vpn_button.remove_css_class("on");
} else {
vpn_button.remove_css_class("on");
vpn_button.remove_css_class("login");
}
}
if wg_button.has_css_class("on") || netbird_button.has_css_class("on") {
vpn_button.add_css_class("on");
vpn_button.remove_css_class("login");
} else if wg_button.has_css_class("login") || netbird_button.has_css_class("login") {
vpn_button.add_css_class("login");
vpn_button.remove_css_class("on");
} else {
vpn_button.remove_css_class("on");
vpn_button.remove_css_class("login");
}
while let Ok(stats) = stats_rx.try_recv() {
if let Some(cpu) = stats.cpu {
cpu_label.set_label(&format!("{}%", cpu));
}
if let Some(ram) = stats.ram {
ram_label.set_label(&format!("{}%", ram));
}
for disk in stats.disks {
if disk.0.eq("/") {
disk_label.set_label(&format!("{}%", disk.1));
break;
while let Ok(stats) = stats_rx.try_recv() {
if let Some(cpu) = stats.cpu {
cpu_label.set_label(&format!("{}%", cpu));
}
if let Some(ram) = stats.ram {
ram_label.set_label(&format!("{}%", ram));
}
for disk in stats.disks {
if disk.0.eq("/") {
disk_label.set_label(&format!("{}%", disk.1));
break;
}
}
}
if let Some(gpu) = stats.gpus.into_iter().next() {
gpu_label.set_label(&format!("{}%", gpu.1));
}
if let Some(gpu) = stats.gpus.into_iter().next() {
gpu_label.set_label(&format!("{}%", gpu.1));
}
set_battery_css_classes(&battery_widget, stats.battery_state, stats.battery_charge);
let idx = ((stats.battery_charge as f32 / 100.0) * (BATTERY_ICONS.len() - 1) as f32
+ 0.5) as usize;
let idx = idx.min(BATTERY_ICONS.len() - 1);
battery_widget.set_title(&format!("{} {}%", BATTERY_ICONS[idx], stats.battery_charge));
wattage.set_label(&format!("{:.1}W", stats.battery_draw));
remaining_time.set_label(&format!(" {}h", format_remaining(stats.battery_time)));
set_battery_css_classes(&battery_widget, stats.battery_state, stats.battery_charge);
let idx = ((stats.battery_charge as f32 / 100.0) * (BATTERY_ICONS.len() - 1) as f32
+ 0.5) as usize;
let idx = idx.min(BATTERY_ICONS.len() - 1);
battery_widget
.set_title(&format!("{} {}%", BATTERY_ICONS[idx], stats.battery_charge));
wattage.set_label(&format!(" {:.1}W", stats.battery_draw));
remaining_time.set_label(&format!("{}h", format_remaining(stats.battery_time)));
}
ControlFlow::Continue
}
ControlFlow::Continue
});
utilities
}