Compare commits

...

21 Commits

Author SHA1 Message Date
32d2ffeb3d chore: Release
All checks were successful
Continuous integration / Test Suite (push) Successful in 44s
Continuous integration / Trunk (push) Successful in 41s
Continuous integration / Rustfmt (push) Successful in 32s
Continuous integration / Check (push) Successful in 2m37s
Continuous integration / build (push) Successful in 56s
Continuous integration / Disallow unused dependencies (push) Successful in 2m36s
2025-02-27 15:16:09 -08:00
d41946e0a5 web: change style for mark read catchup button 2025-02-27 15:15:49 -08:00
61402858f4 web: add TODO 2025-02-27 15:15:42 -08:00
17de318645 chore: Release
All checks were successful
Continuous integration / Test Suite (push) Successful in 47s
Continuous integration / Check (push) Successful in 2m0s
Continuous integration / Trunk (push) Successful in 39s
Continuous integration / build (push) Successful in 52s
Continuous integration / Rustfmt (push) Successful in 1m6s
Continuous integration / Disallow unused dependencies (push) Successful in 56s
2025-02-26 15:43:34 -08:00
3aa0144e8d web: try setting history.scroll_restoration to manual to impove inter-page flow 2025-02-26 15:43:18 -08:00
f9eafff4c7 web: add "go home" button to catchup view 2025-02-26 15:43:18 -08:00
4c6d67901d fix(deps): update rust crate uuid to v1.15.1
All checks were successful
Continuous integration / Check (pull_request) Successful in 38s
Continuous integration / Test Suite (pull_request) Successful in 43s
Continuous integration / Trunk (pull_request) Successful in 39s
Continuous integration / Rustfmt (pull_request) Successful in 32s
Continuous integration / Disallow unused dependencies (pull_request) Successful in 55s
Continuous integration / build (pull_request) Successful in 3m42s
Continuous integration / Check (push) Successful in 37s
Continuous integration / Test Suite (push) Successful in 45s
Continuous integration / Rustfmt (push) Successful in 31s
Continuous integration / build (push) Successful in 50s
Continuous integration / Trunk (push) Successful in 1m39s
Continuous integration / Disallow unused dependencies (push) Successful in 55s
2025-02-26 21:15:57 +00:00
e9aa97a089 fix(deps): update rust crate chrono to v0.4.40
All checks were successful
Continuous integration / Check (pull_request) Successful in 37s
Continuous integration / Test Suite (pull_request) Successful in 43s
Continuous integration / Trunk (pull_request) Successful in 38s
Continuous integration / build (pull_request) Successful in 51s
Continuous integration / Rustfmt (pull_request) Successful in 1m4s
Continuous integration / Disallow unused dependencies (pull_request) Successful in 55s
Continuous integration / Check (push) Successful in 37s
Continuous integration / Test Suite (push) Successful in 43s
Continuous integration / Rustfmt (push) Successful in 31s
Continuous integration / build (push) Successful in 50s
Continuous integration / Trunk (push) Successful in 1m37s
Continuous integration / Disallow unused dependencies (push) Successful in 55s
2025-02-26 08:46:20 +00:00
a82b047f75 fix(deps): update rust crate uuid to v1.15.0
All checks were successful
Continuous integration / Check (pull_request) Successful in 39s
Continuous integration / Test Suite (pull_request) Successful in 43s
Continuous integration / Trunk (pull_request) Successful in 38s
Continuous integration / Rustfmt (pull_request) Successful in 57s
Continuous integration / build (pull_request) Successful in 50s
Continuous integration / Disallow unused dependencies (pull_request) Successful in 2m27s
Continuous integration / Check (push) Successful in 38s
Continuous integration / Test Suite (push) Successful in 43s
Continuous integration / Rustfmt (push) Successful in 31s
Continuous integration / build (push) Successful in 49s
Continuous integration / Trunk (push) Successful in 1m31s
Continuous integration / Disallow unused dependencies (push) Successful in 56s
2025-02-26 06:16:01 +00:00
9a8b44a8df fix(deps): update all non-major dependencies to 0.0.40
All checks were successful
Continuous integration / Test Suite (pull_request) Successful in 44s
Continuous integration / Check (pull_request) Successful in 1m48s
Continuous integration / Trunk (pull_request) Successful in 38s
Continuous integration / build (pull_request) Successful in 50s
Continuous integration / Rustfmt (pull_request) Successful in 1m3s
Continuous integration / Disallow unused dependencies (pull_request) Successful in 1m0s
Continuous integration / Test Suite (push) Successful in 43s
Continuous integration / Trunk (push) Successful in 38s
Continuous integration / Check (push) Successful in 1m49s
Continuous integration / Rustfmt (push) Successful in 30s
Continuous integration / Disallow unused dependencies (push) Successful in 54s
Continuous integration / build (push) Successful in 2m43s
2025-02-26 04:47:10 +00:00
a96693004c chore: Release
All checks were successful
Continuous integration / Test Suite (push) Successful in 42s
Continuous integration / Check (push) Successful in 2m9s
Continuous integration / Trunk (push) Successful in 38s
Continuous integration / build (push) Successful in 50s
Continuous integration / Rustfmt (push) Successful in 1m7s
Continuous integration / Disallow unused dependencies (push) Successful in 56s
2025-02-25 20:43:47 -08:00
ed9fe11fbf web: trimmed views for catchup mode 2025-02-25 20:43:27 -08:00
09fb14a796 chore: Release
All checks were successful
Continuous integration / Check (push) Successful in 37s
Continuous integration / Test Suite (push) Successful in 43s
Continuous integration / Trunk (push) Successful in 37s
Continuous integration / Rustfmt (push) Successful in 52s
Continuous integration / build (push) Successful in 50s
Continuous integration / Disallow unused dependencies (push) Successful in 2m28s
2025-02-25 20:08:44 -08:00
58a7936bba web: address lint 2025-02-25 20:08:31 -08:00
cd0ee361f5 chore: Release 2025-02-25 20:06:18 -08:00
77bd5abe0d Don't do incremental builds when release 2025-02-25 20:06:11 -08:00
450c5496b3 chore: Release 2025-02-25 20:04:01 -08:00
4411e45a3c Don't allow warnings when publishing 2025-02-25 20:03:40 -08:00
e7d20896d5 web: remove unnecessary Msg variant 2025-02-25 16:20:32 -08:00
32a1115abd chore: Release
Some checks failed
Continuous integration / Check (push) Successful in 38s
Continuous integration / Test Suite (push) Successful in 45s
Continuous integration / Trunk (push) Failing after 36s
Continuous integration / Rustfmt (push) Successful in 30s
Continuous integration / Disallow unused dependencies (push) Successful in 54s
Continuous integration / build (push) Successful in 2m44s
2025-02-25 15:58:46 -08:00
4982057500 web: more scroll to top improvements by reworking URL changes 2025-02-25 15:58:24 -08:00
9 changed files with 117 additions and 81 deletions

