Compare commits

...

16 Commits

Author SHA1 Message Date
b9df41559f Merge pull request 'chore(deps): update rust crate clap to v4.5.57' (#249) from renovate/all-minor-patch into master
Some checks failed
Continuous integration / Check (push) Successful in 1m50s
Continuous integration / Test Suite (push) Successful in 3m11s
Continuous integration / Trunk (push) Successful in 2m1s
Continuous integration / Rustfmt (push) Failing after 1m33s
Continuous integration / Disallow unused dependencies (push) Failing after 29s
Continuous integration / build (push) Successful in 2m7s
2026-02-03 08:16:57 -08:00
4bb5307904 chore(deps): update rust crate clap to v4.5.57
Some checks failed
Continuous integration / Check (push) Successful in 1m47s
Continuous integration / Trunk (push) Successful in 1m1s
Continuous integration / Test Suite (push) Successful in 3m14s
Continuous integration / Rustfmt (push) Failing after 50s
Continuous integration / Disallow unused dependencies (push) Successful in 2m35s
Continuous integration / build (push) Successful in 3m26s
2026-02-03 16:16:47 +00:00
0cbe860d0d Merge pull request 'chore(deps): update rust crate regex to v1.12.3' (#248) from renovate/all-minor-patch into master
Some checks failed
Continuous integration / Check (push) Successful in 1m29s
Continuous integration / Trunk (push) Successful in 1m3s
Continuous integration / Rustfmt (push) Failing after 44s
Continuous integration / Test Suite (push) Successful in 3m33s
Continuous integration / build (push) Successful in 2m12s
Continuous integration / Disallow unused dependencies (push) Successful in 5m42s
2026-02-03 06:31:26 -08:00
6eaedfaae8 chore(deps): update rust crate regex to v1.12.3
Some checks failed
Continuous integration / Check (push) Successful in 2m20s
Continuous integration / Test Suite (push) Successful in 4m12s
Continuous integration / Trunk (push) Successful in 2m18s
Continuous integration / Rustfmt (push) Failing after 59s
Continuous integration / Disallow unused dependencies (push) Successful in 2m36s
Continuous integration / build (push) Successful in 4m5s
2026-02-03 14:31:20 +00:00
d1787bac32 Merge pull request 'chore(deps): update rust crate flate2 to v1.1.9' (#247) from renovate/all-minor-patch into master
Some checks failed
Continuous integration / Check (push) Successful in 1m43s
Continuous integration / Trunk (push) Successful in 1m4s
Continuous integration / Rustfmt (push) Failing after 44s
Continuous integration / Test Suite (push) Successful in 3m26s
Continuous integration / build (push) Successful in 2m33s
Continuous integration / Disallow unused dependencies (push) Successful in 5m42s
2026-02-02 23:31:36 -08:00
58554e7f40 chore(deps): update rust crate flate2 to v1.1.9
Some checks failed
Continuous integration / Test Suite (push) Successful in 3m14s
Continuous integration / Check (push) Successful in 4m58s
Continuous integration / Rustfmt (push) Failing after 1m35s
Continuous integration / Trunk (push) Successful in 7m49s
Continuous integration / Disallow unused dependencies (push) Successful in 2m28s
Continuous integration / build (push) Successful in 7m50s
2026-02-03 07:31:27 +00:00
fa6fe673bd chore: Release
Some checks failed
Continuous integration / Check (push) Successful in 1m13s
Continuous integration / Test Suite (push) Successful in 2m2s
Continuous integration / Trunk (push) Successful in 59s
Continuous integration / Rustfmt (push) Failing after 47s
Continuous integration / build (push) Successful in 1m42s
Continuous integration / Disallow unused dependencies (push) Successful in 5m40s
2026-02-01 17:16:48 -08:00
44961f6ef1 web: conditionally show spam button in catchup 2026-02-01 17:16:24 -08:00
cd09594347 Merge pull request 'chore(deps): lock file maintenance' (#245) from renovate/lock-file-maintenance into master
Some checks failed
Continuous integration / Check (push) Successful in 1m8s
Continuous integration / Test Suite (push) Successful in 2m12s
Continuous integration / Rustfmt (push) Failing after 46s
Continuous integration / Trunk (push) Successful in 2m11s
Continuous integration / build (push) Successful in 2m0s
Continuous integration / Disallow unused dependencies (push) Successful in 5m47s
2026-02-01 16:02:24 -08:00
3d09ab7c15 chore(deps): lock file maintenance
Some checks failed
Continuous integration / Check (push) Successful in 2m11s
Continuous integration / Test Suite (push) Successful in 4m10s
Continuous integration / Rustfmt (push) Failing after 45s
Continuous integration / Trunk (push) Successful in 2m58s
Continuous integration / build (push) Successful in 3m48s
Continuous integration / Disallow unused dependencies (push) Successful in 5m46s
2026-02-02 00:02:21 +00:00
0cf3e3ce05 chore: Release
Some checks failed
Continuous integration / Check (push) Successful in 1m15s
Continuous integration / Trunk (push) Successful in 1m25s
Continuous integration / Test Suite (push) Successful in 2m54s
Continuous integration / Rustfmt (push) Failing after 1m7s
Continuous integration / build (push) Successful in 3m12s
Continuous integration / Disallow unused dependencies (push) Successful in 3m16s
2026-02-01 15:27:54 -08:00
d10a34e32e web: allow currently unused RemoveTag for symmetry 2026-02-01 15:27:25 -08:00
f311e517a9 chore: Release 2026-02-01 15:26:22 -08:00
aacee2f537 chore: Release 2026-02-01 15:25:23 -08:00
e2bec7760b web: don't return to search page when marking spam in catchup 2026-02-01 15:24:35 -08:00
a4ef7e48a6 web: add mark as spam button to catchup mode 2026-02-01 15:10:58 -08:00
4 changed files with 117 additions and 60 deletions

110
Cargo.lock generated
View File

@@ -109,7 +109,7 @@ version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
dependencies = [
"windows-sys 0.61.2",
"windows-sys 0.60.2",
]
[[package]]
@@ -120,7 +120,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.61.2",
"windows-sys 0.60.2",
]
[[package]]
@@ -746,9 +746,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "bytemuck"
version = "1.24.0"
version = "1.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
[[package]]
name = "byteorder"
@@ -845,9 +845,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.54"
version = "1.2.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583"
checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29"
dependencies = [
"find-msvc-tools",
"jobserver",
@@ -931,9 +931,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.56"
version = "4.5.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75ca66430e33a14957acc24c5077b503e7d374151b2b4b3a10c83b4ceb4be0e"
checksum = "6899ea499e3fb9305a65d5ebf6e3d2248c5fab291f300ad0a704fbe142eae31a"
dependencies = [
"clap_builder",
"clap_derive",
@@ -941,9 +941,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.56"
version = "4.5.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793207c7fa6300a0608d1080b858e5fdbe713cdc1c8db9fb17777d8a13e63df0"
checksum = "7b12c8b680195a62a8364d16b8447b01b6c2c8f9aaf68bee653be34d4245e238"
dependencies = [
"anstream",
"anstyle",
@@ -1779,15 +1779,15 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "find-msvc-tools"
version = "0.1.8"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "flate2"
version = "1.1.8"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369"
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -2826,9 +2826,9 @@ dependencies = [
[[package]]
name = "iana-time-zone"
version = "0.1.64"
version = "0.1.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@@ -3165,9 +3165,9 @@ dependencies = [
[[package]]
name = "letterbox-notmuch"
version = "0.17.61"
version = "0.17.65"
source = "sparse+https://git.z.xinu.tv/api/packages/wathiede/cargo/"
checksum = "28f7db11bd5e63d2e4e3e870e5ca224e2a7acee4eb722aafb9b430f9b24d7dc6"
checksum = "a24b7c129088ca40ce69b0d738a5fed4bc389b92512cb43b9c5e2fc3c88d4cbc"
dependencies = [
"log",
"mailparse",
@@ -3179,7 +3179,7 @@ dependencies = [
[[package]]
name = "letterbox-notmuch"
version = "0.17.62"
version = "0.17.66"
dependencies = [
"itertools",
"log",
@@ -3194,12 +3194,12 @@ dependencies = [
[[package]]
name = "letterbox-procmail2notmuch"
version = "0.17.62"
version = "0.17.66"
dependencies = [
"anyhow",
"clap",
"letterbox-notmuch 0.17.61",
"letterbox-shared 0.17.61",
"letterbox-notmuch 0.17.65",
"letterbox-shared 0.17.65",
"serde",
"sqlx",
"tokio 1.49.0",
@@ -3207,7 +3207,7 @@ dependencies = [
[[package]]
name = "letterbox-server"
version = "0.17.62"
version = "0.17.66"
dependencies = [
"ammonia",
"anyhow",
@@ -3230,8 +3230,8 @@ dependencies = [
"html-escape",
"html2text",
"ical",
"letterbox-notmuch 0.17.62",
"letterbox-shared 0.17.62",
"letterbox-notmuch 0.17.66",
"letterbox-shared 0.17.66",
"linkify",
"lol_html",
"mailparse",
@@ -3257,12 +3257,12 @@ dependencies = [
[[package]]
name = "letterbox-shared"
version = "0.17.61"
version = "0.17.65"
source = "sparse+https://git.z.xinu.tv/api/packages/wathiede/cargo/"
checksum = "ca342be12e54e0a54aa3df86b2bda6e3ff014c75a00f6fb3cd087a80fa5e46df"
checksum = "41ad8210629ccaca787173628b19314076261038870e920c370fc2205533d01b"
dependencies = [
"build-info",
"letterbox-notmuch 0.17.61",
"letterbox-notmuch 0.17.65",
"regex",
"serde",
"sqlx",
@@ -3272,10 +3272,10 @@ dependencies = [
[[package]]
name = "letterbox-shared"
version = "0.17.62"
version = "0.17.66"
dependencies = [
"build-info",
"letterbox-notmuch 0.17.62",
"letterbox-notmuch 0.17.66",
"regex",
"serde",
"sqlx",
@@ -3285,7 +3285,7 @@ dependencies = [
[[package]]
name = "letterbox-web"
version = "0.17.62"
version = "0.17.66"
dependencies = [
"build-info",
"build-info-build",
@@ -3297,7 +3297,7 @@ dependencies = [
"graphql_client",
"human_format",
"itertools",
"letterbox-shared 0.17.62",
"letterbox-shared 0.17.66",
"log",
"seed",
"seed_hooks",
@@ -3927,9 +3927,9 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "oneshot"
version = "0.1.12"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ce66197e99546da6c6d991285f605192e794ceae69686c17163844a7bf8fcc2"
checksum = "269bca4c2591a28585d6bf10d9ed0332b7d76900a1b02bec41bdc3a2cdcda107"
[[package]]
name = "opaque-debug"
@@ -4646,7 +4646,7 @@ dependencies = [
"once_cell",
"socket2 0.6.2",
"tracing",
"windows-sys 0.52.0",
"windows-sys 0.60.2",
]
[[package]]
@@ -4845,9 +4845,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.12.2"
version = "1.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
dependencies = [
"aho-corasick",
"memchr",
@@ -5670,9 +5670,9 @@ checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
[[package]]
name = "siphasher"
version = "1.0.1"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
[[package]]
name = "sketches-ddsketch"
@@ -5685,9 +5685,9 @@ dependencies = [
[[package]]
name = "slab"
version = "0.4.11"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
name = "slotmap"
@@ -6779,9 +6779,9 @@ dependencies = [
[[package]]
name = "tonic"
version = "0.14.2"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203"
checksum = "a286e33f82f8a1ee2df63f4fa35c0becf4a85a0cb03091a15fd7bf0b402dc94a"
dependencies = [
"async-trait",
"axum",
@@ -6810,9 +6810,9 @@ dependencies = [
[[package]]
name = "tonic-prost"
version = "0.14.2"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67"
checksum = "d6c55a2d6a14174563de34409c9f92ff981d006f56da9c6ecd40d9d4a31500b0"
dependencies = [
"bytes 1.11.0",
"prost",
@@ -7007,9 +7007,9 @@ dependencies = [
[[package]]
name = "typed-path"
version = "0.12.1"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e43ffa54726cdc9ea78392023ffe9fe9cf9ac779e1c6fcb0d23f9862e3879d20"
checksum = "3015e6ce46d5ad8751e4a772543a30c7511468070e98e64e20165f8f81155b64"
[[package]]
name = "typenum"
@@ -7892,18 +7892,18 @@ dependencies = [
[[package]]
name = "zerocopy"
version = "0.8.34"
version = "0.8.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71ddd76bcebeed25db614f82bf31a9f4222d3fbba300e6fb6c00afa26cbd4d9d"
checksum = "7456cf00f0685ad319c5b1693f291a650eaf345e941d082fc4e03df8a03996ac"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.34"
version = "0.8.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8187381b52e32220d50b255276aa16a084ec0a9017a0ca2152a1f55c539758d"
checksum = "1328722bbf2115db7e19d69ebcc15e795719e2d66b60827c6a69a117365e37a0"
dependencies = [
"proc-macro2",
"quote",
@@ -8012,15 +8012,15 @@ dependencies = [
[[package]]
name = "zlib-rs"
version = "0.5.5"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3"
checksum = "a7948af682ccbc3342b6e9420e8c51c1fe5d7bf7756002b4a3c6cabfe96a7e3c"
[[package]]
name = "zmij"
version = "1.0.17"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02aae0f83f69aafc94776e879363e9771d7ecbffe2c7fbb6c14c5e00dfe88439"
checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445"
[[package]]
name = "zopfli"

View File

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

View File

@@ -224,6 +224,24 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
});
}
Msg::AddTag(query, tag) => {
orders.skip().perform_cmd(async move {
let res: Result<
graphql_client::Response<graphql::add_tag_mutation::ResponseData>,
gloo_net::Error,
> = send_graphql(graphql::AddTagMutation::build_query(
graphql::add_tag_mutation::Variables {
query: query.clone(),
tag: tag.clone(),
},
))
.await;
if let Err(e) = res {
error!("Failed to add tag {tag} to {query}: {e}");
}
Msg::Refresh
});
}
Msg::AddTagAndGoToSearch(query, tag) => {
orders.skip().perform_cmd(async move {
let res: Result<
graphql_client::Response<graphql::add_tag_mutation::ResponseData>,
@@ -256,7 +274,24 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
if let Err(e) = res {
error!("Failed to remove tag {tag} to {query}: {e}");
}
// TODO: reconsider this behavior
Msg::Refresh
});
}
Msg::RemoveTagAndGoToSearch(query, tag) => {
orders.skip().perform_cmd(async move {
let res: Result<
graphql_client::Response<graphql::remove_tag_mutation::ResponseData>,
gloo_net::Error,
> = send_graphql(graphql::RemoveTagMutation::build_query(
graphql::remove_tag_mutation::Variables {
query: query.clone(),
tag: tag.clone(),
},
))
.await;
if let Err(e) = res {
error!("Failed to remove tag {tag} to {query}: {e}");
}
Msg::GoToSearchResults
});
}
@@ -505,7 +540,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
.join(" ");
orders
.skip()
.perform_cmd(async move { Msg::AddTag(threads, tag) });
.perform_cmd(async move { Msg::AddTagAndGoToSearch(threads, tag) });
}
}
Msg::SelectionRemoveTag(tag) => {
@@ -520,7 +555,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
.join(" ");
orders
.skip()
.perform_cmd(async move { Msg::RemoveTag(threads, tag) });
.perform_cmd(async move { Msg::RemoveTagAndGoToSearch(threads, tag) });
}
}
Msg::SelectionMarkAsRead => {
@@ -692,6 +727,13 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
};
orders.send_msg(Msg::CatchupNext);
}
Msg::CatchupMarkAsSpam => {
if let Some(thread_id) = current_thread_id(&model.context) {
orders.send_msg(Msg::AddTag(thread_id.clone(), "Spam".to_string()));
orders.send_msg(Msg::SetUnread(thread_id, false));
};
orders.send_msg(Msg::CatchupNext);
}
Msg::CatchupNext => {
orders.send_msg(Msg::ScrollToTop);
let Some(catchup) = &mut model.catchup else {
@@ -852,7 +894,10 @@ pub enum Msg {
SetUnread(String, bool),
AddTag(String, String),
AddTagAndGoToSearch(String, String),
#[allow(dead_code)]
RemoveTag(String, String),
RemoveTagAndGoToSearch(String, String),
Snooze(String, DateTime<Utc>),
FrontPageRequest {
@@ -902,6 +947,7 @@ pub enum Msg {
CatchupStart,
CatchupKeepUnread,
CatchupMarkAsRead,
CatchupMarkAsSpam,
CatchupNext,
CatchupExit,

View File

@@ -100,6 +100,7 @@ pub fn view(model: &Model) -> Node<Msg> {
&catchup.items,
is_loading,
model.read_completion_ratio,
true, // show spam button for email
)
} else {
normal_view(
@@ -127,6 +128,7 @@ pub fn view(model: &Model) -> Node<Msg> {
&catchup.items,
is_loading,
model.read_completion_ratio,
false, // no spam button for news
)
} else {
normal_view(
@@ -193,6 +195,7 @@ fn catchup_view(
items: &[CatchupItem],
is_loading: bool,
read_completion_ratio: f64,
show_spam_button: bool,
) -> Node<Msg> {
div![
C!["w-full", "relative", "text-white"],
@@ -268,6 +271,14 @@ fn catchup_view(
Msg::GoToSearchResults
]))
],
IF!(show_spam_button => button![
tw_classes::button(),
C!["text-red-500"],
attrs! {At::Title => "Mark as spam"},
span![i![C!["far", "fa-hand"]]],
span![C!["pl-2"], "Spam"],
ev(Ev::Click, |_| Msg::CatchupMarkAsSpam)
]),
button![
tw_classes::button_with_color("bg-green-800", "hover:bg-green-700"),
span![i![C!["far", "fa-envelope-open"]]],
@@ -450,7 +461,7 @@ fn removable_tags_chiclet<'a>(thread_id: &'a str, tags: &'a [String]) -> Node<Ms
a![
C![&tw_classes::TAG_X],
span![i![C!["fa-solid", "fa-xmark"]]],
ev(Ev::Click, move |_| Msg::RemoveTag(thread_id, rm_tag))
ev(Ev::Click, move |_| Msg::RemoveTagAndGoToSearch(thread_id, rm_tag))
]
]
})