use crate::{
widget_default,
widgets::{Rectangle, Result, Text, Widget, WidgetConfig},
};
use async_trait::async_trait;
use cairo::Context;
use log::debug;
use std::{
fmt::Display,
fs::{metadata, read_to_string},
};
fn get_interface_stats(ifname: &str) -> Result<(bool, bool)> {
metadata(format!("/sys/class/net/{}", ifname)).map_err(Error::from)?;
let wireless = metadata(format!("/sys/class/net/{}/wireless", ifname)).is_ok();
let operstate =
read_to_string(format!("/sys/class/net/{}/operstate", ifname)).map_err(Error::from)?;
Ok((wireless, operstate == "up\n"))
}
#[derive(Debug)]
pub struct NetworkIcons {
pub wireless: String,
pub ethernet: String,
pub online: String,
pub offline: String,
}
impl Default for NetworkIcons {
fn default() -> Self {
Self {
wireless: String::from("W"),
ethernet: String::from("E"),
online: String::from("Connected"),
offline: String::from("Offline"),
}
}
}
#[derive(Debug)]
pub struct Network {
format: String,
interface: String,
icons: NetworkIcons,
inner: Text,
}
impl Network {
pub async fn new(
format: impl ToString,
interface: String,
icons: Option<NetworkIcons>,
config: &WidgetConfig,
) -> Box<Self> {
Box::new(Self {
format: format.to_string(),
interface,
inner: *Text::new("", config).await,
icons: icons.unwrap_or_default(),
})
}
}
#[async_trait]
impl Widget for Network {
async fn update(&mut self) -> Result<()> {
debug!("updating network");
let text = if let Ok((wireless, online)) = get_interface_stats(&self.interface) {
self.format
.replace("%n", &self.interface)
.replace("%s", {
if online {
self.icons.online.as_str()
} else {
self.icons.offline.as_str()
}
})
.replace("%t", {
if wireless {
self.icons.wireless.as_str()
} else {
self.icons.ethernet.as_str()
}
})
} else {
"No interface".to_string()
};
self.inner.set_text(text);
Ok(())
}
widget_default!(draw, size, padding);
}
impl Display for Network {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
String::from("Network").fmt(f)
}
}
#[derive(thiserror::Error, Debug)]
#[error(transparent)]
pub enum Error {
IO(#[from] std::io::Error),
}