74
Cargo.lock generated
View File

@@ -562,9 +562,9 @@ dependencies = [
[[package]] [[package]]
name = "build-info" name = "build-info"
version = "0.0.39" version = "0.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24c8169feaff1e5d9686706c0a56a54ed0422d2df41fa1c543e53f7cea0e70d4" checksum = "288657edd15bfa5a7f30ca3b123c1af2c503eaf218e517fa10bc9063dbc2ad99"
dependencies = [ dependencies = [
"bincode", "bincode",
"build-info-common", "build-info-common",
@@ -573,9 +573,9 @@ dependencies = [
[[package]] [[package]]
name = "build-info-build" name = "build-info-build"
version = "0.0.39" version = "0.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e73a4a2bdb1e3fae84472b5a9f806208331eb89783bf9b19819cb1d8fbc6d5ec" checksum = "3146483d5bc5081ec26f9c4e60232e770980d750b2802d6cc2563cded665cc73"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.22.1", "base64 0.22.1",
@@ -593,21 +593,21 @@ dependencies = [
[[package]] [[package]]
name = "build-info-common" name = "build-info-common"
version = "0.0.39" version = "0.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b6fa54101dfbd88efc3981859e92c3d47c729ff54d5df73ec36505c337e5c5e" checksum = "8524ad59f5958f37f95e66bf6c9a8fa8440c4f56c069247c44244434cfca3eb1"
dependencies = [ dependencies = [
"chrono", "chrono",
"derive_more 1.0.0", "derive_more 2.0.1",
"semver 1.0.25", "semver 1.0.25",
"serde", "serde",
] ]
[[package]] [[package]]
name = "build-info-proc" name = "build-info-proc"
version = "0.0.39" version = "0.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5458d2f0ed8bb88f7f6b5706460ca55fab08db16456ea03b920691b4cac163" checksum = "6b58fb02636d968e8327d84a5a256df9704ac27a1eda98429c35dbe50a278f69"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.22.1", "base64 0.22.1",
@@ -713,16 +713,16 @@ dependencies = [
[[package]] [[package]]
name = "cargo_metadata" name = "cargo_metadata"
version = "0.18.1" version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924"
dependencies = [ dependencies = [
"camino", "camino",
"cargo-platform", "cargo-platform",
"semver 1.0.25", "semver 1.0.25",
"serde", "serde",
"serde_json", "serde_json",
"thiserror 1.0.69", "thiserror 2.0.11",
] ]
[[package]] [[package]]
@@ -772,9 +772,9 @@ dependencies = [
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.39" version = "0.4.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
dependencies = [ dependencies = [
"android-tzdata", "android-tzdata",
"iana-time-zone", "iana-time-zone",
@@ -782,7 +782,7 @@ dependencies = [
"num-traits", "num-traits",
"serde", "serde",
"wasm-bindgen", "wasm-bindgen",
"windows-targets 0.52.6", "windows-link",
] ]
[[package]] [[package]]
@@ -910,9 +910,9 @@ dependencies = [
[[package]] [[package]]
name = "console_log" name = "console_log"
version = "0.1.2" version = "0.1.4"
source = "sparse+https://git.z.xinu.tv/api/packages/wathiede/cargo/" source = "sparse+https://git.z.xinu.tv/api/packages/wathiede/cargo/"
checksum = "e628484ff9348e6c256644436f215c0a9766867820da8cf161c567db1c877e32" checksum = "d36495b7586d34322c3ffcff0e0d9d0b70f3a4ce88a9c199b3d8a01afb1debd7"
dependencies = [ dependencies = [
"log", "log",
"wasm-bindgen", "wasm-bindgen",
@@ -1337,18 +1337,18 @@ dependencies = [
[[package]] [[package]]
name = "derive_more" name = "derive_more"
version = "1.0.0" version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
dependencies = [ dependencies = [
"derive_more-impl", "derive_more-impl",
] ]
[[package]] [[package]]
name = "derive_more-impl" name = "derive_more-impl"
version = "1.0.0" version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -1620,9 +1620,9 @@ dependencies = [
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.35" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
dependencies = [ dependencies = [
"crc32fast", "crc32fast",
"miniz_oxide", "miniz_oxide",
@@ -1927,9 +1927,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]] [[package]]
name = "git2" name = "git2"
version = "0.19.0" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" checksum = "3fda788993cc341f69012feba8bf45c0ba4f3291fcc08e214b4d5a7332d88aff"
dependencies = [ dependencies = [
"bitflags 2.8.0", "bitflags 2.8.0",
"libc", "libc",
@@ -2965,7 +2965,7 @@ dependencies = [
[[package]] [[package]]
name = "letterbox-notmuch" name = "letterbox-notmuch"
version = "0.9.3" version = "0.9.10"
dependencies = [ dependencies = [
"itertools 0.14.0", "itertools 0.14.0",
"log", "log",
@@ -2980,14 +2980,14 @@ dependencies = [
[[package]] [[package]]
name = "letterbox-procmail2notmuch" name = "letterbox-procmail2notmuch"
version = "0.9.3" version = "0.9.10"
dependencies = [ dependencies = [
"anyhow", "anyhow",
] ]
[[package]] [[package]]
name = "letterbox-server" name = "letterbox-server"
version = "0.9.3" version = "0.9.10"
dependencies = [ dependencies = [
"ammonia", "ammonia",
"anyhow", "anyhow",
@@ -3030,7 +3030,7 @@ dependencies = [
[[package]] [[package]]
name = "letterbox-shared" name = "letterbox-shared"
version = "0.9.3" version = "0.9.10"
dependencies = [ dependencies = [
"build-info", "build-info",
"letterbox-notmuch", "letterbox-notmuch",
@@ -3039,7 +3039,7 @@ dependencies = [
[[package]] [[package]]
name = "letterbox-web" name = "letterbox-web"
version = "0.9.3" version = "0.9.10"
dependencies = [ dependencies = [
"build-info", "build-info",
"build-info-build", "build-info-build",
@@ -3079,9 +3079,9 @@ checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
[[package]] [[package]]
name = "libgit2-sys" name = "libgit2-sys"
version = "0.17.0+1.8.1" version = "0.18.0+1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" checksum = "e1a117465e7e1597e8febea8bb0c410f1c7fb93b1e1cddf34363f8390367ffec"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
@@ -7035,9 +7035,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.14.0" version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93d59ca99a559661b96bf898d8fce28ed87935fd2bea9f05983c1464dd6c71b1" checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587"
dependencies = [ dependencies = [
"getrandom 0.3.1", "getrandom 0.3.1",
"js-sys", "js-sys",
@@ -7322,6 +7322,12 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "windows-link"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3"
[[package]] [[package]]
name = "windows-registry" name = "windows-registry"
version = "0.2.0" version = "0.2.0"

View File

@@ -8,7 +8,7 @@ authors = ["Bill Thiede <git@xinu.tv>"]
edition = "2021" edition = "2021"
license = "UNLICENSED" license = "UNLICENSED"
publish = ["xinu"] publish = ["xinu"]
version = "0.9.3" version = "0.9.10"
repository = "https://git.z.xinu.tv/wathiede/letterbox" repository = "https://git.z.xinu.tv/wathiede/letterbox"
[profile.dev] [profile.dev]

View File

@@ -1,3 +1,6 @@
export CARGO_INCREMENTAL := "0"
export RUSTFLAGS := "-D warnings"
default: default:
@echo "Run: just patch|minor|major" @echo "Run: just patch|minor|major"

View File

@@ -17,7 +17,7 @@ anyhow = "1.0.79"
async-graphql = { version = "7", features = ["log"] } async-graphql = { version = "7", features = ["log"] }
async-graphql-rocket = "7" async-graphql-rocket = "7"
async-trait = "0.1.81" async-trait = "0.1.81"
build-info = "0.0.39" build-info = "0.0.40"
cacher = { version = "0.1.0", registry = "xinu" } cacher = { version = "0.1.0", registry = "xinu" }
chrono = "0.4.39" chrono = "0.4.39"
clap = { version = "4.5.23", features = ["derive"] } clap = { version = "4.5.23", features = ["derive"] }
@@ -48,11 +48,11 @@ urlencoding = "2.1.3"
#xtracing = { path = "../../xtracing" } #xtracing = { path = "../../xtracing" }
#xtracing = { git = "http://git-private.h.xinu.tv/wathiede/xtracing.git" } #xtracing = { git = "http://git-private.h.xinu.tv/wathiede/xtracing.git" }
xtracing = { version = "0.3.0", registry = "xinu" } xtracing = { version = "0.3.0", registry = "xinu" }
letterbox-notmuch = { version = "0.9.3", path = "../notmuch", registry = "xinu" } letterbox-notmuch = { version = "0.9.10", path = "../notmuch", registry = "xinu" }
letterbox-shared = { version = "0.9.3", path = "../shared", registry = "xinu" } letterbox-shared = { version = "0.9.10", path = "../shared", registry = "xinu" }
[build-dependencies] [build-dependencies]
build-info-build = "0.0.39" build-info-build = "0.0.40"
[features] [features]
#default = [ "tantivy" ] #default = [ "tantivy" ]

View File

@@ -11,6 +11,6 @@ version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
build-info = "0.0.39" build-info = "0.0.40"
letterbox-notmuch = { version = "0.9.3", path = "../notmuch", registry = "xinu" } letterbox-notmuch = { version = "0.9.10", path = "../notmuch", registry = "xinu" }
serde = { version = "1.0.147", features = ["derive"] } serde = { version = "1.0.147", features = ["derive"] }

View File

@@ -9,7 +9,7 @@ repository.workspace = true
version.workspace = true version.workspace = true
[build-dependencies] [build-dependencies]
build-info-build = "0.0.39" build-info-build = "0.0.40"
[dev-dependencies] [dev-dependencies]
wasm-bindgen-test = "0.3.33" wasm-bindgen-test = "0.3.33"
@@ -28,13 +28,13 @@ graphql_client = "0.14.0"
thiserror = "2.0.0" thiserror = "2.0.0"
gloo-net = { version = "0.6.0", features = ["json", "serde_json"] } gloo-net = { version = "0.6.0", features = ["json", "serde_json"] }
human_format = "1.1.0" human_format = "1.1.0"
build-info = "0.0.39" build-info = "0.0.40"
wasm-bindgen = "=0.2.100" wasm-bindgen = "=0.2.100"
uuid = { version = "1.13.1", features = [ uuid = { version = "1.13.1", features = [
"js", "js",
] } # direct dep to set js feature, prevents Rng issues ] } # direct dep to set js feature, prevents Rng issues
letterbox-shared = { version = "0.9.3", path = "../shared", registry = "xinu" } letterbox-shared = { version = "0.9.10", path = "../shared", registry = "xinu" }
letterbox-notmuch = { version = "0.9.3", path = "../notmuch", registry = "xinu" } letterbox-notmuch = { version = "0.9.10", path = "../notmuch", registry = "xinu" }
seed_hooks = { version = "0.4.0", registry = "xinu" } seed_hooks = { version = "0.4.0", registry = "xinu" }
strum_macros = "0.27.1" strum_macros = "0.27.1"
@@ -50,4 +50,6 @@ features = [
"MediaQueryList", "MediaQueryList",
"Navigator", "Navigator",
"Window", "Window",
"History",
"ScrollRestoration",
] ]

View File

@@ -18,6 +18,9 @@ fn main() {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
console_error_panic_hook::set_once(); console_error_panic_hook::set_once();
#[cfg(debug_assertions)]
let lvl = Level::Debug;
#[cfg(not(debug_assertions))]
let lvl = Level::Info; let lvl = Level::Info;
console_log::init_with_level(lvl).expect("failed to initialize console logging"); console_log::init_with_level(lvl).expect("failed to initialize console logging");
// Mount the `app` to the element with the `id` "app". // Mount the `app` to the element with the `id` "app".

View File

@@ -29,16 +29,21 @@ pub fn unread_query() -> &'static str {
pub fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model { pub fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
let version = letterbox_shared::build_version(bi); let version = letterbox_shared::build_version(bi);
info!("Build Info: {}", version); info!("Build Info: {}", version);
// Disable restoring to scroll position when navigating
window()
.history()
.expect("couldn't get history")
.set_scroll_restoration(web_sys::ScrollRestoration::Manual)
.expect("failed to set scroll restoration to manual");
if url.hash().is_none() { if url.hash().is_none() {
orders.request_url(urls::search(unread_query(), 0)); orders.request_url(urls::search(unread_query(), 0));
} else { } else {
orders.notify(subs::UrlRequested::new(url)); orders.request_url(url);
}; };
orders.stream(streams::window_event(Ev::Resize, |_| Msg::OnResize));
// TODO(wathiede): only do this while viewing the index? Or maybe add a new message that force // TODO(wathiede): only do this while viewing the index? Or maybe add a new message that force
// 'notmuch new' on the server periodically? // 'notmuch new' on the server periodically?
orders.stream(streams::interval(30_000, || Msg::RefreshStart)); orders.stream(streams::interval(30_000, || Msg::RefreshStart));
orders.subscribe(on_url_changed); orders.subscribe(Msg::OnUrlChanged);
orders.stream(streams::window_event(Ev::Scroll, |_| Msg::WindowScrolled)); orders.stream(streams::window_event(Ev::Scroll, |_| Msg::WindowScrolled));
build_info::build_info!(fn bi); build_info::build_info!(fn bi);
@@ -54,24 +59,21 @@ pub fn init(url: Url, orders: &mut impl Orders<Msg>) -> Model {
server: None, server: None,
}, },
catchup: None, catchup: None,
last_url: Url::current(),
} }
} }
fn on_url_changed(uc: subs::UrlChanged) -> Msg { fn on_url_changed(old: &Url, mut new: Url) -> Msg {
let mut url = uc.0; let did_change = *old != new;
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(); let mut messages = Vec::new();
if did_change { if did_change {
messages.push(Msg::ScrollToTop) messages.push(Msg::ScrollToTop)
} }
info!( info!(
"url changed\nold '{current_url}'\nnew '{url}', history {}", "url changed\nold '{old}'\nnew '{new}', history {}",
history().length().unwrap_or(0) history().length().unwrap_or(0)
); );
let hpp = url.remaining_hash_path_parts(); let hpp = new.remaining_hash_path_parts();
let msg = 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(),
@@ -142,7 +144,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
orders.perform_cmd(async move { Msg::Refresh }); orders.perform_cmd(async move { Msg::Refresh });
} }
Msg::Refresh => { Msg::Refresh => {
orders.perform_cmd(async move { on_url_changed(subs::UrlChanged(Url::current())) }); orders.request_url(Url::current());
} }
Msg::Reload => { Msg::Reload => {
window() window()
@@ -150,7 +152,10 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
.reload() .reload()
.expect("failed to reload window"); .expect("failed to reload window");
} }
Msg::OnResize => (), Msg::OnUrlChanged(new_url) => {
orders.send_msg(on_url_changed(&model.last_url, new_url.0.clone()));
model.last_url = new_url.0;
}
Msg::NextPage => { Msg::NextPage => {
match &model.context { match &model.context {
@@ -547,6 +552,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
web_sys::window().unwrap().scroll_to_with_x_and_y(0., 0.); web_sys::window().unwrap().scroll_to_with_x_and_y(0., 0.);
} }
Msg::WindowScrolled => { Msg::WindowScrolled => {
// TODO: model.content_el doesn't go to None like it should when a DOM is recreated and the refrenced element goes away
if let Some(el) = model.content_el.get() { if let Some(el) = model.content_el.get() {
let ih = window() let ih = window()
.inner_height() .inner_height()
@@ -676,6 +682,7 @@ pub struct Model {
pub content_el: ElRef<HtmlElement>, pub content_el: ElRef<HtmlElement>,
pub versions: Version, pub versions: Version,
pub catchup: Option<Catchup>, pub catchup: Option<Catchup>,
pub last_url: Url,
} }
#[derive(Debug)] #[derive(Debug)]
@@ -741,8 +748,8 @@ pub enum Msg {
Refresh, Refresh,
// Tell the client to reload whole page from server // Tell the client to reload whole page from server
Reload, Reload,
// Window has changed size // TODO: add GoToUrl
OnResize, OnUrlChanged(subs::UrlChanged),
// Tell the server to update state // Tell the server to update state
RefreshStart, RefreshStart,
RefreshDone(Option<gloo_net::Error>), RefreshDone(Option<gloo_net::Error>),

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}; use log::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};
@@ -93,13 +93,13 @@ pub fn view(model: &Model) -> Node<Msg> {
} => { } => {
if let Some(catchup) = &model.catchup { if let Some(catchup) = &model.catchup {
catchup_view( catchup_view(
thread(thread_data, open_messages, &model.content_el), thread(thread_data, open_messages, &model.content_el, true),
&catchup.items, &catchup.items,
model.read_completion_ratio, model.read_completion_ratio,
) )
} else { } else {
normal_view( normal_view(
thread(thread_data, open_messages, &model.content_el), thread(thread_data, open_messages, &model.content_el, false),
&model.versions, &model.versions,
&model.query, &model.query,
&model.refreshing_state, &model.refreshing_state,
@@ -114,13 +114,13 @@ pub fn view(model: &Model) -> Node<Msg> {
} => { } => {
if let Some(catchup) = &model.catchup { if let Some(catchup) = &model.catchup {
catchup_view( catchup_view(
news_post(post, &model.content_el), news_post(post, &model.content_el, true),
&catchup.items, &catchup.items,
model.read_completion_ratio, model.read_completion_ratio,
) )
} else { } else {
normal_view( normal_view(
news_post(post, &model.content_el), news_post(post, &model.content_el, false),
&model.versions, &model.versions,
&model.query, &model.query,
&model.refreshing_state, &model.refreshing_state,
@@ -198,10 +198,10 @@ fn catchup_view(
"p-4", "p-4",
"border-b", "border-b",
"border-gray-500", "border-gray-500",
"bg-black", "bg-black/50",
], ],
div![ div![
C!["absolute", "right-4", "text-gray-500"], C!["absolute", "top-0", "right-4", "text-gray-500", "p-4"],
span![i![C!["fas", "fa-x"]]], span![i![C!["fas", "fa-x"]]],
ev(Ev::Click, move |_| Msg::CatchupExit) ev(Ev::Click, move |_| Msg::CatchupExit)
], ],
@@ -210,7 +210,7 @@ fn catchup_view(
format!("{} left ", items.iter().filter(|i| !i.seen).count(),) format!("{} left ", items.iter().filter(|i| !i.seen).count(),)
] ]
], ],
div![C!["mt-12", "mb-4"], content], div![C!["mt-12", "mb-20"], content],
div![ div![
C![ C![
"fixed", "fixed",
@@ -223,19 +223,28 @@ fn catchup_view(
"p-4", "p-4",
"border-t", "border-t",
"border-gray-500", "border-gray-500",
"bg-black", "bg-black/50",
], ],
button![ button![
tw_classes::button(), tw_classes::button(),
span![i![C!["far", "fa-envelope"]]], span![i![C!["far", "fa-envelope"]]],
span![C!["pl-2"], "Keep unread"], span![C!["pl-2"], "Keep unread"],
ev(Ev::Click, move |_| Msg::CatchupKeepUnread) ev(Ev::Click, |_| Msg::CatchupKeepUnread)
], ],
button![ button![
tw_classes::button_with_color("bg-green-800", "hover:bg-neutral-700"), tw_classes::button(),
span![i![C!["fas", "fa-house"]]],
span![C!["pl-2"], "Go home"],
ev(Ev::Click, |_| Msg::MultiMsg(vec![
Msg::CatchupExit,
Msg::GoToSearchResults
]))
],
button![
tw_classes::button_with_color("bg-green-800", "hover:bg-green-700"),
span![i![C!["far", "fa-envelope-open"]]], span![i![C!["far", "fa-envelope-open"]]],
span![C!["pl-2"], "Mark as read"], span![C!["pl-2"], "Mark as read"],
ev(Ev::Click, move |_| Msg::CatchupMarkAsRead) ev(Ev::Click, |_| Msg::CatchupMarkAsRead)
] ]
], ],
reading_progress(read_completion_ratio) reading_progress(read_completion_ratio)
@@ -1048,11 +1057,13 @@ fn render_attachements(
] ]
} }
// TODO: add cathup_mode:bool and hide elements when true
#[topo::nested] #[topo::nested]
fn thread( fn thread(
thread: &ShowThreadQueryThreadOnEmailThread, thread: &ShowThreadQueryThreadOnEmailThread,
open_messages: &HashSet<String>, open_messages: &HashSet<String>,
content_el: &ElRef<HtmlElement>, content_el: &ElRef<HtmlElement>,
catchup_mode: bool,
) -> Node<Msg> { ) -> Node<Msg> {
// TODO(wathiede): show per-message subject if it changes significantly from top-level subject // TODO(wathiede): show per-message subject if it changes significantly from top-level subject
let subject = if thread.subject.is_empty() { let subject = if thread.subject.is_empty() {
@@ -1085,7 +1096,7 @@ fn thread(
C!["p-4", "lg:p-0"], C!["p-4", "lg:p-0"],
h3![C!["text-xl"], subject], h3![C!["text-xl"], subject],
span![removable_tags_chiclet(&thread.thread_id, &tags)], span![removable_tags_chiclet(&thread.thread_id, &tags)],
div![ IF!(!catchup_mode => div![
C!["pt-4", "gap-2", "flex", "justify-around"], C!["pt-4", "gap-2", "flex", "justify-around"],
div![ div![
button![ button![
@@ -1123,13 +1134,13 @@ fn thread(
Msg::GoToSearchResults Msg::GoToSearchResults
])), ])),
]] ]]
], ]),
], ],
div![ div![
C!["lg:mt-4", "mail-thread"], C!["lg:mt-4", "mail-thread"],
el_ref(content_el), el_ref(content_el),
messages, messages,
click_to_top() IF!(!catchup_mode => click_to_top())
], ],
/* TODO(wathiede): plumb in orignal id /* TODO(wathiede): plumb in orignal id
a![ a![
@@ -1348,7 +1359,13 @@ pub fn view_tags(tags: &Option<Vec<Tag>>) -> Node<Msg> {
] ]
] ]
} }
fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElement>) -> Node<Msg> {
// TODO: add cathup_mode:bool and hide elements when true
fn news_post(
post: &ShowThreadQueryThreadOnNewsPost,
content_el: &ElRef<HtmlElement>,
catchup_mode: bool,
) -> Node<Msg> {
let subject = &post.title; let subject = &post.title;
set_title(subject); set_title(subject);
let read_thread_id = post.thread_id.clone(); let read_thread_id = post.thread_id.clone();
@@ -1379,7 +1396,7 @@ fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElem
C!["p-4", "lg:p-0"], C!["p-4", "lg:p-0"],
h3![C!["text-xl"], subject], h3![C!["text-xl"], subject],
span![tag(format!("News/{}", post.slug))], span![tag(format!("News/{}", post.slug))],
div![ IF!(!catchup_mode => div![
C!["pt-4", "gap-2", "flex", "justify-around"], C!["pt-4", "gap-2", "flex", "justify-around"],
div![ div![
button![ button![
@@ -1407,7 +1424,7 @@ fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElem
], ],
// Placeholder for symmetry with email view that has Spam button // Placeholder for symmetry with email view that has Spam button
div![], div![],
], ]),
], ],
div![ div![
C!["lg:mt-4"], C!["lg:mt-4"],
@@ -1427,12 +1444,11 @@ fn news_post(post: &ShowThreadQueryThreadOnNewsPost, content_el: &ElRef<HtmlElem
raw![&post.body] raw![&post.body]
] ]
], ],
click_to_top(), IF!(!catchup_mode => click_to_top()),
] ]
} }
fn render_news_post_header(post: &ShowThreadQueryThreadOnNewsPost) -> Node<Msg> { fn render_news_post_header(post: &ShowThreadQueryThreadOnNewsPost) -> Node<Msg> {
let from = &post.site; let from = &post.site;
// TODO: move avatar/favicon stuff to the server side and and come up with a solution for emails
let id = post.thread_id.clone(); let id = post.thread_id.clone();
let is_unread = !post.is_read; let is_unread = !post.is_read;
let url = &post.url; let url = &post.url;
@@ -1540,7 +1556,6 @@ fn reading_progress(ratio: f64) -> Node<Msg> {
] ]
} }
pub fn view_versions(versions: &Version) -> Node<Msg> { pub fn view_versions(versions: &Version) -> Node<Msg> {
debug!("versions {versions:?}");
aside![ aside![
C!["p-2"], C!["p-2"],
p![C!["uppercase", "font-bold"], "Versions"], p![C!["uppercase", "font-bold"], "Versions"],