diff --git a/web/src/state.rs b/web/src/state.rs index 5ef23b6..f66d249 100644 --- a/web/src/state.rs +++ b/web/src/state.rs @@ -59,13 +59,20 @@ pub fn init(url: Url, orders: &mut impl Orders) -> Model { fn on_url_changed(uc: subs::UrlChanged) -> Msg { let mut url = uc.0; + let href = document().location().unwrap().href().unwrap(); + let origin = document().location().unwrap().origin().unwrap(); + let current_url = &href[origin.len()..]; + let did_change = current_url != url.to_string(); + let mut messages = Vec::new(); + if did_change { + messages.push(Msg::ScrollToTop) + } info!( - "url changed '{}', history {}", - url, + "url changed\nold '{current_url}'\nnew '{url}', history {}", history().length().unwrap_or(0) ); let hpp = url.remaining_hash_path_parts(); - match hpp.as_slice() { + let msg = match hpp.as_slice() { ["t", tid] => Msg::ShowThreadRequest { thread_id: tid.to_string(), }, @@ -102,7 +109,9 @@ fn on_url_changed(uc: subs::UrlChanged) -> Msg { last: None, } } - } + }; + messages.push(msg); + Msg::MultiMsg(messages) } // `update` describes how to handle each `Msg`. @@ -536,6 +545,10 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { .expect("failed to copy to clipboard"); }); } + Msg::ScrollToTop => { + info!("scrolling to the top"); + web_sys::window().unwrap().scroll_to_with_x_and_y(0., 0.); + } Msg::WindowScrolled => { if let Some(el) = model.content_el.get() { let ih = window() @@ -608,6 +621,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { orders.send_msg(Msg::CatchupNext); } Msg::CatchupNext => { + orders.send_msg(Msg::ScrollToTop); let Some(catchup) = &mut model.catchup else { orders.send_msg(Msg::GoToSearchResults); return; @@ -777,6 +791,7 @@ pub enum Msg { CopyToClipboard(String), + ScrollToTop, WindowScrolled, SetProgress(f64), UpdateServerVersion(String), diff --git a/web/src/view/mod.rs b/web/src/view/mod.rs index 3668dcb..0d8746b 100644 --- a/web/src/view/mod.rs +++ b/web/src/view/mod.rs @@ -4,7 +4,7 @@ use chrono::{DateTime, Datelike, Duration, Local, Utc}; use human_format::{Formatter, Scales}; use itertools::Itertools; use letterbox_shared::compute_color; -use log::{debug, error, info}; +use log::{debug, error}; use seed::{prelude::*, *}; use seed_hooks::{state_access::CloneState, topo, use_state, StateAccessEventHandlers}; use web_sys::{HtmlElement, HtmlInputElement}; @@ -1067,7 +1067,7 @@ fn thread( let spam_add_thread_id = thread.thread_id.clone(); let spam_unread_thread_id = thread.thread_id.clone(); div![ - C!["lg:p-4"], + C!["lg:p-4", "max-w-4xl"], div![ C!["p-4", "lg:p-0"], h3![C!["text-xl"], subject], @@ -1252,11 +1252,7 @@ pub fn view_tags(tags: &Option>) -> Node { ], IF!(t.unread>0 => format!("{}", t.unread)) ], - ev(Ev::Click, |_| { - // Scroll window to the top when searching for a tag. - info!("scrolling to the top because you clicked a tag"); - web_sys::window().unwrap().scroll_to_with_x_and_y(0., 0.); - }) + ev(Ev::Click, |_| { Msg::ScrollToTop }) ] } fn matches(a: &[&str], b: &[&str]) -> usize { @@ -1544,8 +1540,6 @@ fn click_to_top() -> Node { C![&tw_classes::BUTTON, "bg-red-500", "lg:m-0", "m-4"], span!["Top"], span![i![C!["fas", "fa-arrow-turn-up"]]], - ev(Ev::Click, |_| web_sys::window() - .unwrap() - .scroll_to_with_x_and_y(0., 0.)) + ev(Ev::Click, |_| Msg::ScrollToTop) ] }