From f8f23faece07dd853693dd49cdf193ac64e40a4d Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Fri, 5 Apr 2024 12:54:05 +0200 Subject: [PATCH] feat: Add conditional features based on daemon capabilities --- src/components/plugin/function.rs | 6 +- src/components/utils.rs | 27 ++++ src/components/window/consts.rs | 48 ++++++ src/components/window/handle_sidebar_click.rs | 142 ++++++++++++------ src/components/window/mod.rs | 1 + src/components/window/reset_window.rs | 70 ++++----- src/components/window/reset_window_impl.rs | 2 + 7 files changed, 207 insertions(+), 89 deletions(-) create mode 100644 src/components/window/consts.rs diff --git a/src/components/plugin/function.rs b/src/components/plugin/function.rs index c01cee2..c422474 100644 --- a/src/components/plugin/function.rs +++ b/src/components/plugin/function.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use gtk::FlowBox; -use crate::components::base::utils::{Listeners, Position}; +use crate::components::{base::utils::{Listeners, Position}, utils::Capabilities}; // extern "C" { // pub fn startup() -> SidebarInfo; @@ -12,7 +12,7 @@ use crate::components::base::utils::{Listeners, Position}; // pub fn run_test(); // } -pub type RegularClickEvent = fn(Arc, FlowBox, Rc>); +pub type RegularClickEvent = fn(&Capabilities, Arc, FlowBox, Rc>); pub type PluginClickEvent = Rc>, Vec)>; pub trait TSideBarInfo { @@ -28,7 +28,9 @@ pub struct ReSetSidebarInfo { pub name: &'static str, pub icon_name: &'static str, pub parent: Option<&'static str>, + // pub pre_click: pub click_event: RegularClickEvent, + // pub post_click: } impl TSideBarInfo for ReSetSidebarInfo { diff --git a/src/components/utils.rs b/src/components/utils.rs index 5a9f398..9f9b263 100644 --- a/src/components/utils.rs +++ b/src/components/utils.rs @@ -1,6 +1,11 @@ +use std::cell::Cell; +use std::time::Duration; + use adw::gdk::pango::EllipsizeMode; use adw::prelude::ListModelExtManual; use adw::{ActionRow, ComboRow}; +use dbus::blocking::Connection; +use dbus::Error; use glib::prelude::Cast; use glib::Object; use gtk::prelude::{GObjectPropertyExpressionExt, ListBoxRowExt, ListItemExt, WidgetExt}; @@ -12,6 +17,21 @@ pub const BLUETOOTH: &str = "org.Xetibo.ReSet.Bluetooth"; pub const AUDIO: &str = "org.Xetibo.ReSet.Audio"; pub const BASE: &str = "org.Xetibo.ReSet.Daemon"; +#[derive(Default)] +pub struct Capabilities { + pub wifi: Cell, + pub bluetooth: Cell, + pub audio: Cell, +} + +impl Capabilities { + pub fn set(&self, wifi: bool, bluetooth: bool, audio: bool) { + self.wifi.set(wifi); + self.bluetooth.set(bluetooth); + self.audio.set(audio); + } +} + pub fn create_dropdown_label_factory() -> SignalListItemFactory { let factory = SignalListItemFactory::new(); factory.connect_setup(|_, item| { @@ -68,3 +88,10 @@ pub fn set_action_row_ellipsis(element: ActionRow) { } } } + +pub fn get_capabilities() -> Vec { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(Vec,), Error> = proxy.method_call(BASE, "GetCapabilities", ()); + res.unwrap().0 +} diff --git a/src/components/window/consts.rs b/src/components/window/consts.rs new file mode 100644 index 0000000..99c1a62 --- /dev/null +++ b/src/components/window/consts.rs @@ -0,0 +1,48 @@ +use crate::components::plugin::function::ReSetSidebarInfo; + +use super::handle_sidebar_click::{ + HANDLE_AUDIO_CLICK, HANDLE_BLUETOOTH_CLICK, HANDLE_CONNECTIVITY_CLICK, HANDLE_MICROPHONE_CLICK, + HANDLE_VOLUME_CLICK, HANDLE_WIFI_CLICK, +}; + +pub const CONNECTIVITY_SIDEBAR: ReSetSidebarInfo = ReSetSidebarInfo { + name: "Connectivity", + icon_name: "network-wired-symbolic", + parent: None, + click_event: HANDLE_CONNECTIVITY_CLICK, +}; + +pub const WIFI_SIDEBAR: ReSetSidebarInfo = ReSetSidebarInfo { + name: "WiFi", + icon_name: "network-wireless-symbolic", + parent: Some("Connectivity"), + click_event: HANDLE_WIFI_CLICK, +}; + +pub const BLUETOOTH_SIDEBAR: ReSetSidebarInfo = ReSetSidebarInfo { + name: "Bluetooth", + icon_name: "bluetooth-symbolic", + parent: Some("Connectivity"), + click_event: HANDLE_BLUETOOTH_CLICK, +}; + +pub const AUDIO_SIDEBAR: ReSetSidebarInfo = ReSetSidebarInfo { + name: "Audio", + icon_name: "audio-headset-symbolic", + parent: None, + click_event: HANDLE_AUDIO_CLICK, +}; + +pub const SINK_SIDEBAR: ReSetSidebarInfo = ReSetSidebarInfo { + name: "Output", + icon_name: "audio-volume-high-symbolic", + parent: Some("Audio"), + click_event: HANDLE_VOLUME_CLICK, +}; + +pub const SOURCE_SIDEBAR: ReSetSidebarInfo = ReSetSidebarInfo { + name: "Input", + icon_name: "audio-input-microphone-symbolic", + parent: Some("Audio"), + click_event: HANDLE_MICROPHONE_CLICK, +}; diff --git a/src/components/window/handle_sidebar_click.rs b/src/components/window/handle_sidebar_click.rs index 4c2ca41..00b67ce 100644 --- a/src/components/window/handle_sidebar_click.rs +++ b/src/components/window/handle_sidebar_click.rs @@ -12,63 +12,96 @@ use crate::components::base::utils::{start_audio_listener, Listeners, Position}; use crate::components::bluetooth::bluetooth_box::{ populate_connected_bluetooth_devices, BluetoothBox, }; +use crate::components::utils::Capabilities; use crate::components::wifi::wifi_box::{ scan_for_wifi, show_stored_connections, start_event_listener, WifiBox, }; use gtk::prelude::WidgetExt; use gtk::{Align, FlowBox, FlowBoxChild, Frame}; -pub const HANDLE_CONNECTIVITY_CLICK: fn(Arc, FlowBox, Rc>) = - |listeners: Arc, reset_main: FlowBox, position: Rc>| { - if handle_init(listeners.clone(), position, Position::Connectivity) { - return; - } +pub const HANDLE_CONNECTIVITY_CLICK: fn( + &Capabilities, + Arc, + FlowBox, + Rc>, +) = |capabilities: &Capabilities, + listeners: Arc, + reset_main: FlowBox, + position: Rc>| { + if handle_init(listeners.clone(), position, Position::Connectivity) { + return; + } + reset_main.remove_all(); + + let mut count = 0; + + if capabilities.wifi.get() { let wifi_box = WifiBox::new(listeners.clone()); start_event_listener(listeners.clone(), wifi_box.clone()); show_stored_connections(wifi_box.clone()); scan_for_wifi(wifi_box.clone()); let wifi_frame = wrap_in_flow_box_child(SettingBox::new(&*wifi_box)); + reset_main.insert(&wifi_frame, -1); + count += 1; + } + + if capabilities.bluetooth.get() { let bluetooth_box = BluetoothBox::new(listeners.clone()); populate_connected_bluetooth_devices(listeners, bluetooth_box.clone()); - // start_bluetooth_listener(listeners, bluetooth_box.clone()); let bluetooth_frame = wrap_in_flow_box_child(SettingBox::new(&*bluetooth_box)); - reset_main.remove_all(); - reset_main.insert(&wifi_frame, -1); reset_main.insert(&bluetooth_frame, -1); - reset_main.set_max_children_per_line(2); - }; + count += 1; + } -pub const HANDLE_WIFI_CLICK: fn(Arc, FlowBox, Rc>) = - |listeners: Arc, reset_main: FlowBox, position: Rc>| { + reset_main.set_max_children_per_line(count); +}; + +pub const HANDLE_WIFI_CLICK: fn(&Capabilities, Arc, FlowBox, Rc>) = + |_: &Capabilities, + listeners: Arc, + reset_main: FlowBox, + position: Rc>| { if handle_init(listeners.clone(), position, Position::Wifi) { return; } + reset_main.remove_all(); + let wifi_box = WifiBox::new(listeners.clone()); start_event_listener(listeners, wifi_box.clone()); show_stored_connections(wifi_box.clone()); scan_for_wifi(wifi_box.clone()); let wifi_frame = wrap_in_flow_box_child(SettingBox::new(&*wifi_box)); - reset_main.remove_all(); reset_main.insert(&wifi_frame, -1); + reset_main.set_max_children_per_line(1); }; -pub const HANDLE_BLUETOOTH_CLICK: fn(Arc, FlowBox, Rc>) = - |listeners: Arc, reset_main: FlowBox, position: Rc>| { - if handle_init(listeners.clone(), position, Position::Bluetooth) { - return; - } - let bluetooth_box = BluetoothBox::new(listeners.clone()); - populate_connected_bluetooth_devices(listeners, bluetooth_box.clone()); - // start_bluetooth_listener(listeners, bluetooth_box.clone()); - let bluetooth_frame = wrap_in_flow_box_child(SettingBox::new(&*bluetooth_box)); - reset_main.remove_all(); - reset_main.insert(&bluetooth_frame, -1); - reset_main.set_max_children_per_line(1); - }; +pub const HANDLE_BLUETOOTH_CLICK: fn( + &Capabilities, + Arc, + FlowBox, + Rc>, +) = |_: &Capabilities, + listeners: Arc, + reset_main: FlowBox, + position: Rc>| { + if handle_init(listeners.clone(), position, Position::Bluetooth) { + return; + } + let bluetooth_box = BluetoothBox::new(listeners.clone()); + populate_connected_bluetooth_devices(listeners, bluetooth_box.clone()); + // start_bluetooth_listener(listeners, bluetooth_box.clone()); + let bluetooth_frame = wrap_in_flow_box_child(SettingBox::new(&*bluetooth_box)); + reset_main.remove_all(); + reset_main.insert(&bluetooth_frame, -1); + reset_main.set_max_children_per_line(1); +}; -pub const HANDLE_AUDIO_CLICK: fn(Arc, FlowBox, Rc>) = - |listeners: Arc, reset_main: FlowBox, position: Rc>| { +pub const HANDLE_AUDIO_CLICK: fn(&Capabilities, Arc, FlowBox, Rc>) = + |_: &Capabilities, + listeners: Arc, + reset_main: FlowBox, + position: Rc>| { if handle_init(listeners.clone(), position, Position::Audio) { return; } @@ -92,8 +125,11 @@ pub const HANDLE_AUDIO_CLICK: fn(Arc, FlowBox, Rc>) reset_main.set_max_children_per_line(2); }; -pub const HANDLE_VOLUME_CLICK: fn(Arc, FlowBox, Rc>) = - |listeners: Arc, reset_main: FlowBox, position: Rc>| { +pub const HANDLE_VOLUME_CLICK: fn(&Capabilities, Arc, FlowBox, Rc>) = + |_: &Capabilities, + listeners: Arc, + reset_main: FlowBox, + position: Rc>| { if handle_init(listeners.clone(), position, Position::AudioOutput) { return; } @@ -109,25 +145,35 @@ pub const HANDLE_VOLUME_CLICK: fn(Arc, FlowBox, Rc> reset_main.set_max_children_per_line(1); }; -pub const HANDLE_MICROPHONE_CLICK: fn(Arc, FlowBox, Rc>) = - |listeners: Arc, reset_main: FlowBox, position: Rc>| { - if handle_init(listeners.clone(), position, Position::AudioInput) { - return; - } - let audio_input = Arc::new(SourceBox::new()); - start_audio_listener(listeners.clone(), None, Some(audio_input.clone())); - if !listeners.pulse_listener.load(Ordering::SeqCst) { - spin_loop(); - } - populate_sources(audio_input.clone()); - let source_frame = wrap_in_flow_box_child(SettingBox::new(&*audio_input)); - reset_main.remove_all(); - reset_main.insert(&source_frame, -1); - reset_main.set_max_children_per_line(1); - }; +pub const HANDLE_MICROPHONE_CLICK: fn( + &Capabilities, + Arc, + FlowBox, + Rc>, +) = |_: &Capabilities, + listeners: Arc, + reset_main: FlowBox, + position: Rc>| { + if handle_init(listeners.clone(), position, Position::AudioInput) { + return; + } + let audio_input = Arc::new(SourceBox::new()); + start_audio_listener(listeners.clone(), None, Some(audio_input.clone())); + if !listeners.pulse_listener.load(Ordering::SeqCst) { + spin_loop(); + } + populate_sources(audio_input.clone()); + let source_frame = wrap_in_flow_box_child(SettingBox::new(&*audio_input)); + reset_main.remove_all(); + reset_main.insert(&source_frame, -1); + reset_main.set_max_children_per_line(1); +}; -pub const HANDLE_HOME: fn(Arc, FlowBox, Rc>) = - |listeners: Arc, reset_main: FlowBox, position: Rc>| { +pub const HANDLE_HOME: fn(&Capabilities, Arc, FlowBox, Rc>) = + |_: &Capabilities, + listeners: Arc, + reset_main: FlowBox, + position: Rc>| { if handle_init(listeners, position, Position::Home) { return; } diff --git a/src/components/window/mod.rs b/src/components/window/mod.rs index 8062f39..d4e55c6 100644 --- a/src/components/window/mod.rs +++ b/src/components/window/mod.rs @@ -3,3 +3,4 @@ pub mod reset_window; pub mod reset_window_impl; pub mod sidebar_entry; pub mod sidebar_entry_impl; +pub mod consts; diff --git a/src/components/window/reset_window.rs b/src/components/window/reset_window.rs index 42e8deb..620acc6 100644 --- a/src/components/window/reset_window.rs +++ b/src/components/window/reset_window.rs @@ -16,11 +16,17 @@ use re_set_lib::utils::plugin_setup::FRONTEND_PLUGINS; use crate::components::base::setting_box::SettingBox; use crate::components::base::utils::{Listeners, Position}; -use crate::components::plugin::function::{PluginSidebarInfo, ReSetSidebarInfo}; +use crate::components::plugin::function::PluginSidebarInfo; +use crate::components::utils::get_capabilities; use crate::components::window::handle_sidebar_click::*; use crate::components::window::reset_window_impl; use crate::components::window::sidebar_entry::SidebarEntry; +use super::consts::{ + AUDIO_SIDEBAR, BLUETOOTH_SIDEBAR, CONNECTIVITY_SIDEBAR, SINK_SIDEBAR, SOURCE_SIDEBAR, + WIFI_SIDEBAR, +}; + glib::wrapper! { pub struct ReSetWindow(ObjectSubclass) @extends adw::ApplicationWindow, gtk::Window, gtk::Widget, @@ -112,45 +118,29 @@ impl ReSetWindow { pub fn setup_sidebar_entries(&self) { let self_imp = self.imp(); + let capabilities = get_capabilities(); + let wifi = capabilities.contains(&"WiFi".to_string()); + let bluetooth = capabilities.contains(&"Bluetooth".to_string()); + let audio = capabilities.contains(&"Audio".to_string()); + self_imp.capabilities.set(wifi, bluetooth, audio); - let sidebar_list = vec![ - ReSetSidebarInfo { - name: "Connectivity", - icon_name: "network-wired-symbolic", - parent: None, - click_event: HANDLE_CONNECTIVITY_CLICK, - }, - ReSetSidebarInfo { - name: "WiFi", - icon_name: "network-wireless-symbolic", - parent: Some("Connectivity"), - click_event: HANDLE_WIFI_CLICK, - }, - ReSetSidebarInfo { - name: "Bluetooth", - icon_name: "bluetooth-symbolic", - parent: Some("Connectivity"), - click_event: HANDLE_BLUETOOTH_CLICK, - }, - ReSetSidebarInfo { - name: "Audio", - icon_name: "audio-headset-symbolic", - parent: None, - click_event: HANDLE_AUDIO_CLICK, - }, - ReSetSidebarInfo { - name: "Output", - icon_name: "audio-volume-high-symbolic", - parent: Some("Audio"), - click_event: HANDLE_VOLUME_CLICK, - }, - ReSetSidebarInfo { - name: "Input", - icon_name: "audio-input-microphone-symbolic", - parent: Some("Audio"), - click_event: HANDLE_MICROPHONE_CLICK, - }, - ]; + // let sidebar_list = vec![CONNECTIVITY_SIDEBAR, WIFI_SIDEBAR, BLUETOOTH_SIDEBAR, AUDIO_SIDEBAR, SINK_SIDEBAR, SOURCE_SIDEBAR]; + let mut sidebar_list = Vec::new(); + + if wifi || bluetooth { + sidebar_list.push(CONNECTIVITY_SIDEBAR); + } + if wifi { + sidebar_list.push(WIFI_SIDEBAR); + }; + if bluetooth { + sidebar_list.push(BLUETOOTH_SIDEBAR); + }; + if audio { + sidebar_list.push(AUDIO_SIDEBAR); + sidebar_list.push(SINK_SIDEBAR); + sidebar_list.push(SOURCE_SIDEBAR); + } let mut plugin_sidebar_list = vec![]; unsafe { @@ -191,6 +181,7 @@ impl ReSetWindow { } HANDLE_VOLUME_CLICK( + &self_imp.capabilities, self_imp.listeners.clone(), self_imp.reset_main.clone(), self_imp.position.clone(), @@ -361,6 +352,7 @@ fn setup_callback(window: Rc) -> Rc { let click_event = result.imp().on_click_event.borrow(); if let Some(event) = click_event.on_click_event { event( + &imp.capabilities, imp.listeners.clone(), imp.reset_main.get(), imp.position.clone(), diff --git a/src/components/window/reset_window_impl.rs b/src/components/window/reset_window_impl.rs index 4c81c53..6dfac0d 100644 --- a/src/components/window/reset_window_impl.rs +++ b/src/components/window/reset_window_impl.rs @@ -12,6 +12,7 @@ use gtk::{Button, CompositeTemplate, FlowBox, ListBox, SearchEntry}; use crate::components::base::error::ReSetError; use crate::components::base::utils::{Listeners, Position}; +use crate::components::utils::Capabilities; use crate::components::wifi::wifi_box::WifiBox; use crate::components::window::reset_window; use crate::components::window::sidebar_entry::SidebarEntry; @@ -40,6 +41,7 @@ pub struct ReSetWindow { pub listeners: Arc, pub position: Rc>, pub error_popup: ReSetError, + pub capabilities: Capabilities, } unsafe impl Send for ReSetWindow {}