use leptos::*; use crate::prelude::*; pub type Auth = Signal>; pub trait AuthToken { fn present(&self) -> bool; fn token(&self) -> String; } #[component] pub fn LoginBox( token_tx: WriteSignal>, token: Signal>, username: Signal>, username_tx: WriteSignal>, home_tl: Timeline, server_tl: Timeline, ) -> impl IntoView { let username_ref: NodeRef = create_node_ref(); let password_ref: NodeRef = create_node_ref(); view! { "hi "{move || username.get().unwrap_or_default() } () .await else { if let Some(rf) = password_ref.get() { rf.set_value("") }; return }; logging::log!("logged in until {}", auth.expires); // update our username and token cookies let username = auth.user.split('/').last().unwrap_or_default().to_string(); username_tx.set(Some(username.clone())); token_tx.set(Some(auth.token)); // reset home feed and point it to our user's inbox home_tl.reset(format!("{URL_BASE}/users/{}/inbox/page", username)); spawn_local(async move { if let Err(e) = home_tl.more(token).await { tracing::error!("failed refreshing home timeline: {e}"); } }); // reset server feed: there may be more content now that we're authed server_tl.reset(format!("{URL_BASE}/inbox/page")); spawn_local(async move { if let Err(e) = server_tl.more(token).await { tracing::error!("failed refreshing server timeline: {e}"); } }); }); } > } } #[derive(Debug, serde::Serialize)] struct LoginForm { email: String, password: String, } #[derive(Debug, Clone, serde::Deserialize)] struct AuthResponse { token: String, user: String, expires: chrono::DateTime, } impl AuthToken for Signal> { fn token(&self) -> String { match self.get() { None => String::new(), Some(x) => x.clone(), } } fn present(&self) -> bool { match self.get() { None => false, Some(x) => !x.is_empty(), } } }