mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-09-18 12:46:58 +02:00
refactor(networkmanager): replace state-based w/ event-based approach
This commit is contained in:
parent
9ca5f4baa4
commit
1836ab2943
6 changed files with 230 additions and 205 deletions
|
@ -1,17 +1,18 @@
|
|||
use color_eyre::Result;
|
||||
use futures_lite::StreamExt;
|
||||
use gtk::prelude::{ContainerExt, WidgetExt};
|
||||
use gtk::{Box as GtkBox, Image, Orientation};
|
||||
use serde::Deserialize;
|
||||
use tokio::sync::mpsc::Receiver;
|
||||
|
||||
use crate::channels::{AsyncSenderExt, BroadcastReceiverExt};
|
||||
use crate::clients::networkmanager::Client;
|
||||
use crate::clients::networkmanager::dbus::{DeviceState, DeviceType};
|
||||
use crate::clients::networkmanager::event::Event;
|
||||
use crate::config::CommonConfig;
|
||||
use crate::gtk_helpers::IronbarGtkExt;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||
use crate::image::Provider;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, WidgetContext};
|
||||
use crate::{module_impl, spawn};
|
||||
use color_eyre::{Result, eyre::Ok};
|
||||
use glib::spawn_future_local;
|
||||
use gtk::prelude::{ContainerExt, WidgetExt};
|
||||
use gtk::{Image, Orientation};
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
|
@ -27,7 +28,7 @@ const fn default_icon_size() -> i32 {
|
|||
24
|
||||
}
|
||||
|
||||
impl Module<GtkBox> for NetworkManagerModule {
|
||||
impl Module<gtk::Box> for NetworkManagerModule {
|
||||
type SendMessage = Event;
|
||||
type ReceiveMessage = ();
|
||||
|
||||
|
@ -37,19 +38,19 @@ impl Module<GtkBox> for NetworkManagerModule {
|
|||
&self,
|
||||
_info: &ModuleInfo,
|
||||
context: &WidgetContext<Event, ()>,
|
||||
_rx: Receiver<()>,
|
||||
_rx: mpsc::Receiver<()>,
|
||||
) -> Result<()> {
|
||||
let client = context.try_client::<Client>()?;
|
||||
// let mut client_signal = client.subscribe().to_stream();
|
||||
// let widget_transmitter = context.tx.clone();
|
||||
// Should we be using context.tx with ModuleUpdateEvent::Update instead?
|
||||
let tx = context.update_tx.clone();
|
||||
spawn(async move {
|
||||
let mut client_rx = client.subscribe();
|
||||
while let Result::Ok(event) = client_rx.recv().await {
|
||||
tx.send(event)?;
|
||||
}
|
||||
|
||||
// spawn(async move {
|
||||
// while let Some(state) = client_signal.next().await {
|
||||
// widget_transmitter
|
||||
// .send_expect(ModuleUpdateEvent::Update(state))
|
||||
// .await;
|
||||
// }
|
||||
// });
|
||||
Ok(())
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -58,37 +59,116 @@ impl Module<GtkBox> for NetworkManagerModule {
|
|||
self,
|
||||
context: WidgetContext<Event, ()>,
|
||||
_info: &ModuleInfo,
|
||||
) -> Result<ModuleParts<GtkBox>> {
|
||||
let container = GtkBox::new(Orientation::Horizontal, 0);
|
||||
) -> Result<ModuleParts<gtk::Box>> {
|
||||
let container = gtk::Box::new(Orientation::Horizontal, 0);
|
||||
|
||||
// Wired icon
|
||||
let wired_icon = Image::new();
|
||||
wired_icon.add_class("icon");
|
||||
wired_icon.add_class("wired-icon");
|
||||
container.add(&wired_icon);
|
||||
|
||||
// Wifi icon
|
||||
let wifi_icon = Image::new();
|
||||
wifi_icon.add_class("icon");
|
||||
wifi_icon.add_class("wifi-icon");
|
||||
container.add(&wifi_icon);
|
||||
|
||||
// Cellular icon
|
||||
let cellular_icon = Image::new();
|
||||
cellular_icon.add_class("icon");
|
||||
cellular_icon.add_class("cellular-icon");
|
||||
container.add(&cellular_icon);
|
||||
|
||||
// VPN icon
|
||||
let vpn_icon = Image::new();
|
||||
vpn_icon.add_class("icon");
|
||||
vpn_icon.add_class("vpn-icon");
|
||||
container.add(&vpn_icon);
|
||||
|
||||
context
|
||||
.subscribe()
|
||||
.recv_glib_async((), move |(), event| async {});
|
||||
// TODO: Check if passing the widget context in its entirety here is possible
|
||||
// We cannot use recv_glib_async() here because the lifetimes don't work out
|
||||
spawn_future_local(handle_update_events(
|
||||
context.subscribe(),
|
||||
container.clone(),
|
||||
self.icon_size,
|
||||
context.ironbar.image_provider(),
|
||||
));
|
||||
|
||||
Ok(ModuleParts::new(container, None))
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_update_events(
|
||||
mut rx: broadcast::Receiver<Event>,
|
||||
container: gtk::Box,
|
||||
icon_size: i32,
|
||||
image_provider: Provider,
|
||||
) {
|
||||
let mut icons = HashMap::<String, Image>::new();
|
||||
|
||||
while let Result::Ok(event) = rx.recv().await {
|
||||
println!("NM UI event: {:?}", event);
|
||||
|
||||
match event {
|
||||
Event::DeviceAdded { interface, r#type } => {
|
||||
if !is_supported_device_type(&r#type) {
|
||||
continue;
|
||||
}
|
||||
let icon = Image::new();
|
||||
icon.add_class("icon");
|
||||
container.add(&icon);
|
||||
icons.insert(interface, icon);
|
||||
}
|
||||
Event::DeviceStateChanged {
|
||||
interface,
|
||||
r#type,
|
||||
state,
|
||||
} => {
|
||||
if !is_supported_device_type(&r#type) {
|
||||
continue;
|
||||
}
|
||||
let icon = icons
|
||||
.get(&interface)
|
||||
.expect("the icon for the interface to be present");
|
||||
let icon_name = get_icon_for_device_state(&r#type, &state);
|
||||
match icon_name {
|
||||
Some(icon_name) => {
|
||||
image_provider
|
||||
.load_into_image_silent(icon_name, icon_size, false, icon)
|
||||
.await;
|
||||
icon.show();
|
||||
}
|
||||
None => {
|
||||
icon.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn is_supported_device_type(r#type: &DeviceType) -> bool {
|
||||
matches!(
|
||||
r#type,
|
||||
DeviceType::Ethernet | DeviceType::Wifi | DeviceType::Tun | DeviceType::Wireguard
|
||||
)
|
||||
}
|
||||
|
||||
fn get_icon_for_device_state(r#type: &DeviceType, state: &DeviceState) -> Option<&'static str> {
|
||||
match r#type {
|
||||
DeviceType::Ethernet => match state {
|
||||
DeviceState::Unavailable => Some("icon:network-wired-disconnected-symbolic"),
|
||||
DeviceState::Disconnected => Some("icon:network-wired-disconnected-symbolic"),
|
||||
DeviceState::Prepare => Some("icon:network-wired-disconnected-symbolic"),
|
||||
DeviceState::Config => Some("icon:network-wired-disconnected-symbolic"),
|
||||
DeviceState::NeedAuth => Some("icon:network-wired-disconnected-symbolic"),
|
||||
DeviceState::IpConfig => Some("icon:network-wired-disconnected-symbolic"),
|
||||
DeviceState::IpCheck => Some("icon:network-wired-disconnected-symbolic"),
|
||||
DeviceState::Secondaries => Some("icon:network-wired-disconnected-symbolic"),
|
||||
DeviceState::Activated => Some("icon:network-wired-symbolic"),
|
||||
DeviceState::Deactivating => Some("icon:network-wired-disconnected-symbolic"),
|
||||
DeviceState::Failed => Some("icon:network-wired-disconnected-symbolic"),
|
||||
_ => None,
|
||||
},
|
||||
DeviceType::Wifi => match state {
|
||||
DeviceState::Unavailable => Some("icon:network-wireless-hardware-disabled-symbolic"),
|
||||
DeviceState::Disconnected => Some("icon:network-wireless-offline-symbolic"),
|
||||
DeviceState::Prepare => Some("icon:network-wireless-offline-symbolic"),
|
||||
DeviceState::Config => Some("icon:network-wireless-offline-symbolic"),
|
||||
DeviceState::NeedAuth => Some("icon:network-wireless-offline-symbolic"),
|
||||
DeviceState::IpConfig => Some("icon:network-wireless-offline-symbolic"),
|
||||
DeviceState::IpCheck => Some("icon:network-wireless-offline-symbolic"),
|
||||
DeviceState::Secondaries => Some("icon:network-wireless-offline-symbolic"),
|
||||
DeviceState::Activated => Some("icon:network-wireless-connected-symbolic"),
|
||||
DeviceState::Deactivating => Some("icon:network-wireless-offline-symbolic"),
|
||||
DeviceState::Failed => Some("icon:network-wireless-offline-symbolic"),
|
||||
_ => None,
|
||||
},
|
||||
DeviceType::Tun => match state {
|
||||
DeviceState::Activated => Some("icon:network-vpn-symbolic"),
|
||||
_ => None,
|
||||
},
|
||||
DeviceType::Wireguard => match state {
|
||||
DeviceState::Activated => Some("icon:network-vpn-symbolic"),
|
||||
_ => None,
|
||||
},
|
||||
_ => panic!("Device type should be a supported one"),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue