diff --git a/dialog-gtk3/src/main.rs b/dialog-gtk3/src/main.rs index bd2a7b6..e266113 100644 --- a/dialog-gtk3/src/main.rs +++ b/dialog-gtk3/src/main.rs @@ -1,7 +1,7 @@ use chrono::prelude::*; use gdkx11::X11Window; use gethostname::gethostname; -use glib::GString; +use glib::{GString, clone, SourceId}; use gtk::{prelude::*, Button, Entry, Label, Plug, Window}; use log::{debug, error, warn}; use std::{io::{self, Write}, process::exit, rc::Rc, thread, time::Duration}; @@ -155,24 +155,26 @@ fn main() -> anyhow::Result<()> { let mut bold_desc = gtk::pango::FontDescription::new(); bold_desc.set_weight(gtk::pango::Weight::Bold); attrs.insert(gtk::pango::AttrFontDesc::new(&bold_desc)); - let auth_failed_label = gtk::Label::builder() - .label("Authentication Failed!") + let auth_status_label = gtk::Label::builder() + .label("") .xalign(0.5) .yalign(0.5) .attributes(&attrs) .opacity(0.0) .build(); - vbox.pack_start(&auth_failed_label, false, false, 0); + vbox.pack_start(&auth_status_label, false, false, 0); - rx.attach(None, move |exit_status| { + rx.attach(None, clone!(@strong auth_status_label => move |(exit_status, auth_dots_id): (i32, SourceId)| { + auth_dots_id.remove(); if exit_status != 0 { - auth_failed_label.set_opacity(1.0); - glib::timeout_add_seconds_local_once(2, move || exit(exit_status)); + auth_status_label.set_label("Authentication Failed!"); + auth_status_label.set_opacity(1.0); + glib::timeout_add_seconds_local_once(1, move || exit(exit_status)); } else { exit(exit_status); } glib::Continue(true) - }); + })); let sep = gtk::Separator::builder() .orientation(gtk::Orientation::Vertical) @@ -220,14 +222,14 @@ fn main() -> anyhow::Result<()> { label_sg.add_widget(&label); hbox.pack_start(&label, false, true, 8); - let password_box = Rc::new(Entry::builder() + let password_box = Entry::builder() .visibility(false) .input_purpose(gtk::InputPurpose::Password) .activates_default(true) .width_chars(25) - .build()); - entry_sg.add_widget(&*password_box); - hbox.pack_start(&*password_box, true, true, 8); + .build(); + entry_sg.add_widget(&password_box); + hbox.pack_start(&password_box, true, true, 8); password_box.connect_key_press_event(|_, ev| { if ev.keyval().name() == Some(GString::from("Escape")) { exit(1); @@ -262,25 +264,34 @@ fn main() -> anyhow::Result<()> { let unlock_button = Button::builder() .label("Unlock") .build(); - { - let password_box = Rc::clone(&password_box); - unlock_button.connect_clicked(move |unlock_button| { - unlock_button.set_sensitive(false); - password_box.set_sensitive(false); + unlock_button.connect_clicked(clone!(@strong password_box, @strong auth_status_label => move |unlock_button| { + unlock_button.set_sensitive(false); + password_box.set_sensitive(false); - let username = username.clone(); - let password = password_box.text().to_string(); + let username = username.clone(); + let password = password_box.text().to_string(); - let tx = tx.clone(); - thread::spawn(move || { - let status = if authenticate(&username, &password) { 0 } else { -1 }; - if let Err(err) = tx.send(status) { - error!("Failed to send exit status to main thread: {}", err); - exit(2); - } - }); + auth_status_label.set_label("Authenticating"); + auth_status_label.set_opacity(1.0); + let auth_dots_id = glib::timeout_add_local(Duration::from_millis(500), clone!(@strong auth_status_label => move || { + let s = auth_status_label.label(); + auth_status_label.set_label(&(s.as_str().to_string() + ".")); + Continue(true) + })); + + let tx = tx.clone(); + thread::spawn(move || { + let status = if authenticate(&username, &password) { + 0 + } else { + -1 + }; + if let Err(err) = tx.send((status, auth_dots_id)) { + error!("Failed to send exit status to main thread: {}", err); + exit(2); + } }); - } + })); hbox.pack_end(&unlock_button, false, true, 8); unlock_button.set_can_default(true); unlock_button.set_has_default(true);