feat: Add conditional features based on daemon capabilities

This commit is contained in:
Fabio Lenherr / DashieTM 2024-04-05 12:54:05 +02:00
parent 9dbf4228fc
commit f8f23faece
7 changed files with 207 additions and 89 deletions

View file

@ -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<Listeners>, FlowBox, Rc<RefCell<Position>>);
pub type RegularClickEvent = fn(&Capabilities, Arc<Listeners>, FlowBox, Rc<RefCell<Position>>);
pub type PluginClickEvent = Rc<dyn Fn(FlowBox, Rc<RefCell<Position>>, Vec<gtk::Box>)>;
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 {

View file

@ -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<bool>,
pub bluetooth: Cell<bool>,
pub audio: Cell<bool>,
}
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<String> {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000));
let res: Result<(Vec<String>,), Error> = proxy.method_call(BASE, "GetCapabilities", ());
res.unwrap().0
}

View file

@ -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,
};

View file

@ -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<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
if handle_init(listeners.clone(), position, Position::Connectivity) {
return;
}
pub const HANDLE_CONNECTIVITY_CLICK: fn(
&Capabilities,
Arc<Listeners>,
FlowBox,
Rc<RefCell<Position>>,
) = |capabilities: &Capabilities,
listeners: Arc<Listeners>,
reset_main: FlowBox,
position: Rc<RefCell<Position>>| {
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<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
reset_main.set_max_children_per_line(count);
};
pub const HANDLE_WIFI_CLICK: fn(&Capabilities, Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|_: &Capabilities,
listeners: Arc<Listeners>,
reset_main: FlowBox,
position: Rc<RefCell<Position>>| {
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<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
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<Listeners>,
FlowBox,
Rc<RefCell<Position>>,
) = |_: &Capabilities,
listeners: Arc<Listeners>,
reset_main: FlowBox,
position: Rc<RefCell<Position>>| {
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<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
pub const HANDLE_AUDIO_CLICK: fn(&Capabilities, Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|_: &Capabilities,
listeners: Arc<Listeners>,
reset_main: FlowBox,
position: Rc<RefCell<Position>>| {
if handle_init(listeners.clone(), position, Position::Audio) {
return;
}
@ -92,8 +125,11 @@ pub const HANDLE_AUDIO_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>)
reset_main.set_max_children_per_line(2);
};
pub const HANDLE_VOLUME_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
pub const HANDLE_VOLUME_CLICK: fn(&Capabilities, Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|_: &Capabilities,
listeners: Arc<Listeners>,
reset_main: FlowBox,
position: Rc<RefCell<Position>>| {
if handle_init(listeners.clone(), position, Position::AudioOutput) {
return;
}
@ -109,25 +145,35 @@ pub const HANDLE_VOLUME_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>
reset_main.set_max_children_per_line(1);
};
pub const HANDLE_MICROPHONE_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
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<Listeners>,
FlowBox,
Rc<RefCell<Position>>,
) = |_: &Capabilities,
listeners: Arc<Listeners>,
reset_main: FlowBox,
position: Rc<RefCell<Position>>| {
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<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
pub const HANDLE_HOME: fn(&Capabilities, Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|_: &Capabilities,
listeners: Arc<Listeners>,
reset_main: FlowBox,
position: Rc<RefCell<Position>>| {
if handle_init(listeners, position, Position::Home) {
return;
}

View file

@ -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;

View file

@ -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<reset_window_impl::ReSetWindow>)
@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<ReSetWindow>) -> Rc<ReSetWindow> {
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(),

View file

@ -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<Listeners>,
pub position: Rc<RefCell<Position>>,
pub error_popup: ReSetError,
pub capabilities: Capabilities,
}
unsafe impl Send for ReSetWindow {}