use gtk4::glib; glib::wrapper! { pub struct LoginDialog(ObjectSubclass) @extends libadwaita::Dialog, gtk4::Widget, @implements gtk4::Accessible, gtk4::Buildable, gtk4::ConstraintTarget; } impl LoginDialog { pub fn new() -> Self { glib::Object::new() } } mod imp { use super::*; use gtk4::prelude::*; use gtk4::subclass::prelude::*; use gtk4::CompositeTemplate; use libadwaita::prelude::*; use libadwaita::subclass::prelude::*; #[derive(CompositeTemplate, Default)] #[template(resource = "/net/jeena/FeedTheMonkey/ui/login_dialog.ui")] pub struct LoginDialog { #[template_child] pub server_url_row: TemplateChild, #[template_child] pub username_row: TemplateChild, #[template_child] pub password_row: TemplateChild, #[template_child] pub login_button: TemplateChild, } #[glib::object_subclass] impl ObjectSubclass for LoginDialog { const NAME: &'static str = "LoginDialog"; type Type = super::LoginDialog; type ParentType = libadwaita::Dialog; fn class_init(klass: &mut Self::Class) { klass.bind_template(); } fn instance_init(obj: &glib::subclass::InitializingObject) { obj.init_template(); } } impl ObjectImpl for LoginDialog { fn signals() -> &'static [glib::subclass::Signal] { use std::sync::OnceLock; static SIGNALS: OnceLock> = OnceLock::new(); SIGNALS.get_or_init(|| { vec![ glib::subclass::Signal::builder("logged-in") .param_types([ String::static_type(), String::static_type(), String::static_type(), ]) .build(), ] }) } fn constructed(&self) { self.parent_constructed(); // Login button let obj_weak = self.obj().downgrade(); self.login_button.connect_activated(move |_| { if let Some(dialog) = obj_weak.upgrade() { dialog.imp().on_login_clicked(); } }); // Enter in any row submits the form (connect_entry_activated fires on Return) for weak in [ self.server_url_row.downgrade(), self.username_row.downgrade(), ] { let obj_weak = self.obj().downgrade(); weak.upgrade().unwrap().connect_entry_activated(move |_| { if let Some(dialog) = obj_weak.upgrade() { dialog.imp().on_login_clicked(); } }); } let obj_weak2 = self.obj().downgrade(); self.password_row.connect_entry_activated(move |_| { if let Some(dialog) = obj_weak2.upgrade() { dialog.imp().on_login_clicked(); } }); } } impl LoginDialog { fn on_login_clicked(&self) { let raw_url = self.server_url_row.text().trim().to_string(); let username = self.username_row.text().trim().to_string(); let password = self.password_row.text().to_string(); if raw_url.is_empty() || username.is_empty() || password.is_empty() { return; } // Prepend https:// if no scheme given let server_url = if raw_url.starts_with("http://") || raw_url.starts_with("https://") { raw_url } else { format!("https://{raw_url}") }; self.obj().close(); self.obj().emit_by_name::<()>("logged-in", &[&server_url, &username, &password]); } } impl WidgetImpl for LoginDialog {} impl AdwDialogImpl for LoginDialog {} }