login: prefill dialog after a failed login attempt
After a failed login the dialog was recreated empty, so a single mistyped password meant retyping the server URL and username too, and on a first-time login everything the user had just typed was lost. Fill the form with the credentials of the last attempt so that a wrong password only needs retyping. Nothing is written to the keyring on failure: credentials are stored on success and cleared only on explicit logout.
This commit is contained in:
parent
36bac44395
commit
037e5a1c7e
2 changed files with 19 additions and 6 deletions
|
|
@ -1,4 +1,6 @@
|
||||||
use gtk4::glib;
|
use gtk4::glib;
|
||||||
|
use gtk4::prelude::*;
|
||||||
|
use gtk4::subclass::prelude::*;
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct LoginDialog(ObjectSubclass<imp::LoginDialog>)
|
pub struct LoginDialog(ObjectSubclass<imp::LoginDialog>)
|
||||||
|
|
@ -10,12 +12,19 @@ impl LoginDialog {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
glib::Object::new()
|
glib::Object::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pre-fill the form, e.g. after a failed login attempt so that the
|
||||||
|
/// server URL, username and password don't have to be retyped.
|
||||||
|
pub fn set_prefill(&self, server_url: &str, username: &str, password: &str) {
|
||||||
|
let imp = self.imp();
|
||||||
|
imp.server_url_row.set_text(server_url);
|
||||||
|
imp.username_row.set_text(username);
|
||||||
|
imp.password_row.set_text(password);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod imp {
|
mod imp {
|
||||||
use super::*;
|
use super::*;
|
||||||
use gtk4::prelude::*;
|
|
||||||
use gtk4::subclass::prelude::*;
|
|
||||||
use gtk4::CompositeTemplate;
|
use gtk4::CompositeTemplate;
|
||||||
use libadwaita::prelude::*;
|
use libadwaita::prelude::*;
|
||||||
use libadwaita::subclass::prelude::*;
|
use libadwaita::subclass::prelude::*;
|
||||||
|
|
|
||||||
|
|
@ -557,12 +557,15 @@ pub mod imp {
|
||||||
if let Some((server_url, username, password)) = credentials::load_credentials() {
|
if let Some((server_url, username, password)) = credentials::load_credentials() {
|
||||||
self.do_login(server_url, username, password, false);
|
self.do_login(server_url, username, password, false);
|
||||||
} else {
|
} else {
|
||||||
self.show_login_dialog();
|
self.show_login_dialog(None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_login_dialog(&self) {
|
fn show_login_dialog(&self, prefill: Option<(String, String, String)>) {
|
||||||
let dialog = LoginDialog::new();
|
let dialog = LoginDialog::new();
|
||||||
|
if let Some((server_url, username, password)) = prefill {
|
||||||
|
dialog.set_prefill(&server_url, &username, &password);
|
||||||
|
}
|
||||||
let win = self.obj();
|
let win = self.obj();
|
||||||
let win_weak = win.downgrade();
|
let win_weak = win.downgrade();
|
||||||
dialog.connect_local("logged-in", false, move |args| {
|
dialog.connect_local("logged-in", false, move |args| {
|
||||||
|
|
@ -580,6 +583,7 @@ pub mod imp {
|
||||||
fn do_login(&self, server_url: String, username: String, password: String, store: bool) {
|
fn do_login(&self, server_url: String, username: String, password: String, store: bool) {
|
||||||
let is_auto = !store;
|
let is_auto = !store;
|
||||||
let win_weak = self.obj().downgrade();
|
let win_weak = self.obj().downgrade();
|
||||||
|
let prefill = (server_url.clone(), username.clone(), password.clone());
|
||||||
crate::runtime::spawn(
|
crate::runtime::spawn(
|
||||||
async move { Api::login(&server_url, &username, &password).await
|
async move { Api::login(&server_url, &username, &password).await
|
||||||
.map(|api| (api, server_url, username, password)) },
|
.map(|api| (api, server_url, username, password)) },
|
||||||
|
|
@ -615,7 +619,7 @@ pub mod imp {
|
||||||
let toast = libadwaita::Toast::new("Offline — showing cached articles");
|
let toast = libadwaita::Toast::new("Offline — showing cached articles");
|
||||||
win.imp().toast_overlay.add_toast(toast);
|
win.imp().toast_overlay.add_toast(toast);
|
||||||
} else {
|
} else {
|
||||||
win.imp().show_login_dialog();
|
win.imp().show_login_dialog(Some(prefill));
|
||||||
win.imp().show_error_dialog("Login Failed", &e);
|
win.imp().show_error_dialog("Login Failed", &e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -652,7 +656,7 @@ pub mod imp {
|
||||||
}
|
}
|
||||||
win.imp().sidebar_content.set_visible_child_name("placeholder");
|
win.imp().sidebar_content.set_visible_child_name("placeholder");
|
||||||
win.imp().article_menu_button.set_visible(false);
|
win.imp().article_menu_button.set_visible(false);
|
||||||
win.imp().show_login_dialog();
|
win.imp().show_login_dialog(None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue