use dioxus::prelude::*;
use crate::app::Route;
use crate::client;
use crate::state::app_state::{AppState, AuthStatus};
#[component]
pub fn LoginForm() -> Element {
let mut state = use_context::<Signal<AppState>>();
let navigator = use_navigator();
let mut homeserver = use_signal(|| "https://matrix.org".to_string());
let mut username = use_signal(|| String::new());
let mut password = use_signal(|| String::new());
let mut error_message = use_signal(|| Option::<String>::None);
let mut is_loading = use_signal(|| false);
let on_submit = move |evt: Event<FormData>| {
evt.prevent_default();
let hs = homeserver.read().clone();
let user = username.read().clone();
let pass = password.read().clone();
if user.is_empty() || pass.is_empty() {
error_message.set(Some("Please enter username and password".to_string()));
return;
}
is_loading.set(true);
error_message.set(None);
state.write().auth_status = AuthStatus::LoggingIn;
spawn(async move {
match client::login_with_password(&hs, &user, &pass).await {
Ok(matrix_client) => {
tracing::info!("Login successful");
{
let mut w = state.write();
w.auth_status = AuthStatus::LoggedIn;
w.client = Some(matrix_client);
}
navigator.push(Route::Home {});
}
Err(e) => {
tracing::error!("Login failed: {e}");
let msg = if e.to_string().contains("403") {
"Invalid username or password".to_string()
} else {
format!("Login failed: {e}")
};
error_message.set(Some(msg));
state.write().auth_status = AuthStatus::Error(e.to_string());
}
}
is_loading.set(false);
});
};
rsx! {
form {
class: "login-form",
onsubmit: on_submit,
h2 { class: "login-form__title", "Sign In" }
if let Some(ref err) = *error_message.read() {
div {
class: "login-form__error",
"{err}"
}
}
div {
class: "login-form__field",
label {
r#for: "homeserver",
"Homeserver"
}
input {
id: "homeserver",
r#type: "url",
placeholder: "https://matrix.org",
value: "{homeserver}",
oninput: move |evt| homeserver.set(evt.value()),
disabled: *is_loading.read(),
}
}
div {
class: "login-form__field",
label {
r#for: "username",
"Username"
}
input {
id: "username",
r#type: "text",
placeholder: "@user:matrix.org",
value: "{username}",
oninput: move |evt| username.set(evt.value()),
disabled: *is_loading.read(),
autofocus: true,
}
}
div {
class: "login-form__field",
label {
r#for: "password",
"Password"
}
input {
id: "password",
r#type: "password",
placeholder: "Password",
value: "{password}",
oninput: move |evt| password.set(evt.value()),
disabled: *is_loading.read(),
}
}
button {
r#type: "submit",
class: "login-form__submit",
disabled: *is_loading.read(),
if *is_loading.read() {
"Signing in..."
} else {
"Sign In"
}
}
}
}
}