web: scroll to top on page changes

This commit is contained in:
Bill Thiede 2025-02-24 18:39:47 -08:00
parent 45e4edb1dd
commit 77943b3570
2 changed files with 23 additions and 14 deletions

View File

@ -59,13 +59,20 @@ pub fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
fn on_url_changed(uc: subs::UrlChanged) -> Msg { fn on_url_changed(uc: subs::UrlChanged) -> Msg {
let mut url = uc.0; 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!( info!(
"url changed '{}', history {}", "url changed\nold '{current_url}'\nnew '{url}', history {}",
url,
history().length().unwrap_or(0) history().length().unwrap_or(0)
); );
let hpp = url.remaining_hash_path_parts(); let hpp = url.remaining_hash_path_parts();
match hpp.as_slice() { let msg = match hpp.as_slice() {
["t", tid] => Msg::ShowThreadRequest { ["t", tid] => Msg::ShowThreadRequest {
thread_id: tid.to_string(), thread_id: tid.to_string(),
}, },
@ -102,7 +109,9 @@ fn on_url_changed(uc: subs::UrlChanged) -> Msg {
last: None, last: None,
} }
} }
} };
messages.push(msg);
Msg::MultiMsg(messages)
} }
// `update` describes how to handle each `Msg`. // `update` describes how to handle each `Msg`.
@ -536,6 +545,10 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
.expect("failed to copy to clipboard"); .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 => { Msg::WindowScrolled => {
if let Some(el) = model.content_el.get() { if let Some(el) = model.content_el.get() {
let ih = window() let ih = window()
@ -608,6 +621,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
orders.send_msg(Msg::CatchupNext); orders.send_msg(Msg::CatchupNext);
} }
Msg::CatchupNext => { Msg::CatchupNext => {
orders.send_msg(Msg::ScrollToTop);
let Some(catchup) = &mut model.catchup else { let Some(catchup) = &mut model.catchup else {
orders.send_msg(Msg::GoToSearchResults); orders.send_msg(Msg::GoToSearchResults);
return; return;
@ -777,6 +791,7 @@ pub enum Msg {
CopyToClipboard(String), CopyToClipboard(String),
ScrollToTop,
WindowScrolled, WindowScrolled,
SetProgress(f64), SetProgress(f64),
UpdateServerVersion(String), UpdateServerVersion(String),

View File

@ -4,7 +4,7 @@ use chrono::{DateTime, Datelike, Duration, Local, Utc};
use human_format::{Formatter, Scales}; use human_format::{Formatter, Scales};
use itertools::Itertools; use itertools::Itertools;
use letterbox_shared::compute_color; use letterbox_shared::compute_color;
use log::{debug, error, info}; use log::{debug, error};
use seed::{prelude::*, *}; use seed::{prelude::*, *};
use seed_hooks::{state_access::CloneState, topo, use_state, StateAccessEventHandlers}; use seed_hooks::{state_access::CloneState, topo, use_state, StateAccessEventHandlers};
use web_sys::{HtmlElement, HtmlInputElement}; use web_sys::{HtmlElement, HtmlInputElement};
@ -1067,7 +1067,7 @@ fn thread(
let spam_add_thread_id = thread.thread_id.clone(); let spam_add_thread_id = thread.thread_id.clone();
let spam_unread_thread_id = thread.thread_id.clone(); let spam_unread_thread_id = thread.thread_id.clone();
div![ div![
C!["lg:p-4"], C!["lg:p-4", "max-w-4xl"],
div![ div![
C!["p-4", "lg:p-0"], C!["p-4", "lg:p-0"],
h3![C!["text-xl"], subject], h3![C!["text-xl"], subject],
@ -1252,11 +1252,7 @@ pub fn view_tags(tags: &Option<Vec<Tag>>) -> Node<Msg> {
], ],
IF!(t.unread>0 => format!("{}", t.unread)) IF!(t.unread>0 => format!("{}", t.unread))
], ],
ev(Ev::Click, |_| { ev(Ev::Click, |_| { Msg::ScrollToTop })
// 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.);
})
] ]
} }
fn matches(a: &[&str], b: &[&str]) -> usize { fn matches(a: &[&str], b: &[&str]) -> usize {
@ -1544,8 +1540,6 @@ fn click_to_top() -> Node<Msg> {
C![&tw_classes::BUTTON, "bg-red-500", "lg:m-0", "m-4"], C![&tw_classes::BUTTON, "bg-red-500", "lg:m-0", "m-4"],
span!["Top"], span!["Top"],
span![i![C!["fas", "fa-arrow-turn-up"]]], span![i![C!["fas", "fa-arrow-turn-up"]]],
ev(Ev::Click, |_| web_sys::window() ev(Ev::Click, |_| Msg::ScrollToTop)
.unwrap()
.scroll_to_with_x_and_y(0., 0.))
] ]
} }