diff --git a/web/Cargo.toml b/web/Cargo.toml index ab9deaad..eacdf4ea 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -24,7 +24,6 @@ dashmap = "5.5" leptos = { version = "0.6", features = ["csr", "tracing"] } leptos_router = { version = "0.6", features = ["csr"] } leptos-use = { version = "0.10", features = ["serde"] } -web-sys = { version = "0.3", features = ["Screen"] } reqwest = { version = "0.12", features = ["json"] } apb = { path = "../apb", features = ["unstructured", "activitypub-fe", "activitypub-counters", "litepub"] } uriproxy = { path = "../utils/uriproxy/" } @@ -34,3 +33,5 @@ lazy_static = "1.4" chrono = { version = "0.4", features = ["serde"] } jrd = "0.1" tld = "2.35" +web-sys = { version = "0.3", features = ["Screen"] } +regex = "1.10.5" diff --git a/web/index.html b/web/index.html index d37d447a..f6a25e56 100644 --- a/web/index.html +++ b/web/index.html @@ -39,6 +39,10 @@ * { font-family: 'Fira Code', Menlo, DejaVu Sans Mono, Monaco, Consolas, Ubuntu Mono, monospace; } + html { + overflow-y: scroll; + height: 100vh; + } body { margin: 0; @@ -76,14 +80,23 @@ hyphens: auto; border-left: solid 3px var(--background-secondary); } - blockquote.tl { + article.tl { color: var(--text); border-left: solid 3px var(--accent); + margin-left: 1.25em; + margin-right: 1em; margin-top: 0; margin-bottom: 0; + word-wrap: break-word; } - blockquote.tl p { - margin: 0 .5em; + article p { + margin: 0 0 0 .5em; + } + b.displayname { + overflow-wrap: break-word; + } + table.align { + max-width: 100%; } span.footer { padding: .1em; @@ -257,10 +270,10 @@ color: var(--background); cursor: pointer; } - .ml-1-l { + .ml-1-r { margin-left: 1em; } - .ml-1-r { + .mr-1-r { margin-right: 1em; } .ml-3-r { @@ -282,7 +295,7 @@ .ml-1-l { margin-left: 0; } - .ml-1-r { + .mr-1-r { margin-right: 0; } .ml-3-r { diff --git a/web/src/actors/view.rs b/web/src/actors/header.rs similarity index 98% rename from web/src/actors/view.rs rename to web/src/actors/header.rs index 29726da1..a0998709 100644 --- a/web/src/actors/view.rs +++ b/web/src/actors/header.rs @@ -27,7 +27,7 @@ pub fn ActorHeader() -> impl IntoView { } ); move || match actor.get() { - None => view! { }.into_view(), + None => view! { }.into_view(), Some(Err(e)) => view! { "could not resolve user: "{e} }.into_view(), Some(Ok(actor)) => { let avatar_url = actor.icon().get().map(|x| x.url().id().str().unwrap_or(DEFAULT_AVATAR_URL.into())).unwrap_or(DEFAULT_AVATAR_URL.into()); diff --git a/web/src/actors/mod.rs b/web/src/actors/mod.rs index d6621713..9b947c05 100644 --- a/web/src/actors/mod.rs +++ b/web/src/actors/mod.rs @@ -1,6 +1,6 @@ pub mod follow; -pub mod view; pub mod posts; +pub mod header; use leptos_router::Params; // TODO can i remove this? #[derive(Clone, leptos::Params, PartialEq)] diff --git a/web/src/actors/posts.rs b/web/src/actors/posts.rs index 004d3337..d9c453f7 100644 --- a/web/src/actors/posts.rs +++ b/web/src/actors/posts.rs @@ -7,14 +7,15 @@ pub fn ActorPosts() -> impl IntoView { let feeds = use_context::().expect("missing feeds context"); let params = use_params::(); Signal::derive(move || { - let id = params.get().ok().and_then(|x| x.id).unwrap_or_default(); + let id = params.get_untracked().ok().and_then(|x| x.id).unwrap_or_default(); let tl_url = format!("{}/outbox/page", Uri::api(U::Actor, &id, false)); if !feeds.user.next.get_untracked().starts_with(&tl_url) { feeds.user.reset(Some(tl_url)); } + id }).track(); view! { "🖂"" "posts - + } } diff --git a/web/src/app.rs b/web/src/app.rs index a20dca03..3f4159fb 100644 --- a/web/src/app.rs +++ b/web/src/app.rs @@ -2,7 +2,7 @@ use leptos::*; use leptos_router::*; use crate::prelude::*; -use leptos_use::{storage::use_local_storage, use_cookie, utils::{FromToStringCodec, JsonCodec}}; +use leptos_use::{signal_throttled, storage::use_local_storage, use_cookie, use_element_size, use_window_scroll, utils::{FromToStringCodec, JsonCodec}, UseElementSizeReturn}; #[derive(Clone, Copy)] pub struct Feeds { @@ -64,29 +64,18 @@ pub fn App() -> impl IntoView { let reply_controls = ReplyControls::default(); provide_context(reply_controls); - let screen_width = window().screen().map(|x| x.avail_width().unwrap_or_default()).unwrap_or_default(); + let screen_width = document().body().map(|x| x.client_width()).unwrap_or_default(); + tracing::info!("detected width of {screen_width}"); - let (menu, set_menu) = create_signal(screen_width <= 786); + let (menu, set_menu) = create_signal(screen_width < 768); let (advanced, set_advanced) = create_signal(false); let title_target = move || if auth.present() { "/web/home" } else { "/web/server" }; - spawn_local(async move { - // refresh token first, or verify that we're still authed - if Auth::refresh(auth.token, set_token, set_userid).await { - feeds.home.more(auth); // home inbox requires auth to be read - feeds.private.more(auth); - } - feeds.global.more(auth); - feeds.public.more(auth); // server inbox may contain private posts - }); - - - // refresh token every hour - set_interval( - move || spawn_local(async move { Auth::refresh(auth.token, set_token, set_userid).await; }), - std::time::Duration::from_secs(3600) - ); + // refresh token immediately and every hour + let refresh = move || spawn_local(async move { Auth::refresh(auth.token, set_token, set_userid).await; }); + refresh(); + set_interval(refresh, std::time::Duration::from_secs(3600)); view! {