mirror of
https://gitea.mizah.xyz/mizah/dergchat
synced 2024-11-21 13:15:01 -05:00
Cleaned up and documented the login screen code.
This commit is contained in:
parent
640db8e166
commit
d7292505a5
@ -28,6 +28,10 @@ pub enum LoginStatus {
|
||||
Error(String),
|
||||
}
|
||||
|
||||
/// A struct that represents a login attempt, containing a username, a default nick, and a password.
|
||||
/// None are validated in any way.
|
||||
///
|
||||
/// Warning: this struct contains the user's password; keep it in memory only as short as possible.
|
||||
#[derive(Clone)]
|
||||
pub struct LoginAttempt {
|
||||
pub username: String,
|
||||
@ -45,6 +49,11 @@ impl Debug for LoginAttempt {
|
||||
}
|
||||
}
|
||||
|
||||
/// The props for the login screen widget, including:
|
||||
/// * The xmpp address to pre-fill in the username field.
|
||||
/// * The default nick to pre-fill in the default nick field.
|
||||
/// * The current login state, which will change as the user attempts to log in.
|
||||
/// * The event handler for when the user clicks the login button.
|
||||
#[derive(Props)]
|
||||
pub struct LoginScreenProps<'a> {
|
||||
cached_username: String,
|
||||
@ -53,10 +62,32 @@ pub struct LoginScreenProps<'a> {
|
||||
on_login_attempt: EventHandler<'a, LoginAttempt>,
|
||||
}
|
||||
|
||||
/// A login screen widget.
|
||||
///
|
||||
/// This widget is used to query the user for their login credentials, namely:
|
||||
/// * Username (XMPP address/Jid)
|
||||
/// * Default nick
|
||||
/// * Password
|
||||
///
|
||||
/// The default nick and username may be pre-filled from the cache.
|
||||
///
|
||||
/// The widget itself only contains the UI, and does not know how to validate the credentials
|
||||
/// or log the user in; the parent context is responsible for that.
|
||||
///
|
||||
/// As a small UX improvement, the widget will automatically fill in the default nick
|
||||
/// based on the username, if the user has not changed the default nick.
|
||||
pub fn LoginScreen<'a>(cx: Scope<'a, LoginScreenProps>) -> Element<'a> {
|
||||
|
||||
// The username.
|
||||
let username = use_state(cx, || cx.props.cached_username.clone());
|
||||
|
||||
// The default nick.
|
||||
let default_nick = use_state(cx, || cx.props.cached_nick.clone());
|
||||
|
||||
// The password.
|
||||
let password = use_state(cx, || "".to_string());
|
||||
|
||||
// Track whether the default nick was directly changed by the user.
|
||||
let default_nick_was_changed = use_state(cx, || false);
|
||||
|
||||
render! {
|
||||
@ -64,13 +95,17 @@ pub fn LoginScreen<'a>(cx: Scope<'a, LoginScreenProps>) -> Element<'a> {
|
||||
div {
|
||||
class: "login-form",
|
||||
|
||||
// The username input.
|
||||
input {
|
||||
"type": "text",
|
||||
placeholder: "Username",
|
||||
placeholder: "XMPP Address",
|
||||
value: "{username}",
|
||||
oninput: move |x| {
|
||||
|
||||
// Set the username state variable.
|
||||
username.set(x.value.clone());
|
||||
|
||||
// If the default nick was not changed by the user, set it to the part before the @.
|
||||
if !default_nick_was_changed.get() {
|
||||
if let Some(before_at) = x.value.split('@').next() {
|
||||
default_nick.set(before_at.to_string());
|
||||
@ -79,16 +114,21 @@ pub fn LoginScreen<'a>(cx: Scope<'a, LoginScreenProps>) -> Element<'a> {
|
||||
},
|
||||
}
|
||||
|
||||
// The default nick input.
|
||||
input {
|
||||
placeholder: "Default nick",
|
||||
"type": "text",
|
||||
value: "{default_nick}",
|
||||
oninput: move |x| {
|
||||
// Store the nick in the state variable.
|
||||
default_nick.set(x.value.clone());
|
||||
|
||||
// Mark the nick as changed, so that it won't be overwritten by the username.
|
||||
default_nick_was_changed.set(true);
|
||||
},
|
||||
}
|
||||
|
||||
// The password input.
|
||||
input {
|
||||
placeholder: "Password",
|
||||
"type": "password",
|
||||
@ -109,11 +149,11 @@ pub fn LoginScreen<'a>(cx: Scope<'a, LoginScreenProps>) -> Element<'a> {
|
||||
rsx! {
|
||||
button {
|
||||
|
||||
class: match cx.props.login_state {
|
||||
LoginStatus::LoggedOut => "login-button logged-out",
|
||||
LoginStatus::LoggingIn => "login-button logging-in",
|
||||
LoginStatus::LoggedIn => "login-button logged-in",
|
||||
LoginStatus::Error(_) => "error",
|
||||
disabled: match cx.props.login_state {
|
||||
LoginStatus::LoggedIn => true,
|
||||
LoginStatus::LoggedOut => false,
|
||||
LoginStatus::LoggingIn => true,
|
||||
LoginStatus::Error(_) => false,
|
||||
},
|
||||
|
||||
onclick: move |_| {
|
||||
@ -124,7 +164,12 @@ pub fn LoginScreen<'a>(cx: Scope<'a, LoginScreenProps>) -> Element<'a> {
|
||||
});
|
||||
},
|
||||
|
||||
"Login"
|
||||
match cx.props.login_state {
|
||||
LoginStatus::LoggedOut => "Log in",
|
||||
LoginStatus::LoggingIn => "Logging in...",
|
||||
LoginStatus::LoggedIn => "Logged in",
|
||||
LoginStatus::Error(_) => "Log in",
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user