Add: Wifi widget
- Use `nmcli`
This commit is contained in:
parent
8851869f07
commit
61f7020fd3
@ -4,6 +4,7 @@ mod common;
|
||||
mod datewidget;
|
||||
mod timewidget;
|
||||
mod volumewidget;
|
||||
mod wifiwidget;
|
||||
|
||||
use crate::TopBar;
|
||||
|
||||
@ -13,7 +14,8 @@ pub fn install_callbacks(ui: &TopBar) {
|
||||
batterywidget::install(ui);
|
||||
volumewidget::install(ui);
|
||||
brightnesswidget::install(ui);
|
||||
wifiwidget::install(ui);
|
||||
|
||||
// In the future:
|
||||
// networkwidget::install(ui);
|
||||
// weatherwidget::install(ui);
|
||||
}
|
||||
|
||||
104
src/widgets/wifiwidget.rs
Normal file
104
src/widgets/wifiwidget.rs
Normal file
@ -0,0 +1,104 @@
|
||||
// Wi-Fi widget backend. Polls NetworkManager every second using `nmcli`.
|
||||
use super::common::run_cmd;
|
||||
use crate::TopBar;
|
||||
use slint::{ComponentHandle, SharedString, Timer, TimerMode};
|
||||
use std::process::Command;
|
||||
use std::time::Duration;
|
||||
|
||||
/// Run a shell command and capture stdout as a string
|
||||
fn run_cmd_output(cmd: &str, args: &[&str]) -> Option<String> {
|
||||
let out = Command::new(cmd).args(args).output().ok()?;
|
||||
if !out.status.success() {
|
||||
return None;
|
||||
}
|
||||
Some(String::from_utf8_lossy(&out.stdout).trim().to_string())
|
||||
}
|
||||
|
||||
/// Return (connected: bool, ssid: String, signal: u8)
|
||||
fn read_wifi_status() -> Option<(bool, String, u8)> {
|
||||
// Fields: ACTIVE:SSID:SIGNAL
|
||||
let out = run_cmd_output("nmcli", &["-t", "-f", "ACTIVE,SSID,SIGNAL", "dev", "wifi"])?;
|
||||
for line in out.lines() {
|
||||
let mut parts = line.split(':');
|
||||
let active = parts.next()?.trim();
|
||||
let ssid = parts.next().unwrap_or("").trim().to_string();
|
||||
let signal = parts.next().unwrap_or("0").trim().parse().unwrap_or(0);
|
||||
|
||||
if active == "yes" {
|
||||
return Some((true, ssid, signal));
|
||||
}
|
||||
}
|
||||
Some((false, String::new(), 0))
|
||||
}
|
||||
|
||||
/// True if Wi-Fi hardware is enabled
|
||||
fn wifi_enabled() -> bool {
|
||||
// nmcli -t -f WIFI g → "enabled" or "disabled"
|
||||
if let Some(out) = run_cmd_output("nmcli", &["-t", "-f", "WIFI", "g"]) {
|
||||
return out.trim() == "enabled";
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Choose icon based on Wi-Fi signal
|
||||
fn wifi_icon(signal: u8, connected: bool, enabled: bool) -> SharedString {
|
||||
let icon = if !enabled {
|
||||
"" // wifi off
|
||||
} else if !connected {
|
||||
"" // wifi on, no connection
|
||||
} else {
|
||||
match signal {
|
||||
0..=20 => "",
|
||||
21..=40 => "",
|
||||
41..=60 => "",
|
||||
61..=100 => "",
|
||||
_ => "", // error/unexpected
|
||||
}
|
||||
};
|
||||
SharedString::from(icon)
|
||||
}
|
||||
|
||||
/// Tooltip shown on hover
|
||||
fn wifi_tooltip(connected: bool, ssid: &str, signal: u8, enabled: bool) -> String {
|
||||
if !enabled {
|
||||
"Wi-Fi: disabled".into()
|
||||
} else if !connected {
|
||||
"Wi-Fi: no internet".into()
|
||||
} else {
|
||||
format!("Wi-Fi: {ssid} ({signal}%)")
|
||||
}
|
||||
}
|
||||
|
||||
/// Periodic Wi-Fi updater
|
||||
fn start_wifi_updater(ui: &TopBar) {
|
||||
let weak = ui.as_weak();
|
||||
|
||||
let timer = Box::leak(Box::new(Timer::default()));
|
||||
|
||||
// Update every second (connection quality can change quickly)
|
||||
timer.start(TimerMode::Repeated, Duration::from_secs(1), move || {
|
||||
if let Some(ui) = weak.upgrade() {
|
||||
let enabled = wifi_enabled();
|
||||
let (connected, ssid, signal) = read_wifi_status().unwrap_or((false, String::new(), 0));
|
||||
|
||||
let icon = wifi_icon(signal, connected, enabled);
|
||||
let tooltip = wifi_tooltip(connected, &ssid, signal, enabled);
|
||||
|
||||
ui.set_wifi_icon(icon);
|
||||
ui.set_wifi_tooltip(tooltip.into());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Install Wi-Fi click action + updater
|
||||
pub fn install(ui: &TopBar) {
|
||||
let weak = ui.as_weak();
|
||||
|
||||
ui.on_show_wifi(move || {
|
||||
if weak.upgrade().is_some() {
|
||||
run_cmd("xclock"); // Fix later
|
||||
}
|
||||
});
|
||||
|
||||
start_wifi_updater(ui);
|
||||
}
|
||||
@ -36,7 +36,7 @@ export component TopBar inherits Window {
|
||||
in property <color> volume_bg_clicked;*/
|
||||
callback show_volume();
|
||||
|
||||
// brightness widget
|
||||
// Brightness widget
|
||||
in property <string> brightness_tooltip;
|
||||
in property <string> brightness_icon;
|
||||
/*in property <color> brightness_icon_color;
|
||||
@ -44,6 +44,15 @@ export component TopBar inherits Window {
|
||||
in property <color> brightness_bg_hover;
|
||||
in property <color> brightness_bg_clicked;*/
|
||||
callback show_brightness();
|
||||
|
||||
// Wifi widget
|
||||
in property <string> wifi_tooltip;
|
||||
in property <string> wifi_icon;
|
||||
/*in property <color> wifi_icon_color: #ffffff;
|
||||
in property <color> wifi_bg_normal: #8e9162;
|
||||
in property <color> wifi_bg_hover: #6d8a4d;
|
||||
in property <color> wifi_bg_clicked: #4a5f70;*/
|
||||
callback show_wifi();
|
||||
|
||||
title: "chocobar";
|
||||
width: bar_width *1px;
|
||||
@ -88,6 +97,18 @@ export component TopBar inherits Window {
|
||||
|
||||
HorizontalLayout {
|
||||
alignment: end; // Right-align
|
||||
|
||||
// SquareIconWidget - Wifi
|
||||
SquareIconWidget {
|
||||
bar_height: root.bar_height;
|
||||
icon_text: root.wifi_icon;
|
||||
tooltip_text: root.wifi_tooltip;
|
||||
/*icon_color: root.wifi_icon_color;
|
||||
bg_normal: root.wifi_bg_normal;
|
||||
bg_hover: root.wifi_bg_hover;
|
||||
bg_clicked: root.wifi_bg_clicked;*/
|
||||
square_btn_callback => root.show_wifi();
|
||||
}
|
||||
|
||||
// SquareIconWidget - brightness
|
||||
SquareIconWidget {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user