feat(bar): add battery and network widgets

This commit is contained in:
LGUG2Z
2024-08-27 20:00:40 -07:00
parent 92bb9f680b
commit 8e74e97706
5 changed files with 471 additions and 14 deletions

228
Cargo.lock generated
View File

@@ -780,6 +780,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "cfg_aliases"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "cgl"
version = "0.3.2"
@@ -1156,6 +1162,17 @@ dependencies = [
"libloading 0.8.4",
]
[[package]]
name = "dlopen2"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa"
dependencies = [
"libc",
"once_cell",
"winapi",
]
[[package]]
name = "document-features"
version = "0.2.10"
@@ -1783,7 +1800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746"
dependencies = [
"bitflags 2.6.0",
"cfg_aliases",
"cfg_aliases 0.1.1",
"cgl",
"core-foundation",
"dispatch",
@@ -1806,7 +1823,7 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ebcdfba24f73b8412c5181e56f092b5eff16671c514ce896b258a0a64bd7735"
dependencies = [
"cfg_aliases",
"cfg_aliases 0.1.1",
"glutin",
"raw-window-handle 0.5.2",
"winit",
@@ -2348,7 +2365,7 @@ dependencies = [
"serde_yaml",
"shadow-rs",
"strum",
"sysinfo",
"sysinfo 0.30.13",
"tracing",
"tracing-appender",
"tracing-subscriber",
@@ -2372,8 +2389,10 @@ dependencies = [
"crossbeam-channel",
"eframe",
"komorebi-client",
"netdev",
"serde_json",
"sysinfo",
"starship-battery",
"sysinfo 0.31.3",
"windows 0.54.0",
]
@@ -2418,7 +2437,7 @@ dependencies = [
"serde_json_lenient",
"serde_yaml",
"shadow-rs",
"sysinfo",
"sysinfo 0.30.13",
"thiserror",
"uds_windows",
"which",
@@ -2456,6 +2475,12 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.155"
@@ -2561,6 +2586,15 @@ version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "mach2"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
dependencies = [
"libc",
]
[[package]]
name = "malloc_buf"
version = "0.0.6"
@@ -2579,6 +2613,12 @@ dependencies = [
"regex-automata 0.1.10",
]
[[package]]
name = "memalloc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df39d232f5c40b0891c10216992c2f250c054105cb1e56f0fc9032db6203ecc1"
[[package]]
name = "memchr"
version = "2.7.4"
@@ -2794,6 +2834,71 @@ dependencies = [
"winapi",
]
[[package]]
name = "netdev"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7516ad2c46cc25da098ed7d6b9a0cbe9e1fbffbd04b1596148b95f2841179c83"
dependencies = [
"dlopen2",
"libc",
"memalloc",
"netlink-packet-core",
"netlink-packet-route",
"netlink-sys",
"once_cell",
"system-configuration 0.6.1",
"windows-sys 0.52.0",
]
[[package]]
name = "netlink-packet-core"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4"
dependencies = [
"anyhow",
"byteorder",
"netlink-packet-utils",
]
[[package]]
name = "netlink-packet-route"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66"
dependencies = [
"anyhow",
"bitflags 1.3.2",
"byteorder",
"libc",
"netlink-packet-core",
"netlink-packet-utils",
]
[[package]]
name = "netlink-packet-utils"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34"
dependencies = [
"anyhow",
"byteorder",
"paste",
"thiserror",
]
[[package]]
name = "netlink-sys"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "416060d346fbaf1f23f9512963e3e878f1a78e707cb699ba9215761754244307"
dependencies = [
"bytes",
"libc",
"log",
]
[[package]]
name = "nix"
version = "0.26.4"
@@ -2814,7 +2919,19 @@ checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
dependencies = [
"bitflags 2.6.0",
"cfg-if 1.0.0",
"cfg_aliases",
"cfg_aliases 0.1.1",
"libc",
]
[[package]]
name = "nix"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
"bitflags 2.6.0",
"cfg-if 1.0.0",
"cfg_aliases 0.2.1",
"libc",
]
@@ -3295,6 +3412,19 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "plist"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016"
dependencies = [
"base64",
"indexmap",
"quick-xml 0.32.0",
"serde",
"time",
]
[[package]]
name = "png"
version = "0.17.13"
@@ -3421,6 +3551,15 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58"
[[package]]
name = "quick-xml"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2"
dependencies = [
"memchr",
]
[[package]]
name = "quick-xml"
version = "0.34.0"
@@ -3636,7 +3775,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"sync_wrapper",
"system-configuration",
"system-configuration 0.5.1",
"tokio",
"tokio-native-tls",
"tower-service",
@@ -4090,6 +4229,24 @@ dependencies = [
"bitflags 2.6.0",
]
[[package]]
name = "starship-battery"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da7915746794358b8f649d3032c8ce150f55b7a0cd41951f170162e82e6cf43f"
dependencies = [
"cfg-if 1.0.0",
"core-foundation",
"lazycell",
"libc",
"mach2",
"nix 0.29.0",
"num-traits",
"plist",
"uom",
"winapi",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
@@ -4200,6 +4357,20 @@ dependencies = [
"windows 0.52.0",
]
[[package]]
name = "sysinfo"
version = "0.31.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b92e0bdf838cbc1c4c9ba14f9c97a7ec6cdcd1ae66b10e1e42775a25553f45d"
dependencies = [
"core-foundation-sys",
"libc",
"memchr",
"ntapi",
"rayon",
"windows 0.54.0",
]
[[package]]
name = "system-configuration"
version = "0.5.1"
@@ -4208,7 +4379,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"system-configuration-sys",
"system-configuration-sys 0.5.0",
]
[[package]]
name = "system-configuration"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags 2.6.0",
"core-foundation",
"system-configuration-sys 0.6.0",
]
[[package]]
@@ -4221,6 +4403,16 @@ dependencies = [
"libc",
]
[[package]]
name = "system-configuration-sys"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "tempfile"
version = "3.10.1"
@@ -4696,6 +4888,16 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "uom"
version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffd36e5350a65d112584053ee91843955826bf9e56ec0d1351214e01f6d7cd9c"
dependencies = [
"num-traits",
"typenum",
]
[[package]]
name = "url"
version = "2.5.2"
@@ -4921,7 +5123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edf466fc49a4feb65a511ca403fec3601494d0dee85dbf37fff6fa0dd4eec3b6"
dependencies = [
"proc-macro2",
"quick-xml",
"quick-xml 0.34.0",
"quote",
]
@@ -4983,7 +5185,7 @@ checksum = "90e37c7b9921b75dfd26dd973fdcbce36f13dfa6e2dc82aece584e0ed48c355c"
dependencies = [
"arrayvec",
"cfg-if 1.0.0",
"cfg_aliases",
"cfg_aliases 0.1.1",
"document-features",
"js-sys",
"log",
@@ -5009,7 +5211,7 @@ dependencies = [
"arrayvec",
"bit-vec",
"bitflags 2.6.0",
"cfg_aliases",
"cfg_aliases 0.1.1",
"codespan-reporting",
"document-features",
"indexmap",
@@ -5037,7 +5239,7 @@ dependencies = [
"arrayvec",
"ash",
"bitflags 2.6.0",
"cfg_aliases",
"cfg_aliases 0.1.1",
"core-graphics-types",
"glow",
"glutin_wgl_sys",
@@ -5460,7 +5662,7 @@ dependencies = [
"bitflags 2.6.0",
"bytemuck",
"calloop",
"cfg_aliases",
"cfg_aliases 0.1.1",
"core-foundation",
"core-graphics",
"cursor-icon",

View File

@@ -11,7 +11,9 @@ komorebi-client = { path = "../komorebi-client" }
anyhow = "1"
chrono = "0.4"
eframe = "0.28"
netdev = "0.30"
serde_json = "1"
sysinfo = "0.30"
starship-battery = "0.9"
sysinfo = "0.31"
crossbeam-channel = "0.5"
windows = { workspace = true }

View File

@@ -0,0 +1,81 @@
use crate::widget::BarWidget;
use starship_battery::units::ratio::percent;
use starship_battery::Manager;
use starship_battery::State;
use std::time::Duration;
use std::time::Instant;
#[derive(Copy, Clone, Debug)]
pub struct BatteryConfig {
pub enable: bool,
}
impl From<BatteryConfig> for Battery {
fn from(value: BatteryConfig) -> Self {
let manager = Manager::new().unwrap();
let mut last_state = vec![];
let mut state = None;
if let Ok(mut batteries) = manager.batteries() {
if let Some(Ok(first)) = batteries.nth(0) {
let percentage = first.state_of_charge().get::<percent>();
match first.state() {
State::Charging => state = Some(BatteryState::Charging),
State::Discharging => state = Some(BatteryState::Discharging),
_ => {}
}
last_state.push(format!("{percentage}%"));
}
}
Self {
enable: value.enable,
manager,
last_state,
state: state.unwrap_or(BatteryState::Discharging),
last_updated: Instant::now(),
}
}
}
pub enum BatteryState {
Charging,
Discharging,
}
pub struct Battery {
pub enable: bool,
manager: Manager,
pub state: BatteryState,
last_state: Vec<String>,
last_updated: Instant,
}
impl BarWidget for Battery {
fn output(&mut self) -> Vec<String> {
let mut outputs = self.last_state.clone();
let now = Instant::now();
if now.duration_since(self.last_updated) > Duration::from_secs(10) {
outputs.clear();
if let Ok(mut batteries) = self.manager.batteries() {
if let Some(Ok(first)) = batteries.nth(0) {
let percentage = first.state_of_charge().get::<percent>();
match first.state() {
State::Charging => self.state = BatteryState::Charging,
State::Discharging => self.state = BatteryState::Discharging,
_ => {}
}
outputs.push(format!("{percentage}%"));
}
}
self.last_state.clone_from(&outputs);
self.last_updated = now;
}
outputs
}
}

View File

@@ -1,16 +1,23 @@
mod battery;
mod date;
mod media;
mod memory;
mod network;
mod storage;
mod time;
mod widget;
use crate::battery::Battery;
use crate::battery::BatteryConfig;
use crate::battery::BatteryState;
use crate::date::Date;
use crate::date::DateFormat;
use crate::media::Media;
use crate::media::MediaConfig;
use crate::memory::Memory;
use crate::memory::MemoryConfig;
use crate::network::Network;
use crate::network::NetworkConfig;
use crate::storage::Storage;
use crate::storage::StorageConfig;
use crate::time::TimeFormat;
@@ -71,6 +78,8 @@ pub struct Config {
storage: StorageConfig,
memory: MemoryConfig,
media: MediaConfig,
battery: BatteryConfig,
network: NetworkConfig,
}
fn main() -> eframe::Result<()> {
@@ -91,6 +100,11 @@ fn main() -> eframe::Result<()> {
storage: StorageConfig { enable: true },
memory: MemoryConfig { enable: true },
media: MediaConfig { enable: true },
battery: BatteryConfig { enable: true },
network: NetworkConfig {
enable: true,
show_data: true,
},
};
// TODO: ensure that config.monitor_index represents a valid komorebi monitor index
@@ -199,6 +213,8 @@ struct Komobar {
memory: Memory,
storage: Storage,
media: Media,
battery: Battery,
network: Network,
}
impl Komobar {
@@ -224,6 +240,8 @@ impl Komobar {
memory: Memory::from(config.memory),
storage: Storage::from(config.storage),
media: Media::from(config.media),
battery: Battery::from(config.battery),
network: Network::from(config.network),
}
}
}
@@ -352,6 +370,26 @@ impl eframe::App for Komobar {
// TODO: make the order configurable
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
if self.battery.enable {
let battery_output = self.battery.output();
if !battery_output.is_empty() {
for battery in battery_output {
let emoji = match self.battery.state {
BatteryState::Charging => "⚡️",
BatteryState::Discharging => "🔋",
};
ui.add(
Label::new(format!("{emoji} {battery}"))
.selectable(false)
.sense(Sense::click()),
);
}
ui.add_space(10.0);
}
}
if self.time.enable {
for time in self.time.output() {
if ui
@@ -388,6 +426,53 @@ impl eframe::App for Komobar {
ui.add_space(10.0);
}
if self.network.enable {
let network_output = self.network.output();
if !network_output.is_empty() {
match network_output.len() {
1 => {
if ui
.add(
Label::new(format!("📶 {}", network_output[0]))
.selectable(false)
.sense(Sense::click()),
)
.clicked()
{
if let Err(error) =
Command::new("cmd.exe").args(["/C", "ncpa"]).spawn()
{
eprintln!("{}", error)
}
}
}
2 => {
if ui
.add(
Label::new(format!(
"📶 {} - {}",
network_output[0], network_output[1]
))
.selectable(false)
.sense(Sense::click()),
)
.clicked()
{
if let Err(error) =
Command::new("cmd.exe").args(["/C", "ncpa"]).spawn()
{
eprintln!("{}", error)
}
};
}
_ => {}
}
ui.add_space(10.0);
}
}
if self.memory.enable {
for ram in self.memory.output() {
if ui

View File

@@ -0,0 +1,87 @@
use crate::widget::BarWidget;
use std::time::Duration;
use std::time::Instant;
use sysinfo::Networks;
#[derive(Copy, Clone, Debug)]
pub struct NetworkConfig {
pub enable: bool,
pub show_data: bool,
}
impl From<NetworkConfig> for Network {
fn from(value: NetworkConfig) -> Self {
let mut last_state = vec![];
let mut networks = Networks::new_with_refreshed_list();
if let Ok(interface) = netdev::get_default_interface() {
if let Some(friendly_name) = interface.friendly_name {
last_state.push(friendly_name.clone());
if value.show_data {
networks.refresh();
for (interface_name, data) in &networks {
if friendly_name.eq(interface_name) {
last_state.push(format!(
"{} MB (down) / {} MB (up)",
data.total_received() / 1024 / 1024,
data.total_transmitted() / 1024 / 1024,
))
}
}
}
}
}
Self {
enable: value.enable,
last_state,
networks,
show_data: value.show_data,
last_updated: Instant::now(),
}
}
}
pub struct Network {
pub enable: bool,
pub show_data: bool,
networks: Networks,
last_state: Vec<String>,
last_updated: Instant,
}
impl BarWidget for Network {
fn output(&mut self) -> Vec<String> {
let mut outputs = self.last_state.clone();
let now = Instant::now();
if now.duration_since(self.last_updated) > Duration::from_secs(10) {
outputs.clear();
if let Ok(interface) = netdev::get_default_interface() {
if let Some(friendly_name) = &interface.friendly_name {
outputs.push(friendly_name.clone());
if self.show_data {
self.networks.refresh();
for (interface_name, data) in &self.networks {
if friendly_name.eq(interface_name) {
outputs.push(format!(
"{} MB (down) / {} MB (up)",
data.total_received() / 1024 / 1024,
data.total_transmitted() / 1024 / 1024,
))
}
}
}
}
}
self.last_state.clone_from(&outputs);
self.last_updated = now;
}
outputs
}
}