use crate::components::base::popup::{self, Popup}; use crate::components::wifi::wifiEntryImpl; use adw::glib; use adw::glib::{Object, PropertySet}; use adw::prelude::{ButtonExt, EditableExt, EntryExt, PopoverExt}; use adw::subclass::prelude::ObjectSubclassIsExt; use dbus::blocking::Connection; use dbus::Error; use glib::{clone, Cast}; use gtk::prelude::WidgetExt; use gtk::{AlertDialog, Editable, GestureClick, PasswordEntry, PasswordEntryBuffer, Window}; use std::sync::atomic::AtomicBool; use std::sync::Arc; use std::time::Duration; use ReSet_Lib::network::network::{AccessPoint, WifiStrength}; glib::wrapper! { pub struct WifiEntry(ObjectSubclass) @extends gtk::Box, gtk::Widget, @implements gtk::Accessible, gtk::Buildable, gtk::Actionable, gtk::ConstraintTarget; } unsafe impl Send for WifiEntry {} unsafe impl Sync for WifiEntry {} impl WifiEntry { pub fn new(access_point: AccessPoint) -> Arc { let entry: Arc = Arc::new(Object::builder().build()); let stored_entry = entry.clone(); let new_entry = entry.clone(); let entryImp = entry.imp(); let strength = WifiStrength::from_u8(access_point.strength); let ssid = access_point.ssid.clone(); let name_opt = String::from_utf8(ssid).unwrap_or_else(|_| String::from("")); let name = name_opt.as_str(); let stored = access_point.stored; entryImp.wifiStrength.set(strength); entryImp.resetWifiLabel.get().set_text(name); entryImp.resetWifiEncrypted.set_visible(false); // TODO handle encryption thing entryImp .resetWifiStrength .get() .set_from_icon_name(match strength { WifiStrength::Excellent => Some("network-wireless-signal-excellent-symbolic"), WifiStrength::Ok => Some("network-wireless-signal-ok-symbolic"), WifiStrength::Weak => Some("network-wireless-signal-weak-symbolic"), WifiStrength::None => Some("network-wireless-signal-none-symbolic"), }); if access_point.connected == true { entryImp .resetWifiConnected .get() .set_from_icon_name(Some("network-wireless-connected-symbolic")); } { let mut wifiName = entryImp.wifiName.borrow_mut(); *wifiName = String::from(name); } entryImp.accessPoint.set(access_point); let gesture = GestureClick::new(); if stored { entryImp .resetWifiStored .get() .set_from_icon_name(Some("document-save-symbolic")); gesture.connect_released(move |_, _, _, _| { click_stored_network(stored_entry.clone()); }); } else { gesture.connect_released(move |_, _, _, _| { click_new_network(new_entry.clone()); }); } entry.add_controller(gesture); entry } } pub fn click_stored_network(entry: Arc) { let alert = AlertDialog::builder().build(); let root = &entry.root().unwrap(); let root = root.downcast_ref::(); if root.is_none() { println!("ERROR BRO"); return; } let root = root.unwrap(); // TODO handle unknown access point -> should be done by having 2 different categories let entryImp = entry.imp(); let conn = Connection::new_session().unwrap(); let proxy = conn.with_proxy( "org.xetibo.ReSet", "/org/xetibo/ReSet", Duration::from_millis(1000), ); let access_point = entryImp.accessPoint.clone().into_inner(); if access_point.connected == true { let res: Result<(bool,), Error> = proxy.method_call("org.xetibo.ReSet", "DisconnectFromCurrentAccessPoint", ()); if res.is_err() { alert.set_message("Error on connecting to dbus."); alert.show(Some(root)); return; } let (res,) = res.unwrap(); if res == false { alert.set_message("Could not disconnect from access point."); alert.show(Some(root)); } else { entryImp.resetWifiConnected.get().set_from_icon_name(None); let mut access_point = entryImp.accessPoint.borrow_mut(); (*access_point).connected = false; } return; } dbg!(access_point.clone()); let res: Result<(bool,), Error> = proxy.method_call( "org.xetibo.ReSet", "ConnectToKnownAccessPoint", (access_point,), ); if res.is_err() { alert.set_message("Error on connecting to dbus."); alert.show(Some(root)); } else { let (res,) = res.unwrap(); if res == false { alert.set_message("Could not connect to access point."); alert.show(Some(root)); } else { entryImp .resetWifiConnected .get() .set_from_icon_name(Some("network-wireless-connected-symbolic")); let mut access_point = entryImp.accessPoint.borrow_mut(); (*access_point).connected = true; } } } pub fn click_new_network(entry: Arc) { let connect_new_network = |entry: Arc, access_point: AccessPoint, password: String| -> bool { let alert = AlertDialog::builder().build(); let root = &entry.root().unwrap(); let root = root.downcast_ref::(); if root.is_none() { println!("ERROR BRO"); return false; } let root = root.unwrap(); let conn = Connection::new_session().unwrap(); let proxy = conn.with_proxy( "org.xetibo.ReSet", "/org/xetibo/ReSet", Duration::from_millis(10000), ); // TODO crate spinner animation and block UI let res: Result<(bool,), Error> = proxy.method_call( "org.xetibo.ReSet", "ConnectToNewAccessPoint", (access_point, password), ); if res.is_err() { alert.set_message("Could not connect to dbus."); alert.show(Some(root)); return false; } if res.unwrap() == (false,) { alert.set_message("Could not connect to access point."); alert.show(Some(root)); return false; } true }; let result = Arc::new(AtomicBool::new(false)); let result_ref = result.clone(); let result_ref_button = result.clone(); let entryImp = entry.imp(); let popupImp = entryImp.resetWifiPopup.imp(); popupImp .resetPopupEntry .connect_activate(clone!(@weak entry as origEntry, @weak entryImp => move |entry| { result_ref.store( connect_new_network(origEntry, entryImp.accessPoint.clone().take(), entry.text().to_string()), std::sync::atomic::Ordering::SeqCst, ); entryImp.resetWifiPopup.popdown(); })); popupImp .resetPopupButton .connect_clicked(clone!(@weak entry as origEntry,@weak entryImp, @weak popupImp => move |_| { let entry = entryImp.resetWifiPopup.imp().resetPopupEntry.text().to_string(); result_ref_button.store( connect_new_network(origEntry, entryImp.accessPoint.clone().take(), entry), std::sync::atomic::Ordering::SeqCst, ); entryImp.resetWifiPopup.popdown(); })); entryImp.resetWifiPopup.popup(); println!( "result is {}", result.load(std::sync::atomic::Ordering::SeqCst) ); }