General Dev
This commit is contained in:
parent
255be18ca2
commit
e233750b24
5 changed files with 61 additions and 22 deletions
BIN
Pasted image.png
Normal file
BIN
Pasted image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
|
|
@ -10,7 +10,11 @@ pub fn spawn_ticker(sender: ComponentSender<App>) {
|
|||
relm4::spawn(async move {
|
||||
loop {
|
||||
sender.input(AppInput::ClockTick);
|
||||
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
||||
// Sleep until the top of the next minute — display is HH:MM only.
|
||||
let secs = gtk4::glib::DateTime::now_local()
|
||||
.map_or(0, |dt| dt.second());
|
||||
let wait = (60 - secs.rem_euclid(60)) as u64;
|
||||
tokio::time::sleep(std::time::Duration::from_secs(wait.max(1))).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
use crate::{App, AppInput};
|
||||
use relm4::ComponentSender;
|
||||
use std::{fs, path::PathBuf, sync::Mutex};
|
||||
use std::{
|
||||
fs,
|
||||
path::PathBuf,
|
||||
sync::{
|
||||
atomic::{AtomicU8, Ordering},
|
||||
LazyLock, Mutex, OnceLock,
|
||||
},
|
||||
};
|
||||
|
||||
const WIFI_STRONG: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/WiFi Strong.svg");
|
||||
const WIFI_MEDIUM: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/WiFi Medium.svg");
|
||||
const WIFI_WEAK: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/WiFi Weak.svg");
|
||||
const WIFI_OFF: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/WiFi Connecting.svg");
|
||||
pub const WIFI_STRONG: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/WiFi Strong.svg");
|
||||
pub const WIFI_MEDIUM: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/WiFi Medium.svg");
|
||||
pub const WIFI_WEAK: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/WiFi Weak.svg");
|
||||
pub const WIFI_OFF: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/WiFi Connecting.svg");
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stats {
|
||||
|
|
@ -22,7 +29,11 @@ struct CpuSnapshot {
|
|||
idle: u64,
|
||||
}
|
||||
|
||||
static PREV_CPU: std::sync::OnceLock<Mutex<CpuSnapshot>> = std::sync::OnceLock::new();
|
||||
static PREV_CPU: OnceLock<Mutex<CpuSnapshot>> = OnceLock::new();
|
||||
static BAT_PATH: OnceLock<Option<PathBuf>> = OnceLock::new();
|
||||
static WIFI_CACHE: LazyLock<Mutex<(String, &'static str)>> =
|
||||
LazyLock::new(|| Mutex::new(("—".to_string(), WIFI_OFF)));
|
||||
static WIFI_TICK: AtomicU8 = AtomicU8::new(0);
|
||||
|
||||
fn read_cpu() -> f32 {
|
||||
let text = fs::read_to_string("/proc/stat").unwrap_or_default();
|
||||
|
|
@ -65,15 +76,16 @@ fn read_ram() -> u64 {
|
|||
total.saturating_sub(avail)
|
||||
}
|
||||
|
||||
fn bat_path() -> Option<PathBuf> {
|
||||
fs::read_dir("/sys/class/power_supply")
|
||||
.ok()?
|
||||
.filter_map(|e| e.ok())
|
||||
.map(|e| e.path())
|
||||
.find(|p| {
|
||||
p.file_name()
|
||||
.map_or(false, |n| n.to_string_lossy().starts_with("BAT"))
|
||||
fn bat_path() -> Option<&'static PathBuf> {
|
||||
BAT_PATH
|
||||
.get_or_init(|| {
|
||||
fs::read_dir("/sys/class/power_supply")
|
||||
.ok()?
|
||||
.filter_map(|e| e.ok())
|
||||
.map(|e| e.path())
|
||||
.find(|p| p.file_name().map_or(false, |n| n.to_string_lossy().starts_with("BAT")))
|
||||
})
|
||||
.as_ref()
|
||||
}
|
||||
|
||||
fn read_power() -> Option<f32> {
|
||||
|
|
@ -161,7 +173,17 @@ pub async fn poll() -> Stats {
|
|||
let mem = read_ram();
|
||||
let power = read_power().map_or_else(|| " —W".into(), |w| format!("{w:4.1}W"));
|
||||
let bat = read_battery().map_or_else(|| " —".into(), |p| format!("{p:3}%"));
|
||||
let (wifi_ssid, wifi_icon) = read_wifi().await;
|
||||
// Refresh WiFi every 8 cycles (~16 s); cache the result in between.
|
||||
let (wifi_ssid, wifi_icon) = {
|
||||
let tick = WIFI_TICK.fetch_add(1, Ordering::Relaxed);
|
||||
if tick % 8 == 0 {
|
||||
let fresh = read_wifi().await;
|
||||
*WIFI_CACHE.lock().unwrap() = fresh.clone();
|
||||
fresh
|
||||
} else {
|
||||
WIFI_CACHE.lock().unwrap().clone()
|
||||
}
|
||||
};
|
||||
Stats {
|
||||
cpu: format!("{cpu:3.0}%"),
|
||||
mem: if mem >= 1024 * 1024 {
|
||||
|
|
|
|||
14
src/main.rs
14
src/main.rs
|
|
@ -25,6 +25,8 @@ pub struct App {
|
|||
bat_lbl: gtk4::Label,
|
||||
wifi_lbl: gtk4::Label,
|
||||
wifi_img: gtk4::Image,
|
||||
// Pre-loaded textures indexed by the WIFI_* constant pointer values.
|
||||
wifi_textures: std::collections::HashMap<usize, gtk4::gdk::Texture>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -53,7 +55,6 @@ impl SimpleComponent for App {
|
|||
set_start_widget = >k::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_spacing: 0,
|
||||
set_margin_start: 8,
|
||||
|
||||
#[name = "workspace_box"]
|
||||
gtk::Box {
|
||||
|
|
@ -92,6 +93,12 @@ impl SimpleComponent for App {
|
|||
wifi_lbl.set_max_width_chars(12);
|
||||
let wifi_img = gtk4::Image::from_paintable(Some(&svg_texture(asset!("WiFi Connecting.svg"))));
|
||||
|
||||
use bar::stats::{WIFI_OFF, WIFI_STRONG, WIFI_MEDIUM, WIFI_WEAK};
|
||||
let wifi_textures = [WIFI_STRONG, WIFI_MEDIUM, WIFI_WEAK, WIFI_OFF]
|
||||
.into_iter()
|
||||
.map(|p| (p.as_ptr() as usize, svg_texture(p)))
|
||||
.collect();
|
||||
|
||||
let mut model = App {
|
||||
workspaces: vec![],
|
||||
active_ws: 1,
|
||||
|
|
@ -103,6 +110,7 @@ impl SimpleComponent for App {
|
|||
bat_lbl: bat_lbl.clone(),
|
||||
wifi_lbl: wifi_lbl.clone(),
|
||||
wifi_img: wifi_img.clone(),
|
||||
wifi_textures,
|
||||
};
|
||||
let widgets = view_output!();
|
||||
model.workspace_box = widgets.workspace_box.clone();
|
||||
|
|
@ -149,7 +157,9 @@ impl SimpleComponent for App {
|
|||
self.pwr_lbl.set_label(&stats.power);
|
||||
self.bat_lbl.set_label(&stats.bat);
|
||||
self.wifi_lbl.set_label(&stats.wifi_ssid);
|
||||
self.wifi_img.set_paintable(Some(&svg_texture(stats.wifi_icon)));
|
||||
if let Some(tex) = self.wifi_textures.get(&(stats.wifi_icon.as_ptr() as usize)) {
|
||||
self.wifi_img.set_paintable(Some(tex));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
src/theme.rs
11
src/theme.rs
|
|
@ -44,10 +44,13 @@ fn load_css() -> String {
|
|||
};
|
||||
|
||||
format!(
|
||||
"window.breadbar {{ background-color: {bg_rgba}; }}\
|
||||
.workspace-btn {{ background: {surface}; color: {fg}; border-radius: 4px;\
|
||||
border: none; min-width: 24px; padding: 0 8px; }}\
|
||||
.workspace-btn:hover, .workspace-btn.active {{ background: {accent}; }}\
|
||||
"* {{ font-family: 'JetBrainsMono Nerd Font Mono', monospace; font-size: 12px; }}\
|
||||
window.breadbar {{ background-color: {bg_rgba}; border-radius: 0; }}\
|
||||
.workspace-btn {{ background: transparent; color: {fg}; opacity: 0.45;\
|
||||
border-radius: 0 0 8px 8px; border: none; outline: none; box-shadow: none;\
|
||||
min-width: 24px; padding: 2px 8px; }}\
|
||||
.workspace-btn:hover {{ opacity: 0.8; }}\
|
||||
.workspace-btn.active {{ background: {accent}; opacity: 1; }}\
|
||||
label {{ color: {fg}; }}\
|
||||
window.breadbar-notification {{ background-color: alpha({bg_plain}, 0.95); }}\
|
||||
.notification-card {{ background: {surface}; border-radius: 6px;\
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue