chore(web): update to leptos 0.7
it was painful, but hopefully worth it everything seems ok, lmk if stuff broke things will need further improving.....
This commit is contained in:
parent
5ed13e41a6
commit
fab8742bc1
28 changed files with 643 additions and 579 deletions
548
Cargo.lock
generated
548
Cargo.lock
generated
|
@ -1,6 +1,6 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
|
@ -113,6 +113,17 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "any_spawner"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41058deaa38c9d9dd933d6d238d825227cffa668e2839b52879f6619c63eee3b"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"thiserror 2.0.10",
|
||||
"wasm-bindgen-futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.95"
|
||||
|
@ -144,6 +155,17 @@ version = "0.7.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
"event-listener-strategy",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-recursion"
|
||||
version = "1.1.1"
|
||||
|
@ -205,9 +227,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
|||
|
||||
[[package]]
|
||||
name = "attribute-derive"
|
||||
version = "0.9.2"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f1ee502851995027b06f99f5ffbeffa1406b38d0b318a1ebfa469332c6cbafd"
|
||||
checksum = "0053e96dd3bec5b4879c23a138d6ef26f2cb936c9cdc96274ac2b9ed44b5bb54"
|
||||
dependencies = [
|
||||
"attribute-derive-macro",
|
||||
"derive-where",
|
||||
|
@ -219,14 +241,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "attribute-derive-macro"
|
||||
version = "0.9.2"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3601467f634cfe36c4780ca9c75dea9a5b34529c1f2810676a337e7e0997f954"
|
||||
checksum = "463b53ad0fd5b460af4b1915fe045ff4d946d025fb6c4dc3337752eaa980f71b"
|
||||
dependencies = [
|
||||
"collection_literals",
|
||||
"interpolator",
|
||||
"manyhow",
|
||||
"proc-macro-utils 0.8.0",
|
||||
"proc-macro-utils",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"quote-use",
|
||||
|
@ -534,33 +556,6 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"ciborium-ll",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-io"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-ll"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.25"
|
||||
|
@ -702,6 +697,12 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_str_slice_concat"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f67855af358fcb20fac58f9d714c94e2b228fe5694c1c9b4ead4a366343eda1b"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.6.0"
|
||||
|
@ -786,12 +787,6 @@ version = "0.8.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
|
@ -837,19 +832,6 @@ dependencies = [
|
|||
"syn 2.0.95",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "5.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"hashbrown 0.14.5",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "6.1.0"
|
||||
|
@ -958,6 +940,15 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either_of"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2dc0006c5cf511f802ddcffc0a6df9dcc1912f5f0e448f6641b3b035f14f43d"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.35"
|
||||
|
@ -1021,6 +1012,16 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener-strategy"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fancy-regex"
|
||||
version = "0.11.0"
|
||||
|
@ -1150,6 +1151,7 @@ dependencies = [
|
|||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1318,7 +1320,7 @@ dependencies = [
|
|||
"gloo-events",
|
||||
"gloo-utils 0.1.7",
|
||||
"serde",
|
||||
"serde-wasm-bindgen 0.5.0",
|
||||
"serde-wasm-bindgen",
|
||||
"serde_urlencoded",
|
||||
"thiserror 1.0.69",
|
||||
"wasm-bindgen",
|
||||
|
@ -1457,6 +1459,12 @@ dependencies = [
|
|||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "guardian"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "493913a18c0d7bebb75127a26a432162c59edbe06f6cf712001e3e769345e8b5"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.7"
|
||||
|
@ -1476,16 +1484,6 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
|
@ -1533,6 +1531,12 @@ version = "0.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
|
@ -1657,6 +1661,20 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hydration_context"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d35485b3dcbf7e044b8f28c73f04f13e7b509c2466fd10cb2a8a447e38f8a93a"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"once_cell",
|
||||
"or_poisoned",
|
||||
"pin-project-lite",
|
||||
"serde",
|
||||
"throw_error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.5.2"
|
||||
|
@ -1925,15 +1943,6 @@ version = "0.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8"
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b31349d02fe60f80bbbab1a9402364cad7460626d6030494b08ac4a2075bf81"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.10.1"
|
||||
|
@ -1955,6 +1964,15 @@ dependencies = [
|
|||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.14"
|
||||
|
@ -1992,17 +2010,34 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "leptos"
|
||||
version = "0.6.15"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cbb3237c274dadf00dcc27db96c52601b40375117178fb24a991cda073624f0"
|
||||
checksum = "21c31c9d022c77702c53e02830d08b28320aca9c0899a19c443096c114623fa5"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"cfg-if",
|
||||
"either_of",
|
||||
"futures",
|
||||
"getrandom",
|
||||
"hydration_context",
|
||||
"leptos_config",
|
||||
"leptos_dom",
|
||||
"leptos_hot_reload",
|
||||
"leptos_macro",
|
||||
"leptos_reactive",
|
||||
"leptos_server",
|
||||
"oco_ref",
|
||||
"or_poisoned",
|
||||
"paste",
|
||||
"reactive_graph",
|
||||
"rustc-hash",
|
||||
"send_wrapper",
|
||||
"serde",
|
||||
"serde_qs",
|
||||
"server_fn",
|
||||
"slotmap",
|
||||
"tachys",
|
||||
"thiserror 2.0.10",
|
||||
"throw_error",
|
||||
"tracing",
|
||||
"typed-builder",
|
||||
"typed-builder-macro",
|
||||
|
@ -2012,12 +2047,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "leptos-use"
|
||||
version = "0.13.13"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "789bf9f4337e6ebd8f1b407e3f762fdc538d48dc145f9d1dce2338014b38f4dd"
|
||||
checksum = "bb81bee40ad4fd7c0e8a84ed4b4396b27928d8d91a271c3cca9de6ba58f1cafc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
"codee",
|
||||
"cookie",
|
||||
"default-struct-builder",
|
||||
|
@ -2027,7 +2061,8 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"leptos",
|
||||
"paste",
|
||||
"thiserror 1.0.69",
|
||||
"send_wrapper",
|
||||
"thiserror 2.0.10",
|
||||
"unic-langid",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
|
@ -2036,52 +2071,38 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "leptos_config"
|
||||
version = "0.6.15"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62ed778611380ddea47568ac6ad6ec5158d39b5bd59e6c4dcd24efc15dc3dc0d"
|
||||
checksum = "5d874993c7664d757677d056c8f46b5cb5365fe622005e1bf26050f4996e7e52"
|
||||
dependencies = [
|
||||
"config",
|
||||
"regex",
|
||||
"serde",
|
||||
"thiserror 1.0.69",
|
||||
"thiserror 2.0.10",
|
||||
"typed-builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leptos_dom"
|
||||
version = "0.6.15"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8401c46c86c1f4c16dcb7881ed319fcdca9cda9b9e78a6088955cb423afcf119"
|
||||
checksum = "a462aaeec85bc4ecfb26bf324437b92690bf3add1e30eb29b3acc08b20e8b4cb"
|
||||
dependencies = [
|
||||
"async-recursion",
|
||||
"cfg-if",
|
||||
"drain_filter_polyfill",
|
||||
"futures",
|
||||
"getrandom",
|
||||
"html-escape",
|
||||
"indexmap",
|
||||
"itertools",
|
||||
"js-sys",
|
||||
"leptos_reactive",
|
||||
"once_cell",
|
||||
"pad-adapter",
|
||||
"paste",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"server_fn",
|
||||
"smallvec",
|
||||
"or_poisoned",
|
||||
"reactive_graph",
|
||||
"send_wrapper",
|
||||
"tachys",
|
||||
"tracing",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leptos_hot_reload"
|
||||
version = "0.6.15"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6cb53d4794240b684a2f4be224b84bee9e62d2abc498cf2bcd643cd565e01d96"
|
||||
checksum = "07eb295ad2f3b2af190da62af339b84fd01ce3c71702f09eb69a57310fcf0c6d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"camino",
|
||||
|
@ -2097,15 +2118,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "leptos_macro"
|
||||
version = "0.6.15"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b13bc3db70715cd8218c4535a5af3ae3c0e5fea6f018531fc339377b36bc0e0"
|
||||
checksum = "90291b25ee576bc9c299d3371cc8f09bf60ea939a8de61fa8b744650aff76e24"
|
||||
dependencies = [
|
||||
"attribute-derive",
|
||||
"cfg-if",
|
||||
"convert_case",
|
||||
"html-escape",
|
||||
"itertools",
|
||||
"itertools 0.13.0",
|
||||
"leptos_hot_reload",
|
||||
"prettyplease",
|
||||
"proc-macro-error2",
|
||||
|
@ -2119,71 +2140,59 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "leptos_reactive"
|
||||
version = "0.6.15"
|
||||
name = "leptos_router"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4161acbf80f59219d8d14182371f57302bc7ff81ee41aba8ba1ff7295727f23"
|
||||
checksum = "9a193dbd62b9617a5d7d199ea70c570da01a1bbe798e617373b6351845be6778"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"cfg-if",
|
||||
"any_spawner",
|
||||
"either_of",
|
||||
"futures",
|
||||
"indexmap",
|
||||
"gloo-net 0.6.0",
|
||||
"js-sys",
|
||||
"oco_ref",
|
||||
"paste",
|
||||
"pin-project",
|
||||
"rustc-hash",
|
||||
"self_cell",
|
||||
"serde",
|
||||
"serde-wasm-bindgen 0.6.5",
|
||||
"serde_json",
|
||||
"slotmap",
|
||||
"thiserror 1.0.69",
|
||||
"leptos",
|
||||
"leptos_router_macro",
|
||||
"once_cell",
|
||||
"or_poisoned",
|
||||
"reactive_graph",
|
||||
"send_wrapper",
|
||||
"tachys",
|
||||
"thiserror 2.0.10",
|
||||
"tracing",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leptos_router"
|
||||
version = "0.6.15"
|
||||
name = "leptos_router_macro"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d71dea7d42c0d29c40842750232d3425ed1cf10e313a1f898076d20871dad32"
|
||||
checksum = "34bc3f80ad810b22058f12d278bb0bf929779cc0bc1289a06980d896f62743f0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"gloo-net 0.6.0",
|
||||
"itertools",
|
||||
"js-sys",
|
||||
"lazy_static",
|
||||
"leptos",
|
||||
"linear-map",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"send_wrapper",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_qs 0.13.0",
|
||||
"thiserror 1.0.69",
|
||||
"tracing",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leptos_server"
|
||||
version = "0.6.15"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a97eb90a13f71500b831c7119ddd3bdd0d7ae0a6b0487cade4fddeed3b8c03f"
|
||||
checksum = "18caffe32c245ddb35697edd898ccb3393efce67672a707a14eebd0db2e8249a"
|
||||
dependencies = [
|
||||
"inventory",
|
||||
"lazy_static",
|
||||
"leptos_macro",
|
||||
"leptos_reactive",
|
||||
"any_spawner",
|
||||
"base64",
|
||||
"codee",
|
||||
"futures",
|
||||
"hydration_context",
|
||||
"or_poisoned",
|
||||
"reactive_graph",
|
||||
"send_wrapper",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"server_fn",
|
||||
"thiserror 1.0.69",
|
||||
"tachys",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
@ -2215,10 +2224,6 @@ name = "linear-map"
|
|||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfae20f6b19ad527b550c223fddc3077a547fc70cda94b9b566575423fd303ee"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
|
@ -2266,9 +2271,9 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
|||
|
||||
[[package]]
|
||||
name = "manyhow"
|
||||
version = "0.10.4"
|
||||
version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f91ea592d76c0b6471965708ccff7e6a5d277f676b90ab31f4d3f3fc77fade64"
|
||||
checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587"
|
||||
dependencies = [
|
||||
"manyhow-macros",
|
||||
"proc-macro2",
|
||||
|
@ -2278,11 +2283,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "manyhow-macros"
|
||||
version = "0.10.4"
|
||||
version = "0.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c64621e2c08f2576e4194ea8be11daf24ac01249a4f53cd8befcbb7077120ead"
|
||||
checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495"
|
||||
dependencies = [
|
||||
"proc-macro-utils 0.8.0",
|
||||
"proc-macro-utils",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
@ -2427,6 +2432,12 @@ version = "1.0.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
|
||||
|
||||
[[package]]
|
||||
name = "next_tuple"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60993920e071b0c9b66f14e2b32740a4e27ffc82854dcd72035887f336a09a28"
|
||||
|
||||
[[package]]
|
||||
name = "nodeinfo"
|
||||
version = "0.0.2"
|
||||
|
@ -2520,6 +2531,16 @@ dependencies = [
|
|||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
|
@ -2531,9 +2552,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "oco_ref"
|
||||
version = "0.1.1"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c51ebcefb2f0b9a5e0bea115532c8ae4215d1b01eff176d0f4ba4192895c2708"
|
||||
checksum = "64b94982fe39a861561cf67ff17a7849f2cedadbbad960a797634032b7abb998"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"thiserror 1.0.69",
|
||||
|
@ -2611,6 +2632,12 @@ dependencies = [
|
|||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "or_poisoned"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c04f5d74368e4d0dfe06c45c8627c81bd7c317d52762d118fb9b3076f6420fd"
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "3.9.2"
|
||||
|
@ -2638,7 +2665,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "39b0deead1528fd0e5947a8546a9642a9777c25f6e1e26f34c97b204bbb465bd"
|
||||
dependencies = [
|
||||
"heck 0.4.1",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"proc-macro2",
|
||||
"proc-macro2-diagnostics",
|
||||
"quote",
|
||||
|
@ -2651,12 +2678,6 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "pad-adapter"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56d80efc4b6721e8be2a10a5df21a30fa0b470f1539e53d8b4e6e75faf938b63"
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.2.1"
|
||||
|
@ -2927,17 +2948,6 @@ dependencies = [
|
|||
"syn 2.0.95",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-utils"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f59e109e2f795a5070e69578c4dc101068139f74616778025ae1011d4cd41a8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-utils"
|
||||
version = "0.10.0"
|
||||
|
@ -3025,7 +3035,7 @@ version = "0.8.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82ebfb7faafadc06a7ab141a6f67bcfb24cb8beb158c6fe933f2f035afa99f35"
|
||||
dependencies = [
|
||||
"proc-macro-utils 0.10.0",
|
||||
"proc-macro-utils",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.95",
|
||||
|
@ -3067,6 +3077,56 @@ dependencies = [
|
|||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reactive_graph"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fbf210c04505e128fb7f64acecc23c71f82f56c7d481b190e1010b7bada2cb9"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"async-lock",
|
||||
"futures",
|
||||
"guardian",
|
||||
"hydration_context",
|
||||
"or_poisoned",
|
||||
"pin-project-lite",
|
||||
"rustc-hash",
|
||||
"send_wrapper",
|
||||
"serde",
|
||||
"slotmap",
|
||||
"thiserror 2.0.10",
|
||||
"tracing",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reactive_stores"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80bb1913eeb71f74028213455ee971550c2b3cb91b6acd5efa8a0f8dc59f5039"
|
||||
dependencies = [
|
||||
"guardian",
|
||||
"itertools 0.13.0",
|
||||
"or_poisoned",
|
||||
"paste",
|
||||
"reactive_graph",
|
||||
"reactive_stores_macro",
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reactive_stores_macro"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d86e4f08f361b05d11422398cef4bc4cf356f2fdd2f06a96646b0e9cd902226"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.95",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.8"
|
||||
|
@ -3239,10 +3299,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rstml"
|
||||
version = "0.11.2"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe542870b8f59dd45ad11d382e5339c9a1047cde059be136a7016095bbdefa77"
|
||||
checksum = "51187e564f12336ef40cd04f6f4d805d6919188001dcf1e0a021898ea0fe28ce"
|
||||
dependencies = [
|
||||
"derive-where",
|
||||
"proc-macro2",
|
||||
"proc-macro2-diagnostics",
|
||||
"quote",
|
||||
|
@ -3275,9 +3336,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
|||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
|
@ -3556,12 +3617,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "self_cell"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe"
|
||||
|
||||
[[package]]
|
||||
name = "send_wrapper"
|
||||
version = "0.6.0"
|
||||
|
@ -3602,17 +3657,6 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_default"
|
||||
version = "0.2.0"
|
||||
|
@ -3667,17 +3711,6 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_qs"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0431a35568651e363364210c91983c1da5eb29404d9f0928b67d4ebcfa7d330c"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_qs"
|
||||
version = "0.13.0"
|
||||
|
@ -3698,15 +3731,6 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_test"
|
||||
version = "1.0.177"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
|
@ -3721,25 +3745,26 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "server_fn"
|
||||
version = "0.6.15"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fae7a3038a32e5a34ba32c6c45eb4852f8affaf8b794ebfcd4b1099e2d62ebe"
|
||||
checksum = "f5dd7fcccd3ef2081da086c1f8595b506627abbbbc9f64be0141d2251219570e"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"ciborium",
|
||||
"const_format",
|
||||
"dashmap 5.5.3",
|
||||
"dashmap",
|
||||
"futures",
|
||||
"gloo-net 0.6.0",
|
||||
"http 1.2.0",
|
||||
"js-sys",
|
||||
"once_cell",
|
||||
"pin-project-lite",
|
||||
"send_wrapper",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_qs 0.12.0",
|
||||
"serde_qs",
|
||||
"server_fn_macro_default",
|
||||
"thiserror 1.0.69",
|
||||
"thiserror 2.0.10",
|
||||
"throw_error",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
|
@ -3750,9 +3775,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "server_fn_macro"
|
||||
version = "0.6.15"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faaaf648c6967aef78177c0610478abb5a3455811f401f3c62d10ae9bd3901a1"
|
||||
checksum = "e0bbac4f01a714b0490247ac625bdb7055548210556c39e8f56a2dbbe3abc70b"
|
||||
dependencies = [
|
||||
"const_format",
|
||||
"convert_case",
|
||||
|
@ -3764,9 +3789,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "server_fn_macro_default"
|
||||
version = "0.6.15"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f2aa8119b558a17992e0ac1fd07f080099564f24532858811ce04f742542440"
|
||||
checksum = "f07dfd1744a5f5612f00f69fe035b0bfafdf12bb46d76e785673078a9e56b170"
|
||||
dependencies = [
|
||||
"server_fn_macro",
|
||||
"syn 2.0.95",
|
||||
|
@ -3902,7 +3927,6 @@ version = "1.0.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
|
@ -4406,6 +4430,39 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tachys"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d777e4426a597296b020edcb5c3d8f25a3ccd8adfd22eb5154ac81da946aef9f"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"const_str_slice_concat",
|
||||
"drain_filter_polyfill",
|
||||
"either_of",
|
||||
"futures",
|
||||
"html-escape",
|
||||
"indexmap",
|
||||
"itertools 0.13.0",
|
||||
"js-sys",
|
||||
"linear-map",
|
||||
"next_tuple",
|
||||
"oco_ref",
|
||||
"once_cell",
|
||||
"or_poisoned",
|
||||
"parking_lot",
|
||||
"paste",
|
||||
"reactive_graph",
|
||||
"reactive_stores",
|
||||
"rustc-hash",
|
||||
"send_wrapper",
|
||||
"slotmap",
|
||||
"throw_error",
|
||||
"tracing",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
|
@ -4497,6 +4554,15 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "throw_error"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4ef8bf264c6ae02a065a4a16553283f0656bd6266fc1fcb09fd2e6b5e91427b"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.37"
|
||||
|
@ -4799,18 +4865,18 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
|
|||
|
||||
[[package]]
|
||||
name = "typed-builder"
|
||||
version = "0.18.2"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77739c880e00693faef3d65ea3aad725f196da38b22fdc7ea6ded6e1ce4d3add"
|
||||
checksum = "7e14ed59dc8b7b26cacb2a92bad2e8b1f098806063898ab42a3bd121d7d45e75"
|
||||
dependencies = [
|
||||
"typed-builder-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typed-builder-macro"
|
||||
version = "0.18.2"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63"
|
||||
checksum = "560b82d656506509d43abe30e0ba64c56b1953ab3d4fe7ba5902747a7a3cedd5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -4922,7 +4988,6 @@ dependencies = [
|
|||
"sha2",
|
||||
"sha256",
|
||||
"thiserror 2.0.10",
|
||||
"tokio",
|
||||
"toml",
|
||||
"tracing",
|
||||
"uriproxy",
|
||||
|
@ -4957,7 +5022,6 @@ dependencies = [
|
|||
"chrono",
|
||||
"clap",
|
||||
"futures",
|
||||
"mdhtml",
|
||||
"openssl",
|
||||
"reqwest",
|
||||
"sea-orm",
|
||||
|
@ -4998,7 +5062,6 @@ dependencies = [
|
|||
"tower-http",
|
||||
"tracing",
|
||||
"upub",
|
||||
"uriproxy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5011,7 +5074,7 @@ dependencies = [
|
|||
"codee",
|
||||
"console_error_panic_hook",
|
||||
"cookie",
|
||||
"dashmap 6.1.0",
|
||||
"dashmap",
|
||||
"futures",
|
||||
"jrd",
|
||||
"lazy_static",
|
||||
|
@ -5038,7 +5101,6 @@ name = "upub-worker"
|
|||
version = "0.3.0"
|
||||
dependencies = [
|
||||
"apb",
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"mdhtml",
|
||||
"regex",
|
||||
|
|
|
@ -24,10 +24,10 @@ serde_json = "1.0"
|
|||
serde_default = "0.2"
|
||||
serde-inline-default = "0.2"
|
||||
dashmap = "6.1"
|
||||
leptos = { version = "0.6.15", features = ["csr", "tracing"] } # locked because upgrading is hell
|
||||
leptos_router = { version = "0.6.15", features = ["csr"] } # locked because upgrading is hell
|
||||
leptos-use = "0.13.13" # locked because upgrading is hell
|
||||
codee = { version = "0.2", features = ["json_serde"] }
|
||||
leptos = { version = "0.7", features = ["csr", "tracing"] }
|
||||
leptos_router = { version = "0.7", features = ["tracing"] }
|
||||
leptos-use = "0.15"
|
||||
codee = { version = "0.2", features = ["json_serde"] } # WHYYY LEPTOS-USE AKSJFOASHGOAEG
|
||||
reqwest = { version = "0.12", features = ["json"] }
|
||||
apb = { path = "../apb", features = ["unstructured", "activitypub-fe", "activitypub-counters", "litepub", "did-core"] }
|
||||
uriproxy = { path = "../utils/uriproxy/" }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
use apb::{Activity, ActivityMut, Base, Object};
|
||||
|
@ -36,7 +36,7 @@ pub fn ActivityLine(activity: crate::Object, children: Children) -> impl IntoVie
|
|||
{kind.as_ref().to_string()}
|
||||
</a>
|
||||
{activity_url}
|
||||
<PrivacyMarker privacy=privacy to=&to cc=&cc />
|
||||
<PrivacyMarker privacy=privacy to=to cc=cc />
|
||||
</code>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -62,7 +62,7 @@ pub fn Item(
|
|||
match item.object_type().unwrap_or(apb::ObjectType::Object) {
|
||||
// special case for placeholder activities
|
||||
apb::ObjectType::Note | apb::ObjectType::Document(_) =>
|
||||
Some(view! { <Object object=item.clone() />{sep.clone()} }.into_view()),
|
||||
Some(view! { <Object object=item.clone() />{sep.clone()} }.into_any()),
|
||||
// everything else
|
||||
apb::ObjectType::Activity(t) => {
|
||||
let object_id = item.object().id().unwrap_or_default();
|
||||
|
@ -70,7 +70,7 @@ pub fn Item(
|
|||
apb::ActivityType::Create | apb::ActivityType::Announce =>
|
||||
cache::OBJECTS.get(&object_id).map(|obj| {
|
||||
view! { <Object object=obj /> }
|
||||
}.into_view()),
|
||||
}.into_any()),
|
||||
apb::ActivityType::Follow =>
|
||||
cache::OBJECTS.get(&object_id).map(|obj| {
|
||||
view! {
|
||||
|
@ -79,11 +79,11 @@ pub fn Item(
|
|||
<FollowRequestButtons activity_id=id.clone() actor_id=object_id />
|
||||
</div>
|
||||
}
|
||||
}.into_view()),
|
||||
}.into_any()),
|
||||
_ => None,
|
||||
};
|
||||
if !seen {
|
||||
let (not_seen, not_seen_tx) = create_signal(!seen);
|
||||
let (not_seen, not_seen_tx) = signal(!seen);
|
||||
let id = id.clone();
|
||||
Some(view! {
|
||||
<div class:notification=not_seen>
|
||||
|
@ -97,7 +97,7 @@ pub fn Item(
|
|||
{object}
|
||||
</div>
|
||||
{sep.clone()}
|
||||
}.into_view())
|
||||
}.into_any())
|
||||
} else {
|
||||
Some(view! {
|
||||
<div>
|
||||
|
@ -105,11 +105,11 @@ pub fn Item(
|
|||
{object}
|
||||
</div>
|
||||
{sep.clone()}
|
||||
}.into_view())
|
||||
}.into_any())
|
||||
}
|
||||
},
|
||||
// should never happen
|
||||
t => Some(view! { <p><code>type not implemented : {t.as_ref().to_string()}</code></p> }.into_view()),
|
||||
t => Some(view! { <p><code>type not implemented : {t.as_ref().to_string()}</code></p> }.into_any()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ fn AckBtn(id: String, tx: WriteSignal<bool>) -> impl IntoView {
|
|||
.set_activity_type(Some(apb::ActivityType::View))
|
||||
.set_object(apb::Node::link(id.clone()));
|
||||
let id = id.clone();
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
if let Err(e) = Http::post(&auth.outbox(), &payload, auth).await {
|
||||
tracing::error!("failed marking notification as seen: {e}");
|
||||
} else {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use leptos::*;
|
||||
use leptos_router::*;
|
||||
use leptos::prelude::*;
|
||||
use leptos_router::hooks::use_params;
|
||||
use crate::prelude::*;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
@ -11,7 +11,8 @@ pub fn FollowList(outgoing: bool) -> impl IntoView {
|
|||
let follow___ = if outgoing { "following" } else { "followers" };
|
||||
let params = use_params::<IdParam>();
|
||||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
let resource = create_local_resource(
|
||||
// TODO this was a LocalResource!
|
||||
let resource = Resource::new(
|
||||
move || params.get().ok().and_then(|x| x.id).unwrap_or_default(),
|
||||
move |id| {
|
||||
async move {
|
||||
|
@ -28,10 +29,10 @@ pub fn FollowList(outgoing: bool) -> impl IntoView {
|
|||
view! {
|
||||
<div class="tl ml-3-r mr-3-r pl-1 pt-1 pb-1">
|
||||
{move || match resource.get() {
|
||||
None => view! { <Loader /> }.into_view(),
|
||||
None => view! { <Loader /> }.into_any(),
|
||||
Some(Err(e)) => {
|
||||
tracing::error!("could not load followers: {e}");
|
||||
view! { <code class="cw center color">{follow___}" unavailable"</code> }.into_view()
|
||||
view! { <code class="cw center color">{follow___}" unavailable"</code> }.into_any()
|
||||
},
|
||||
Some(Ok(mut arr)) => {
|
||||
// TODO cheap fix: server gives us follows from oldest to newest
|
||||
|
@ -50,10 +51,10 @@ pub fn FollowList(outgoing: bool) -> impl IntoView {
|
|||
view! {
|
||||
<ActorBanner object=actor />
|
||||
<hr />
|
||||
}.into_view()
|
||||
}.into_any()
|
||||
}
|
||||
/ >
|
||||
}.into_view()
|
||||
}.into_any()
|
||||
},
|
||||
}}
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use leptos::*;
|
||||
use leptos_router::*;
|
||||
use leptos::{either::Either, prelude::*, reactive::signal::signal};
|
||||
use leptos_router::{components::Outlet, hooks::use_params};
|
||||
use crate::{app::FeedRoute, prelude::*, FALLBACK_IMAGE_URL};
|
||||
|
||||
use apb::{ActivityMut, Actor, Base, Object, ObjectMut, Shortcuts};
|
||||
|
@ -11,8 +11,9 @@ pub fn ActorHeader() -> impl IntoView {
|
|||
let config = use_context::<Signal<crate::Config>>().expect("missing config context");
|
||||
let relevant_tl = use_context::<Signal<Option<Timeline>>>().expect("missing relevant timeline context");
|
||||
let matched_route = use_context::<ReadSignal<crate::app::FeedRoute>>().expect("missing route context");
|
||||
let (loading, set_loading) = create_signal(false);
|
||||
let actor = create_local_resource(
|
||||
let (loading, set_loading) = signal(false);
|
||||
// TODO this was a LocalResource!
|
||||
let actor = Resource::new(
|
||||
move || params.get().ok().and_then(|x| x.id).unwrap_or_default(),
|
||||
move |id| {
|
||||
async move {
|
||||
|
@ -27,8 +28,8 @@ pub fn ActorHeader() -> impl IntoView {
|
|||
}
|
||||
);
|
||||
move || match actor.get() {
|
||||
None => view! { <Loader /> }.into_view(),
|
||||
Some(None) => view! { <code class="center cw color">"could not resolve user"</code> }.into_view(),
|
||||
None => view! { <Loader /> }.into_any(),
|
||||
Some(None) => view! { <code class="center cw color">"could not resolve user"</code> }.into_any(),
|
||||
Some(Some(actor)) => {
|
||||
let avatar_url = actor.icon_url().unwrap_or(FALLBACK_IMAGE_URL.into());
|
||||
let background_url = actor.image_url().unwrap_or(FALLBACK_IMAGE_URL.into());
|
||||
|
@ -104,7 +105,7 @@ pub fn ActorHeader() -> impl IntoView {
|
|||
<small class="mr-s">following</small>
|
||||
</span>
|
||||
</a>
|
||||
}.into_view()
|
||||
}.into_any()
|
||||
} else {
|
||||
view! {
|
||||
<a class="clean dim" href="#follow" on:click=move |_| send_follow_request(_uid.clone())>
|
||||
|
@ -113,7 +114,7 @@ pub fn ActorHeader() -> impl IntoView {
|
|||
<small class="mr-s">follow</small>
|
||||
</span>
|
||||
</a>
|
||||
}.into_view()
|
||||
}.into_any()
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -137,14 +138,14 @@ pub fn ActorHeader() -> impl IntoView {
|
|||
</span>
|
||||
{move || if auth.present() {
|
||||
if loading.get() {
|
||||
Some(view! {
|
||||
Some(Either::Left(view! {
|
||||
<span style="float: right">
|
||||
<span class="hidden-on-mobile">"fetching "</span><span class="dots"></span>
|
||||
</span>
|
||||
})
|
||||
}))
|
||||
} else {
|
||||
let uid = __uid.clone();
|
||||
Some(view! {
|
||||
Some(Either::Right(view! {
|
||||
<span style="float: right">
|
||||
<a
|
||||
class="clean"
|
||||
|
@ -154,7 +155,7 @@ pub fn ActorHeader() -> impl IntoView {
|
|||
<span class="emoji ml-2">"↺ "</span><span class="hidden-on-mobile">"fetch"</span>
|
||||
</a>
|
||||
</span>
|
||||
})
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
|
@ -162,7 +163,7 @@ pub fn ActorHeader() -> impl IntoView {
|
|||
</p>
|
||||
<hr class="color" />
|
||||
<Outlet />
|
||||
}.into_view()
|
||||
}.into_any()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +181,7 @@ async fn send_follow_response(kind: apb::ActivityType, target: String, to: Strin
|
|||
|
||||
fn send_follow_request(target: String) {
|
||||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
let payload = apb::new()
|
||||
.set_activity_type(Some(apb::ActivityType::Follow))
|
||||
.set_object(apb::Node::link(target.clone()))
|
||||
|
@ -193,7 +194,7 @@ fn send_follow_request(target: String) {
|
|||
|
||||
fn unfollow(target: String) {
|
||||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
let payload = apb::new()
|
||||
.set_activity_type(Some(apb::ActivityType::Undo))
|
||||
.set_to(apb::Node::links(vec![target.clone()]))
|
||||
|
@ -208,11 +209,11 @@ fn unfollow(target: String) {
|
|||
})
|
||||
}
|
||||
|
||||
fn fetch_cb(ev: ev::MouseEvent, set_loading: WriteSignal<bool>, uid: String, auth: Auth, config: Signal<crate::Config>, relevant_tl: Signal<Option<Timeline>>) {
|
||||
fn fetch_cb(ev: leptos::ev::MouseEvent, set_loading: WriteSignal<bool>, uid: String, auth: Auth, config: Signal<crate::Config>, relevant_tl: Signal<Option<Timeline>>) {
|
||||
let api = Uri::api(U::Actor, &uid, false);
|
||||
ev.prevent_default();
|
||||
set_loading.set(true);
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
if let Err(e) = Http::fetch::<serde_json::Value>(&format!("{api}/outbox?fetch=true"), auth).await {
|
||||
tracing::error!("failed fetching outbox for {uid}: {e}");
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use leptos::*;
|
||||
use leptos_router::*;
|
||||
use leptos::prelude::*;
|
||||
use leptos_router::hooks::use_params;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn ActorPosts() -> impl IntoView {
|
||||
let feeds = use_context::<Feeds>().expect("missing feeds context");
|
||||
let params = use_params::<IdParam>();
|
||||
create_effect(move |_| {
|
||||
Effect::new(move |_| {
|
||||
let id = params.get().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) {
|
||||
|
@ -22,7 +22,7 @@ pub fn ActorPosts() -> impl IntoView {
|
|||
pub fn ActorLikes() -> impl IntoView {
|
||||
let feeds = use_context::<Feeds>().expect("missing feeds context");
|
||||
let params = use_params::<IdParam>();
|
||||
create_effect(move |_| {
|
||||
Effect::new(move |_| {
|
||||
let id = params.get().ok().and_then(|x| x.id).unwrap_or_default();
|
||||
let likes_url = format!("{}/likes/page", Uri::api(U::Actor, &id, false));
|
||||
if !feeds.user.next.get_untracked().starts_with(&likes_url) {
|
||||
|
|
111
web/src/app.rs
111
web/src/app.rs
|
@ -1,9 +1,8 @@
|
|||
use apb::Collection;
|
||||
use leptos::*;
|
||||
use leptos_router::*;
|
||||
use leptos::{either::Either, prelude::*};
|
||||
use leptos_router::{components::*, hooks::use_location, path};
|
||||
use crate::prelude::*;
|
||||
|
||||
use codee::string::{FromToStringCodec, JsonSerdeCodec};
|
||||
use leptos_use::{
|
||||
signal_debounced, storage::use_local_storage, use_cookie_with_options, use_element_size, use_window_scroll,
|
||||
UseCookieOptions, UseElementSizeReturn
|
||||
|
@ -59,31 +58,30 @@ impl Feeds {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[component]
|
||||
pub fn App() -> impl IntoView {
|
||||
let (token, set_token) = use_cookie_with_options::<String, FromToStringCodec>(
|
||||
let (token, set_token) = use_cookie_with_options::<String, codee::string::FromToStringCodec>(
|
||||
"token",
|
||||
UseCookieOptions::default()
|
||||
.same_site(cookie::SameSite::Strict)
|
||||
// .secure(true)
|
||||
.path("/")
|
||||
);
|
||||
let (userid, set_userid) = use_cookie_with_options::<String, FromToStringCodec>(
|
||||
let (userid, set_userid) = use_cookie_with_options::<String, codee::string::FromToStringCodec>(
|
||||
"user_id",
|
||||
UseCookieOptions::default()
|
||||
.same_site(cookie::SameSite::Strict)
|
||||
// .secure(true)
|
||||
.path("/")
|
||||
);
|
||||
let (config, set_config, _) = use_local_storage::<crate::Config, JsonSerdeCodec>("config");
|
||||
let (config, set_config, _) = use_local_storage::<crate::Config, codee::string::JsonSerdeCodec>("config");
|
||||
|
||||
let (privacy, set_privacy) = create_signal(Privacy::Private);
|
||||
let (privacy, set_privacy) = signal(Privacy::Private);
|
||||
|
||||
let auth = Auth { token, userid };
|
||||
|
||||
let (be_version, set_be_version) = create_signal("?.?.?".to_string());
|
||||
spawn_local(async move {
|
||||
let (be_version, set_be_version) = signal("?.?.?".to_string());
|
||||
leptos::task::spawn_local(async move {
|
||||
match Http::fetch::<serde_json::Value>(&format!("{URL_BASE}/nodeinfo/2.0.json"), auth).await {
|
||||
Err(e) => tracing::error!("failed fetching backend version: {e} - {e:?}"),
|
||||
Ok(nodeinfo) => {
|
||||
|
@ -115,19 +113,19 @@ pub fn App() -> impl IntoView {
|
|||
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 < 768);
|
||||
let (advanced, set_advanced) = create_signal(false);
|
||||
let (menu, set_menu) = signal(screen_width < 768);
|
||||
let (advanced, set_advanced) = signal(false);
|
||||
|
||||
let title_target = move || if auth.present() { "/web/home" } else { "/web/global" };
|
||||
|
||||
// refresh token immediately and every hour
|
||||
let refresh_token = move || spawn_local(async move { Auth::refresh(auth.token, set_token, set_userid).await; });
|
||||
let refresh_token = move || leptos::task::spawn_local(async move { Auth::refresh(auth.token, set_token, set_userid).await; });
|
||||
refresh_token();
|
||||
set_interval(refresh_token, std::time::Duration::from_secs(3600));
|
||||
|
||||
// refresh notifications
|
||||
let (notifications, set_notifications) = create_signal(0);
|
||||
let fetch_notifications = move || spawn_local(async move {
|
||||
let (notifications, set_notifications) = signal(0);
|
||||
let fetch_notifications = move || leptos::task::spawn_local(async move {
|
||||
let actor_id = userid.get_untracked().unwrap_or_default();
|
||||
let notif_url = format!("{actor_id}/notifications");
|
||||
match Http::fetch::<serde_json::Value>(¬if_url, auth).await {
|
||||
|
@ -162,60 +160,57 @@ pub fn App() -> impl IntoView {
|
|||
<div class:hidden=move || !auth.present() >
|
||||
<PrivacySelector setter=set_privacy />
|
||||
<hr class="mt-1 mb-1" />
|
||||
{move || if advanced.get() { view! {
|
||||
{move || if advanced.get() { Either::Left(view! {
|
||||
<AdvancedPostBox advanced=set_advanced/>
|
||||
}} else { view! {
|
||||
})} else { Either::Right(view! {
|
||||
<PostBox advanced=set_advanced/>
|
||||
}}}
|
||||
})}}
|
||||
<hr class="only-on-mobile sep mb-0 pb-0" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-main" class:w-100=menu >
|
||||
<Router // TODO maybe set base="/web" ?
|
||||
trailing_slash=TrailingSlash::Redirect
|
||||
fallback=|| view! { <NotFound /> }
|
||||
>
|
||||
<Router>
|
||||
<main>
|
||||
<Routes>
|
||||
<Route path="/" view=move || view! { <Redirect path="/web" /> } />
|
||||
<Route path="/web" view=Scrollable >
|
||||
<Route path="" view=move ||
|
||||
<Routes fallback=NotFound>
|
||||
<Route path=path!("/") view=move || view! { <Redirect path="/web" /> } />
|
||||
<ParentRoute path=path!("/web") view=Scrollable >
|
||||
<Route path=path!("") view=move ||
|
||||
if auth.present() {
|
||||
view! { <Redirect path="home" /> }
|
||||
} else {
|
||||
view! { <Redirect path="global" /> }
|
||||
}
|
||||
/>
|
||||
<Route path="home" view=move || view! { <Feed tl=feeds.home /> } />
|
||||
<Route path="global" view=move || view! { <Feed tl=feeds.global /> } />
|
||||
<Route path="local" view=move || view! { <Feed tl=feeds.server /> } />
|
||||
<Route path="notifications" view=move || view! { <Feed tl=feeds.notifications ignore_filters=true /> } />
|
||||
<Route path="tags/:id" view=move || view! { <HashtagFeed tl=feeds.tag /> } />
|
||||
<Route path=path!("home") view=move || view! { <Feed tl=feeds.home /> } />
|
||||
<Route path=path!("global") view=move || view! { <Feed tl=feeds.global /> } />
|
||||
<Route path=path!("local") view=move || view! { <Feed tl=feeds.server /> } />
|
||||
<Route path=path!("notifications") view=move || view! { <Feed tl=feeds.notifications ignore_filters=true /> } />
|
||||
<Route path=path!("tags/:id") view=move || view! { <HashtagFeed tl=feeds.tag /> } />
|
||||
|
||||
<Route path="about" view=AboutPage />
|
||||
<Route path="config" view=move || view! { <ConfigPage setter=set_config /> } />
|
||||
<Route path="explore" view=DebugPage />
|
||||
<Route path=path!("about") view=AboutPage />
|
||||
<Route path=path!("config") view=move || view! { <ConfigPage setter=set_config /> } />
|
||||
<Route path=path!("explore") view=DebugPage />
|
||||
|
||||
<Route path="actors/:id" view=ActorHeader > // TODO can we avoid this?
|
||||
<Route path="" view=ActorPosts />
|
||||
<Route path="likes" view=ActorLikes />
|
||||
<Route path="following" view=move || view! { <FollowList outgoing=true /> } />
|
||||
<Route path="followers" view=move || view! { <FollowList outgoing=false /> } />
|
||||
</Route>
|
||||
<ParentRoute path=path!("actors/:id") view=ActorHeader > // TODO can we avoid this?
|
||||
<Route path=path!("") view=ActorPosts />
|
||||
<Route path=path!("likes") view=ActorLikes />
|
||||
<Route path=path!("following") view=move || view! { <FollowList outgoing=true /> } />
|
||||
<Route path=path!("followers") view=move || view! { <FollowList outgoing=false /> } />
|
||||
</ParentRoute>
|
||||
|
||||
|
||||
<Route path="objects/:id" view=ObjectView >
|
||||
<Route path="" view=ObjectContext />
|
||||
<Route path="replies" view=ObjectReplies />
|
||||
<Route path="likes" view=ObjectLikes />
|
||||
<ParentRoute path=path!("objects/:id") view=ObjectView >
|
||||
<Route path=path!("") view=ObjectContext />
|
||||
<Route path=path!("replies") view=ObjectReplies />
|
||||
<Route path=path!("likes") view=ObjectLikes />
|
||||
// <Route path="announced" view=ObjectAnnounced />
|
||||
</Route>
|
||||
</ParentRoute>
|
||||
|
||||
// <Route path="/web/activities/:id" view=move || view! { <ActivityPage tl=context_tl /> } />
|
||||
|
||||
<Route path="search" view=SearchPage />
|
||||
<Route path="register" view=RegisterPage />
|
||||
</Route>
|
||||
<Route path=path!("search") view=SearchPage />
|
||||
<Route path=path!("register") view=RegisterPage />
|
||||
</ParentRoute>
|
||||
</Routes>
|
||||
</main>
|
||||
</Router>
|
||||
|
@ -244,7 +239,7 @@ fn Scrollable() -> impl IntoView {
|
|||
// TODO this is terrible!! omg maybe it should receive from context current timeline?? idk this
|
||||
// is awful and i patched it another time instead of doing it properly...
|
||||
// at least im going to provide a route enum to use in other places
|
||||
let (route, set_route) = create_signal(FeedRoute::Home);
|
||||
let (route, set_route) = signal(FeedRoute::Home);
|
||||
let relevant_timeline = Signal::derive(move || {
|
||||
let path = location.pathname.get();
|
||||
if path.contains("/web/home") {
|
||||
|
@ -325,7 +320,7 @@ fn Scrollable() -> impl IntoView {
|
|||
None => "?".to_string(),
|
||||
}
|
||||
});
|
||||
let element = create_node_ref();
|
||||
let element = NodeRef::new();
|
||||
let should_load = use_scroll_limit(element, 500.0);
|
||||
provide_context(should_load);
|
||||
view! {
|
||||
|
@ -361,21 +356,23 @@ pub fn Loader() -> impl IntoView {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn use_scroll_limit<El, T>(el: El, offset: f64) -> Signal<bool>
|
||||
where
|
||||
El: Into<leptos_use::core::ElementMaybeSignal<T, web_sys::Element>> + Clone + 'static,
|
||||
T: Into<web_sys::Element> + Clone + 'static,
|
||||
pub fn use_scroll_limit<T, Marker>(el: NodeRef<T>, offset: f64) -> Signal<bool>
|
||||
where
|
||||
T: leptos::html::ElementType,
|
||||
NodeRef<T>: leptos_use::core::IntoElementMaybeSignal<web_sys::Element, Marker>,
|
||||
{
|
||||
let (load, set_load) = create_signal(false);
|
||||
let (load, set_load) = signal(false);
|
||||
let (_x, y) = use_window_scroll();
|
||||
let UseElementSizeReturn { height: screen_height, .. } = use_element_size("html");
|
||||
let html_node_ref = NodeRef::new();
|
||||
leptos::html::html().node_ref(html_node_ref);
|
||||
let UseElementSizeReturn { height: screen_height, .. } = use_element_size(html_node_ref);
|
||||
let UseElementSizeReturn { height, .. } = use_element_size(el);
|
||||
let scroll_state = Signal::derive(move || (y.get(), height.get(), screen_height.get()));
|
||||
let scroll_state_throttled = signal_debounced(
|
||||
scroll_state,
|
||||
50.
|
||||
);
|
||||
let _ = watch(
|
||||
let _ = Effect::watch(
|
||||
move || scroll_state_throttled.get(),
|
||||
move |(y, height, screen), _, _| {
|
||||
let before = load.get();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
use reqwest::Method;
|
||||
use crate::{components::AuthResponse, URL_BASE};
|
||||
|
||||
|
@ -28,7 +28,7 @@ impl Auth {
|
|||
}
|
||||
|
||||
pub fn present(&self) -> bool {
|
||||
self.token.get().map_or(false, |x| !x.is_empty())
|
||||
self.token.get().is_some_and(|x| !x.is_empty())
|
||||
}
|
||||
|
||||
pub fn outbox(&self) -> String {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[component]
|
||||
|
@ -8,8 +8,8 @@ pub fn LoginBox(
|
|||
) -> impl IntoView {
|
||||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
let config = use_context::<Signal<crate::Config>>().expect("missing config context");
|
||||
let username_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let password_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let username_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let password_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let feeds = use_context::<Feeds>().expect("missing feeds context");
|
||||
view! {
|
||||
<div>
|
||||
|
@ -25,10 +25,10 @@ pub fn LoginBox(
|
|||
<div class:hidden=move || auth.present() >
|
||||
<form on:submit=move|ev| {
|
||||
ev.prevent_default();
|
||||
logging::log!("logging in...");
|
||||
tracing::info!("logging in...");
|
||||
let email = username_ref.get().map(|x| x.value()).unwrap_or("".into());
|
||||
let password = password_ref.get().map(|x| x.value()).unwrap_or("".into());
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
let Ok(res) = reqwest::Client::new()
|
||||
.post(format!("{URL_BASE}/auth"))
|
||||
.json(&LoginForm { email, password })
|
||||
|
@ -39,7 +39,7 @@ pub fn LoginBox(
|
|||
.json::<AuthResponse>()
|
||||
.await
|
||||
else { if let Some(rf) = password_ref.get() { rf.set_value("") }; return };
|
||||
logging::log!("logged in until {}", auth_response.expires);
|
||||
tracing::info!("logged in until {}", auth_response.expires);
|
||||
// update our username and token cookies
|
||||
let username = auth_response.user.split('/').last().unwrap_or_default().to_string();
|
||||
userid_tx.set(Some(auth_response.user));
|
||||
|
|
|
@ -10,7 +10,7 @@ pub use user::*;
|
|||
mod post;
|
||||
pub use post::*;
|
||||
|
||||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn DateTime(t: Option<chrono::DateTime<chrono::Utc>>) -> impl IntoView {
|
||||
|
@ -38,10 +38,10 @@ pub fn DateTime(t: Option<chrono::DateTime<chrono::Utc>>) -> impl IntoView {
|
|||
}
|
||||
|
||||
#[component]
|
||||
pub fn PrivacyMarker<'a>(
|
||||
pub fn PrivacyMarker(
|
||||
privacy: Privacy,
|
||||
#[prop(optional)] to: &'a [String],
|
||||
#[prop(optional)] cc: &'a [String],
|
||||
#[prop(optional)] to: Vec<String>,
|
||||
#[prop(optional)] cc: Vec<String>,
|
||||
#[prop(optional)] big: bool,
|
||||
) -> impl IntoView {
|
||||
let to_txt = if to.is_empty() { String::new() } else { format!("to: {}", to.join(", ")) };
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[component]
|
||||
|
@ -20,7 +20,7 @@ pub fn Breadcrumb(
|
|||
#[component]
|
||||
pub fn Navigator(notifications: ReadSignal<u64>) -> impl IntoView {
|
||||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
let (query, set_query) = create_signal("".to_string());
|
||||
let (query, set_query) = signal("".to_string());
|
||||
view! {
|
||||
<form action={move|| format!("/web/search?q={}", query.get())}>
|
||||
<table class="align">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use apb::{ActivityMut, Base, BaseMut, Object, ObjectMut};
|
||||
|
||||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
|
@ -135,7 +135,7 @@ pub fn PrivacySelector(setter: WriteSignal<Privacy>) -> impl IntoView {
|
|||
let p = privacy.get();
|
||||
let (to, cc) = p.address(&auth.username());
|
||||
view! {
|
||||
<PrivacyMarker privacy=p to=&to cc=&cc big=true />
|
||||
<PrivacyMarker privacy=p to=to cc=cc big=true />
|
||||
}
|
||||
}}
|
||||
</td>
|
||||
|
@ -149,16 +149,16 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
|||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
let privacy = use_context::<PrivacyControl>().expect("missing privacy context");
|
||||
let reply = use_context::<ReplyControls>().expect("missing reply controls");
|
||||
let (posting, set_posting) = create_signal(false);
|
||||
let (error, set_error) = create_signal(None);
|
||||
let (content, set_content) = create_signal("".to_string());
|
||||
let summary_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let (posting, set_posting) = signal(false);
|
||||
let (error, set_error) = signal(None);
|
||||
let (content, set_content) = signal("".to_string());
|
||||
let summary_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
|
||||
// TODO is this too abusive with resources? im even checking if TLD exists...
|
||||
// TODO debounce this!
|
||||
let mentions = create_local_resource(
|
||||
move || content.get(),
|
||||
move |c| async move {
|
||||
let mentions = LocalResource::new(
|
||||
move || async move {
|
||||
let c = content.get();
|
||||
let mut out = Vec::new();
|
||||
for word in c.split(' ') {
|
||||
if word.starts_with('@') {
|
||||
|
@ -203,13 +203,14 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
|||
{move ||
|
||||
mentions.get()
|
||||
.map(|x| x
|
||||
.take()
|
||||
.into_iter()
|
||||
.map(|u| match u {
|
||||
TextMatch::Mention { href, .. } => match cache::OBJECTS.get(&href) {
|
||||
Some(u) => view! { <span class="nowrap"><span class="emoji mr-s ml-s">"📨"</span><ActorStrip object=u /></span> }.into_view(),
|
||||
None => view! { <span class="nowrap"><span class="emoji mr-s ml-s">"📨"</span><a href={Uri::web(U::Actor, &href)}>{href}</a></span> }.into_view(),
|
||||
TextMatch::Mention { href: ref h, .. } => match cache::OBJECTS.get(h) {
|
||||
Some(u) => view! { <span class="nowrap"><span class="emoji mr-s ml-s">"📨"</span><ActorStrip object=u /></span> }.into_any(),
|
||||
None => view! { <span class="nowrap"><span class="emoji mr-s ml-s">"📨"</span><a href={Uri::web(U::Actor, h)}>{h.to_string()}</a></span> }.into_any(),
|
||||
},
|
||||
TextMatch::Hashtag { name } => view! { <code class="color">#{name}</code> }.into_view(),
|
||||
TextMatch::Hashtag { name } => view! { <code class="color">#{name}</code> }.into_any(),
|
||||
})
|
||||
.collect_view()
|
||||
)
|
||||
|
@ -233,10 +234,11 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
|||
return;
|
||||
}
|
||||
set_posting.set(true);
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
let summary = get_if_some(summary_ref);
|
||||
let (mut to_vec, cc_vec) = privacy.get().address(&auth.username());
|
||||
let mut mention_tags : Vec<serde_json::Value> = mentions.get()
|
||||
.map(|x| x.take())
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|x| match x {
|
||||
|
@ -272,7 +274,7 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
|||
}
|
||||
}
|
||||
}
|
||||
for mention in mentions.get().as_deref().unwrap_or(&[]) {
|
||||
for mention in mentions.get().map(|x| x.take()).as_deref().unwrap_or(&[]) {
|
||||
if let TextMatch::Mention { href, .. } = mention {
|
||||
to_vec.push(href.clone());
|
||||
}
|
||||
|
@ -306,21 +308,21 @@ pub fn PostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
|||
#[component]
|
||||
pub fn AdvancedPostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
||||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
let (posting, set_posting) = create_signal(false);
|
||||
let (error, set_error) = create_signal(None);
|
||||
let (value, set_value) = create_signal("Like".to_string());
|
||||
let (embedded, set_embedded) = create_signal(false);
|
||||
let sensitive_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let summary_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let content_ref: NodeRef<html::Textarea> = create_node_ref();
|
||||
let context_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let name_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let reply_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let to_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let object_id_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let bto_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let cc_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let bcc_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let (posting, set_posting) = signal(false);
|
||||
let (error, set_error) = signal(None);
|
||||
let (value, set_value) = signal("Like".to_string());
|
||||
let (embedded, set_embedded) = signal(false);
|
||||
let sensitive_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let summary_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let content_ref: NodeRef<leptos::html::Textarea> = NodeRef::new();
|
||||
let context_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let name_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let reply_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let to_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let object_id_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let bto_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let cc_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let bcc_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
view! {
|
||||
<div>
|
||||
|
||||
|
@ -385,7 +387,7 @@ pub fn AdvancedPostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
|||
|
||||
<button class="w-100" type="button" prop:disabled=posting on:click=move |_| {
|
||||
set_posting.set(true);
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
let content = content_ref.get().filter(|x| !x.value().is_empty()).map(|x| x.value());
|
||||
let summary = get_if_some(summary_ref);
|
||||
let name = get_if_some(name_ref);
|
||||
|
@ -435,13 +437,13 @@ pub fn AdvancedPostBox(advanced: WriteSignal<bool>) -> impl IntoView {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_if_some(node: NodeRef<html::Input>) -> Option<String> {
|
||||
fn get_if_some(node: NodeRef<leptos::html::Input>) -> Option<String> {
|
||||
node.get()
|
||||
.map(|x| x.value())
|
||||
.filter(|x| !x.is_empty())
|
||||
}
|
||||
|
||||
fn get_vec_if_some(node: NodeRef<html::Input>) -> Vec<String> {
|
||||
fn get_vec_if_some(node: NodeRef<leptos::html::Input>) -> Vec<String> {
|
||||
node.get()
|
||||
.map(|x| x.value())
|
||||
.filter(|x| !x.is_empty())
|
||||
|
@ -453,7 +455,7 @@ fn get_vec_if_some(node: NodeRef<html::Input>) -> Vec<String> {
|
|||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn get_checked(node: NodeRef<html::Input>) -> bool {
|
||||
fn get_checked(node: NodeRef<leptos::html::Input>) -> bool {
|
||||
node.get()
|
||||
.map(|x| x.checked())
|
||||
.unwrap_or_default()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
use crate::{prelude::*, FALLBACK_IMAGE_URL};
|
||||
|
||||
use apb::{Activity, ActivityMut, Actor, Base, Object, ObjectMut, Shortcuts};
|
||||
|
@ -25,7 +25,7 @@ pub fn ActorBanner(object: crate::Object) -> impl IntoView {
|
|||
match object.as_ref() {
|
||||
serde_json::Value::String(id) => view! {
|
||||
<div><b>?</b>" "<a class="clean hover" href={Uri::web(U::Actor, id)}>{Uri::pretty(id, 50)}</a></div>
|
||||
},
|
||||
}.into_any(),
|
||||
serde_json::Value::Object(_) => {
|
||||
let uid = object.id().unwrap_or_default().to_string();
|
||||
let uri = Uri::web(U::Actor, &uid);
|
||||
|
@ -45,11 +45,11 @@ pub fn ActorBanner(object: crate::Object) -> impl IntoView {
|
|||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
}.into_any()
|
||||
},
|
||||
_ => view! {
|
||||
<div><b>invalid actor</b></div>
|
||||
}
|
||||
}.into_any()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ pub fn FollowRequestButtons(activity_id: String, actor_id: String) -> impl IntoV
|
|||
on:click=move |_| {
|
||||
let activity_id = _activity_id.clone();
|
||||
let actor_id = _from_actor.clone();
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
send_follow_response(
|
||||
apb::ActivityType::Accept(apb::AcceptType::Accept),
|
||||
activity_id,
|
||||
|
@ -93,7 +93,7 @@ pub fn FollowRequestButtons(activity_id: String, actor_id: String) -> impl IntoV
|
|||
on:click=move |_| {
|
||||
let activity_id = activity_id.clone();
|
||||
let actor_id = from_actor.clone();
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
send_follow_response(
|
||||
apb::ActivityType::Reject(apb::RejectType::Reject),
|
||||
activity_id,
|
||||
|
|
|
@ -146,7 +146,7 @@ impl DashmapCache<String> {
|
|||
pub fn resolve(&self, user: &str, domain: &str) -> Option<String> {
|
||||
if let Some(x) = self.resource(user, domain) { return Some(x); }
|
||||
let (_self, user, domain) = (self.clone(), user.to_string(), domain.to_string());
|
||||
leptos::spawn_local(async move { _self.fetch(&user, &domain).await });
|
||||
leptos::task::spawn_local(async move { _self.fetch(&user, &domain).await });
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ impl DashmapCache<String> {
|
|||
}
|
||||
}
|
||||
|
||||
use leptos_router::Params; // TODO can i remove this?
|
||||
use leptos_router::params::Params; // TODO can i remove this?
|
||||
#[derive(Clone, leptos::Params, PartialEq)]
|
||||
pub struct IdParam {
|
||||
id: Option<String>,
|
||||
|
@ -201,7 +201,7 @@ impl Http {
|
|||
data: Option<&T>,
|
||||
auth: Auth,
|
||||
) -> reqwest::Result<reqwest::Response> {
|
||||
use leptos::SignalGetUntracked;
|
||||
use leptos::prelude::GetUntracked;
|
||||
|
||||
let mut req = reqwest::Client::new()
|
||||
.request(method, url);
|
||||
|
|
|
@ -10,5 +10,5 @@ fn main() {
|
|||
.without_time()
|
||||
.init();
|
||||
|
||||
leptos::mount_to_body(upub_web::App);
|
||||
leptos::mount::mount_to_body(upub_web::App);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
use crate::{prelude::*, URL_SENSITIVE};
|
||||
|
||||
use base64::prelude::*;
|
||||
|
@ -16,7 +16,7 @@ pub fn Attachment(
|
|||
sensitive: bool
|
||||
) -> impl IntoView {
|
||||
let config = use_context::<Signal<crate::Config>>().expect("missing config context");
|
||||
let (expand, set_expand) = create_signal(false);
|
||||
let (expand, set_expand) = signal(false);
|
||||
let href = object.url().id().ok().unwrap_or_default();
|
||||
let uncloaked = uncloak(href.split('/').last()).unwrap_or_default();
|
||||
let media_type = object.media_type()
|
||||
|
@ -53,7 +53,7 @@ pub fn Attachment(
|
|||
on:click=move |_| set_expand.set(!expand.get())
|
||||
/>
|
||||
</p>
|
||||
}.into_view(),
|
||||
}.into_any(),
|
||||
|
||||
"video" => {
|
||||
let _href = href.clone();
|
||||
|
@ -67,7 +67,7 @@ pub fn Attachment(
|
|||
<a href={href.clone()} target="_blank">video clip</a>
|
||||
</video>
|
||||
</div>
|
||||
}.into_view()
|
||||
}.into_any()
|
||||
},
|
||||
|
||||
"audio" =>
|
||||
|
@ -78,7 +78,7 @@ pub fn Attachment(
|
|||
<a href={href} target="_blank">audio clip</a>
|
||||
</audio>
|
||||
</p>
|
||||
}.into_view(),
|
||||
}.into_any(),
|
||||
|
||||
"link" | "text" =>
|
||||
view! {
|
||||
|
@ -87,7 +87,7 @@ pub fn Attachment(
|
|||
{Uri::pretty(&uncloaked, 50)}
|
||||
</a>
|
||||
</p>
|
||||
}.into_view(),
|
||||
}.into_any(),
|
||||
|
||||
_ =>
|
||||
view! {
|
||||
|
@ -99,7 +99,7 @@ pub fn Attachment(
|
|||
view! { <p class="tiny-text"><small>{name.to_string()}</small></p> }
|
||||
})}
|
||||
</p>
|
||||
}.into_view(),
|
||||
}.into_any(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use apb::Object;
|
||||
use leptos::*;
|
||||
use leptos_router::*;
|
||||
use leptos::prelude::*;
|
||||
use leptos_router::hooks::use_params;
|
||||
use crate::prelude::*;
|
||||
|
||||
|
||||
|
@ -17,7 +17,7 @@ pub fn ObjectContext() -> impl IntoView {
|
|||
.and_then(|x| x.context().id().ok())
|
||||
.unwrap_or_default()
|
||||
);
|
||||
create_effect(move |_| {
|
||||
Effect::new(move |_| {
|
||||
let tl_url = format!("{}/context/page", Uri::api(U::Object, &context_id.get(), false));
|
||||
if !feeds.context.next.get_untracked().starts_with(&tl_url) {
|
||||
feeds.context.reset(Some(tl_url));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use leptos::*;
|
||||
use leptos::{either::Either, prelude::*};
|
||||
use crate::{prelude::*, URL_SENSITIVE};
|
||||
|
||||
use apb::{ActivityMut, Base, Collection, CollectionMut, Object, ObjectMut, Shortcuts};
|
||||
|
@ -38,8 +38,9 @@ pub fn Object(object: crate::Object, #[prop(default = true)] controls: bool) ->
|
|||
.map(|x| {
|
||||
// TODO this isn't guaranteed to work every time...
|
||||
let name = x.split('/').last().unwrap_or_default().to_string();
|
||||
let uri = Uri::web(U::Actor, &x);
|
||||
view! {
|
||||
<a class="clean dim" href={Uri::web(U::Actor, &x)}>
|
||||
<a class="clean dim" href={uri}>
|
||||
<span class="border-button ml-s" title={x}>
|
||||
<code class="color mr-s">&</code>
|
||||
<small class="mr-s">
|
||||
|
@ -90,7 +91,7 @@ pub fn Object(object: crate::Object, #[prop(default = true)] controls: bool) ->
|
|||
Ok(apb::LinkType::Hashtag) => {
|
||||
let name = apb::Link::name(link.as_ref()).unwrap_or_default().replace('#', "");
|
||||
let href = Uri::web(U::Hashtag, &name);
|
||||
Some(view! {
|
||||
Some(Either::Left(view! {
|
||||
<a class="clean dim" href={href}>
|
||||
<span class="border-button ml-s" >
|
||||
<code class="color mr-s">#</code>
|
||||
|
@ -99,7 +100,7 @@ pub fn Object(object: crate::Object, #[prop(default = true)] controls: bool) ->
|
|||
</small>
|
||||
</span>
|
||||
</a>" "
|
||||
})
|
||||
}))
|
||||
},
|
||||
Ok(apb::LinkType::Mention) => {
|
||||
let uid = apb::Link::href(link.as_ref()).unwrap_or_default();
|
||||
|
@ -113,23 +114,24 @@ pub fn Object(object: crate::Object, #[prop(default = true)] controls: bool) ->
|
|||
)
|
||||
};
|
||||
let href = Uri::web(U::Actor, &uid);
|
||||
Some(view! {
|
||||
let title = format!("@{username}@{domain}");
|
||||
Some(Either::Right(view! {
|
||||
<a class="clean dim" href={href}>
|
||||
<span class="border-button ml-s" title={format!("@{username}@{domain}")} >
|
||||
<span class="border-button ml-s" title={title} >
|
||||
<code class="color mr-s">@</code>
|
||||
<small class="mr-s">
|
||||
{username}
|
||||
</small>
|
||||
</span>
|
||||
</a>" "
|
||||
})
|
||||
}))
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}).collect_view();
|
||||
|
||||
let post_image = object.image().inner().and_then(|x| x.url().id()).ok().map(|x| {
|
||||
let (expand, set_expand) = create_signal(false);
|
||||
let (expand, set_expand) = signal(false);
|
||||
view! {
|
||||
<img
|
||||
class="flex-pic box cursor"
|
||||
|
@ -158,7 +160,7 @@ pub fn Object(object: crate::Object, #[prop(default = true)] controls: bool) ->
|
|||
{post_inner}
|
||||
{quote_block}
|
||||
</article>
|
||||
}.into_view(),
|
||||
}.into_any(),
|
||||
// lemmy with Page, peertube with Video
|
||||
Ok(apb::ObjectType::Document(t)) => view! {
|
||||
<article class="float-container ml-1 mr-1" >
|
||||
|
@ -171,7 +173,7 @@ pub fn Object(object: crate::Object, #[prop(default = true)] controls: bool) ->
|
|||
{quote_block}
|
||||
</div>
|
||||
</article>
|
||||
}.into_view(),
|
||||
}.into_any(),
|
||||
// wordpress, ... ?
|
||||
Ok(apb::ObjectType::Article) => view! {
|
||||
<article>
|
||||
|
@ -180,15 +182,15 @@ pub fn Object(object: crate::Object, #[prop(default = true)] controls: bool) ->
|
|||
{post_inner}
|
||||
{quote_block}
|
||||
</article>
|
||||
}.into_view(),
|
||||
}.into_any(),
|
||||
// everything else
|
||||
Ok(t) => view! {
|
||||
<h3>{t.as_ref().to_string()}</h3>
|
||||
{post_inner}
|
||||
{quote_block}
|
||||
}.into_view(),
|
||||
}.into_any(),
|
||||
// object without type?
|
||||
Err(_) => view! { <code>missing object type</code> }.into_view(),
|
||||
Err(_) => view! { <code>missing object type</code> }.into_any(),
|
||||
};
|
||||
view! {
|
||||
<table class="align w-100 ml-s mr-s">
|
||||
|
@ -198,7 +200,7 @@ pub fn Object(object: crate::Object, #[prop(default = true)] controls: bool) ->
|
|||
{object.in_reply_to().id().ok().map(|reply| view! {
|
||||
<small><i><a class="clean" href={Uri::web(U::Object, &reply)} title={reply}>reply</a></i></small>
|
||||
})}
|
||||
<PrivacyMarker privacy=privacy to=&to cc=&cc />
|
||||
<PrivacyMarker privacy=privacy to=to cc=cc />
|
||||
<a class="clean hover ml-s" href={Uri::web(U::Object, &object.id().unwrap_or_default())}>
|
||||
<DateTime t=object.published().ok() />
|
||||
</a>
|
||||
|
@ -228,7 +230,7 @@ pub fn Object(object: crate::Object, #[prop(default = true)] controls: bool) ->
|
|||
pub fn Summary(summary: Option<String>, children: Children) -> impl IntoView {
|
||||
let config = use_context::<Signal<crate::Config>>().expect("missing config context");
|
||||
match summary.filter(|x| !x.is_empty()) {
|
||||
None => children().into_view(),
|
||||
None => children().into_any(),
|
||||
Some(summary) => view! {
|
||||
<details class="pa-s" prop:open=move || !config.get().collapse_content_warnings>
|
||||
<summary>
|
||||
|
@ -236,7 +238,7 @@ pub fn Summary(summary: Option<String>, children: Children) -> impl IntoView {
|
|||
</summary>
|
||||
{children()}
|
||||
</details>
|
||||
}.into_view(),
|
||||
}.into_any(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -249,8 +251,8 @@ pub fn LikeButton(
|
|||
#[prop(optional)]
|
||||
private: bool,
|
||||
) -> impl IntoView {
|
||||
let (count, set_count) = create_signal(n);
|
||||
let (clicked, set_clicked) = create_signal(!liked);
|
||||
let (count, set_count) = signal(n);
|
||||
let (clicked, set_clicked) = signal(!liked);
|
||||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
let privacy = use_context::<PrivacyControl>().expect("missing privacy context");
|
||||
view! {
|
||||
|
@ -274,7 +276,7 @@ pub fn LikeButton(
|
|||
.set_to(apb::Node::links(to))
|
||||
.set_cc(apb::Node::links(cc));
|
||||
let target = target.clone();
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
match Http::post(&auth.outbox(), &payload, auth).await {
|
||||
Ok(()) => {
|
||||
set_clicked.set(false);
|
||||
|
@ -327,8 +329,8 @@ pub fn ReplyButton(n: i32, target: String) -> impl IntoView {
|
|||
|
||||
#[component]
|
||||
pub fn RepostButton(n: i32, target: String, author: String) -> impl IntoView {
|
||||
let (count, set_count) = create_signal(n);
|
||||
let (clicked, set_clicked) = create_signal(true);
|
||||
let (count, set_count) = signal(n);
|
||||
let (clicked, set_clicked) = signal(true);
|
||||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
let privacy = use_context::<PrivacyControl>().expect("missing privacy context");
|
||||
view! {
|
||||
|
@ -348,7 +350,7 @@ pub fn RepostButton(n: i32, target: String, author: String) -> impl IntoView {
|
|||
.set_object(apb::Node::link(target.clone()))
|
||||
.set_to(apb::Node::links(to))
|
||||
.set_cc(apb::Node::links(cc));
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
match Http::post(&auth.outbox(), &payload, auth).await {
|
||||
Ok(()) => set_count.set(count.get() + 1),
|
||||
Err(e) => tracing::error!("failed sending like: {e}"),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use leptos::*;
|
||||
use leptos_router::*;
|
||||
use leptos::prelude::*;
|
||||
use leptos_router::hooks::use_params;
|
||||
use crate::prelude::*;
|
||||
|
||||
|
||||
|
@ -10,7 +10,7 @@ pub fn ObjectReplies() -> impl IntoView {
|
|||
let id = Signal::derive(move ||
|
||||
params.with(|p| p.as_ref().ok().and_then(|x| x.id.as_ref()).cloned()).unwrap_or_default()
|
||||
);
|
||||
create_effect(move |_| {
|
||||
Effect::new(move |_| {
|
||||
let tl_url = format!("{}/replies/page", Uri::api(U::Object, &id.get(), false));
|
||||
if !feeds.replies.next.get_untracked().starts_with(&tl_url) {
|
||||
feeds.replies.reset(Some(tl_url));
|
||||
|
@ -30,7 +30,7 @@ pub fn ObjectLikes() -> impl IntoView {
|
|||
let id = Signal::derive(move ||
|
||||
params.with(|p| p.as_ref().ok().and_then(|x| x.id.as_ref()).cloned()).unwrap_or_default()
|
||||
);
|
||||
create_effect(move |_| {
|
||||
Effect::new(move |_| {
|
||||
let tl_url = format!("{}/likes/page", Uri::api(U::Object, &id.get(), false));
|
||||
if !feeds.object_likes.next.get_untracked().starts_with(&tl_url) {
|
||||
feeds.object_likes.reset(Some(tl_url));
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use ev::MouseEvent;
|
||||
use leptos::*;
|
||||
use leptos_router::*;
|
||||
use leptos::{either::Either, ev::MouseEvent};
|
||||
use leptos::prelude::*;
|
||||
use leptos_router::components::Outlet;
|
||||
use leptos_router::hooks::use_params_map;
|
||||
use crate::{app::FeedRoute, prelude::*, Config};
|
||||
|
||||
use apb::Object;
|
||||
|
@ -12,44 +13,46 @@ pub fn ObjectView() -> impl IntoView {
|
|||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
let config = use_context::<Signal<Config>>().expect("missing config context");
|
||||
let relevant_tl = use_context::<Signal<Option<Timeline>>>().expect("missing relevant timeline context");
|
||||
let (loading, set_loading) = create_signal(false);
|
||||
let id = Signal::derive(move || params.get().get("id").cloned().unwrap_or_default());
|
||||
let object = create_local_resource(
|
||||
move || (id.get(), loading.get()),
|
||||
move |(oid, _loading)| async move {
|
||||
tracing::info!("rerunning fetcher");
|
||||
let obj = cache::OBJECTS.resolve(&oid, U::Object, auth).await?;
|
||||
let (loading, set_loading) = signal(false);
|
||||
let id = Signal::derive(move || params.get().get("id").unwrap_or_default());
|
||||
let object = LocalResource::new(
|
||||
move || {
|
||||
let (oid, _loading) = (id.get(), loading.get());
|
||||
async move {
|
||||
tracing::info!("rerunning fetcher");
|
||||
let obj = cache::OBJECTS.resolve(&oid, U::Object, auth).await?;
|
||||
|
||||
// TODO these two can be parallelized
|
||||
if let Ok(author) = obj.attributed_to().id() {
|
||||
cache::OBJECTS.resolve(&author, U::Actor, auth).await;
|
||||
// TODO these two can be parallelized
|
||||
if let Ok(author) = obj.attributed_to().id() {
|
||||
cache::OBJECTS.resolve(&author, U::Actor, auth).await;
|
||||
}
|
||||
if let Ok(quote) = obj.quote_url().id() {
|
||||
cache::OBJECTS.resolve("e, U::Object, auth).await;
|
||||
}
|
||||
|
||||
Some(obj)
|
||||
|
||||
// if let Ok(ctx) = obj.context().id() {
|
||||
// let tl_url = format!("{}/context/page", Uri::api(U::Object, ctx, false));
|
||||
// if !feeds.context.next.get_untracked().starts_with(&tl_url) {
|
||||
// feeds.context.reset(Some(tl_url));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
if let Ok(quote) = obj.quote_url().id() {
|
||||
cache::OBJECTS.resolve("e, U::Object, auth).await;
|
||||
}
|
||||
|
||||
Some(obj)
|
||||
|
||||
// if let Ok(ctx) = obj.context().id() {
|
||||
// let tl_url = format!("{}/context/page", Uri::api(U::Object, ctx, false));
|
||||
// if !feeds.context.next.get_untracked().starts_with(&tl_url) {
|
||||
// feeds.context.reset(Some(tl_url));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
);
|
||||
|
||||
view! {
|
||||
{move || match object.get() {
|
||||
None => view! { <Loader /> }.into_view(),
|
||||
{move || match object.get().map(|x| x.take()) {
|
||||
None => view! { <Loader /> }.into_any(),
|
||||
Some(None) => {
|
||||
let raw_id = params.get().get("id").cloned().unwrap_or_default();
|
||||
let raw_id = params.get().get("id").unwrap_or_default();
|
||||
let uid = uriproxy::uri(URL_BASE, uriproxy::UriClass::Object, &raw_id);
|
||||
view! { <p class="center"><code>loading failed</code><sup><small><a class="clean" href={uid} target="_blank">"↗"</a></small></sup></p> }.into_view()
|
||||
view! { <p class="center"><code>loading failed</code><sup><small><a class="clean" href={uid} target="_blank">"↗"</a></small></sup></p> }.into_any()
|
||||
},
|
||||
Some(Some(o)) => {
|
||||
tracing::info!("redrawing object");
|
||||
view! { <Object object=o.clone() /> }.into_view()
|
||||
view! { <Object object=o.clone() /> }.into_any()
|
||||
},
|
||||
}}
|
||||
|
||||
|
@ -59,13 +62,13 @@ pub fn ObjectView() -> impl IntoView {
|
|||
<span class:tab-active=move || matches!(matched_route.get(), FeedRoute::ObjectLikes)><a class="clean" href=move || format!("/web/objects/{}/likes", id.get())><span class="emoji ml-2">"⭐"</span><span class:hidden-on-mobile=move || !matches!(matched_route.get(), FeedRoute::ObjectLikes)>" likes"</span></a></span>
|
||||
{move || if auth.present() {
|
||||
if loading.get() {
|
||||
Some(view! {
|
||||
Some(Either::Left(view! {
|
||||
<span style="float: right">
|
||||
"fetching "<span class="dots"></span>
|
||||
</span>
|
||||
})
|
||||
}))
|
||||
} else {
|
||||
Some(view! {
|
||||
Some(Either::Right(view! {
|
||||
<span style="float: right">
|
||||
<a
|
||||
class="clean"
|
||||
|
@ -75,7 +78,7 @@ pub fn ObjectView() -> impl IntoView {
|
|||
<span class="emoji ml-2">"↺ "</span>"fetch"
|
||||
</a>
|
||||
</span>
|
||||
})
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
|
@ -96,7 +99,7 @@ fn fetch_cb(ev: MouseEvent, set_loading: WriteSignal<bool>, oid: String, auth: A
|
|||
let api = Uri::api(U::Object, &oid, false);
|
||||
ev.prevent_default();
|
||||
set_loading.set(true);
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
if let Err(e) = Http::fetch::<serde_json::Value>(&format!("{api}/replies?fetch=true"), auth).await {
|
||||
tracing::error!("failed crawling replies for {oid}: {e}");
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn AboutPage() -> impl IntoView {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use apb::{ActivityMut, DocumentMut, Object, ObjectMut};
|
||||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
use crate::{prelude::*, DEFAULT_COLOR};
|
||||
|
||||
#[component]
|
||||
|
@ -15,10 +15,10 @@ pub fn ConfigPage(setter: WriteSignal<crate::Config>) -> impl IntoView {
|
|||
set_color_rgb.set(parse_hex(&previous_color));
|
||||
set_color.set(previous_color);
|
||||
|
||||
let display_name_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let summary_ref: NodeRef<html::Textarea> = create_node_ref();
|
||||
let avatar_url_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let banner_url_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let display_name_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let summary_ref: NodeRef<leptos::html::Textarea> = NodeRef::new();
|
||||
let avatar_url_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let banner_url_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
|
||||
let myself = cache::OBJECTS.get(&auth.userid.get_untracked().unwrap_or_default());
|
||||
let (curr_display_name, curr_summary, curr_icon, curr_banner) = match myself.as_ref() {
|
||||
|
@ -187,7 +187,7 @@ pub fn ConfigPage(setter: WriteSignal<crate::Config>) -> impl IntoView {
|
|||
.set_published(Some(chrono::Utc::now()))
|
||||
));
|
||||
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
if let Err(e) = Http::post(&format!("{id}/outbox"), &payload, auth).await {
|
||||
tracing::error!("could not send update activity: {e}");
|
||||
}
|
||||
|
|
|
@ -1,41 +1,44 @@
|
|||
use leptos::*;
|
||||
use leptos_router::*;
|
||||
use leptos::prelude::*;
|
||||
use leptos_router::{hooks::{use_navigate, use_query_map}, NavigateOptions};
|
||||
use crate::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn DebugPage() -> impl IntoView {
|
||||
let query_params = use_query_map();
|
||||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
let (cached, set_cached) = create_signal(false);
|
||||
let (error, set_error) = create_signal(false);
|
||||
let (plain, set_plain) = create_signal(false);
|
||||
let (text, set_text) = create_signal("".to_string());
|
||||
let (cached, set_cached) = signal(false);
|
||||
let (error, set_error) = signal(false);
|
||||
let (plain, set_plain) = signal(false);
|
||||
let (text, set_text) = signal("".to_string());
|
||||
let navigate = use_navigate();
|
||||
|
||||
let cached_query = move || (
|
||||
query_params.with(|params| params.get("q").cloned().unwrap_or_default()),
|
||||
query_params.with(|params| params.get("q").unwrap_or_default()),
|
||||
cached.get(),
|
||||
);
|
||||
let object = create_local_resource(
|
||||
cached_query,
|
||||
move |(query, cached)| async move {
|
||||
set_text.set(query.clone());
|
||||
set_error.set(false);
|
||||
if query.is_empty() { return serde_json::Value::Null };
|
||||
if cached {
|
||||
match cache::OBJECTS.get(&query) {
|
||||
Some(x) => (*x).clone(),
|
||||
None => {
|
||||
set_error.set(true);
|
||||
serde_json::Value::Null
|
||||
},
|
||||
|
||||
let object = LocalResource::new(
|
||||
move || {
|
||||
let (query, cached) = cached_query();
|
||||
async move {
|
||||
set_text.set(query.clone());
|
||||
set_error.set(false);
|
||||
if query.is_empty() { return serde_json::Value::Null };
|
||||
if cached {
|
||||
match cache::OBJECTS.get(&query) {
|
||||
Some(x) => (*x).clone(),
|
||||
None => {
|
||||
set_error.set(true);
|
||||
serde_json::Value::Null
|
||||
},
|
||||
}
|
||||
} else {
|
||||
debug_fetch(&format!("{URL_BASE}/fetch?uri={query}"), auth, set_error).await
|
||||
}
|
||||
} else {
|
||||
debug_fetch(&format!("{URL_BASE}/fetch?uri={query}"), auth, set_error).await
|
||||
}
|
||||
}
|
||||
);
|
||||
let loading = object.loading();
|
||||
let loading = true; // object.loading(); // TODO no longer exists?
|
||||
|
||||
|
||||
view! {
|
||||
|
@ -69,12 +72,12 @@ pub fn DebugPage() -> impl IntoView {
|
|||
</form>
|
||||
</div>
|
||||
<pre class="ma-1" class:striped=error>
|
||||
{move || match object.get() {
|
||||
None => view! { <p class="center"><span class="dots"></span></p> }.into_view(),
|
||||
{move || match object.get().map(|x| x.take()) {
|
||||
None => view! { <p class="center"><span class="dots"></span></p> }.into_any(),
|
||||
Some(o) => if plain.get() {
|
||||
serde_json::to_string_pretty(&o).unwrap_or_else(|e| e.to_string()).into_view()
|
||||
serde_json::to_string_pretty(&o).unwrap_or_else(|e| e.to_string()).into_any()
|
||||
} else {
|
||||
view! { <DocumentNode obj=o /> }.into_view()
|
||||
view! { <DocumentNode obj=o /> }.into_any()
|
||||
},
|
||||
}}
|
||||
</pre>
|
||||
|
@ -91,7 +94,7 @@ pub fn DebugPage() -> impl IntoView {
|
|||
onclick={move ||
|
||||
format!(
|
||||
"javascript:navigator.clipboard.writeText(`{}`)",
|
||||
object.get().map(|x| serde_json::to_string(&x).unwrap_or_default()).unwrap_or_default()
|
||||
object.get().map(|x| serde_json::to_string(&x.take()).unwrap_or_default()).unwrap_or_default()
|
||||
)
|
||||
} >copy</a>
|
||||
</p>
|
||||
|
@ -132,14 +135,15 @@ fn DocumentNode(obj: serde_json::Value, #[prop(optional)] depth: usize) -> impl
|
|||
let prefix = " ".repeat(depth);
|
||||
let newline_replace = format!("\n{prefix} ");
|
||||
match obj {
|
||||
serde_json::Value::Null => view! { <b>null</b> }.into_view(),
|
||||
serde_json::Value::Bool(x) => view! { <b>{x}</b> }.into_view(),
|
||||
serde_json::Value::Number(n) => view! { <b>{n.to_string()}</b> }.into_view(),
|
||||
serde_json::Value::Null => view! { <b>null</b> }.into_any(),
|
||||
serde_json::Value::Bool(x) => view! { <b>{x}</b> }.into_any(),
|
||||
serde_json::Value::Number(n) => view! { <b>{n.to_string()}</b> }.into_any(),
|
||||
serde_json::Value::String(s) => {
|
||||
if s.starts_with("https://") || s.starts_with("http://") {
|
||||
let href = format!("/web/explore?q={s}");
|
||||
view! {
|
||||
<a href=format!("/web/explore?q={s}")>{s}</a>
|
||||
}.into_view()
|
||||
<a href=href>{s}</a>
|
||||
}.into_any()
|
||||
} else {
|
||||
let pretty_string = s
|
||||
.replace("<br/>", "<br/>\n")
|
||||
|
@ -147,11 +151,11 @@ fn DocumentNode(obj: serde_json::Value, #[prop(optional)] depth: usize) -> impl
|
|||
.replace('\n', &newline_replace);
|
||||
view! {
|
||||
"\""<span class="json-text"><i>{pretty_string}</i></span>"\""
|
||||
}.into_view()
|
||||
}.into_any()
|
||||
}
|
||||
},
|
||||
serde_json::Value::Array(arr) => if arr.is_empty() {
|
||||
view! { "[]" }.into_view()
|
||||
view! { "[]" }.into_any()
|
||||
} else {
|
||||
view! {
|
||||
"[\n"
|
||||
|
@ -159,10 +163,10 @@ fn DocumentNode(obj: serde_json::Value, #[prop(optional)] depth: usize) -> impl
|
|||
{prefix.clone()}" "<DocumentNode obj=x depth=depth+1 />"\n"
|
||||
}).collect_view()}
|
||||
{prefix.clone()}"]"
|
||||
}.into_view()
|
||||
}.into_any()
|
||||
},
|
||||
serde_json::Value::Object(map) => if map.is_empty() {
|
||||
view! { "{}" }.into_view()
|
||||
view! { "{}" }.into_any()
|
||||
} else {
|
||||
view! {
|
||||
"{\n"
|
||||
|
@ -174,7 +178,7 @@ fn DocumentNode(obj: serde_json::Value, #[prop(optional)] depth: usize) -> impl
|
|||
.collect_view()
|
||||
}
|
||||
{prefix.clone()}"}"
|
||||
}.into_view()
|
||||
}.into_any()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
use reqwest::Method;
|
||||
use crate::prelude::*;
|
||||
|
||||
|
@ -28,13 +28,13 @@ pub struct RegisterForm {
|
|||
#[component]
|
||||
pub fn RegisterPage() -> impl IntoView {
|
||||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
let username_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let password_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let display_name_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let summary_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let avatar_url_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let banner_url_ref: NodeRef<html::Input> = create_node_ref();
|
||||
let (error, set_error) = create_signal(None);
|
||||
let username_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let password_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let display_name_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let summary_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let avatar_url_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let banner_url_ref: NodeRef<leptos::html::Input> = NodeRef::new();
|
||||
let (error, set_error) = signal(None);
|
||||
view! {
|
||||
<div class="two-col">
|
||||
<div class="border ma-2 pa-1">
|
||||
|
@ -49,26 +49,20 @@ pub fn RegisterPage() -> impl IntoView {
|
|||
let banner_url = get_ref!(banner_url_ref);
|
||||
|
||||
if email.is_none() || password.is_none() {
|
||||
set_error.set(Some(
|
||||
view! { <blockquote>no credentials provided</blockquote> }
|
||||
));
|
||||
set_error.set(Some("no credentials provided".to_string()));
|
||||
return;
|
||||
}
|
||||
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
let payload = RegisterForm {
|
||||
username: email.unwrap_or_default(),
|
||||
password: password.unwrap_or_default(),
|
||||
display_name, summary, avatar_url, banner_url
|
||||
};
|
||||
match Http::request(Method::PUT, &format!("{URL_BASE}/auth"), Some(&payload), auth).await {
|
||||
Err(e) => set_error.set(Some(
|
||||
view! { <blockquote>{e.to_string()}</blockquote> }
|
||||
)),
|
||||
Err(e) => set_error.set(Some(e.to_string())),
|
||||
Ok(res) => match res.error_for_status() {
|
||||
Err(e) => set_error.set(Some(
|
||||
view! { <blockquote>{e.to_string()}</blockquote> }
|
||||
)),
|
||||
Err(e) => set_error.set(Some(e.to_string())),
|
||||
Ok(_) => {
|
||||
reset_ref!(username_ref);
|
||||
reset_ref!(password_ref);
|
||||
|
@ -76,9 +70,7 @@ pub fn RegisterPage() -> impl IntoView {
|
|||
reset_ref!(summary_ref);
|
||||
reset_ref!(avatar_url_ref);
|
||||
reset_ref!(banner_url_ref);
|
||||
set_error.set(Some(
|
||||
view! { <blockquote>registration successful! your user may need to be approved by an administrator before you can login</blockquote> }
|
||||
));
|
||||
set_error.set(Some("registration successful! your user may need to be approved by an administrator before you can login".to_string()));
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -123,7 +115,7 @@ pub fn RegisterPage() -> impl IntoView {
|
|||
<input class="w-100" type="submit" value="register" />
|
||||
</form>
|
||||
</div>
|
||||
<p>{error}</p>
|
||||
<p>{error.get().map(|msg| view! { <blockquote>{msg}</blockquote> })}</p>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use apb::Collection;
|
||||
use leptos::*;
|
||||
use leptos_router::*;
|
||||
use leptos::prelude::*;
|
||||
use leptos_router::hooks::use_query_map;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[component]
|
||||
|
@ -10,28 +10,28 @@ pub fn SearchPage() -> impl IntoView {
|
|||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
|
||||
let query = Signal::derive(||
|
||||
use_query_map().with(|x| x.get("q").cloned().unwrap_or_default())
|
||||
use_query_map().with(|x| x.get("q").unwrap_or_default())
|
||||
);
|
||||
|
||||
let user = create_local_resource(
|
||||
move || use_query_map().get().get("q").cloned().unwrap_or_default(),
|
||||
move |q| {
|
||||
let user = LocalResource::new(
|
||||
move || {
|
||||
let q = use_query_map().get().get("q").unwrap_or_default();
|
||||
let user_fetch = Uri::api(U::Actor, &q, true);
|
||||
async move { Some(Arc::new(Http::fetch::<serde_json::Value>(&user_fetch, auth).await.ok()?)) }
|
||||
}
|
||||
);
|
||||
|
||||
let object = create_local_resource(
|
||||
move || use_query_map().get().get("q").cloned().unwrap_or_default(),
|
||||
move |q| {
|
||||
let object = LocalResource::new(
|
||||
move || {
|
||||
let q = use_query_map().get().get("q").unwrap_or_default();
|
||||
let object_fetch = Uri::api(U::Object, &q, true);
|
||||
async move { Some(Arc::new(Http::fetch::<serde_json::Value>(&object_fetch, auth).await.ok()?)) }
|
||||
}
|
||||
);
|
||||
|
||||
let text_search = create_local_resource(
|
||||
move || use_query_map().get().get("q").cloned().unwrap_or_default(),
|
||||
move |q| {
|
||||
let text_search = LocalResource::new(
|
||||
move || {
|
||||
let q = use_query_map().get().get("q").unwrap_or_default();
|
||||
let search = format!("{URL_BASE}/search?q={q}");
|
||||
async move {
|
||||
let items = Http::fetch::<serde_json::Value>(&search, auth).await.ok()?;
|
||||
|
@ -59,10 +59,10 @@ pub fn SearchPage() -> impl IntoView {
|
|||
<code class="cw center color ml-s w-100">actor</code>
|
||||
</summary>
|
||||
<div class="pb-1">
|
||||
{move || match user.get() {
|
||||
None => view! { <p class="center"><small>searching...</small></p> },
|
||||
Some(None) => view! { <p class="center"><code>N/A</code></p> },
|
||||
Some(Some(u)) => view! { <p><ActorBanner object=u /></p> },
|
||||
{move || match user.get().map(|x| x.take()) {
|
||||
None => view! { <p class="center"><small>searching...</small></p> }.into_any(),
|
||||
Some(None) => view! { <p class="center"><code>N/A</code></p> }.into_any(),
|
||||
Some(Some(u)) => view! { <p><ActorBanner object=u /></p> }.into_any(),
|
||||
}}
|
||||
</div>
|
||||
</details>
|
||||
|
@ -74,10 +74,10 @@ pub fn SearchPage() -> impl IntoView {
|
|||
<code class="cw center color ml-s w-100">object</code>
|
||||
</summary>
|
||||
<div class="pb-1">
|
||||
{move || match object.get() {
|
||||
None => view! { <p class="center"><small>searching...</small></p> },
|
||||
Some(None) => view!{ <p class="center"><code>N/A</code></p> },
|
||||
Some(Some(o)) => view! { <p><Object object=o /></p> },
|
||||
{move || match object.get().map(|x| x.take()) {
|
||||
None => view! { <p class="center"><small>searching...</small></p> }.into_any(),
|
||||
Some(None) => view!{ <p class="center"><code>N/A</code></p> }.into_any(),
|
||||
Some(Some(o)) => view! { <p><Object object=o /></p> }.into_any(),
|
||||
}}
|
||||
</div>
|
||||
</details>
|
||||
|
@ -103,8 +103,8 @@ pub fn SearchPage() -> impl IntoView {
|
|||
<code class="cw center color ml-s w-100">full text</code>
|
||||
</summary>
|
||||
<div class="pb-1">
|
||||
{move || match text_search.get() {
|
||||
None => Some(view! { <p class="center"><small>searching...</small></p> }.into_view()),
|
||||
{move || match text_search.get().map(|x| x.take()) {
|
||||
None => Some(view! { <p class="center"><small>searching...</small></p> }.into_any()),
|
||||
Some(None) => None,
|
||||
Some(Some(items)) => Some(view! {
|
||||
// TODO ughhh too many clones
|
||||
|
@ -113,10 +113,10 @@ pub fn SearchPage() -> impl IntoView {
|
|||
key=|id| id.clone()
|
||||
children=move |item| {
|
||||
cache::OBJECTS.get(&item)
|
||||
.map(|x| view! { <Item item=x always=true /> }.into_view())
|
||||
.map(|x| view! { <Item item=x always=true /> }.into_any())
|
||||
}
|
||||
/ >
|
||||
}.into_view())
|
||||
}.into_any())
|
||||
}}
|
||||
</div>
|
||||
</details>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use leptos::*;
|
||||
use leptos_router::use_params;
|
||||
use leptos::{either::Either, prelude::*};
|
||||
use leptos_router::hooks::use_params;
|
||||
use crate::prelude::*;
|
||||
use super::Timeline;
|
||||
|
||||
|
@ -12,7 +12,7 @@ pub fn Feed(
|
|||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
let config = use_context::<Signal<crate::Config>>().expect("missing config context");
|
||||
if let Some(auto_scroll) = use_context::<Signal<bool>>() {
|
||||
let _ = leptos::watch(
|
||||
let _ = Effect::watch(
|
||||
move || auto_scroll.get(),
|
||||
move |at_end, _, _| if *at_end { tl.spawn_more(auth, config) },
|
||||
true,
|
||||
|
@ -26,13 +26,13 @@ pub fn Feed(
|
|||
let:id
|
||||
>
|
||||
{match cache::OBJECTS.get(&id) {
|
||||
Some(i) => view! {
|
||||
Some(i) => Either::Left(view! {
|
||||
<Item item=i sep=true always=ignore_filters />
|
||||
}.into_view(),
|
||||
None => view! {
|
||||
}),
|
||||
None => Either::Right(view! {
|
||||
<p><code>{id}</code>" "[<a href={uri}>go</a>]</p>
|
||||
<hr />
|
||||
}.into_view(),
|
||||
}),
|
||||
}}
|
||||
</For>
|
||||
</div>
|
||||
|
@ -43,7 +43,7 @@ pub fn Feed(
|
|||
#[component]
|
||||
pub fn HashtagFeed(tl: Timeline) -> impl IntoView {
|
||||
let params = use_params::<IdParam>();
|
||||
create_effect(move |_| {
|
||||
Effect::new(move |_| {
|
||||
let current_tag = tl.next.get_untracked()
|
||||
.split('/')
|
||||
.last()
|
||||
|
|
|
@ -4,7 +4,7 @@ pub mod thread;
|
|||
use std::{collections::BTreeSet, pin::Pin, sync::Arc};
|
||||
|
||||
use apb::{Activity, ActivityMut, Base, Object};
|
||||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
@ -17,10 +17,10 @@ pub struct Timeline {
|
|||
|
||||
impl Timeline {
|
||||
pub fn new(url: String) -> Self {
|
||||
let feed = create_rw_signal(vec![]);
|
||||
let next = create_rw_signal(url);
|
||||
let over = create_rw_signal(false);
|
||||
let loading = create_rw_signal(false);
|
||||
let feed = RwSignal::new(vec![]);
|
||||
let next = RwSignal::new(url);
|
||||
let over = RwSignal::new(false);
|
||||
let loading = RwSignal::new(false);
|
||||
Timeline { feed, next, over, loading }
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ impl Timeline {
|
|||
|
||||
pub fn spawn_more(&self, auth: Auth, config: Signal<crate::Config>) {
|
||||
let _self = *self;
|
||||
spawn_local(async move {
|
||||
leptos::task::spawn_local(async move {
|
||||
_self.more(auth, config).await
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use apb::{Activity, Base, Object};
|
||||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
use crate::prelude::*;
|
||||
use super::Timeline;
|
||||
|
||||
|
@ -8,7 +8,7 @@ pub fn Thread(tl: Timeline, root: String) -> impl IntoView {
|
|||
let auth = use_context::<Auth>().expect("missing auth context");
|
||||
let config = use_context::<Signal<crate::Config>>().expect("missing config context");
|
||||
if let Some(auto_scroll) = use_context::<Signal<bool>>() {
|
||||
let _ = leptos::watch(
|
||||
let _ = Effect::watch(
|
||||
move || auto_scroll.get(),
|
||||
move |new, old, _| {
|
||||
match old {
|
||||
|
@ -72,5 +72,5 @@ fn FeedRecursive(tl: Timeline, root: String) -> impl IntoView {
|
|||
</div>
|
||||
}
|
||||
/ >
|
||||
}
|
||||
}.into_any()
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue