diff --git a/web/src/context.rs b/web/src/context.rs index d414e28..e7ea2e8 100644 --- a/web/src/context.rs +++ b/web/src/context.rs @@ -4,7 +4,7 @@ use apb::{Activity, ActivityMut, Base, Collection, CollectionPage}; use dashmap::DashMap; use leptos::{create_signal, leptos_dom::logging::console_warn, ReadSignal, Signal, SignalGet, SignalSet, WriteSignal}; -use crate::{Auth, URL_BASE}; +use crate::URL_BASE; lazy_static::lazy_static! { pub static ref CACHE: ObjectCache = ObjectCache::default(); @@ -39,8 +39,8 @@ impl Uri { if url.len() < 50 { url.replace("https://", "") } else { - format!("{}..", url.replace("https://", "").get(..50).unwrap_or_default().to_string()) - }.replace('/', "​/​") + format!("{}..", url.replace("https://", "").get(..50).unwrap_or_default()) + }.replace('/', "\u{200B}/\u{200B}") } pub fn short(url: &str) -> String { @@ -103,12 +103,17 @@ impl Uri { pub struct Http; impl Http { - pub async fn request(method: reqwest::Method, url: &str, data: Option<&serde_json::Value>, token: &Signal>) -> reqwest::Result { + pub async fn request( + method: reqwest::Method, + url: &str, + data: Option<&serde_json::Value>, + token: Signal> + ) -> reqwest::Result { let mut req = reqwest::Client::new() .request(method, url); if let Some(auth) = token.get() { - req = req.header("Authorization", format!("Bearer {}", auth.token)); + req = req.header("Authorization", format!("Bearer {}", auth)); } if let Some(data) = data { @@ -122,11 +127,11 @@ impl Http { .await } - pub async fn fetch(url: &str, token: &Signal>) -> reqwest::Result { + pub async fn fetch(url: &str, token: Signal>) -> reqwest::Result { Self::request(reqwest::Method::GET, url, None, token).await } - pub async fn post(url: &str, data: &serde_json::Value, token: &Signal>) -> reqwest::Result { + pub async fn post(url: &str, data: &serde_json::Value, token: Signal>) -> reqwest::Result { Self::request(reqwest::Method::POST, url, Some(data), token).await } } @@ -162,10 +167,10 @@ impl Timeline { self.set_next.set(feed); } - pub async fn more(&self, auth: Signal>) -> reqwest::Result<()> { + pub async fn more(&self, auth: Signal>) -> reqwest::Result<()> { let feed_url = self.next(); - let collection : serde_json::Value = Http::fetch(&feed_url, &auth).await?; + let collection : serde_json::Value = Http::fetch(&feed_url, auth).await?; let activities : Vec = collection @@ -202,11 +207,9 @@ impl Timeline { } if let Some(uid) = activity.actor().id() { - if CACHE.get(&uid).is_none() { - if !gonna_fetch.contains(&uid) { - gonna_fetch.insert(uid.clone()); - sub_tasks.push(fetch_and_update("users", uid, auth)); - } + if CACHE.get(&uid).is_none() && !gonna_fetch.contains(&uid) { + gonna_fetch.insert(uid.clone()); + sub_tasks.push(fetch_and_update("users", uid, auth)); } } } @@ -223,8 +226,8 @@ impl Timeline { } } -async fn fetch_and_update(kind: &'static str, id: String, auth: Signal>) { - match Http::fetch(&Uri::api(kind, &id), &auth).await { +async fn fetch_and_update(kind: &'static str, id: String, auth: Signal>) { + match Http::fetch(&Uri::api(kind, &id), auth).await { Ok(data) => CACHE.put(id, data), Err(e) => console_warn(&format!("could not fetch '{id}': {e}")), } diff --git a/web/src/lib.rs b/web/src/lib.rs index 8585652..a66a2cd 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -26,46 +26,42 @@ pub struct Auth { pub trait MaybeToken { fn present(&self) -> bool; fn token(&self) -> String; - fn username(&self) -> String; } -impl MaybeToken for Option { +impl MaybeToken for Option { fn token(&self) -> String { match self { None => String::new(), - Some(x) => x.token.clone(), + Some(x) => x.clone(), } } fn present(&self) -> bool { match self { None => false, - Some(x) => !x.token.is_empty(), - } - } - fn username(&self) -> String { - match self { - None => "anon".to_string(), - Some(x) => x.user.split('/').last().unwrap_or_default().to_string() + Some(x) => !x.is_empty(), } } } #[component] pub fn LoginBox( - rx: Signal>, - tx: WriteSignal>, + token_tx: WriteSignal>, + token: Signal>, + username: Signal>, + username_tx: WriteSignal>, + home_tl: Timeline, ) -> impl IntoView { let username_ref: NodeRef = create_node_ref(); let password_ref: NodeRef = create_node_ref(); view! {
-
- "Hello "{move || rx.get().username()} + -
+
() .await.unwrap(); console_log(&format!("logged in until {}", auth.expires)); - tx.set(Some(auth)); + let username = auth.user.split('/').last().unwrap_or_default().to_string(); + // reset home feed and point it to our user's inbox + home_tl.set_feed(vec![]); + home_tl.set_next(format!("{URL_BASE}/users/{}/inbox/page", username)); + // update our username and token cookies + username_tx.set(Some(username)); + token_tx.set(Some(auth.token)); }); } />
@@ -91,7 +93,7 @@ pub fn LoginBox( #[component] pub fn TimelineNavigation() -> impl IntoView { - let auth = use_context::>>().expect("missing auth context"); + let auth = use_context::>>().expect("missing auth context"); view! { impl IntoView { #[component] pub fn PostBox() -> impl IntoView { - let auth = use_context::>>().expect("missing auth context"); + let auth = use_context::>>().expect("missing auth context"); let summary_ref: NodeRef = create_node_ref(); let content_ref: NodeRef = create_node_ref(); view! { @@ -133,7 +135,7 @@ pub fn PostBox() -> impl IntoView { .set_content(Some(&content)) .set_to(apb::Node::links(vec![apb::target::PUBLIC.to_string()])) .set_cc(apb::Node::links(vec![format!("{URL_BASE}/users/test/followers")])), - &auth + auth ) .await.unwrap() }) @@ -199,13 +201,13 @@ pub fn ActorBanner(object: serde_json::Value) -> impl IntoView { #[component] pub fn UserPage() -> impl IntoView { let params = use_params_map(); - let auth = use_context::>>().expect("missing auth context"); + let auth = use_context::>>().expect("missing auth context"); let actor = create_local_resource(move || params.get().get("id").cloned().unwrap_or_default(), move |id| { async move { match CACHE.get(&Uri::full("users", &id)) { Some(x) => Some(x.clone()), None => { - let user : serde_json::Value = Http::fetch(&Uri::api("users", &id), &auth).await.ok()?; + let user : serde_json::Value = Http::fetch(&Uri::api("users", &id), auth).await.ok()?; CACHE.put(Uri::full("users", &id), user.clone()); Some(user) }, @@ -255,13 +257,13 @@ pub fn UserPage() -> impl IntoView { #[component] pub fn ObjectPage() -> impl IntoView { let params = use_params_map(); - let auth = use_context::>>().expect("missing auth context"); + let auth = use_context::>>().expect("missing auth context"); let object = create_local_resource(move || params.get().get("id").cloned().unwrap_or_default(), move |oid| { async move { match CACHE.get(&Uri::full("objects", &oid)) { Some(x) => Some(x.clone()), None => { - let obj = Http::fetch::(&Uri::api("objects", &oid), &auth).await.ok()?; + let obj = Http::fetch::(&Uri::api("objects", &oid), auth).await.ok()?; CACHE.put(Uri::full("objects", &oid), obj.clone()); Some(obj) } @@ -396,7 +398,7 @@ pub fn TimelinePage(name: &'static str, tl: Timeline) -> impl IntoView { #[component] pub fn TimelineFeed(tl: Timeline) -> impl IntoView { - let auth = use_context::>>().expect("missing auth context"); + let auth = use_context::>>().expect("missing auth context"); view! { ("token"); + let (cookie, set_cookie) = use_cookie::("token"); + let (username, set_username) = use_cookie::("username"); provide_context(cookie); - let home_tl = Timeline::new(format!("{URL_BASE}/users/{}/inbox/page", cookie.get().username())); + let home_tl = Timeline::new(format!("{URL_BASE}/users/{}/inbox/page", username.get().unwrap_or_default())); let server_tl = Timeline::new(format!("{URL_BASE}/inbox/page")); spawn_local(async move { @@ -61,8 +62,11 @@ fn main() {