From 872ebc7cf05e6a16f57db9a2c2836528bdfcec92 Mon Sep 17 00:00:00 2001 From: rupansh Date: Fri, 19 Apr 2024 15:12:09 +0530 Subject: [PATCH 1/9] fix(event_streaming): fix compilation --- src/utils/event_streaming/events.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/event_streaming/events.rs b/src/utils/event_streaming/events.rs index dc0b061c..8f5e1634 100644 --- a/src/utils/event_streaming/events.rs +++ b/src/utils/event_streaming/events.rs @@ -11,6 +11,7 @@ use crate::canister::individual_user_template::UserProfileDetailsForFrontend; use crate::component::auth_providers::ProviderKind; use crate::state::canisters::Canisters; use crate::state::history::HistoryCtx; +#[cfg(feature = "ga4")] use crate::utils::event_streaming::{send_event, send_event_warehouse, send_user_id}; use crate::utils::profile::ProfileDetails; use crate::{ From 0ca4fab92ade89f83f641bec91c49ec0845b83be Mon Sep 17 00:00:00 2001 From: rupansh Date: Fri, 19 Apr 2024 18:16:37 +0530 Subject: [PATCH 2/9] chore(CI): switch back to mainline nightly --- .github/workflows/build-check.yml | 2 +- rust-toolchain.toml | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-check.yml b/.github/workflows/build-check.yml index 66e0055c..e09be7c1 100644 --- a/.github/workflows/build-check.yml +++ b/.github/workflows/build-check.yml @@ -28,7 +28,7 @@ jobs: - name: Rust Setup uses: dtolnay/rust-toolchain@master with: - toolchain: "nightly-2024-04-15" + toolchain: "nightly" targets: "x86_64-unknown-linux-musl,wasm32-unknown-unknown" components: "clippy,rustfmt" diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 7ea080de..5d56faf9 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,2 @@ [toolchain] -channel = "nightly-2024-04-15" -components = ["rust-src"] -targets = ["wasm32-unknown-unknown"] +channel = "nightly" From f1661df4331b8fc26cf29d17cdb4da15ceeff132 Mon Sep 17 00:00:00 2001 From: rupansh Date: Fri, 19 Apr 2024 18:32:54 +0530 Subject: [PATCH 3/9] refactor!: refactor resource management for authentication --- Cargo.lock | 486 ++++++++++++++-------------- Cargo.toml | 4 - src/app.rs | 6 +- src/component/auth_provider.rs | 31 -- src/component/auth_providers/mod.rs | 5 +- src/component/base_route.rs | 83 +++-- src/component/connect.rs | 7 +- src/component/logout.rs | 14 +- src/component/mod.rs | 1 - src/page/menu.rs | 50 +-- src/page/post_view/mod.rs | 123 +++---- src/page/post_view/overlay.rs | 73 +---- src/page/post_view/video_iter.rs | 25 +- src/page/refer_earn/history.rs | 27 +- src/page/refer_earn/mod.rs | 36 +-- src/page/root.rs | 2 +- src/page/upload/mod.rs | 28 +- src/page/upload/video_upload.rs | 97 +++--- src/page/wallet/mod.rs | 77 ++--- src/page/wallet/transactions.rs | 19 +- src/state/auth/mod.rs | 21 +- src/state/canisters.rs | 78 +++-- src/utils/event_streaming/events.rs | 220 +++++-------- src/utils/mod.rs | 3 +- 24 files changed, 635 insertions(+), 881 deletions(-) delete mode 100644 src/component/auth_provider.rs diff --git a/Cargo.lock b/Cargo.lock index 9d13cc4e..23d03310 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,9 +76,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -97,9 +97,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "arbitrary" @@ -136,7 +136,7 @@ checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -158,18 +158,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -183,7 +183,7 @@ dependencies = [ "manyhow", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -199,7 +199,7 @@ dependencies = [ "proc-macro2", "quote", "quote-use", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -250,7 +250,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", "itoa", "matchit", @@ -264,7 +264,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.0", + "sync_wrapper 1.0.1", "tokio", "tower", "tower-layer", @@ -339,10 +339,10 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -524,9 +524,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" @@ -593,9 +593,9 @@ checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" [[package]] name = "candid" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965e86b1bd1c0c26df70cf0c92ae16c56204ab402eb915c26a541cf949d841cf" +checksum = "818394610ed32d9e4c81025f97c8580698b69542527efde18514cf9ad1f8f5f0" dependencies = [ "anyhow", "binread", @@ -623,7 +623,7 @@ dependencies = [ "lazy_static", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -647,9 +647,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.90" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" [[package]] name = "cfg-if" @@ -659,9 +659,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -669,7 +669,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -696,7 +696,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", - "half 2.4.0", + "half 2.4.1", ] [[package]] @@ -743,9 +743,9 @@ dependencies = [ [[package]] name = "combine" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "futures-core", @@ -938,7 +938,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -999,7 +999,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -1021,7 +1021,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core 0.20.8", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -1052,14 +1052,14 @@ dependencies = [ "darling 0.20.8", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "pem-rfc7468", @@ -1084,7 +1084,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -1202,9 +1202,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] name = "elliptic-curve" @@ -1241,9 +1241,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -1257,7 +1257,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -1400,7 +1400,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -1446,9 +1446,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "js-sys", @@ -1484,11 +1484,11 @@ dependencies = [ "gloo-events", "gloo-file", "gloo-history", - "gloo-net 0.5.0", + "gloo-net", "gloo-render", "gloo-storage", "gloo-timers", - "gloo-utils 0.2.0", + "gloo-utils", "gloo-worker", ] @@ -1498,7 +1498,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a17868f56b4a24f677b17c8cb69958385102fa879418052d60b50bc1727e261" dependencies = [ - "gloo-utils 0.2.0", + "gloo-utils", "js-sys", "serde", "wasm-bindgen", @@ -1546,7 +1546,7 @@ checksum = "903f432be5ba34427eac5e16048ef65604a82061fe93789f2212afc73d8617d6" dependencies = [ "getrandom", "gloo-events", - "gloo-utils 0.2.0", + "gloo-utils", "serde", "serde-wasm-bindgen", "serde_urlencoded", @@ -1555,26 +1555,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "gloo-net" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9902a044653b26b99f7e3693a42f171312d9be8b26b5697bd1e43ad1f8a35e10" -dependencies = [ - "futures-channel", - "futures-core", - "futures-sink", - "gloo-utils 0.1.7", - "js-sys", - "pin-project", - "serde", - "serde_json", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "gloo-net" version = "0.5.0" @@ -1584,7 +1564,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-sink", - "gloo-utils 0.2.0", + "gloo-utils", "http 0.2.12", "js-sys", "pin-project", @@ -1612,7 +1592,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a" dependencies = [ - "gloo-utils 0.2.0", + "gloo-utils", "js-sys", "serde", "serde_json", @@ -1633,19 +1613,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "gloo-utils" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" -dependencies = [ - "js-sys", - "serde", - "serde_json", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "gloo-utils" version = "0.2.0" @@ -1667,7 +1634,7 @@ checksum = "085f262d7604911c8150162529cefab3782e91adb20202e8658f7275d2aefe5d" dependencies = [ "bincode", "futures", - "gloo-utils 0.2.0", + "gloo-utils", "gloo-worker-macros", "js-sys", "pinned", @@ -1687,7 +1654,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -1696,7 +1663,7 @@ version = "0.1.0" source = "git+https://github.com/go-bazzinga/gob-cloudflare?rev=c847ba87ecc73a33520b24bd62503420d7e23e3e#c847ba87ecc73a33520b24bd62503420d7e23e3e" dependencies = [ "bytes", - "reqwest 0.12.2", + "reqwest 0.12.3", "serde", "serde_json", "thiserror", @@ -1727,9 +1694,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -1746,9 +1713,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" +checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" dependencies = [ "bytes", "fnv", @@ -1771,9 +1738,9 @@ checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" [[package]] name = "half" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ "cfg-if", "crunchy", @@ -1807,6 +1774,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -1856,7 +1829,7 @@ dependencies = [ "enum_dispatch", "futures", "gloo", - "gloo-utils 0.2.0", + "gloo-utils", "gob-cloudflare", "hex", "http 1.1.0", @@ -1877,7 +1850,7 @@ dependencies = [ "rand_chacha", "redb", "redis", - "reqwest 0.12.2", + "reqwest 0.12.3", "serde", "serde-wasm-bindgen", "serde_bytes", @@ -1991,7 +1964,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.3.25", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -2007,14 +1980,14 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.3", + "h2 0.4.4", "http 1.1.0", "http-body 1.0.0", "httparse", @@ -2048,7 +2021,7 @@ checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", "rustls 0.22.3", "rustls-pki-types", @@ -2077,7 +2050,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", "native-tls", "tokio", @@ -2096,7 +2069,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.2.0", + "hyper 1.3.1", "pin-project-lite", "socket2", "tokio", @@ -2604,9 +2577,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "leptos" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd996d00a55895327b2eb5d2d7d440ab756b4a9fe43ec78411c74199306808c" +checksum = "20f79fe71c41f5a0506c273f6698a1971bb994ef52a88aeaf4eccb159fcd1e11" dependencies = [ "cfg-if", "leptos_config", @@ -2624,9 +2597,9 @@ dependencies = [ [[package]] name = "leptos-use" -version = "0.10.5" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da9de6ad687891009b32026dc424a1b596f765bab5e9ec1067d10c7f081f44c" +checksum = "9d6be6f1d02c3277f03a55c4a05ee5a069ea75ec5323c4415f6efed69cb5acea" dependencies = [ "async-trait", "cfg-if", @@ -2634,7 +2607,7 @@ dependencies = [ "default-struct-builder", "futures-util", "gloo-timers", - "gloo-utils 0.2.0", + "gloo-utils", "http 1.1.0", "js-sys", "lazy_static", @@ -2651,9 +2624,9 @@ dependencies = [ [[package]] name = "leptos_axum" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2276bb8b97638d67c7b704a1351ef88ff3b41a286fc46d48aa59da9f1916bd3c" +checksum = "590b945e92fe5790820f348f82c0937ea9b58ba5976459377134946eb8ed449b" dependencies = [ "axum 0.7.5", "cfg-if", @@ -2675,9 +2648,9 @@ dependencies = [ [[package]] name = "leptos_config" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc190458a62433fb1d31f65f1afe7f1044650c667cdf9166956b48907ac821bd" +checksum = "a3caa62f62e8e575051305ed6ac5648dc695f202c7220a98aca21cf4e9a978cf" dependencies = [ "config", "regex", @@ -2688,9 +2661,9 @@ dependencies = [ [[package]] name = "leptos_dom" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ffd84c459d7c517fb8c9bfff704e819f3e6a2f5baf574d8636cb23840323d0a" +checksum = "96e84abb02efd711f0842ff3e444292bfa9963811c37e7be3980a052628ed63b" dependencies = [ "async-recursion", "cfg-if", @@ -2718,9 +2691,9 @@ dependencies = [ [[package]] name = "leptos_hot_reload" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2f157fc6d4a356e3dd2734c6a65cba9e5eadb7c7cfd979c0adb752d293dba1" +checksum = "c4ee917deba2522a7f22ca826df84a8800d66ac918e58b489875e1f4fb8bc6b8" dependencies = [ "anyhow", "camino", @@ -2730,7 +2703,7 @@ dependencies = [ "quote", "rstml", "serde", - "syn 2.0.57", + "syn 2.0.60", "walkdir", ] @@ -2751,9 +2724,9 @@ dependencies = [ [[package]] name = "leptos_integration_utils" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff00799857159434d31b6bd1898e21c63f69f39289621da5a554fcab1c3e7300" +checksum = "a1f504afe3e2ac30ca15ba9b74d27243e8919e93d1f78bad32e5e8ec23eaca4b" dependencies = [ "futures", "leptos", @@ -2765,9 +2738,9 @@ dependencies = [ [[package]] name = "leptos_macro" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69a20596eb0afe56296d3187c8f46680bb8ea1df58b6566e2588c9c53c549581" +checksum = "31197c2c624c405bec5f1dc8dd5d903a6030d1f0b8e362a01a3a215fcbad5051" dependencies = [ "attribute-derive", "cfg-if", @@ -2781,16 +2754,16 @@ dependencies = [ "quote", "rstml", "server_fn_macro", - "syn 2.0.57", + "syn 2.0.60", "tracing", "uuid", ] [[package]] name = "leptos_meta" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b9dac59a2f88f5235dbe17cfa81b738a6f47238a64e4f23b921f1a90a9bf11" +checksum = "a00900e82a4ca892828db93fce1d4c009480ff3959406e6965aa937c8bab7403" dependencies = [ "cfg-if", "indexmap 2.2.6", @@ -2802,9 +2775,9 @@ dependencies = [ [[package]] name = "leptos_reactive" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9152b4b9af932896ae69d08b8ab7108513b9cdddf8e2922d5c234dab7ac9af" +checksum = "057de706568ce8f1f223ae69f796c10ad0563ad270d10717e70c2b2d22eefa60" dependencies = [ "base64 0.22.0", "cfg-if", @@ -2829,13 +2802,13 @@ dependencies = [ [[package]] name = "leptos_router" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9460a5dc184fa05d8eb635b687ad3220d02d2d23d6f49c3bf146aa71e427f423" +checksum = "d7fcc2a95a20c8f41adb39770e65c48ffe33cd9503b83669c54edd9b33ba8aa8" dependencies = [ "cached 0.45.1", "cfg-if", - "gloo-net 0.2.6", + "gloo-net", "itertools 0.12.1", "js-sys", "lazy_static", @@ -2861,9 +2834,9 @@ dependencies = [ [[package]] name = "leptos_server" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bed1e82ded6bfbfd61ad2f77066a789b94dc889513a47223e3c6a3e8ca2b109f" +checksum = "8f197d9cbf7db3a09a5d6c561ad0547ad6bf4326bc6bc454171d5f6ee94f745a" dependencies = [ "inventory", "lazy_static", @@ -2889,13 +2862,12 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.5.0", "libc", - "redox_syscall", ] [[package]] @@ -2950,7 +2922,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax 0.6.29", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -2980,7 +2952,7 @@ dependencies = [ "manyhow-macros", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -3286,7 +3258,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -3297,9 +3269,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.101" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -3457,7 +3429,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -3559,12 +3531,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +checksum = "5ac2cf0f2e4f42b49f5ffd07dae8d746508ef7526c13940e5f524012ae6c6550" dependencies = [ "proc-macro2", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -3622,9 +3594,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -3637,7 +3609,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", "version_check", "yansi", ] @@ -3659,7 +3631,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80b776a1b2dc779f5ee0641f8ade0125bc1298dd41a9a0c16d8bd57b42d222b1" dependencies = [ "bytes", - "heck", + "heck 0.5.0", "itertools 0.12.1", "log", "multimap", @@ -3669,7 +3641,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.57", + "syn 2.0.60", "tempfile", ] @@ -3683,7 +3655,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -3706,9 +3678,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -3733,7 +3705,7 @@ dependencies = [ "proc-macro-utils", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -3783,9 +3755,9 @@ dependencies = [ [[package]] name = "redis" -version = "0.25.2" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d64e978fd98a0e6b105d066ba4889a7301fca65aeac850a877d8797343feeb" +checksum = "6472825949c09872e8f2c50bde59fcefc17748b6be5c90fd67cd8b4daca73bfd" dependencies = [ "ahash", "arc-swap", @@ -3799,7 +3771,7 @@ dependencies = [ "pin-project-lite", "rustls 0.22.3", "rustls-native-certs", - "rustls-pemfile 2.1.1", + "rustls-pemfile 2.1.2", "rustls-pki-types", "ryu", "socket2", @@ -3821,9 +3793,9 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", "libredox", @@ -3876,7 +3848,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.3.25", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", @@ -3905,24 +3877,24 @@ dependencies = [ "wasm-streams", "web-sys", "webpki-roots 0.25.4", - "winreg", + "winreg 0.50.0", ] [[package]] name = "reqwest" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d66674f2b6fb864665eea7a3c1ac4e3dfacd2fda83cf6f935a612e01b0e3338" +checksum = "3e6cc1e89e689536eb5aeede61520e874df5a4707df811cd5da4aa5fbb2aae19" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "bytes", "futures-core", "futures-util", - "h2 0.4.3", + "h2 0.4.4", "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-rustls 0.26.0", "hyper-tls", "hyper-util", @@ -3936,7 +3908,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls 0.22.3", - "rustls-pemfile 1.0.4", + "rustls-pemfile 2.1.2", "rustls-pki-types", "serde", "serde_json", @@ -3951,7 +3923,7 @@ dependencies = [ "wasm-bindgen-futures", "web-sys", "webpki-roots 0.26.1", - "winreg", + "winreg 0.52.0", ] [[package]] @@ -4008,7 +3980,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.57", + "syn 2.0.60", "syn_derive", "thiserror", ] @@ -4080,7 +4052,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.1", + "rustls-pemfile 2.1.2", "rustls-pki-types", "schannel", "security-framework", @@ -4097,11 +4069,11 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "rustls-pki-types", ] @@ -4134,9 +4106,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" [[package]] name = "ryu" @@ -4239,9 +4211,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] @@ -4288,20 +4260,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -4340,13 +4312,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -4406,7 +4378,7 @@ dependencies = [ "darling 0.20.8", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -4421,9 +4393,9 @@ dependencies = [ [[package]] name = "server_fn" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15a46a2ffdecb81430ecfb995989218a18b6e94c1ead50cb806b5927c986a8ce" +checksum = "536a5b959673643ee01e59ae41bf01425482c8070dee95d7061ee2d45296b59c" dependencies = [ "axum 0.7.5", "bytes", @@ -4431,10 +4403,10 @@ dependencies = [ "const_format", "dashmap", "futures", - "gloo-net 0.5.0", + "gloo-net", "http 1.1.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "inventory", "js-sys", "once_cell", @@ -4456,26 +4428,26 @@ dependencies = [ [[package]] name = "server_fn_macro" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a248dedb786315ba738f3618dbd65ba0c1b22ebea76f15a3e96a04643a73f" +checksum = "064dd9b256e78bf2886774f265cc34d2aefdd05b430c58c78a69eceef21b5e60" dependencies = [ "const_format", "convert_case", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", "xxhash-rust", ] [[package]] name = "server_fn_macro_default" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "060af1def72353a779fcc184c53e1965d3055a38b9e827f2259b2bff2d9c371e" +checksum = "f4ad11700cbccdbd313703916eb8c97301ee423c4a06e5421b77956fdcb36a9f" dependencies = [ "server_fn_macro", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -4656,9 +4628,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.57" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -4674,7 +4646,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -4685,9 +4657,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384595c11a4e2969895cad5a8c4029115f5ab956a9e5ef4de79d11a426e5f20c" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" [[package]] name = "system-configuration" @@ -4759,14 +4731,14 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -4788,9 +4760,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -4856,7 +4828,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -4937,7 +4909,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.9", + "toml_edit 0.22.11", ] [[package]] @@ -4962,15 +4934,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.9" +version = "0.22.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +checksum = "fb686a972ccef8537b39eead3968b0e8616cb5040dbb9bba93007c8e07c9215f" dependencies = [ "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.5", + "winnow 0.6.6", ] [[package]] @@ -4984,7 +4956,7 @@ dependencies = [ "axum 0.6.20", "base64 0.21.7", "bytes", - "h2 0.3.25", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", @@ -4992,7 +4964,7 @@ dependencies = [ "percent-encoding", "pin-project", "prost", - "rustls-pemfile 2.1.1", + "rustls-pemfile 2.1.2", "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", @@ -5014,7 +4986,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -5094,7 +5066,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -5120,22 +5092,22 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typed-builder" -version = "0.18.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444d8748011b93cb168770e8092458cb0f8854f931ff82fdf6ddfbd72a9c933e" +checksum = "77739c880e00693faef3d65ea3aad725f196da38b22fdc7ea6ded6e1ce4d3add" dependencies = [ "typed-builder-macro", ] [[package]] name = "typed-builder-macro" -version = "0.18.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "563b3b88238ec95680aef36bdece66896eaa7ce3c0f1b4f39d38fb2435261352" +checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -5299,7 +5271,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", "wasm-bindgen-shared", ] @@ -5333,7 +5305,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5429,7 +5401,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -5447,7 +5419,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -5467,17 +5439,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -5488,9 +5461,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -5500,9 +5473,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -5512,9 +5485,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -5524,9 +5503,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -5536,9 +5515,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -5548,9 +5527,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -5560,9 +5539,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" @@ -5575,9 +5554,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] @@ -5592,6 +5571,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "xxhash-rust" version = "0.8.10" @@ -5622,7 +5611,7 @@ version = "0.1.0" source = "git+https://github.com/go-bazzinga/yral-metadata?rev=c2c5d254ac273681a66966d62b6f01785679a1be#c2c5d254ac273681a66966d62b6f01785679a1be" dependencies = [ "ic-agent", - "reqwest 0.12.2", + "reqwest 0.12.3", "thiserror", "yral-identity", "yral-metadata-types", @@ -5656,7 +5645,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.57", + "syn 2.0.60", ] [[package]] @@ -5664,8 +5653,3 @@ name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" - -[[patch.unused]] -name = "reqwest" -version = "0.11.25" -source = "git+https://github.com/seanmonstar/reqwest.git?rev=e3192638518d577759dd89da489175b8f992b12f#e3192638518d577759dd89da489175b8f992b12f" diff --git a/Cargo.toml b/Cargo.toml index a6a86fc9..31956df9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -164,11 +164,7 @@ release-lib = [ ] mock-wallet-history = ["dep:rand_chacha"] -[patch.crates-io] -# release with hyper v1 is not out yet - -reqwest = { git = "https://github.com/seanmonstar/reqwest.git", rev = "e3192638518d577759dd89da489175b8f992b12f" } [profile.wasm-release] inherits = "release" opt-level = 'z' diff --git a/src/app.rs b/src/app.rs index a907d73b..85374d4f 100644 --- a/src/app.rs +++ b/src/app.rs @@ -14,7 +14,7 @@ use crate::{ upload::UploadPostPage, wallet::{transactions::Transactions, Wallet}, }, - state::{auth::AuthState, canisters::Canisters, history::HistoryCtx}, + state::{canisters::Canisters, history::HistoryCtx}, utils::event_streaming::EventHistory, }; use leptos::*; @@ -62,8 +62,6 @@ pub fn App() -> impl IntoView { provide_meta_context(); provide_context(Canisters::default()); provide_context(PostViewCtx::default()); - let auth_state = AuthState::default(); - provide_context(auth_state.clone()); // History Tracking let history_ctx = HistoryCtx::default(); @@ -114,7 +112,7 @@ pub fn App() -> impl IntoView { // auth redirect routes exist outside main context - + diff --git a/src/component/auth_provider.rs b/src/component/auth_provider.rs deleted file mode 100644 index f85f583a..00000000 --- a/src/component/auth_provider.rs +++ /dev/null @@ -1,31 +0,0 @@ -use crate::{ - auth::{extract_or_generate_identity, DelegatedIdentityWire}, - state::auth::auth_state, - try_or_redirect, -}; -use leptos::*; - -#[component] -pub fn AuthFrame(auth: RwSignal>) -> impl IntoView { - let auth_res = create_local_resource( - || (), - move |_| async move { - let identity = try_or_redirect!(extract_or_generate_identity().await); - auth.set(Some(identity)); - }, - ); - - view! { {move || auth_res.get().map(|_| ())} } -} - -#[component] -pub fn AuthProvider() -> impl IntoView { - let auth = auth_state().identity; - view! { - - } -} diff --git a/src/component/auth_providers/mod.rs b/src/component/auth_providers/mod.rs index 3981a607..26d62a81 100644 --- a/src/component/auth_providers/mod.rs +++ b/src/component/auth_providers/mod.rs @@ -138,7 +138,8 @@ pub fn LoginProviders(show_modal: RwSignal, lock_closing: RwSignal) let referrer = referrer_store.get_untracked(); // This is some redundant work, but saves us 100+ lines of resource handling - let canisters = do_canister_auth(Some(identity.clone())).await?.unwrap(); + let canisters: Canisters = + do_canister_auth(identity.clone()).await?.try_into()?; if let Err(e) = handle_user_login(canisters.clone(), referrer).await { log::warn!("failed to handle user login, err {e}. skipping"); @@ -159,7 +160,7 @@ pub fn LoginProviders(show_modal: RwSignal, lock_closing: RwSignal) login_complete: SignalSetter::map(move |val: DelegatedIdentityWire| { new_identity.set(Some(val.clone())); write_account_connected(true); - auth.identity.set(Some(val)); + auth.set(val); show_modal.set(false); }), }; diff --git a/src/component/base_route.rs b/src/component/base_route.rs index 954ca8ba..488b11f3 100644 --- a/src/component/base_route.rs +++ b/src/component/base_route.rs @@ -2,15 +2,16 @@ use candid::Principal; use leptos::*; use leptos_router::*; -use super::auth_provider::AuthProvider; use crate::{ + auth::DelegatedIdentityWire, + component::spinner::FullScreenSpinner, state::{ - auth::AuthState, - canisters::{do_canister_auth, AuthCanistersResource}, + auth::{auth_resource, AuthState}, + canisters::{do_canister_auth, Canisters}, local_storage::use_referrer_store, }, try_or_redirect_opt, - utils::{profile::ProfileDetails, MockPartialEq}, + utils::MockPartialEq, }; #[derive(Params, PartialEq, Clone)] @@ -18,17 +19,16 @@ struct Referrer { user_refer: String, } -/// Base route is technically rendered **adjacent** to all routes -/// do not use it for any parent -> child communication, such as passing global context #[component] -pub fn BaseRoute() -> impl IntoView { +fn CtxProvider(auth: AuthState, canisters: Canisters, children: Children) -> impl IntoView { + provide_context(canisters); + let referrer_query = use_query::(); let referrer_principal = move || { referrer_query() .ok() .and_then(|r| Principal::from_text(r.user_refer).ok()) }; - let auth_state = expect_context::(); let (referrer_store, set_referrer_store, _) = use_referrer_store(); create_effect(move |_| { @@ -38,32 +38,57 @@ pub fn BaseRoute() -> impl IntoView { let refp = referrer_principal(); set_referrer_store.set(refp); }); + provide_context(auth); - let auth_cans_res: AuthCanistersResource = Resource::local( - move || MockPartialEq(auth_state.identity.get()), - move |auth| do_canister_auth(auth.0), - ); + children() +} - provide_context(auth_cans_res); +#[component] +fn CanistersProvider(id: DelegatedIdentityWire) -> impl IntoView { + let auth = AuthState::new(id); - // User profile and canister details - let canisters = auth_cans_res; - let profile_and_canister_details = create_resource( - move || MockPartialEq(canisters.get().and_then(|c| c.transpose())), - move |canisters| async move { - let canisters = try_or_redirect_opt!(canisters.0?); - let user = canisters.authenticated_user(); - let user_details = user.get_profile_details().await.ok()?; - Some(( - ProfileDetails::from(user_details), - canisters.user_canister(), - )) - }, + let canisters_res = create_resource( + move || MockPartialEq(auth()), + move |id| do_canister_auth(id.0), ); - provide_context(profile_and_canister_details); view! { - - + + {move || { + canisters_res() + .and_then(|cans| { + let cans = try_or_redirect_opt!(cans); + let canisters: Canisters = try_or_redirect_opt!(cans.try_into()); + Some( + view! { + + + + }, + ) + }) + }} + + + } +} + +/// Base route is technically rendered **adjacent** to all routes +/// do not use it for any parent -> child communication, such as passing global context +#[component] +pub fn BaseRoute() -> impl IntoView { + let id_res = auth_resource(); + + view! { + + {move || { + id_res() + .flatten() + .map(move |id| { + view! { } + }) + }} + + } } diff --git a/src/component/connect.rs b/src/component/connect.rs index b7c6fb1c..f03e66c2 100644 --- a/src/component/connect.rs +++ b/src/component/connect.rs @@ -1,9 +1,6 @@ use leptos::*; -use crate::{ - state::auth::auth_state, - utils::event_streaming::events::{LoginCta, LoginJoinOverlayViewed}, -}; +use crate::utils::event_streaming::events::{LoginCta, LoginJoinOverlayViewed}; use super::login_modal::LoginModal; @@ -12,7 +9,6 @@ pub fn ConnectLogin( #[prop(optional, default = "Login")] login_text: &'static str, #[prop(optional, default = "menu")] cta_location: &'static str, ) -> impl IntoView { - let auth = auth_state(); let show_login = create_rw_signal(false); LoginJoinOverlayViewed.send_event(); @@ -30,7 +26,6 @@ pub fn ConnectLogin( } class="font-bold rounded-full bg-primary-600 py-2 md:py-3 w-full text-center text-lg md:text-xl text-white" - disabled=move || auth.identity.with(|a| a.is_none()) > {move || if show_login() { "Connecting..." } else { login_text }} diff --git a/src/component/logout.rs b/src/component/logout.rs index 75ac87fd..28167db1 100644 --- a/src/component/logout.rs +++ b/src/component/logout.rs @@ -6,26 +6,24 @@ use crate::{ auth::logout_identity, component::loading::Loading, consts::ACCOUNT_CONNECTED_STORE, - state::{auth::auth_state, canisters::AuthProfileCanisterResource}, + state::auth::auth_state, try_or_redirect, utils::event_streaming::events::{LogoutClicked, LogoutConfirmation}, }; #[component] pub fn Logout() -> impl IntoView { - let profile_and_canister_details: AuthProfileCanisterResource = expect_context(); - - LogoutClicked.send_event(profile_and_canister_details); + LogoutClicked.send_event(); let auth_res = create_local_resource( || (), move |_| async move { - let _ = try_or_redirect!(logout_identity().await); + let id = try_or_redirect!(logout_identity().await); - LogoutConfirmation.send_event(profile_and_canister_details); + LogoutConfirmation.send_event(); - let auth = auth_state().identity; - auth.set(None); + let auth = auth_state(); + auth.set(id); let (_, write_account_connected, _) = use_local_storage::(ACCOUNT_CONNECTED_STORE); diff --git a/src/component/mod.rs b/src/component/mod.rs index 983c23a0..ec3c2885 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -1,5 +1,4 @@ pub mod airdrop_logo; -pub mod auth_provider; pub mod auth_providers; pub mod back_btn; pub mod base_route; diff --git a/src/page/menu.rs b/src/page/menu.rs index aeb5e3d5..195f2a6e 100644 --- a/src/page/menu.rs +++ b/src/page/menu.rs @@ -4,9 +4,6 @@ use crate::component::{connect::ConnectLogin, social::*, toggle::Toggle}; use crate::consts::{social, NSFW_TOGGLE_STORE}; use crate::state::auth::account_connected_reader; use crate::state::canisters::authenticated_canisters; -use crate::try_or_redirect_opt; -use crate::utils::profile::ProfileDetails; -use crate::utils::MockPartialEq; use leptos::html::Input; use leptos::*; use leptos_icons::*; @@ -65,18 +62,10 @@ fn MenuFooter() -> impl IntoView { } #[component] -fn ProfileLoading() -> impl IntoView { - view! { -
-
-
-
-
- } -} +fn ProfileInfo() -> impl IntoView { + let canisters = authenticated_canisters(); + let user_details = canisters.profile_details(); -#[component] -fn ProfileLoaded(user_details: ProfileDetails) -> impl IntoView { view! {
@@ -95,32 +84,6 @@ fn ProfileLoaded(user_details: ProfileDetails) -> impl IntoView { } } -#[component] -fn ProfileInfo() -> impl IntoView { - let canisters = authenticated_canisters(); - let profile_details = create_resource( - move || MockPartialEq(canisters.get().and_then(|c| c.transpose())), - move |canisters| async move { - let canisters = try_or_redirect_opt!(canisters.0?); - let user = canisters.authenticated_user(); - let user_details = user.get_profile_details().await.ok()?; - Some(ProfileDetails::from(user_details)) - }, - ); - - view! { - - {move || { - profile_details() - .flatten() - .map(|user_details| view! { }) - .unwrap_or_else(|| view! { }) - }} - - - } -} - #[component] fn NsfwToggle() -> impl IntoView { let (nsfw_enabled, set_nsfw_enabled, _) = @@ -180,7 +143,12 @@ pub fn Menu() -> impl IntoView {
- + diff --git a/src/page/post_view/mod.rs b/src/page/post_view/mod.rs index 6ee80d4f..bbc2a7d7 100644 --- a/src/page/post_view/mod.rs +++ b/src/page/post_view/mod.rs @@ -16,7 +16,7 @@ use leptos_use::{ use crate::{ component::spinner::FullScreenSpinner, consts::NSFW_TOGGLE_STORE, - state::canisters::{authenticated_canisters, unauth_canisters}, + state::canisters::authenticated_canisters, try_or_redirect, utils::route::{failure_redirect, go_to_root}, }; @@ -180,46 +180,41 @@ pub fn PostViewWithUpdates(initial_post: Option) -> impl IntoView { }) } let (nsfw_enabled, _, _) = use_local_storage::(NSFW_TOGGLE_STORE); - let auth_cans_res = authenticated_canisters(); - let fetch_video_action = create_action(move |()| async move { - loop { - let auth_canisters = leptos::untrack(|| auth_cans_res.get().transpose()); - let auth_canisters = try_or_redirect!(auth_canisters).flatten(); - let Some(cursor) = fetch_cursor.try_get_untracked() else { - return; - }; - let nsfw_enabled = nsfw_enabled.get_untracked(); - let unauth_canisters = unauth_canisters(); + let canisters = authenticated_canisters(); + let fetch_video_action = create_action(move |()| { + let canisters = canisters.clone(); + async move { + loop { + let Some(cursor) = fetch_cursor.try_get_untracked() else { + return; + }; + let nsfw_enabled = nsfw_enabled.get_untracked(); - let chunks = if let Some(canisters) = auth_canisters.as_ref() { - let fetch_stream = VideoFetchStream::new(canisters, cursor); - fetch_stream.fetch_post_uids_chunked(3, nsfw_enabled).await - } else { - let fetch_stream = VideoFetchStream::new(&unauth_canisters, cursor); - fetch_stream.fetch_post_uids_chunked(3, nsfw_enabled).await - }; + let fetch_stream = VideoFetchStream::new(&canisters, cursor); + let chunks = fetch_stream.fetch_post_uids_chunked(3, nsfw_enabled).await; - let res = try_or_redirect!(chunks); - let mut chunks = res.posts_stream; - let mut cnt = 0; - while let Some(chunk) = chunks.next().await { - cnt += chunk.len(); - video_queue.update(|q| { - for uid in chunk { - let uid = try_or_redirect!(uid); - q.push(uid); - } - }); - } - if res.end || cnt >= 8 { - queue_end.set(res.end); - break; + let res = try_or_redirect!(chunks); + let mut chunks = res.posts_stream; + let mut cnt = 0; + while let Some(chunk) = chunks.next().await { + cnt += chunk.len(); + video_queue.update(|q| { + for uid in chunk { + let uid = try_or_redirect!(uid); + q.push(uid); + } + }); + } + if res.end || cnt >= 8 { + queue_end.set(res.end); + break; + } + fetch_cursor.update(|c| c.advance()); } + fetch_cursor.update(|c| c.advance()); } - - fetch_cursor.update(|c| c.advance()); }); create_effect(move |_| { if !recovering_state.get_untracked() { @@ -269,41 +264,27 @@ pub fn PostView() -> impl IntoView { }) }; - let PostViewCtx { - video_queue, - current_idx, - .. - } = expect_context(); - - let cached_post = move || { - let Some((canister, post_id)) = canister_and_post() else { - go_to_root(); - return None; - }; - - let post = video_queue - .with_untracked(|q| q.get(current_idx.get_untracked()).cloned()) - .filter(|post| post.canister_id == canister && post.post_id == post_id); - - post - }; + let PostViewCtx { .. } = expect_context(); + let canisters = authenticated_canisters(); let fetch_first_video_uid = create_resource( || (), - move |_| async move { - let Some((canister, post_id)) = canister_and_post() else { - go_to_root(); - return None; - }; + move |_| { + let canisters = canisters.clone(); + async move { + let Some((canister, post_id)) = canister_and_post() else { + go_to_root(); + return None; + }; - let canisters = unauth_canisters(); - match get_post_uid(&canisters, canister, post_id).await { - Ok(Some(uid)) => Some(uid), - Err(e) => { - failure_redirect(e); - None + match get_post_uid(&canisters, canister, post_id).await { + Ok(Some(uid)) => Some(uid), + Err(e) => { + failure_redirect(e); + None + } + Ok(None) => None, } - Ok(None) => None, } }, ); @@ -311,14 +292,10 @@ pub fn PostView() -> impl IntoView { view! { {move || { - if let Some(post) = cached_post() { - Some(view! { }) - } else { - fetch_first_video_uid() - .map(|initial_post| { - view! { } - }) - } + fetch_first_video_uid() + .map(|initial_post| { + view! { } + }) }} diff --git a/src/page/post_view/overlay.rs b/src/page/post_view/overlay.rs index aec6ffa6..6b68bacf 100644 --- a/src/page/post_view/overlay.rs +++ b/src/page/post_view/overlay.rs @@ -1,10 +1,8 @@ use crate::{ component::modal::Modal, - state::canisters::{authenticated_canisters, Canisters}, - try_or_redirect_opt, + state::canisters::authenticated_canisters, utils::{ event_streaming::events::LikeVideo, - route::failure_redirect, web::{copy_to_clipboard, share_url}, }, }; @@ -12,7 +10,7 @@ use leptos::*; use leptos_icons::*; use leptos_use::use_window; -use super::video_iter::{post_liked_by_me, PostDetails}; +use super::video_iter::PostDetails; #[component] fn LikeButtonPlaceHolder() -> impl IntoView { @@ -28,11 +26,11 @@ fn LikeButtonPlaceHolder() -> impl IntoView { #[component] fn LikeButton( - canisters: Canisters, post_details: PostDetails, likes: RwSignal, initial_liked: bool, ) -> impl IntoView { + let canisters = authenticated_canisters(); let liked = create_rw_signal(initial_liked); let icon_class = Signal::derive(move || { if liked() { @@ -98,72 +96,20 @@ fn LikeButton( } #[component] -fn LikeLoader( - canisters: Canisters, - post: PostDetails, - likes: RwSignal, -) -> impl IntoView { - let can_c = canisters.clone(); - let liked = create_resource( - || (), - move |_| { - let canisters = can_c.clone(); - async move { - if let Some(liked) = post.liked_by_user { - return liked; - } - match post_liked_by_me(&canisters, post.canister_id, post.post_id).await { - Ok(liked) => liked, - Err(e) => { - failure_redirect(e); - false - } - } - } - }, - ); - let canisters = store_value(canisters); - let post = store_value(post); +fn LikeLoader(post: PostDetails, likes: RwSignal) -> impl IntoView { + let initial_liked = post.liked_by_user; - view! { - - {move || { - liked() - .map(move |initial_liked| { - view! { - - } - }) - }} - - - } + view! { } } #[component] fn LikeAndAuthCanLoader(post: PostDetails) -> impl IntoView { - let auth_cans = authenticated_canisters(); let likes = create_rw_signal(post.likes); let post = store_value(post); view! {
- - {move || { - auth_cans - .get() - .and_then(|canisters| { - let canisters = try_or_redirect_opt!(canisters)?; - Some(view! { }) - }) - }} - - + {likes}
} @@ -189,6 +135,7 @@ pub fn VideoDetailsOverlay(post: PostDetails) -> impl IntoView { let share = create_action(move |&()| { let post_details = post_details.clone(); + let canisters = auth_cans.clone(); async move { let url = video_url(); if share_url(&url).is_some() { @@ -200,9 +147,7 @@ pub fn VideoDetailsOverlay(post: PostDetails) -> impl IntoView { { use crate::utils::event_streaming::events::ShareVideo; - let canisters = auth_cans.get().unwrap().unwrap().unwrap(); - let user = canisters.authenticated_user(); - let user_details = user.get_profile_details().await.unwrap(); + let user_details = canisters.profile_details(); let canister_id = canisters.user_canister(); ShareVideo.send_event(post_details, user_details, canister_id); diff --git a/src/page/post_view/video_iter.rs b/src/page/post_view/video_iter.rs index d7077e77..47b169f9 100644 --- a/src/page/post_view/video_iter.rs +++ b/src/page/post_view/video_iter.rs @@ -37,8 +37,8 @@ impl FetchCursor { } } -pub async fn get_post_uid( - canisters: &Canisters, +pub async fn get_post_uid( + canisters: &Canisters, user_canister: Principal, post_id: u64, ) -> Result, PostViewError> { @@ -65,7 +65,6 @@ pub async fn get_post_uid( } Ok(Some(PostDetails::from_canister_post( - AUTH, user_canister, post_details, ))) @@ -93,9 +92,7 @@ pub struct PostDetails { pub likes: u64, pub display_name: String, pub propic_url: String, - /// Whether post is liked by the authenticated - /// user or not, None if unknown - pub liked_by_user: Option, + pub liked_by_user: bool, pub poster_principal: Principal, pub hastags: Vec, pub is_nsfw: bool, @@ -103,11 +100,7 @@ pub struct PostDetails { } impl PostDetails { - pub fn from_canister_post( - authenticated: bool, - canister_id: Principal, - details: PostDetailsForFrontend, - ) -> Self { + pub fn from_canister_post(canister_id: Principal, details: PostDetailsForFrontend) -> Self { Self { canister_id, post_id: details.id, @@ -122,7 +115,7 @@ impl PostDetails { propic_url: details .created_by_profile_photo_url .unwrap_or_else(|| propic_from_principal(details.created_by_user_principal_id)), - liked_by_user: authenticated.then_some(details.liked_by_me), + liked_by_user: details.liked_by_me, poster_principal: details.created_by_user_principal_id, hastags: details.hashtags, is_nsfw: details.is_nsfw, @@ -138,13 +131,13 @@ pub struct FetchVideosRes<'a> { pub end: bool, } -pub struct VideoFetchStream<'a, const AUTH: bool> { - canisters: &'a Canisters, +pub struct VideoFetchStream<'a> { + canisters: &'a Canisters, cursor: FetchCursor, } -impl<'a, const AUTH: bool> VideoFetchStream<'a, AUTH> { - pub fn new(canisters: &'a Canisters, cursor: FetchCursor) -> Self { +impl<'a> VideoFetchStream<'a> { + pub fn new(canisters: &'a Canisters, cursor: FetchCursor) -> Self { Self { canisters, cursor } } diff --git a/src/page/refer_earn/history.rs b/src/page/refer_earn/history.rs index 75b9cb5c..ee6e18d0 100644 --- a/src/page/refer_earn/history.rs +++ b/src/page/refer_earn/history.rs @@ -1,9 +1,8 @@ use leptos::*; -use crate::component::{bullet_loader::BulletLoader, infinite_scroller::InfiniteScroller}; +use crate::component::infinite_scroller::InfiniteScroller; use crate::{ - state::canisters::{authenticated_canisters, Canisters}, - try_or_redirect_opt, + state::canisters::authenticated_canisters, utils::{profile::propic_from_principal, timestamp::get_day_month}, }; use history_provider::*; @@ -32,7 +31,8 @@ fn HistoryItem(detail: HistoryDetails, _ref: NodeRef) -> impl IntoVie } #[component] -fn AuthenticatedHistory(canisters: Canisters) -> impl IntoView { +pub fn HistoryView() -> impl IntoView { + let canisters = authenticated_canisters(); let provider = get_history_provider(canisters); view! {
@@ -48,25 +48,6 @@ fn AuthenticatedHistory(canisters: Canisters) -> impl IntoView { } } -#[component] -pub fn HistoryView() -> impl IntoView { - let canisters = authenticated_canisters(); - - view! { - - {move || { - canisters() - .and_then(|canisters| { - let canisters = try_or_redirect_opt!(canisters)?; - Some(view! { }) - }) - .unwrap_or_else(|| view! { }) - }} - - - } -} - mod history_provider { use candid::Principal; diff --git a/src/page/refer_earn/mod.rs b/src/page/refer_earn/mod.rs index bc89fe57..415a44e3 100644 --- a/src/page/refer_earn/mod.rs +++ b/src/page/refer_earn/mod.rs @@ -11,11 +11,7 @@ use crate::component::connect::ConnectLogin; use crate::utils::event_streaming::events::{Refer, ReferShareLink}; use crate::{ component::{back_btn::BackButton, title::Title}, - state::{ - auth::account_connected_reader, - canisters::{authenticated_canisters, AuthProfileCanisterResource}, - }, - try_or_redirect_opt, + state::{auth::account_connected_reader, canisters::authenticated_canisters}, utils::web::copy_to_clipboard, }; use history::HistoryView; @@ -46,7 +42,6 @@ fn ReferLoaded(user_principal: Principal) -> impl IntoView { }) .unwrap_or_default(); - let profile_and_canister_details: AuthProfileCanisterResource = expect_context(); let (logged_in, _) = account_connected_reader(); let click_copy = create_action(move |()| { @@ -54,7 +49,7 @@ fn ReferLoaded(user_principal: Principal) -> impl IntoView { async move { let _ = copy_to_clipboard(&refer_link); - ReferShareLink.send_event(profile_and_canister_details, logged_in); + ReferShareLink.send_event(logged_in); } }); @@ -68,35 +63,12 @@ fn ReferLoaded(user_principal: Principal) -> impl IntoView { } } -#[component] -fn ReferLoading() -> impl IntoView { - view! { -
- -
- } -} - #[component] fn ReferCode() -> impl IntoView { let canisters = authenticated_canisters(); + let user_principal = canisters.identity().sender().unwrap(); - view! { - - {move || { - canisters() - .and_then(|canisters| { - let canisters = try_or_redirect_opt!(canisters)?; - let user_principal = canisters.identity().sender().unwrap(); - Some(view! { }) - }) - .unwrap_or_else(|| { - view! { } - }) - }} - - - } + view! { } } #[component] diff --git a/src/page/root.rs b/src/page/root.rs index 634008e8..23bc8e10 100644 --- a/src/page/root.rs +++ b/src/page/root.rs @@ -1,8 +1,8 @@ -use crate::component::spinner::FullScreenSpinner; use candid::Principal; use leptos::*; use leptos_router::*; +use crate::component::spinner::FullScreenSpinner; #[cfg(feature = "ssr")] use crate::{canister::post_cache, state::canisters::unauth_canisters}; diff --git a/src/page/upload/mod.rs b/src/page/upload/mod.rs index f41e884b..865f0176 100644 --- a/src/page/upload/mod.rs +++ b/src/page/upload/mod.rs @@ -4,7 +4,7 @@ mod video_upload; use crate::{ component::toggle::ToggleWithLabel, - state::canisters::AuthProfileCanisterResource, + state::canisters::authenticated_canisters, utils::event_streaming::events::{VideoUploadInitiated, VideoUploadUploadButtonClicked}, }; @@ -52,29 +52,23 @@ fn PreUploadView(trigger_upload: WriteSignal>) -> impl Into let enable_hot_or_not = create_node_ref::(); let is_nsfw = create_node_ref::(); - let profile_and_canister_details: AuthProfileCanisterResource = expect_context(); - let user_id = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.principal) - }; - let display_name = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.display_name) - }; - let canister_id = move || profile_and_canister_details().flatten().map(|(_, q)| q); + let canisters = authenticated_canisters(); + let details = canisters.profile_details(); - VideoUploadInitiated.send_event(user_id(), display_name(), canister_id()); + VideoUploadInitiated.send_event( + details.principal, + details.display_name.clone(), + canisters.user_canister(), + ); let on_submit = move || { VideoUploadUploadButtonClicked.send_event( hashtag_inp, is_nsfw, enable_hot_or_not, - user_id(), - display_name(), - canister_id(), + details.principal, + details.display_name.clone(), + canisters.user_canister(), ); let description = desc.get_untracked().unwrap().value(); diff --git a/src/page/upload/video_upload.rs b/src/page/upload/video_upload.rs index b3dc78d9..7e1fa3e9 100644 --- a/src/page/upload/video_upload.rs +++ b/src/page/upload/video_upload.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::{ component::modal::Modal, - state::canisters::{authenticated_canisters, AuthProfileCanisterResource, Canisters}, + state::canisters::authenticated_canisters, try_or_redirect_opt, utils::{ event_streaming::events::{ @@ -60,31 +60,27 @@ pub fn PreVideoUpload(file_blob: WriteSignal>) -> impl IntoV let video_ref = create_node_ref::
- - {move || { - let uid = upload_uid().flatten()?; - let canisters = try_or_redirect_opt!(canisters.get() ?.transpose() ?); - publish_action.dispatch((canisters, uid)); - Some(()) - }} - - + {move || { + let uid = upload_uid().flatten()?; + publish_action.dispatch(uid); + Some(()) + }} +
- - {move || { - profile_details - .get() - .flatten() - .map(|details| view! { }) - .unwrap_or_else(|| view! { }) - }} - - +
Your Coyns Balance diff --git a/src/page/wallet/transactions.rs b/src/page/wallet/transactions.rs index 5993a1cf..6c12378e 100644 --- a/src/page/wallet/transactions.rs +++ b/src/page/wallet/transactions.rs @@ -1,12 +1,8 @@ use leptos::*; use crate::{ - component::{ - back_btn::BackButton, bullet_loader::BulletLoader, infinite_scroller::InfiniteScroller, - title::Title, - }, + component::{back_btn::BackButton, infinite_scroller::InfiniteScroller, title::Title}, state::canisters::{authenticated_canisters, Canisters}, - try_or_redirect_opt, }; use super::txn::{provider::get_history_provider, TxnView}; @@ -43,18 +39,7 @@ pub fn Transactions() -> impl IntoView {
- - {move || { - canisters - .get() - .and_then(|c| { - let canisters = try_or_redirect_opt!(c)?; - Some(view! { }) - }) - .unwrap_or_else(|| view! { }) - }} - - +
} } diff --git a/src/state/auth/mod.rs b/src/state/auth/mod.rs index 0f6925aa..3bf8f9cc 100644 --- a/src/state/auth/mod.rs +++ b/src/state/auth/mod.rs @@ -1,13 +1,24 @@ -use leptos::{create_effect, create_signal, expect_context, Effect, ReadSignal, RwSignal}; +use leptos::*; use leptos_use::{storage::use_local_storage, utils::FromToStringCodec}; -use crate::{auth::DelegatedIdentityWire, consts::ACCOUNT_CONNECTED_STORE}; +use crate::{ + auth::{extract_or_generate_identity, DelegatedIdentityWire}, + consts::ACCOUNT_CONNECTED_STORE, + try_or_redirect_opt, +}; -#[derive(Default, Clone)] -pub struct AuthState { - pub identity: RwSignal>, +pub fn auth_resource() -> Resource<(), Option> { + create_blocking_resource( + || (), + |_| async move { + let id = try_or_redirect_opt!(extract_or_generate_identity().await); + Some(id) + }, + ) } +pub type AuthState = RwSignal; + pub fn auth_state() -> AuthState { expect_context() } diff --git a/src/state/canisters.rs b/src/state/canisters.rs index 641c0401..c696a269 100644 --- a/src/state/canisters.rs +++ b/src/state/canisters.rs @@ -3,6 +3,7 @@ use std::{collections::HashSet, sync::Arc}; use candid::Principal; use ic_agent::{identity::DelegatedIdentity, AgentError, Identity}; use leptos::*; +use serde::{Deserialize, Serialize}; use yral_metadata_client::MetadataClient; use yral_metadata_types::UserMetadata; @@ -17,9 +18,37 @@ use crate::{ }, consts::{FALLBACK_USER_INDEX, METADATA_API_BASE}, utils::profile::ProfileDetails, - utils::MockPartialEq, }; +#[derive(Serialize, Deserialize, Clone)] +pub struct AuthCanistersWire { + id: DelegatedIdentityWire, + user_canister: Principal, + profile_details: ProfileDetails, + expiry: u64, +} + +impl TryFrom for Canisters { + type Error = ServerFnError; + + fn try_from(value: AuthCanistersWire) -> Result { + let id: DelegatedIdentity = value.id.try_into()?; + let id = Arc::new(id); + Ok(Self { + agent: ic_agent::Agent::builder() + .with_url(AGENT_URL) + .with_arc_identity(id.clone()) + .build() + .unwrap(), + metadata_client: MetadataClient::with_base_url(METADATA_API_BASE.clone()), + id: Some(id), + user_canister: value.user_canister, + expiry: value.expiry, + profile_details: Some(value.profile_details), + }) + } +} + #[derive(Clone)] pub struct Canisters { agent: ic_agent::Agent, @@ -27,6 +56,7 @@ pub struct Canisters { metadata_client: MetadataClient, user_canister: Principal, expiry: u64, + profile_details: Option, } impl Default for Canisters { @@ -40,6 +70,7 @@ impl Default for Canisters { metadata_client: MetadataClient::with_base_url(METADATA_API_BASE.clone()), user_canister: Principal::anonymous(), expiry: 0, + profile_details: None, } } } @@ -64,6 +95,7 @@ impl Canisters { id: Some(id), user_canister: Principal::anonymous(), expiry, + profile_details: None, } } @@ -84,6 +116,12 @@ impl Canisters { pub fn authenticated_user(&self) -> IndividualUserTemplate<'_> { IndividualUserTemplate(self.user_canister, &self.agent) } + + pub fn profile_details(&self) -> ProfileDetails { + self.profile_details + .clone() + .expect("Authenticated canisters must have profile details") + } } impl Canisters { @@ -140,19 +178,8 @@ pub fn unauth_canisters() -> Canisters { expect_context() } -pub type AuthCanistersResource = Resource< - MockPartialEq>, - Result>, ServerFnError>, ->; - -pub type AuthProfileCanisterResource = Resource< - MockPartialEq, ServerFnError>>>, - Option<(ProfileDetails, Principal)>, ->; - async fn create_individual_canister( canisters: &Canisters, - _delegation_id: DelegatedIdentityWire, ) -> Result { let subnet_idxs = canisters.subnet_indexes().await?; @@ -184,14 +211,10 @@ async fn create_individual_canister( } pub async fn do_canister_auth( - auth: Option, -) -> Result>, ServerFnError> { - let Some(delegation_identity) = auth else { - return Ok(None); - }; - - let auth: DelegatedIdentity = delegation_identity.clone().try_into()?; - let mut canisters = Canisters::::authenticated(auth); + auth: DelegatedIdentityWire, +) -> Result { + let id: DelegatedIdentity = auth.clone().try_into()?; + let mut canisters = Canisters::::authenticated(id); canisters.user_canister = if let Some(user_canister) = canisters .get_individual_canister_by_user_principal(canisters.identity().sender().unwrap()) @@ -199,7 +222,7 @@ pub async fn do_canister_auth( { user_canister } else { - create_individual_canister(&canisters, delegation_identity).await? + create_individual_canister(&canisters).await? }; let user = canisters.authenticated_user(); match user @@ -210,10 +233,17 @@ pub async fn do_canister_auth( Ok(Result8::Ok(_)) => (), Err(e) | Ok(Result8::Err(e)) => log::warn!("Failed to update last access time: {}", e), } - - Ok(Some(canisters)) + canisters.profile_details = Some(user.get_profile_details().await?.into()); + let expiry = canisters.expiry_ns(); + + Ok(AuthCanistersWire { + id: auth, + user_canister: canisters.user_canister, + profile_details: canisters.profile_details.unwrap(), + expiry, + }) } -pub fn authenticated_canisters() -> AuthCanistersResource { +pub fn authenticated_canisters() -> Canisters { expect_context() } diff --git a/src/utils/event_streaming/events.rs b/src/utils/event_streaming/events.rs index 8f5e1634..98956bcf 100644 --- a/src/utils/event_streaming/events.rs +++ b/src/utils/event_streaming/events.rs @@ -9,15 +9,12 @@ use wasm_bindgen::JsCast; use crate::canister::individual_user_template::UserProfileDetailsForFrontend; use crate::component::auth_providers::ProviderKind; -use crate::state::canisters::Canisters; +use crate::state::canisters::{authenticated_canisters, Canisters}; use crate::state::history::HistoryCtx; #[cfg(feature = "ga4")] use crate::utils::event_streaming::{send_event, send_event_warehouse, send_user_id}; use crate::utils::profile::ProfileDetails; -use crate::{ - page::post_view::video_iter::PostDetails, - state::{auth::account_connected_reader, canisters::AuthProfileCanisterResource}, -}; +use crate::{page::post_view::video_iter::PostDetails, state::auth::account_connected_reader}; use super::EventHistory; @@ -51,21 +48,14 @@ impl VideoWatched { ) { #[cfg(all(feature = "hydrate", feature = "ga4"))] { - let profile_and_canister_details: AuthProfileCanisterResource = expect_context(); + let canisters = authenticated_canisters(); + let details = canisters.profile_details(); let (is_connected, _) = account_connected_reader(); let publisher_user_id = move || vid_details().as_ref().map(|q| q.poster_principal); - let user_id = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.principal) - }; - let display_name = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.display_name) - }; - let canister_id = move || profile_and_canister_details().flatten().map(|(_, q)| q); + let user_id = details.principal; + let display_name = details.display_name; + let canister_id = canisters.user_canister(); let video_id = move || vid_details().as_ref().map(|q| q.uid.clone()); let hastag_count = move || vid_details().as_ref().map(|q| q.hastags.len()); let is_nsfw = move || vid_details().as_ref().map(|q| q.is_nsfw); @@ -81,6 +71,7 @@ impl VideoWatched { let (video_watched, set_video_watched) = create_signal(false); let (full_video_watched, set_full_video_watched) = create_signal(false); + let display_c = display_name.clone(); let _ = use_event_listener(container_ref, ev::timeupdate, move |evt| { let target = evt.target().unwrap(); let video = target.unchecked_into::(); @@ -97,10 +88,10 @@ impl VideoWatched { "video_duration_watched", &json!({ "publisher_user_id":publisher_user_id(), - "user_id":user_id(), + "user_id": user_id, "is_loggedIn": is_connected(), - "display_name": display_name(), - "canister_id": canister_id(), + "display_name": display_c, + "canister_id": canister_id, "video_id": video_id(), "video_category": "NA", "creator_category": "NA", @@ -129,10 +120,10 @@ impl VideoWatched { "video_viewed", &json!({ "publisher_user_id":publisher_user_id(), - "user_id":user_id(), + "user_id":user_id, "is_loggedIn": is_connected(), - "display_name": display_name(), - "canister_id": canister_id(), + "display_name": display_c.clone(), + "canister_id": canister_id, "video_id": video_id(), "video_category": "NA", "creator_category": "NA", @@ -151,6 +142,7 @@ impl VideoWatched { // video duration watched - warehousing + let display_c = display_name.clone(); let _ = use_event_listener(container_ref, ev::pause, move |evt| { let target = evt.target().unwrap(); let video = target.unchecked_into::(); @@ -166,10 +158,10 @@ impl VideoWatched { "video_duration_watched", &json!({ "publisher_user_id":publisher_user_id(), - "user_id":user_id(), + "user_id":user_id, "is_loggedIn": is_connected(), - "display_name": display_name(), - "canister_id": canister_id(), + "display_name": display_c, + "canister_id": canister_id, "video_id": video_id(), "video_category": "NA", "creator_category": "NA", @@ -248,7 +240,7 @@ impl ShareVideo { pub fn send_event( &self, post_details: PostDetails, - user_details: UserProfileDetailsForFrontend, + profile_details: ProfileDetails, canister_id: Principal, ) { #[cfg(all(feature = "hydrate", feature = "ga4"))] @@ -261,7 +253,6 @@ impl ShareVideo { let view_count = post_details.views; let like_count = post_details.likes; - let profile_details = ProfileDetails::from(user_details); let user_id = profile_details.principal; let display_name = profile_details.display_name; let (is_connected, _) = account_connected_reader(); @@ -296,15 +287,15 @@ pub struct VideoUploadInitiated; impl VideoUploadInitiated { pub fn send_event( &self, - user_id: Option, - display_name: Option>, - canister_id: Option, + user_id: Principal, + display_name: Option, + canister_id: Principal, ) { #[cfg(all(feature = "hydrate", feature = "ga4"))] { // video_upload_initiated - analytics - let display_name = display_name.unwrap_or_default().unwrap_or_default(); + let display_name = display_name.unwrap_or_default(); create_effect(move |_| { send_event( "video_upload_initiated", @@ -329,15 +320,15 @@ impl VideoUploadUploadButtonClicked { hashtag_inp: NodeRef, is_nsfw: NodeRef, enable_hot_or_not: NodeRef, - user_id: Option, - display_name: Option>, - canister_id: Option, + user_id: Principal, + display_name: Option, + canister_id: Principal, ) { #[cfg(all(feature = "hydrate", feature = "ga4"))] { // video_upload_upload_button_clicked - analytics - let display_name = display_name.unwrap_or_default().unwrap_or_default(); + let display_name = display_name.unwrap_or_default(); let hashtag_count = hashtag_inp.get_untracked().unwrap().value().len(); let is_nsfw_val = is_nsfw @@ -373,15 +364,15 @@ pub struct VideoUploadVideoSelected; impl VideoUploadVideoSelected { pub fn send_event( &self, - user_id: Option, - display_name: Option>, - canister_id: Option, + user_id: Principal, + display_name: Option, + canister_id: Principal, ) { #[cfg(all(feature = "hydrate", feature = "ga4"))] { // video_upload_video_selected - analytics - let display_name = display_name.unwrap_or_default().unwrap_or_default(); + let display_name = display_name.unwrap_or_default(); send_event( "video_upload_video_selected", @@ -407,15 +398,15 @@ impl VideoUploadUnsuccessful { hashtags_len: usize, is_nsfw: bool, enable_hot_or_not: bool, - user_id: Option, - display_name: Option>, - canister_id: Option, + user_id: Principal, + display_name: Option, + canister_id: Principal, ) { #[cfg(all(feature = "hydrate", feature = "ga4"))] { // video_upload_unsuccessful - analytics - let display_name = display_name.unwrap_or_default().unwrap_or_default(); + let display_name = display_name.unwrap_or_default(); send_event( "video_upload_unsuccessful", @@ -443,9 +434,9 @@ impl VideoUploadSuccessful { hashtags_len: usize, is_nsfw: bool, enable_hot_or_not: bool, - user_id: Option, - display_name: Option>, - canister_id: Option, + user_id: Principal, + display_name: Option, + canister_id: Principal, ) { #[cfg(all(feature = "hydrate", feature = "ga4"))] { @@ -478,18 +469,13 @@ impl Refer { { // refer - analytics - let profile_and_canister_details: AuthProfileCanisterResource = expect_context(); - let user_id = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.principal) - }; - let display_name = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.display_name) - }; - let canister_id = move || profile_and_canister_details().flatten().map(|(_, q)| q); + let canisters = authenticated_canisters(); + + let details = canisters.profile_details(); + let user_id = details.principal; + let display_name = details.display_name; + let canister_id = canisters.user_canister(); + let history_ctx: HistoryCtx = expect_context(); let prev_site = history_ctx.prev_url(); @@ -498,10 +484,10 @@ impl Refer { send_event( "refer", &json!({ - "user_id":user_id(), + "user_id":user_id, "is_loggedIn": logged_in.get(), - "display_name": display_name(), - "canister_id": canister_id(), + "display_name": display_name, + "canister_id": canister_id, "refer_location": prev_site, }), ); @@ -514,26 +500,18 @@ impl Refer { pub struct ReferShareLink; impl ReferShareLink { - pub fn send_event( - &self, - profile_and_canister_details: AuthProfileCanisterResource, - logged_in: ReadSignal, - ) { + pub fn send_event(&self, logged_in: ReadSignal) { #[cfg(all(feature = "hydrate", feature = "ga4"))] { // refer_share_link - analytics - let user_id = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.principal) - }; - let display_name = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.display_name) - }; - let canister_id = move || profile_and_canister_details().flatten().map(|(_, q)| q); + let canisters = authenticated_canisters(); + let details = canisters.profile_details(); + + let user_id = details.principal; + let display_name = details.display_name; + let canister_id = canisters.user_canister(); + let history_ctx: HistoryCtx = expect_context(); let prev_site = history_ctx.prev_url(); @@ -541,10 +519,10 @@ impl ReferShareLink { send_event( "refer_share_link", &json!({ - "user_id":user_id(), + "user_id":user_id, "is_loggedIn": logged_in.get(), - "display_name": display_name(), - "canister_id": canister_id(), + "display_name": display_name, + "canister_id": canister_id, "refer_location": prev_site, }), ); @@ -612,28 +590,20 @@ impl LoginJoinOverlayViewed { #[cfg(all(feature = "hydrate", feature = "ga4"))] { // login_join_overlay_viewed - analytics - + let canisters = authenticated_canisters(); let event_history: EventHistory = expect_context(); - let profile_and_canister_details: AuthProfileCanisterResource = expect_context(); - let user_id = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.principal) - }; - create_effect(move |_| { - send_event( - "login_join_overlay_viewed", - &json!({ - "user_id_viewer": user_id(), - "previous_event": event_history.event_name.get(), - }), - ); + let user_id = canisters.profile_details().principal; - if let Some(user_id) = user_id() { - send_user_id(user_id.to_string()); - } - }); + send_event( + "login_join_overlay_viewed", + &json!({ + "user_id_viewer": user_id, + "previous_event": event_history.event_name.get(), + }), + ); + + send_user_id(user_id.to_string()); } } } @@ -664,29 +634,23 @@ impl LoginCta { pub struct LogoutClicked; impl LogoutClicked { - pub fn send_event(&self, profile_and_canister_details: AuthProfileCanisterResource) { + pub fn send_event(&self) { #[cfg(all(feature = "hydrate", feature = "ga4"))] { + let canisters = authenticated_canisters(); + let details = canisters.profile_details(); // logout_clicked - analytics - let user_id = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.principal) - }; - let display_name = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.display_name) - }; - let canister_id = move || profile_and_canister_details().flatten().map(|(_, q)| q); + let user_id = details.principal; + let display_name = details.display_name; + let canister_id = canisters.user_canister(); send_event( "logout_clicked", &json!({ - "user_id_viewer": user_id(), - "display_name": display_name(), - "canister_id": canister_id(), + "user_id_viewer": user_id, + "display_name": display_name, + "canister_id": canister_id, }), ); } @@ -697,29 +661,23 @@ impl LogoutClicked { pub struct LogoutConfirmation; impl LogoutConfirmation { - pub fn send_event(&self, profile_and_canister_details: AuthProfileCanisterResource) { + pub fn send_event(&self) { #[cfg(all(feature = "hydrate", feature = "ga4"))] { - // logout_confirmation - analytics + let canisters = authenticated_canisters(); + let details = canisters.profile_details(); - let user_id = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.principal) - }; - let display_name = move || { - profile_and_canister_details() - .flatten() - .map(|(q, _)| q.display_name) - }; - let canister_id = move || profile_and_canister_details().flatten().map(|(_, q)| q); + let user_id = details.principal; + let display_name = details.display_name; + let canister_id = canisters.user_canister(); + // logout_confirmation - analytics send_event( "logout_confirmation", &json!({ - "user_id_viewer": user_id(), - "display_name": display_name(), - "canister_id": canister_id(), + "user_id_viewer": user_id, + "display_name": display_name, + "canister_id": canister_id, }), ); } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 493b18a4..9c71ca64 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,3 +1,4 @@ +use serde::{Deserialize, Serialize}; use web_time::{Duration, SystemTime}; pub mod event_streaming; @@ -16,7 +17,7 @@ pub fn current_epoch() -> Duration { /// Wrapper for PartialEq that always returns false /// this is currently only used for resources /// this does not provide a sane implementation of PartialEq -#[derive(Clone)] +#[derive(Clone, Serialize, Deserialize)] pub struct MockPartialEq(pub T); impl PartialEq for MockPartialEq { From 670ffb8d7626f5f5d6909fe5d00fc6997042b1d7 Mon Sep 17 00:00:00 2001 From: rupansh Date: Fri, 19 Apr 2024 23:00:56 +0530 Subject: [PATCH 4/9] refactor: add lazy loading of canisters back --- src/component/base_route.rs | 35 ++--- src/component/canisters_prov.rs | 99 ++++++++++++ src/component/mod.rs | 1 + src/page/menu.rs | 26 +++- src/page/post_view/mod.rs | 75 ++++++---- src/page/post_view/overlay.rs | 70 ++++----- src/page/post_view/video_iter.rs | 25 ++-- src/page/refer_earn/history.rs | 16 +- src/page/refer_earn/mod.rs | 21 ++- src/page/upload/mod.rs | 19 +-- src/page/upload/video_upload.rs | 183 +++++++++-------------- src/page/wallet/mod.rs | 113 +++++++------- src/page/wallet/transactions.rs | 13 +- src/state/canisters.rs | 15 +- src/utils/event_streaming/events.rs | 224 +++++++++++++--------------- 15 files changed, 506 insertions(+), 429 deletions(-) create mode 100644 src/component/canisters_prov.rs diff --git a/src/component/base_route.rs b/src/component/base_route.rs index 488b11f3..06c1f13e 100644 --- a/src/component/base_route.rs +++ b/src/component/base_route.rs @@ -7,7 +7,7 @@ use crate::{ component::spinner::FullScreenSpinner, state::{ auth::{auth_resource, AuthState}, - canisters::{do_canister_auth, Canisters}, + canisters::{do_canister_auth, AuthCansResource}, local_storage::use_referrer_store, }, try_or_redirect_opt, @@ -20,8 +20,12 @@ struct Referrer { } #[component] -fn CtxProvider(auth: AuthState, canisters: Canisters, children: Children) -> impl IntoView { - provide_context(canisters); +fn CtxProvider( + auth: AuthState, + canisters_res: AuthCansResource, + children: Children, +) -> impl IntoView { + provide_context(canisters_res); let referrer_query = use_query::(); let referrer_principal = move || { @@ -49,27 +53,16 @@ fn CanistersProvider(id: DelegatedIdentityWire) -> impl IntoView { let canisters_res = create_resource( move || MockPartialEq(auth()), - move |id| do_canister_auth(id.0), + move |id| async move { + let cans = try_or_redirect_opt!(do_canister_auth(id.0).await); + Some(cans) + }, ); view! { - - {move || { - canisters_res() - .and_then(|cans| { - let cans = try_or_redirect_opt!(cans); - let canisters: Canisters = try_or_redirect_opt!(cans.try_into()); - Some( - view! { - - - - }, - ) - }) - }} - - + + + } } diff --git a/src/component/canisters_prov.rs b/src/component/canisters_prov.rs new file mode 100644 index 00000000..e682ac76 --- /dev/null +++ b/src/component/canisters_prov.rs @@ -0,0 +1,99 @@ +use futures::Future; +pub use leptos::*; + +use crate::state::canisters::{authenticated_canisters, Canisters}; + +#[component] +pub fn AuthCansProvider( + #[prop(into, optional)] fallback: ViewFn, + children: EF, +) -> impl IntoView +where + N: IntoView + 'static, + EF: Fn(Canisters) -> N + 'static + Clone, +{ + let cans_res = authenticated_canisters(); + let children = store_value(children); + view! { + + {move || { + let cans_wire = cans_res().flatten()?; + Some((children.get_value())(cans_wire.try_into().unwrap())) + }} + + + } +} + +#[component] +fn DataLoader( + cans: Canisters, + fallback: ViewFn, + with: DF, + children: EF, +) -> impl IntoView +where + N: IntoView + 'static, + EF: Fn((Canisters, D)) -> N + 'static + Clone, + DFut: Future, + D: Serializable + Clone + 'static, + DF: Fn(Canisters) -> DFut + 'static + Clone, +{ + let can_c = cans.clone(); + let with_res = create_resource( + || (), + move |_| { + let cans = can_c.clone(); + let with = with.clone(); + async move { (with)(cans).await } + }, + ); + + let cans = store_value(cans.clone()); + let children = store_value(children); + + view! { + + {move || with_res().map(move |d| (children.get_value())((cans.get_value(), d)))} + + } +} + +#[component] +pub fn WithAuthCans( + #[prop(into)] fallback: ViewFn, + with: DF, + children: EF, +) -> impl IntoView +where + N: IntoView + 'static, + EF: Fn((Canisters, D)) -> N + 'static + Clone, + DFut: Future, + D: Serializable + Clone + 'static, + DF: Fn(Canisters) -> DFut + 'static + Clone, +{ + let cans_res = authenticated_canisters(); + let fallback = store_value(fallback); + let children = store_value(children); + let with = store_value(with); + view! { + + {move || { + let cans_wire = cans_res().flatten()?; + let cans: Canisters = cans_wire.try_into().unwrap(); + Some( + view! { + + }, + ) + }} + + + } +} diff --git a/src/component/mod.rs b/src/component/mod.rs index ec3c2885..0457ca8f 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -3,6 +3,7 @@ pub mod auth_providers; pub mod back_btn; pub mod base_route; pub mod bullet_loader; +pub mod canisters_prov; pub mod coming_soon; pub mod connect; pub mod feed_popup; diff --git a/src/page/menu.rs b/src/page/menu.rs index 195f2a6e..1045c099 100644 --- a/src/page/menu.rs +++ b/src/page/menu.rs @@ -1,9 +1,10 @@ use crate::component::back_btn::BackButton; +use crate::component::canisters_prov::AuthCansProvider; use crate::component::title::Title; use crate::component::{connect::ConnectLogin, social::*, toggle::Toggle}; use crate::consts::{social, NSFW_TOGGLE_STORE}; use crate::state::auth::account_connected_reader; -use crate::state::canisters::authenticated_canisters; +use crate::utils::profile::ProfileDetails; use leptos::html::Input; use leptos::*; use leptos_icons::*; @@ -62,10 +63,18 @@ fn MenuFooter() -> impl IntoView { } #[component] -fn ProfileInfo() -> impl IntoView { - let canisters = authenticated_canisters(); - let user_details = canisters.profile_details(); +fn ProfileLoading() -> impl IntoView { + view! { +
+
+
+
+
+ } +} +#[component] +fn ProfileLoaded(user_details: ProfileDetails) -> impl IntoView { view! {
@@ -84,6 +93,15 @@ fn ProfileInfo() -> impl IntoView { } } +#[component] +fn ProfileInfo() -> impl IntoView { + view! { + + + + } +} + #[component] fn NsfwToggle() -> impl IntoView { let (nsfw_enabled, set_nsfw_enabled, _) = diff --git a/src/page/post_view/mod.rs b/src/page/post_view/mod.rs index bbc2a7d7..b8a94826 100644 --- a/src/page/post_view/mod.rs +++ b/src/page/post_view/mod.rs @@ -14,9 +14,9 @@ use leptos_use::{ }; use crate::{ - component::spinner::FullScreenSpinner, + component::{canisters_prov::AuthCansProvider, spinner::FullScreenSpinner}, consts::NSFW_TOGGLE_STORE, - state::canisters::authenticated_canisters, + state::canisters::{unauth_canisters, Canisters}, try_or_redirect, utils::route::{failure_redirect, go_to_root}, }; @@ -180,41 +180,45 @@ pub fn PostViewWithUpdates(initial_post: Option) -> impl IntoView { }) } let (nsfw_enabled, _, _) = use_local_storage::(NSFW_TOGGLE_STORE); + let auth_canisters = create_rw_signal(None::>); - let canisters = authenticated_canisters(); - let fetch_video_action = create_action(move |()| { - let canisters = canisters.clone(); - async move { - loop { - let Some(cursor) = fetch_cursor.try_get_untracked() else { - return; - }; - let nsfw_enabled = nsfw_enabled.get_untracked(); + let fetch_video_action = create_action(move |()| async move { + loop { + let Some(cursor) = fetch_cursor.try_get_untracked() else { + return; + }; + let auth_canisters = auth_canisters.get_untracked(); + let nsfw_enabled = nsfw_enabled.get_untracked(); + let unauth_canisters = unauth_canisters(); - let fetch_stream = VideoFetchStream::new(&canisters, cursor); - let chunks = fetch_stream.fetch_post_uids_chunked(3, nsfw_enabled).await; + let chunks = if let Some(canisters) = auth_canisters.as_ref() { + let fetch_stream = VideoFetchStream::new(canisters, cursor); + fetch_stream.fetch_post_uids_chunked(3, nsfw_enabled).await + } else { + let fetch_stream = VideoFetchStream::new(&unauth_canisters, cursor); + fetch_stream.fetch_post_uids_chunked(3, nsfw_enabled).await + }; - let res = try_or_redirect!(chunks); - let mut chunks = res.posts_stream; - let mut cnt = 0; - while let Some(chunk) = chunks.next().await { - cnt += chunk.len(); - video_queue.update(|q| { - for uid in chunk { - let uid = try_or_redirect!(uid); - q.push(uid); - } - }); - } - if res.end || cnt >= 8 { - queue_end.set(res.end); - break; - } - fetch_cursor.update(|c| c.advance()); + let res = try_or_redirect!(chunks); + let mut chunks = res.posts_stream; + let mut cnt = 0; + while let Some(chunk) = chunks.next().await { + cnt += chunk.len(); + video_queue.update(|q| { + for uid in chunk { + let uid = try_or_redirect!(uid); + q.push(uid); + } + }); + } + if res.end || cnt >= 8 { + queue_end.set(res.end); + break; } - fetch_cursor.update(|c| c.advance()); } + + fetch_cursor.update(|c| c.advance()); }); create_effect(move |_| { if !recovering_state.get_untracked() { @@ -249,7 +253,12 @@ pub fn PostViewWithUpdates(initial_post: Option) -> impl IntoView { ); }); - view! { } + view! { + + + {move || auth_canisters.set(Some(cans.clone()))} + + } } #[component] @@ -265,7 +274,7 @@ pub fn PostView() -> impl IntoView { }; let PostViewCtx { .. } = expect_context(); - let canisters = authenticated_canisters(); + let canisters = unauth_canisters(); let fetch_first_video_uid = create_resource( || (), diff --git a/src/page/post_view/overlay.rs b/src/page/post_view/overlay.rs index 6b68bacf..66964098 100644 --- a/src/page/post_view/overlay.rs +++ b/src/page/post_view/overlay.rs @@ -1,8 +1,9 @@ use crate::{ - component::modal::Modal, - state::canisters::authenticated_canisters, + component::{canisters_prov::WithAuthCans, modal::Modal}, + state::canisters::Canisters, utils::{ - event_streaming::events::LikeVideo, + event_streaming::events::{LikeVideo, ShareVideo}, + route::failure_redirect, web::{copy_to_clipboard, share_url}, }, }; @@ -10,7 +11,7 @@ use leptos::*; use leptos_icons::*; use leptos_use::use_window; -use super::video_iter::PostDetails; +use super::video_iter::{post_liked_by_me, PostDetails}; #[component] fn LikeButtonPlaceHolder() -> impl IntoView { @@ -26,11 +27,11 @@ fn LikeButtonPlaceHolder() -> impl IntoView { #[component] fn LikeButton( + canisters: Canisters, post_details: PostDetails, likes: RwSignal, initial_liked: bool, ) -> impl IntoView { - let canisters = authenticated_canisters(); let liked = create_rw_signal(initial_liked); let icon_class = Signal::derive(move || { if liked() { @@ -55,10 +56,6 @@ fn LikeButton( let post_details = post_details.clone(); async move { - let user = canisters.authenticated_user(); - let user_details = user.get_profile_details().await.unwrap(); - let canister_id = canisters.user_canister(); - batch(move || { if liked.get_untracked() { likes.update(|l| *l -= 1); @@ -67,7 +64,7 @@ fn LikeButton( likes.update(|l| *l += 1); liked.set(true); - LikeVideo.send_event(user_details, post_details, canister_id, likes); + LikeVideo.send_event(post_details, likes); } }); let individual = canisters.individual_user(post_canister); @@ -97,9 +94,28 @@ fn LikeButton( #[component] fn LikeLoader(post: PostDetails, likes: RwSignal) -> impl IntoView { - let initial_liked = post.liked_by_user; + let liked = post.liked_by_user; + let canister_id = post.canister_id; + let post_id = post.post_id; + let liked_fetch = move |cans: Canisters| async move { + if let Some(liked) = liked { + return liked; + } - view! { } + match post_liked_by_me(&cans, canister_id, post_id).await { + Ok(liked) => liked, + Err(e) => { + failure_redirect(e); + false + } + } + }; + + view! { + + + + } } #[component] @@ -131,29 +147,15 @@ pub fn VideoDetailsOverlay(post: PostDetails) -> impl IntoView { let post_details = post.clone(); - let auth_cans = authenticated_canisters(); - - let share = create_action(move |&()| { + let share = move || { let post_details = post_details.clone(); - let canisters = auth_cans.clone(); - async move { - let url = video_url(); - if share_url(&url).is_some() { - return; - } - show_share.set(true); - - #[cfg(all(feature = "hydrate", feature = "ga4"))] - { - use crate::utils::event_streaming::events::ShareVideo; - - let user_details = canisters.profile_details(); - let canister_id = canisters.user_canister(); - - ShareVideo.send_event(post_details, user_details, canister_id); - } + let url = video_url(); + if share_url(&url).is_some() { + return; } - }); + show_share.set(true); + ShareVideo.send_event(post_details); + }; let profile_url = format!("/profile/{}", post.poster_principal.to_text()); let post_c = post.clone(); @@ -185,7 +187,7 @@ pub fn VideoDetailsOverlay(post: PostDetails) -> impl IntoView { -
diff --git a/src/page/post_view/video_iter.rs b/src/page/post_view/video_iter.rs index 47b169f9..d7077e77 100644 --- a/src/page/post_view/video_iter.rs +++ b/src/page/post_view/video_iter.rs @@ -37,8 +37,8 @@ impl FetchCursor { } } -pub async fn get_post_uid( - canisters: &Canisters, +pub async fn get_post_uid( + canisters: &Canisters, user_canister: Principal, post_id: u64, ) -> Result, PostViewError> { @@ -65,6 +65,7 @@ pub async fn get_post_uid( } Ok(Some(PostDetails::from_canister_post( + AUTH, user_canister, post_details, ))) @@ -92,7 +93,9 @@ pub struct PostDetails { pub likes: u64, pub display_name: String, pub propic_url: String, - pub liked_by_user: bool, + /// Whether post is liked by the authenticated + /// user or not, None if unknown + pub liked_by_user: Option, pub poster_principal: Principal, pub hastags: Vec, pub is_nsfw: bool, @@ -100,7 +103,11 @@ pub struct PostDetails { } impl PostDetails { - pub fn from_canister_post(canister_id: Principal, details: PostDetailsForFrontend) -> Self { + pub fn from_canister_post( + authenticated: bool, + canister_id: Principal, + details: PostDetailsForFrontend, + ) -> Self { Self { canister_id, post_id: details.id, @@ -115,7 +122,7 @@ impl PostDetails { propic_url: details .created_by_profile_photo_url .unwrap_or_else(|| propic_from_principal(details.created_by_user_principal_id)), - liked_by_user: details.liked_by_me, + liked_by_user: authenticated.then_some(details.liked_by_me), poster_principal: details.created_by_user_principal_id, hastags: details.hashtags, is_nsfw: details.is_nsfw, @@ -131,13 +138,13 @@ pub struct FetchVideosRes<'a> { pub end: bool, } -pub struct VideoFetchStream<'a> { - canisters: &'a Canisters, +pub struct VideoFetchStream<'a, const AUTH: bool> { + canisters: &'a Canisters, cursor: FetchCursor, } -impl<'a> VideoFetchStream<'a> { - pub fn new(canisters: &'a Canisters, cursor: FetchCursor) -> Self { +impl<'a, const AUTH: bool> VideoFetchStream<'a, AUTH> { + pub fn new(canisters: &'a Canisters, cursor: FetchCursor) -> Self { Self { canisters, cursor } } diff --git a/src/page/refer_earn/history.rs b/src/page/refer_earn/history.rs index ee6e18d0..62928936 100644 --- a/src/page/refer_earn/history.rs +++ b/src/page/refer_earn/history.rs @@ -1,8 +1,10 @@ use leptos::*; +use crate::component::bullet_loader::BulletLoader; +use crate::component::canisters_prov::AuthCansProvider; use crate::component::infinite_scroller::InfiniteScroller; use crate::{ - state::canisters::authenticated_canisters, + state::canisters::Canisters, utils::{profile::propic_from_principal, timestamp::get_day_month}, }; use history_provider::*; @@ -31,8 +33,7 @@ fn HistoryItem(detail: HistoryDetails, _ref: NodeRef) -> impl IntoVie } #[component] -pub fn HistoryView() -> impl IntoView { - let canisters = authenticated_canisters(); +fn AuthenticatedHistory(canisters: Canisters) -> impl IntoView { let provider = get_history_provider(canisters); view! {
@@ -48,6 +49,15 @@ pub fn HistoryView() -> impl IntoView { } } +#[component] +pub fn HistoryView() -> impl IntoView { + view! { + + + + } +} + mod history_provider { use candid::Principal; diff --git a/src/page/refer_earn/mod.rs b/src/page/refer_earn/mod.rs index 415a44e3..1c588e46 100644 --- a/src/page/refer_earn/mod.rs +++ b/src/page/refer_earn/mod.rs @@ -7,11 +7,12 @@ use leptos_icons::*; use leptos_router::create_query_signal; use leptos_use::use_window; +use crate::component::canisters_prov::AuthCansProvider; use crate::component::connect::ConnectLogin; use crate::utils::event_streaming::events::{Refer, ReferShareLink}; use crate::{ component::{back_btn::BackButton, title::Title}, - state::{auth::account_connected_reader, canisters::authenticated_canisters}, + state::auth::account_connected_reader, utils::web::copy_to_clipboard, }; use history::HistoryView; @@ -64,11 +65,21 @@ fn ReferLoaded(user_principal: Principal) -> impl IntoView { } #[component] -fn ReferCode() -> impl IntoView { - let canisters = authenticated_canisters(); - let user_principal = canisters.identity().sender().unwrap(); +fn ReferLoading() -> impl IntoView { + view! { +
+ +
+ } +} - view! { } +#[component] +fn ReferCode() -> impl IntoView { + view! { + + + + } } #[component] diff --git a/src/page/upload/mod.rs b/src/page/upload/mod.rs index 865f0176..a3776c08 100644 --- a/src/page/upload/mod.rs +++ b/src/page/upload/mod.rs @@ -4,7 +4,6 @@ mod video_upload; use crate::{ component::toggle::ToggleWithLabel, - state::canisters::authenticated_canisters, utils::event_streaming::events::{VideoUploadInitiated, VideoUploadUploadButtonClicked}, }; @@ -52,24 +51,10 @@ fn PreUploadView(trigger_upload: WriteSignal>) -> impl Into let enable_hot_or_not = create_node_ref::(); let is_nsfw = create_node_ref::(); - let canisters = authenticated_canisters(); - let details = canisters.profile_details(); - - VideoUploadInitiated.send_event( - details.principal, - details.display_name.clone(), - canisters.user_canister(), - ); + VideoUploadInitiated.send_event(); let on_submit = move || { - VideoUploadUploadButtonClicked.send_event( - hashtag_inp, - is_nsfw, - enable_hot_or_not, - details.principal, - details.display_name.clone(), - canisters.user_canister(), - ); + VideoUploadUploadButtonClicked.send_event(hashtag_inp, is_nsfw, enable_hot_or_not); let description = desc.get_untracked().unwrap().value(); let hashtags = hashtags.get_untracked(); diff --git a/src/page/upload/video_upload.rs b/src/page/upload/video_upload.rs index 7e1fa3e9..2d0c697a 100644 --- a/src/page/upload/video_upload.rs +++ b/src/page/upload/video_upload.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::{ component::modal::Modal, - state::canisters::authenticated_canisters, + state::canisters::{authenticated_canisters, Canisters}, try_or_redirect_opt, utils::{ event_streaming::events::{ @@ -62,26 +62,16 @@ pub fn PreVideoUpload(file_blob: WriteSignal>) -> impl IntoV #[cfg(feature = "hydrate")] { - let canisters = authenticated_canisters(); - let details = canisters.profile_details(); - let user_canister = canisters.user_canister(); - use leptos::ev::change; _ = use_event_listener(file_ref, change, move |ev| { use wasm_bindgen::JsCast; use web_sys::HtmlInputElement; - let display_name = details.display_name.clone(); ev.target().and_then(move |target| { let input: &HtmlInputElement = target.dyn_ref()?; let inp_file = input.files()?.get(0)?; file.set(Some(FileWithUrl::new(inp_file.into()))); - VideoUploadVideoSelected.send_event( - details.principal, - display_name.clone(), - user_canister, - ); - + VideoUploadVideoSelected.send_event(); Some(()) }); }); @@ -192,107 +182,79 @@ pub fn VideoUploader(params: UploadParams) -> impl IntoView { let is_nsfw = params.is_nsfw; let enable_hot_or_not = params.enable_hot_or_not; - let canisters = authenticated_canisters(); - let details = canisters.profile_details(); - let user_id = details.principal; - let display_name = details.display_name; - let canister_id = canisters.user_canister(); - let up_desc = description.clone(); - let display_c = display_name.clone(); - let upload_action = create_action(move |_: &()| { - let hashtags = up_hashtags.clone(); - let description = up_desc.clone(); - let file_blob = file_blob.clone(); - let display_name = display_c.clone(); - async move { - let time_ms = SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap() - .as_millis(); + let upload_action = create_resource( + || (), + move |_| { + let hashtags = up_hashtags.clone(); + let description = up_desc.clone(); + let file_blob = file_blob.clone(); + async move { + let time_ms = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_millis(); + + let res = get_upload_info( + Principal::anonymous(), + hashtags, + description, + time_ms.to_string(), + ) + .await; - let res = get_upload_info( - Principal::anonymous(), - hashtags, - description, - time_ms.to_string(), - ) - .await; + if res.is_err() { + let e = res.as_ref().err().unwrap().to_string(); + VideoUploadUnsuccessful.send_event(e, hashtags_len, is_nsfw, enable_hot_or_not); + } - if res.is_err() { - let e = res.as_ref().err().unwrap().to_string(); - VideoUploadUnsuccessful.send_event( - e, - hashtags_len, - is_nsfw, - enable_hot_or_not, - user_id, - display_name.clone(), - canister_id, - ); - } + let upload_info = try_or_redirect_opt!(res); - let upload_info = try_or_redirect_opt!(res); + let res = upload_video_stream(&upload_info, &file_blob).await; - let res = upload_video_stream(&upload_info, &file_blob).await; + if res.is_err() { + let e = res.as_ref().err().unwrap().to_string(); + VideoUploadUnsuccessful.send_event(e, hashtags_len, is_nsfw, enable_hot_or_not); + } - if res.is_err() { - let e = res.as_ref().err().unwrap().to_string(); - VideoUploadUnsuccessful.send_event( - e, - hashtags_len, - is_nsfw, - enable_hot_or_not, - user_id, - display_name.clone(), - canister_id, - ); - } + try_or_redirect_opt!(res); - try_or_redirect_opt!(res); + uploading.set(false); - uploading.set(false); + let mut check_status = IntervalStream::new(4000); + while (check_status.next().await).is_some() { + let uid = upload_info.uid.clone(); + let res = get_video_status(uid).await; - let mut check_status = IntervalStream::new(4000); - while (check_status.next().await).is_some() { - let uid = upload_info.uid.clone(); - let res = get_video_status(uid).await; + if res.is_err() { + let e = res.as_ref().err().unwrap().to_string(); + VideoUploadUnsuccessful.send_event( + e, + hashtags_len, + is_nsfw, + enable_hot_or_not, + ); + } - if res.is_err() { - let e = res.as_ref().err().unwrap().to_string(); - VideoUploadUnsuccessful.send_event( - e, - hashtags_len, - is_nsfw, - enable_hot_or_not, - user_id, - display_name.clone(), - canister_id, - ); + let status = try_or_redirect_opt!(res); + if status == "ready" { + break; + } } + processing.set(false); - let status = try_or_redirect_opt!(res); - if status == "ready" { - break; - } + Some(upload_info.uid) } - processing.set(false); - - Some(upload_info.uid) - } - }); - upload_action.dispatch(()); + }, + ); - let upload_uid = upload_action.value(); - let display_c = display_name.clone(); - let publish_action = create_action(move |uid: &String| { + let publish_action = create_action(move |(canisters, uid): &(Canisters, String)| { let canisters = canisters.clone(); let hashtags = hashtags.clone(); let hashtags_len = hashtags.len(); let description = description.clone(); let uid = uid.clone(); - let display_name = display_c.clone(); async move { let res = publish_video( canisters, @@ -306,33 +268,19 @@ pub fn VideoUploader(params: UploadParams) -> impl IntoView { if res.is_err() { let e = res.as_ref().err().unwrap().to_string(); - VideoUploadUnsuccessful.send_event( - e, - hashtags_len, - is_nsfw, - enable_hot_or_not, - user_id, - display_name.clone(), - canister_id, - ); + VideoUploadUnsuccessful.send_event(e, hashtags_len, is_nsfw, enable_hot_or_not); } try_or_redirect_opt!(res); publishing.set(false); - VideoUploadSuccessful.send_event( - hashtags_len, - is_nsfw, - enable_hot_or_not, - user_id, - display_name.clone(), - canister_id, - ); + VideoUploadSuccessful.send_event(hashtags_len, is_nsfw, enable_hot_or_not); Some(()) } }); + let cans_res = authenticated_canisters(); view! {
@@ -355,12 +303,15 @@ pub fn VideoUploader(params: UploadParams) -> impl IntoView {
- {move || { - let uid = upload_uid().flatten()?; - publish_action.dispatch(uid); - Some(()) - }} - + + {move || { + let uid = upload_action().flatten()?; + let canisters = cans_res().flatten()?; + publish_action.dispatch((canisters.try_into().unwrap(), uid)); + Some(()) + }} + +
+ {likes} } } @@ -89,6 +90,7 @@ fn LikeButton( > + {likes} } } @@ -112,7 +114,11 @@ fn LikeLoader(post: PostDetails, likes: RwSignal) -> impl IntoView { }; view! { - + } + let:d + > } @@ -121,12 +127,10 @@ fn LikeLoader(post: PostDetails, likes: RwSignal) -> impl IntoView { #[component] fn LikeAndAuthCanLoader(post: PostDetails) -> impl IntoView { let likes = create_rw_signal(post.likes); - let post = store_value(post); view! {
- - {likes} +
} } diff --git a/src/page/post_view/video_loader.rs b/src/page/post_view/video_loader.rs index 2445a815..9a3cf618 100644 --- a/src/page/post_view/video_loader.rs +++ b/src/page/post_view/video_loader.rs @@ -25,7 +25,7 @@ pub fn BgView(idx: usize, children: Children) -> impl IntoView { current_idx, .. } = expect_context(); - let post = move || video_queue.with(|q| q.get(idx).cloned()); + let post = create_memo(move |_| video_queue.with(|q| q.get(idx).cloned())); let uid = move || post().as_ref().map(|q| q.uid.clone()).unwrap_or_default(); let (is_connected, _) = account_connected_reader(); From d62181e2fb210de65f2454d81773cb343def2349 Mon Sep 17 00:00:00 2001 From: rupansh Date: Tue, 23 Apr 2024 05:26:55 +0530 Subject: [PATCH 6/9] fix: fix login flow --- src/component/base_route.rs | 5 +++- src/state/canisters.rs | 4 +++ src/state/history.rs | 6 ++++- src/utils/event_streaming/events.rs | 42 ++++++++++++++--------------- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/component/base_route.rs b/src/component/base_route.rs index 06c1f13e..74f7e11d 100644 --- a/src/component/base_route.rs +++ b/src/component/base_route.rs @@ -49,12 +49,15 @@ fn CtxProvider( #[component] fn CanistersProvider(id: DelegatedIdentityWire) -> impl IntoView { - let auth = AuthState::new(id); + let auth = use_context().unwrap_or_else(move || AuthState::new(id)); + let canisters_store = create_rw_signal(None); + provide_context(canisters_store); let canisters_res = create_resource( move || MockPartialEq(auth()), move |id| async move { let cans = try_or_redirect_opt!(do_canister_auth(id.0).await); + canisters_store.set(Some(cans.clone())); Some(cans) }, ); diff --git a/src/state/canisters.rs b/src/state/canisters.rs index 8f74d344..024c1ea8 100644 --- a/src/state/canisters.rs +++ b/src/state/canisters.rs @@ -250,3 +250,7 @@ pub type AuthCansResource = pub fn authenticated_canisters() -> AuthCansResource { expect_context() } + +pub fn auth_canisters_store() -> RwSignal>> { + expect_context() +} diff --git a/src/state/history.rs b/src/state/history.rs index 04530088..0bfa49a2 100644 --- a/src/state/history.rs +++ b/src/state/history.rs @@ -1,5 +1,5 @@ use circular_buffer::CircularBuffer; -use leptos::{RwSignal, SignalGet, SignalUpdate, SignalWith}; +use leptos::{RwSignal, SignalGet, SignalUpdate, SignalWith, SignalWithUntracked}; #[derive(Clone)] pub struct HistoryCtx { @@ -45,6 +45,10 @@ impl HistoryCtx { self.history.with(|h| h.back().cloned()) } + pub fn prev_url_untracked(&self) -> Option { + self.history.with_untracked(|h| h.back().cloned()) + } + pub fn log_history(&self) -> String { let history = self.history.get(); let history_str = history diff --git a/src/utils/event_streaming/events.rs b/src/utils/event_streaming/events.rs index 309f53c0..09895779 100644 --- a/src/utils/event_streaming/events.rs +++ b/src/utils/event_streaming/events.rs @@ -1,14 +1,14 @@ use candid::Principal; use ic_agent::Identity; use leptos::html::Input; -use leptos::{create_effect, ReadSignal, RwSignal, SignalGetUntracked}; +use leptos::{create_effect, use_context, ReadSignal, RwSignal, SignalGetUntracked}; use leptos::{create_signal, ev, expect_context, html::Video, Memo, NodeRef, SignalGet, SignalSet}; use leptos_use::use_event_listener; use serde_json::json; use wasm_bindgen::JsCast; use crate::component::auth_providers::ProviderKind; -use crate::state::canisters::{authenticated_canisters, Canisters}; +use crate::state::canisters::Canisters; use crate::state::history::HistoryCtx; #[cfg(feature = "ga4")] use crate::utils::event_streaming::{send_event, send_event_warehouse, send_user_id}; @@ -46,13 +46,13 @@ struct UserDetails { #[cfg(feature = "ga4")] impl UserDetails { fn try_get() -> Option { - let cans_res = authenticated_canisters(); - let canisters = cans_res.get().flatten()?; - let details = canisters.profile_details; + let cans_store: RwSignal>> = use_context()?; + let canisters = cans_store.get_untracked()?; + let details = canisters.profile_details(); Some(Self { details, - canister_id: canisters.user_canister, + canister_id: canisters.user_canister(), }) } } @@ -460,21 +460,19 @@ impl Refer { let canister_id = user.canister_id; let history_ctx: HistoryCtx = expect_context(); - let prev_site = history_ctx.prev_url(); + let prev_site = history_ctx.prev_url_untracked(); // refer - analytics - create_effect(move |_| { - send_event( - "refer", - &json!({ - "user_id":user_id, - "is_loggedIn": logged_in.get(), - "display_name": display_name, - "canister_id": canister_id, - "refer_location": prev_site, - }), - ); - }); + send_event( + "refer", + &json!({ + "user_id":user_id, + "is_loggedIn": logged_in.get_untracked(), + "display_name": display_name, + "canister_id": canister_id, + "refer_location": prev_site, + }), + ); } } } @@ -495,14 +493,14 @@ impl ReferShareLink { let canister_id = user.canister_id; let history_ctx: HistoryCtx = expect_context(); - let prev_site = history_ctx.prev_url(); + let prev_site = history_ctx.prev_url_untracked(); // refer_share_link - analytics send_event( "refer_share_link", &json!({ "user_id":user_id, - "is_loggedIn": logged_in.get(), + "is_loggedIn": logged_in.get_untracked(), "display_name": display_name, "canister_id": canister_id, "refer_location": prev_site, @@ -604,7 +602,7 @@ impl LoginCta { send_event( "login_cta", &json!({ - "previous_event": event_history.event_name.get(), + "previous_event": event_history.event_name.get_untracked(), "cta_location": cta_location, }), ); From 762c1cd742c84849828cc2bc0fbadcdf650d017a Mon Sep 17 00:00:00 2001 From: rupansh Date: Tue, 23 Apr 2024 23:28:15 +0530 Subject: [PATCH 7/9] refactor+feat: support lazy loading auth identity --- Cargo.lock | 1 + Cargo.toml | 2 + src/auth/mod.rs | 51 +++++++++++++- src/auth/server_impl/mod.rs | 74 +++++++++++++++++--- src/component/auth_providers/mod.rs | 2 +- src/component/base_route.rs | 60 ++++++++-------- src/component/canisters_prov.rs | 57 +++++++-------- src/component/logout.rs | 2 +- src/consts.rs | 2 + src/page/post_view/mod.rs | 11 +-- src/page/post_view/overlay.rs | 103 ++++++++++------------------ src/page/upload/video_upload.rs | 4 +- src/state/auth/mod.rs | 18 +---- src/state/canisters.rs | 8 ++- 14 files changed, 229 insertions(+), 166 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23d03310..173a3640 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1832,6 +1832,7 @@ dependencies = [ "gloo-utils", "gob-cloudflare", "hex", + "hmac", "http 1.1.0", "ic-agent", "icondata", diff --git a/Cargo.toml b/Cargo.toml index 31956df9..c51457c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -91,6 +91,7 @@ tonic = { version = "0.11.0", features = [ "tls-webpki-roots", ], optional = true } prost = { version = "0.12.4", optional = true } +hmac = { version = "0.12.1", optional = true } [build-dependencies] serde = { version = "1.0", features = ["derive"] } @@ -132,6 +133,7 @@ ssr = [ "bb8-redis", "tonic", "prost", + "hmac", ] # Fetch mock referral history instead of history via canister mock-referral-history = ["dep:rand_chacha", "k256/arithmetic"] diff --git a/src/auth/mod.rs b/src/auth/mod.rs index 2d7bb0e8..d65a7c17 100644 --- a/src/auth/mod.rs +++ b/src/auth/mod.rs @@ -1,13 +1,14 @@ #[cfg(feature = "ssr")] pub mod server_impl; +use candid::Principal; use ic_agent::identity::{DelegatedIdentity, Secp256k1Identity, SignedDelegation}; use k256::elliptic_curve::JwkEcKey; -use leptos::{server, ServerFnError}; +use leptos::{server, server_fn::codec::Cbor, ServerFnError}; use serde::{Deserialize, Serialize}; /// Delegated identity that can be serialized over the wire -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone)] pub struct DelegatedIdentityWire { /// raw bytes of delegated identity's public key from_key: Vec, @@ -19,6 +20,44 @@ pub struct DelegatedIdentityWire { delegation_chain: Vec, } +impl std::fmt::Debug for DelegatedIdentityWire { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("DelegatedIdentityWire").finish() + } +} + +#[derive(Clone, Copy, Deserialize, Serialize, PartialEq, Eq)] +pub enum RefreshTokenKind { + Upgraded, + Temporary, +} + +impl Default for RefreshTokenKind { + fn default() -> Self { + Self::Upgraded + } +} + +#[derive(Clone, Copy, Deserialize, Serialize, PartialEq, Eq)] +pub struct RefreshToken { + principal: Principal, + expiry_epoch_ms: u128, + #[serde(default)] + kind: RefreshTokenKind, +} + +#[derive(Clone, Deserialize, Serialize, PartialEq, Eq)] +pub struct TempRefreshToken { + inner: RefreshToken, + digest: Vec, +} + +impl std::fmt::Debug for TempRefreshToken { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TempRefreshToken").finish() + } +} + impl TryFrom for DelegatedIdentity { type Error = k256::elliptic_curve::Error; @@ -34,10 +73,16 @@ impl TryFrom for DelegatedIdentity { } #[server] -pub async fn extract_or_generate_identity() -> Result { +pub async fn extract_or_generate_identity( +) -> Result<(DelegatedIdentityWire, TempRefreshToken), ServerFnError> { server_impl::extract_or_generate_identity_impl().await } +#[server(input = Cbor)] +pub async fn upgrade_temp_refresh_token(token: TempRefreshToken) -> Result<(), ServerFnError> { + server_impl::upgrade_temp_refresh_token_impl(token).await +} + #[server] pub async fn logout_identity() -> Result { server_impl::logout_identity_impl().await diff --git a/src/auth/server_impl/mod.rs b/src/auth/server_impl/mod.rs index b8b7130d..85ee8f23 100644 --- a/src/auth/server_impl/mod.rs +++ b/src/auth/server_impl/mod.rs @@ -8,24 +8,27 @@ use axum_extra::extract::{ SignedCookieJar, }; use candid::Principal; +use hmac::{Hmac, Mac}; use http::header; use ic_agent::{ identity::{Delegation, Secp256k1Identity, SignedDelegation}, Identity, }; +use k256::sha2::Sha256; use leptos::{expect_context, ServerFnError}; use leptos_axum::{extract_with_state, ResponseOptions}; use rand_chacha::rand_core::OsRng; -use serde::{Deserialize, Serialize}; use crate::{ - consts::auth::{DELEGATION_MAX_AGE, REFRESH_MAX_AGE, REFRESH_TOKEN_COOKIE}, + consts::auth::{ + DELEGATION_MAX_AGE, REFRESH_MAX_AGE, REFRESH_TOKEN_COOKIE, TEMP_REFRESH_MAX_AGE, + }, utils::current_epoch, }; use self::store::{KVStore, KVStoreImpl}; -use super::DelegatedIdentityWire; +use super::{DelegatedIdentityWire, RefreshToken, RefreshTokenKind, TempRefreshToken}; impl DelegatedIdentityWire { pub fn delegate(from: &impl Identity) -> Self { @@ -64,12 +67,6 @@ fn set_cookies(resp: &ResponseOptions, jar: impl IntoResponse) { } } -#[derive(Clone, Copy, Deserialize, Serialize)] -struct RefreshToken { - principal: Principal, - expiry_epoch_ms: u128, -} - async fn extract_principal_from_cookie( jar: &SignedCookieJar, ) -> Result, ServerFnError> { @@ -123,6 +120,7 @@ pub async fn update_user_identity( let refresh_token = RefreshToken { principal: identity.sender().unwrap(), expiry_epoch_ms: (current_epoch() + refresh_max_age).as_millis(), + kind: RefreshTokenKind::Upgraded, }; let refresh_token_enc = serde_json::to_string(&refresh_token)?; @@ -131,6 +129,7 @@ pub async fn update_user_identity( .secure(true) .path("/") .same_site(SameSite::None) + .partitioned(true) .max_age(refresh_max_age.try_into().unwrap()); jar = jar.add(refresh_cookie); @@ -139,7 +138,8 @@ pub async fn update_user_identity( Ok(DelegatedIdentityWire::delegate(&identity)) } -pub async fn extract_or_generate_identity_impl() -> Result { +pub async fn extract_or_generate_identity_impl( +) -> Result<(DelegatedIdentityWire, TempRefreshToken), ServerFnError> { let key: Key = expect_context(); let jar: SignedCookieJar = extract_with_state(&key).await?; let kv: KVStoreImpl = expect_context(); @@ -150,10 +150,62 @@ pub async fn extract_or_generate_identity_impl() -> Result::new_from_slice(s_key)?; + mac.update(&raw); + let s_temp_refresh_token = TempRefreshToken { + inner: temp_refresh_token, + digest: mac.finalize().into_bytes().to_vec(), + }; + let resp: ResponseOptions = expect_context(); let delegated = update_user_identity(&resp, jar, base_identity).await?; - Ok(delegated) + Ok((delegated, s_temp_refresh_token)) +} + +pub async fn upgrade_temp_refresh_token_impl(token: TempRefreshToken) -> Result<(), ServerFnError> { + if token.inner.expiry_epoch_ms < current_epoch().as_millis() { + return Err(ServerFnError::new("Expired token")); + } + if token.inner.kind != RefreshTokenKind::Temporary { + return Err(ServerFnError::new("Invalid token kind")); + } + + let key: Key = expect_context(); + let mut jar: SignedCookieJar = extract_with_state(&key).await?; + + let s_key = key.signing(); + let mut mac = Hmac::::new_from_slice(s_key)?; + let raw_claim = serde_json::to_vec(&token.inner)?; + mac.update(&raw_claim); + mac.verify_slice(&token.digest)?; + + let resp: ResponseOptions = expect_context(); + let refresh_token = RefreshToken { + principal: token.inner.principal, + expiry_epoch_ms: (current_epoch() + REFRESH_MAX_AGE).as_millis(), + kind: RefreshTokenKind::Upgraded, + }; + let refresh_token_enc = serde_json::to_string(&refresh_token)?; + let refresh_cookie = Cookie::build((REFRESH_TOKEN_COOKIE, refresh_token_enc)) + .http_only(true) + .secure(true) + .path("/") + .same_site(SameSite::None) + .partitioned(true) + .max_age(REFRESH_MAX_AGE.try_into().unwrap()); + + jar = jar.add(refresh_cookie); + set_cookies(&resp, jar); + + Ok(()) } pub async fn logout_identity_impl() -> Result { diff --git a/src/component/auth_providers/mod.rs b/src/component/auth_providers/mod.rs index 26d62a81..58741f1b 100644 --- a/src/component/auth_providers/mod.rs +++ b/src/component/auth_providers/mod.rs @@ -160,7 +160,7 @@ pub fn LoginProviders(show_modal: RwSignal, lock_closing: RwSignal) login_complete: SignalSetter::map(move |val: DelegatedIdentityWire| { new_identity.set(Some(val.clone())); write_account_connected(true); - auth.set(val); + auth.set(Some(val)); show_modal.set(false); }), }; diff --git a/src/component/base_route.rs b/src/component/base_route.rs index 74f7e11d..11211cc1 100644 --- a/src/component/base_route.rs +++ b/src/component/base_route.rs @@ -3,14 +3,13 @@ use leptos::*; use leptos_router::*; use crate::{ - auth::DelegatedIdentityWire, - component::spinner::FullScreenSpinner, + auth::{extract_or_generate_identity, upgrade_temp_refresh_token, TempRefreshToken}, state::{ - auth::{auth_resource, AuthState}, - canisters::{do_canister_auth, AuthCansResource}, + auth::AuthState, + canisters::{do_canister_auth, AuthCansResource, Canisters}, local_storage::use_referrer_store, }, - try_or_redirect_opt, + try_or_redirect, utils::MockPartialEq, }; @@ -48,40 +47,47 @@ fn CtxProvider( } #[component] -fn CanistersProvider(id: DelegatedIdentityWire) -> impl IntoView { - let auth = use_context().unwrap_or_else(move || AuthState::new(id)); - let canisters_store = create_rw_signal(None); +pub fn BaseRoute() -> impl IntoView { + let auth = AuthState::default(); + let canisters_store = create_rw_signal(None::>); provide_context(canisters_store); + let temp_refresh_token = create_rw_signal(None::); let canisters_res = create_resource( move || MockPartialEq(auth()), - move |id| async move { - let cans = try_or_redirect_opt!(do_canister_auth(id.0).await); - canisters_store.set(Some(cans.clone())); - Some(cans) + move |auth_id| async move { + let (id, temp_tok) = if let Some(id) = auth_id.0 { + (id, None) + } else { + let (id, temp_tok) = extract_or_generate_identity().await?; + (id, Some(temp_tok)) + }; + let cans = do_canister_auth(id).await?; + Ok((cans, temp_tok)) }, ); + let _refresh_token_upgrade = + create_local_resource(temp_refresh_token, |temp_token| async move { + let Some(temp_token) = temp_token else { + return; + }; + if let Err(e) = upgrade_temp_refresh_token(temp_token).await { + log::warn!("failed to upgrade temp refresh token: {e}... ignoring"); + } + }); view! { - } -} - -/// Base route is technically rendered **adjacent** to all routes -/// do not use it for any parent -> child communication, such as passing global context -#[component] -pub fn BaseRoute() -> impl IntoView { - let id_res = auth_resource(); - - view! { - + {move || { - id_res() - .flatten() - .map(move |id| { - view! { } + canisters_res() + .map(|res| { + let (cans, temp_tok) = try_or_redirect!(res); + let cans = try_or_redirect!(cans.try_into()); + canisters_store.set(Some(cans)); + temp_refresh_token.set(temp_tok); }) }} diff --git a/src/component/canisters_prov.rs b/src/component/canisters_prov.rs index 129ca38b..e101e07b 100644 --- a/src/component/canisters_prov.rs +++ b/src/component/canisters_prov.rs @@ -14,21 +14,23 @@ where { let cans_res = authenticated_canisters(); let children = store_value(children); - view! { - - {move || { - let cans_wire = cans_res().flatten()?; - Some((children.get_value())(cans_wire.try_into().unwrap())) - }} + let loader = move || { + let (cans_wire, _) = cans_res()?.ok()?; + let cans = cans_wire.try_into().ok()?; + Some((children.get_value())(cans).into_view()) + }; + let fallback = store_value(fallback); - + view! { + {move || loader().unwrap_or_else(|| fallback.get_value().run())} } } #[component] fn DataLoader( cans: Canisters, - fallback: ViewFn, + fallback: StoredValue, with: DF, children: EF, ) -> impl IntoView @@ -40,7 +42,7 @@ where DF: Fn(Canisters) -> DFut + 'static + Clone, { let can_c = cans.clone(); - let with_res = create_blocking_resource( + let with_res = create_resource( || (), move |_| { let cans = can_c.clone(); @@ -53,15 +55,21 @@ where let children = store_value(children); view! { - - {move || with_res().map(move |d| (children.get_value())((cans.get_value(), d)))} + + {move || { + with_res() + .map(move |d| (children.get_value())((cans.get_value(), d)).into_view()) + .unwrap_or_else(move || fallback.get_value().run()) + }} + } } #[component] pub fn WithAuthCans( - #[prop(into)] fallback: ViewFn, + #[prop(into, optional)] fallback: ViewFn, with: DF, children: EF, ) -> impl IntoView @@ -76,24 +84,19 @@ where let fallback = store_value(fallback); let children = store_value(children); let with = store_value(with); + + let loader = move || { + let (cans_wire, _) = cans_res()?.ok()?; + let cans: Canisters = cans_wire.try_into().ok()?; + Some( + view! { }, + ) + }; + view! { - {move || { - let cans_wire = cans_res().flatten()?; - let cans: Canisters = cans_wire.try_into().unwrap(); - Some( - view! { - - }, - ) - }} - + {move || loader().unwrap_or_else(move || fallback.get_value().run())} } } diff --git a/src/component/logout.rs b/src/component/logout.rs index 28167db1..103a9366 100644 --- a/src/component/logout.rs +++ b/src/component/logout.rs @@ -23,7 +23,7 @@ pub fn Logout() -> impl IntoView { LogoutConfirmation.send_event(); let auth = auth_state(); - auth.set(id); + auth.set(Some(id)); let (_, write_account_connected, _) = use_local_storage::(ACCOUNT_CONNECTED_STORE); diff --git a/src/consts.rs b/src/consts.rs index dbc4eb65..1730faad 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -33,6 +33,8 @@ pub mod auth { pub const DELEGATION_MAX_AGE: Duration = Duration::from_secs(60 * 60 * 24 * 7); /// Refresh expiry, 30 days pub const REFRESH_MAX_AGE: Duration = Duration::from_secs(60 * 60 * 24 * 30); + /// Temporary refresh token, 5 minutes + pub const TEMP_REFRESH_MAX_AGE: Duration = Duration::from_secs(60 * 5); pub const REFRESH_TOKEN_COOKIE: &str = "user-identity"; } diff --git a/src/page/post_view/mod.rs b/src/page/post_view/mod.rs index b8a94826..c97180ad 100644 --- a/src/page/post_view/mod.rs +++ b/src/page/post_view/mod.rs @@ -14,7 +14,7 @@ use leptos_use::{ }; use crate::{ - component::{canisters_prov::AuthCansProvider, spinner::FullScreenSpinner}, + component::spinner::FullScreenSpinner, consts::NSFW_TOGGLE_STORE, state::canisters::{unauth_canisters, Canisters}, try_or_redirect, @@ -180,7 +180,7 @@ pub fn PostViewWithUpdates(initial_post: Option) -> impl IntoView { }) } let (nsfw_enabled, _, _) = use_local_storage::(NSFW_TOGGLE_STORE); - let auth_canisters = create_rw_signal(None::>); + let auth_canisters: RwSignal>> = expect_context(); let fetch_video_action = create_action(move |()| async move { loop { @@ -253,12 +253,7 @@ pub fn PostViewWithUpdates(initial_post: Option) -> impl IntoView { ); }); - view! { - - - {move || auth_canisters.set(Some(cans.clone()))} - - } + view! { } } #[component] diff --git a/src/page/post_view/overlay.rs b/src/page/post_view/overlay.rs index c3565b08..1bd3d81e 100644 --- a/src/page/post_view/overlay.rs +++ b/src/page/post_view/overlay.rs @@ -1,6 +1,6 @@ use crate::{ component::{canisters_prov::WithAuthCans, modal::Modal}, - state::canisters::Canisters, + state::canisters::{auth_canisters_store, Canisters}, utils::{ event_streaming::events::{LikeVideo, ShareVideo}, route::failure_redirect, @@ -14,56 +14,45 @@ use leptos_use::use_window; use super::video_iter::{post_liked_by_me, PostDetails}; #[component] -fn LikeButtonPlaceHolder(likes: u64) -> impl IntoView { - view! { - - {likes} - } -} +fn LikeAndAuthCanLoader(post: PostDetails) -> impl IntoView { + let likes = create_rw_signal(post.likes); -#[component] -fn LikeButton( - canisters: Canisters, - post_details: PostDetails, - likes: RwSignal, - initial_liked: bool, -) -> impl IntoView { - let liked = create_rw_signal(initial_liked); + let liked = create_rw_signal(None::); let icon_class = Signal::derive(move || { - if liked() { - TextProp::from("fill-primary-600") + if liked().unwrap_or_default() { + Some(TextProp::from("fill-primary-600")) } else { - TextProp::from("text-white") + None } }); let icon_style = Signal::derive(move || { - if liked() { + if liked().unwrap_or_default() { Some(TextProp::from("filter: drop-shadow(2px 0 0 white) drop-shadow(-2px 0 0 white) drop-shadow(0 2px 0 white) drop-shadow(0 -2px 0 white);")) } else { None } }); - let post_canister = post_details.canister_id; - let post_id = post_details.post_id; - let like_toggle = create_action(move |&()| { - let canisters = canisters.clone(); + let post_canister = post.canister_id; + let post_id = post.post_id; + let initial_liked = post.liked_by_user; + let canisters = auth_canisters_store(); - let post_details = post_details.clone(); + let like_toggle = create_action(move |&()| { + let post_details = post.clone(); async move { + let Some(canisters) = canisters.get_untracked() else { + log::warn!("Trying to toggle like without auth"); + return; + }; batch(move || { - if liked.get_untracked() { + if liked.get_untracked().unwrap_or_default() { likes.update(|l| *l -= 1); - liked.set(false) + liked.set(Some(false)); } else { likes.update(|l| *l += 1); - liked.set(true); + liked.set(Some(true)); LikeVideo.send_event(post_details, likes); } @@ -76,35 +65,18 @@ fn LikeButton( Ok(_) => (), Err(e) => { log::warn!("Error toggling like status: {:?}", e); - liked.update(|l| *l = !*l); + liked.update(|l| _ = l.as_mut().map(|l| *l = !*l)); } } } }); - view! { - - {likes} - } -} - -#[component] -fn LikeLoader(post: PostDetails, likes: RwSignal) -> impl IntoView { - let liked = post.liked_by_user; - let canister_id = post.canister_id; - let post_id = post.post_id; let liked_fetch = move |cans: Canisters| async move { - if let Some(liked) = liked { + if let Some(liked) = initial_liked { return liked; } - match post_liked_by_me(&cans, canister_id, post_id).await { + match post_liked_by_me(&cans, post_canister, post_id).await { Ok(liked) => liked, Err(e) => { failure_redirect(e); @@ -113,25 +85,22 @@ fn LikeLoader(post: PostDetails, likes: RwSignal) -> impl IntoView { } }; - view! { - } - let:d - > - - - } -} - -#[component] -fn LikeAndAuthCanLoader(post: PostDetails) -> impl IntoView { - let likes = create_rw_signal(post.likes); + let liking = like_toggle.pending(); view! {
- + + {likes}
+ + {move || liked.set(Some(d.1))} + } } diff --git a/src/page/upload/video_upload.rs b/src/page/upload/video_upload.rs index 2d0c697a..470ca69f 100644 --- a/src/page/upload/video_upload.rs +++ b/src/page/upload/video_upload.rs @@ -306,8 +306,8 @@ pub fn VideoUploader(params: UploadParams) -> impl IntoView { {move || { let uid = upload_action().flatten()?; - let canisters = cans_res().flatten()?; - publish_action.dispatch((canisters.try_into().unwrap(), uid)); + let (canisters, _) = cans_res()?.ok()?; + publish_action.dispatch((canisters.try_into().ok()?, uid)); Some(()) }} diff --git a/src/state/auth/mod.rs b/src/state/auth/mod.rs index 3bf8f9cc..a6565650 100644 --- a/src/state/auth/mod.rs +++ b/src/state/auth/mod.rs @@ -1,23 +1,9 @@ use leptos::*; use leptos_use::{storage::use_local_storage, utils::FromToStringCodec}; -use crate::{ - auth::{extract_or_generate_identity, DelegatedIdentityWire}, - consts::ACCOUNT_CONNECTED_STORE, - try_or_redirect_opt, -}; +use crate::{auth::DelegatedIdentityWire, consts::ACCOUNT_CONNECTED_STORE}; -pub fn auth_resource() -> Resource<(), Option> { - create_blocking_resource( - || (), - |_| async move { - let id = try_or_redirect_opt!(extract_or_generate_identity().await); - Some(id) - }, - ) -} - -pub type AuthState = RwSignal; +pub type AuthState = RwSignal>; pub fn auth_state() -> AuthState { expect_context() diff --git a/src/state/canisters.rs b/src/state/canisters.rs index 024c1ea8..dbd2fd83 100644 --- a/src/state/canisters.rs +++ b/src/state/canisters.rs @@ -8,7 +8,7 @@ use yral_metadata_client::MetadataClient; use yral_metadata_types::UserMetadata; use crate::{ - auth::DelegatedIdentityWire, + auth::{DelegatedIdentityWire, TempRefreshToken}, canister::{ individual_user_template::{IndividualUserTemplate, Result8}, platform_orchestrator::{self, PlatformOrchestrator}, @@ -244,8 +244,10 @@ pub async fn do_canister_auth( }) } -pub type AuthCansResource = - Resource, Option>; +pub type AuthCansResource = Resource< + MockPartialEq>, + Result<(AuthCanistersWire, Option), ServerFnError>, +>; pub fn authenticated_canisters() -> AuthCansResource { expect_context() From 2ff6a5d2e99e17c1703016bd87f009e1d4be14ab Mon Sep 17 00:00:00 2001 From: rupansh Date: Thu, 25 Apr 2024 00:14:35 +0530 Subject: [PATCH 8/9] perf: improve initial loading time --- src/auth/mod.rs | 36 +------------ src/auth/server_impl/mod.rs | 66 ++---------------------- src/component/auth_providers/mod.rs | 3 +- src/component/base_route.rs | 27 +++------- src/component/canisters_prov.rs | 6 +-- src/consts.rs | 2 - src/page/post_view/mod.rs | 80 ++++++++++++++++------------- src/page/upload/video_upload.rs | 4 +- src/state/canisters.rs | 48 ++--------------- 9 files changed, 68 insertions(+), 204 deletions(-) diff --git a/src/auth/mod.rs b/src/auth/mod.rs index d65a7c17..83b6d6fd 100644 --- a/src/auth/mod.rs +++ b/src/auth/mod.rs @@ -4,7 +4,7 @@ pub mod server_impl; use candid::Principal; use ic_agent::identity::{DelegatedIdentity, Secp256k1Identity, SignedDelegation}; use k256::elliptic_curve::JwkEcKey; -use leptos::{server, server_fn::codec::Cbor, ServerFnError}; +use leptos::{server, ServerFnError}; use serde::{Deserialize, Serialize}; /// Delegated identity that can be serialized over the wire @@ -26,36 +26,10 @@ impl std::fmt::Debug for DelegatedIdentityWire { } } -#[derive(Clone, Copy, Deserialize, Serialize, PartialEq, Eq)] -pub enum RefreshTokenKind { - Upgraded, - Temporary, -} - -impl Default for RefreshTokenKind { - fn default() -> Self { - Self::Upgraded - } -} - #[derive(Clone, Copy, Deserialize, Serialize, PartialEq, Eq)] pub struct RefreshToken { principal: Principal, expiry_epoch_ms: u128, - #[serde(default)] - kind: RefreshTokenKind, -} - -#[derive(Clone, Deserialize, Serialize, PartialEq, Eq)] -pub struct TempRefreshToken { - inner: RefreshToken, - digest: Vec, -} - -impl std::fmt::Debug for TempRefreshToken { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("TempRefreshToken").finish() - } } impl TryFrom for DelegatedIdentity { @@ -73,16 +47,10 @@ impl TryFrom for DelegatedIdentity { } #[server] -pub async fn extract_or_generate_identity( -) -> Result<(DelegatedIdentityWire, TempRefreshToken), ServerFnError> { +pub async fn extract_or_generate_identity() -> Result { server_impl::extract_or_generate_identity_impl().await } -#[server(input = Cbor)] -pub async fn upgrade_temp_refresh_token(token: TempRefreshToken) -> Result<(), ServerFnError> { - server_impl::upgrade_temp_refresh_token_impl(token).await -} - #[server] pub async fn logout_identity() -> Result { server_impl::logout_identity_impl().await diff --git a/src/auth/server_impl/mod.rs b/src/auth/server_impl/mod.rs index 85ee8f23..9a420e05 100644 --- a/src/auth/server_impl/mod.rs +++ b/src/auth/server_impl/mod.rs @@ -8,27 +8,23 @@ use axum_extra::extract::{ SignedCookieJar, }; use candid::Principal; -use hmac::{Hmac, Mac}; use http::header; use ic_agent::{ identity::{Delegation, Secp256k1Identity, SignedDelegation}, Identity, }; -use k256::sha2::Sha256; use leptos::{expect_context, ServerFnError}; use leptos_axum::{extract_with_state, ResponseOptions}; use rand_chacha::rand_core::OsRng; use crate::{ - consts::auth::{ - DELEGATION_MAX_AGE, REFRESH_MAX_AGE, REFRESH_TOKEN_COOKIE, TEMP_REFRESH_MAX_AGE, - }, + consts::auth::{DELEGATION_MAX_AGE, REFRESH_MAX_AGE, REFRESH_TOKEN_COOKIE}, utils::current_epoch, }; use self::store::{KVStore, KVStoreImpl}; -use super::{DelegatedIdentityWire, RefreshToken, RefreshTokenKind, TempRefreshToken}; +use super::{DelegatedIdentityWire, RefreshToken}; impl DelegatedIdentityWire { pub fn delegate(from: &impl Identity) -> Self { @@ -120,7 +116,6 @@ pub async fn update_user_identity( let refresh_token = RefreshToken { principal: identity.sender().unwrap(), expiry_epoch_ms: (current_epoch() + refresh_max_age).as_millis(), - kind: RefreshTokenKind::Upgraded, }; let refresh_token_enc = serde_json::to_string(&refresh_token)?; @@ -138,8 +133,7 @@ pub async fn update_user_identity( Ok(DelegatedIdentityWire::delegate(&identity)) } -pub async fn extract_or_generate_identity_impl( -) -> Result<(DelegatedIdentityWire, TempRefreshToken), ServerFnError> { +pub async fn extract_or_generate_identity_impl() -> Result { let key: Key = expect_context(); let jar: SignedCookieJar = extract_with_state(&key).await?; let kv: KVStoreImpl = expect_context(); @@ -150,62 +144,10 @@ pub async fn extract_or_generate_identity_impl( generate_and_save_identity(&kv).await? }; - let temp_refresh_token = RefreshToken { - principal: base_identity.sender().unwrap(), - expiry_epoch_ms: (current_epoch() + TEMP_REFRESH_MAX_AGE).as_millis(), - kind: RefreshTokenKind::Temporary, - }; - let s_key = key.signing(); - let raw = serde_json::to_vec(&temp_refresh_token)?; - let mut mac = Hmac::::new_from_slice(s_key)?; - mac.update(&raw); - let s_temp_refresh_token = TempRefreshToken { - inner: temp_refresh_token, - digest: mac.finalize().into_bytes().to_vec(), - }; - let resp: ResponseOptions = expect_context(); let delegated = update_user_identity(&resp, jar, base_identity).await?; - Ok((delegated, s_temp_refresh_token)) -} - -pub async fn upgrade_temp_refresh_token_impl(token: TempRefreshToken) -> Result<(), ServerFnError> { - if token.inner.expiry_epoch_ms < current_epoch().as_millis() { - return Err(ServerFnError::new("Expired token")); - } - if token.inner.kind != RefreshTokenKind::Temporary { - return Err(ServerFnError::new("Invalid token kind")); - } - - let key: Key = expect_context(); - let mut jar: SignedCookieJar = extract_with_state(&key).await?; - - let s_key = key.signing(); - let mut mac = Hmac::::new_from_slice(s_key)?; - let raw_claim = serde_json::to_vec(&token.inner)?; - mac.update(&raw_claim); - mac.verify_slice(&token.digest)?; - - let resp: ResponseOptions = expect_context(); - let refresh_token = RefreshToken { - principal: token.inner.principal, - expiry_epoch_ms: (current_epoch() + REFRESH_MAX_AGE).as_millis(), - kind: RefreshTokenKind::Upgraded, - }; - let refresh_token_enc = serde_json::to_string(&refresh_token)?; - let refresh_cookie = Cookie::build((REFRESH_TOKEN_COOKIE, refresh_token_enc)) - .http_only(true) - .secure(true) - .path("/") - .same_site(SameSite::None) - .partitioned(true) - .max_age(REFRESH_MAX_AGE.try_into().unwrap()); - - jar = jar.add(refresh_cookie); - set_cookies(&resp, jar); - - Ok(()) + Ok(delegated) } pub async fn logout_identity_impl() -> Result { diff --git a/src/component/auth_providers/mod.rs b/src/component/auth_providers/mod.rs index 58741f1b..85b3650c 100644 --- a/src/component/auth_providers/mod.rs +++ b/src/component/auth_providers/mod.rs @@ -138,8 +138,7 @@ pub fn LoginProviders(show_modal: RwSignal, lock_closing: RwSignal) let referrer = referrer_store.get_untracked(); // This is some redundant work, but saves us 100+ lines of resource handling - let canisters: Canisters = - do_canister_auth(identity.clone()).await?.try_into()?; + let canisters: Canisters = do_canister_auth(identity.clone()).await?; if let Err(e) = handle_user_login(canisters.clone(), referrer).await { log::warn!("failed to handle user login, err {e}. skipping"); diff --git a/src/component/base_route.rs b/src/component/base_route.rs index 11211cc1..daa1a7d9 100644 --- a/src/component/base_route.rs +++ b/src/component/base_route.rs @@ -3,7 +3,7 @@ use leptos::*; use leptos_router::*; use crate::{ - auth::{extract_or_generate_identity, upgrade_temp_refresh_token, TempRefreshToken}, + auth::extract_or_generate_identity, state::{ auth::AuthState, canisters::{do_canister_auth, AuthCansResource, Canisters}, @@ -52,29 +52,18 @@ pub fn BaseRoute() -> impl IntoView { let canisters_store = create_rw_signal(None::>); provide_context(canisters_store); - let temp_refresh_token = create_rw_signal(None::); - let canisters_res = create_resource( + let canisters_res = create_local_resource( move || MockPartialEq(auth()), move |auth_id| async move { - let (id, temp_tok) = if let Some(id) = auth_id.0 { - (id, None) + let id = if let Some(id) = auth_id.0 { + id } else { - let (id, temp_tok) = extract_or_generate_identity().await?; - (id, Some(temp_tok)) + extract_or_generate_identity().await? }; let cans = do_canister_auth(id).await?; - Ok((cans, temp_tok)) + Ok(cans) }, ); - let _refresh_token_upgrade = - create_local_resource(temp_refresh_token, |temp_token| async move { - let Some(temp_token) = temp_token else { - return; - }; - if let Err(e) = upgrade_temp_refresh_token(temp_token).await { - log::warn!("failed to upgrade temp refresh token: {e}... ignoring"); - } - }); view! { @@ -84,10 +73,8 @@ pub fn BaseRoute() -> impl IntoView { {move || { canisters_res() .map(|res| { - let (cans, temp_tok) = try_or_redirect!(res); - let cans = try_or_redirect!(cans.try_into()); + let cans = try_or_redirect!(res); canisters_store.set(Some(cans)); - temp_refresh_token.set(temp_tok); }) }} diff --git a/src/component/canisters_prov.rs b/src/component/canisters_prov.rs index e101e07b..aec245c7 100644 --- a/src/component/canisters_prov.rs +++ b/src/component/canisters_prov.rs @@ -15,8 +15,7 @@ where let cans_res = authenticated_canisters(); let children = store_value(children); let loader = move || { - let (cans_wire, _) = cans_res()?.ok()?; - let cans = cans_wire.try_into().ok()?; + let cans = cans_res()?.ok()?; Some((children.get_value())(cans).into_view()) }; let fallback = store_value(fallback); @@ -86,8 +85,7 @@ where let with = store_value(with); let loader = move || { - let (cans_wire, _) = cans_res()?.ok()?; - let cans: Canisters = cans_wire.try_into().ok()?; + let cans = cans_res()?.ok()?; Some( view! { }, ) diff --git a/src/consts.rs b/src/consts.rs index 1730faad..dbc4eb65 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -33,8 +33,6 @@ pub mod auth { pub const DELEGATION_MAX_AGE: Duration = Duration::from_secs(60 * 60 * 24 * 7); /// Refresh expiry, 30 days pub const REFRESH_MAX_AGE: Duration = Duration::from_secs(60 * 60 * 24 * 30); - /// Temporary refresh token, 5 minutes - pub const TEMP_REFRESH_MAX_AGE: Duration = Duration::from_secs(60 * 5); pub const REFRESH_TOKEN_COOKIE: &str = "user-identity"; } diff --git a/src/page/post_view/mod.rs b/src/page/post_view/mod.rs index c97180ad..540ea003 100644 --- a/src/page/post_view/mod.rs +++ b/src/page/post_view/mod.rs @@ -18,7 +18,7 @@ use crate::{ consts::NSFW_TOGGLE_STORE, state::canisters::{unauth_canisters, Canisters}, try_or_redirect, - utils::route::{failure_redirect, go_to_root}, + utils::route::failure_redirect, }; use video_iter::{get_post_uid, VideoFetchStream}; use video_loader::{BgView, VideoView}; @@ -26,9 +26,9 @@ use video_loader::{BgView, VideoView}; use overlay::HomeButtonOverlay; use video_iter::{FetchCursor, PostDetails}; -#[derive(Params, PartialEq)] +#[derive(Params, PartialEq, Clone, Copy)] struct PostParams { - canister_id: String, + canister_id: Principal, post_id: u64, } @@ -204,7 +204,7 @@ pub fn PostViewWithUpdates(initial_post: Option) -> impl IntoView { let mut cnt = 0; while let Some(chunk) = chunks.next().await { cnt += chunk.len(); - video_queue.update(|q| { + video_queue.try_update(|q| { for uid in chunk { let uid = try_or_redirect!(uid); q.push(uid); @@ -212,13 +212,13 @@ pub fn PostViewWithUpdates(initial_post: Option) -> impl IntoView { }); } if res.end || cnt >= 8 { - queue_end.set(res.end); + queue_end.try_set(res.end); break; } - fetch_cursor.update(|c| c.advance()); + fetch_cursor.try_update(|c| c.advance()); } - fetch_cursor.update(|c| c.advance()); + fetch_cursor.try_update(|c| c.advance()); }); create_effect(move |_| { if !recovering_state.get_untracked() { @@ -259,46 +259,56 @@ pub fn PostViewWithUpdates(initial_post: Option) -> impl IntoView { #[component] pub fn PostView() -> impl IntoView { let params = use_params::(); - let canister_and_post = move || { - params.with_untracked(|p| { - let p = p.as_ref().ok()?; - let canister_id = Principal::from_text(&p.canister_id).ok()?; + let initial_canister_and_post = create_rw_signal(params.get_untracked().ok()); - Some((canister_id, p.post_id)) - }) - }; + create_effect(move |_| { + if initial_canister_and_post.with_untracked(|p| p.is_some()) { + return None; + } + let p = params.get().ok()?; + initial_canister_and_post.set(Some(p)); + Some(()) + }); - let PostViewCtx { .. } = expect_context(); + let PostViewCtx { + video_queue, + current_idx, + .. + } = expect_context(); let canisters = unauth_canisters(); - let fetch_first_video_uid = create_resource( - || (), - move |_| { - let canisters = canisters.clone(); - async move { - let Some((canister, post_id)) = canister_and_post() else { - go_to_root(); - return None; - }; + let fetch_first_video_uid = create_resource(initial_canister_and_post, move |params| { + let canisters = canisters.clone(); + async move { + let Some(params) = params else { + return Err(()); + }; + let cached_post = video_queue + .with_untracked(|q| q.get(current_idx.get_untracked()).cloned()) + .filter(|post| { + post.canister_id == params.canister_id && post.post_id == params.post_id + }); + if let Some(post) = cached_post { + return Ok(Some(post)); + } - match get_post_uid(&canisters, canister, post_id).await { - Ok(Some(uid)) => Some(uid), - Err(e) => { - failure_redirect(e); - None - } - Ok(None) => None, + match get_post_uid(&canisters, params.canister_id, params.post_id).await { + Ok(post) => Ok(post), + Err(e) => { + failure_redirect(e); + Err(()) } } - }, - ); + } + }); view! { {move || { fetch_first_video_uid() - .map(|initial_post| { - view! { } + .and_then(|initial_post| { + let initial_post = initial_post.ok()?; + Some(view! { }) }) }} diff --git a/src/page/upload/video_upload.rs b/src/page/upload/video_upload.rs index 470ca69f..900acbe5 100644 --- a/src/page/upload/video_upload.rs +++ b/src/page/upload/video_upload.rs @@ -306,8 +306,8 @@ pub fn VideoUploader(params: UploadParams) -> impl IntoView { {move || { let uid = upload_action().flatten()?; - let (canisters, _) = cans_res()?.ok()?; - publish_action.dispatch((canisters.try_into().ok()?, uid)); + let canisters = cans_res()?.ok()?; + publish_action.dispatch((canisters, uid)); Some(()) }} diff --git a/src/state/canisters.rs b/src/state/canisters.rs index dbd2fd83..840c23a4 100644 --- a/src/state/canisters.rs +++ b/src/state/canisters.rs @@ -3,12 +3,11 @@ use std::{collections::HashSet, sync::Arc}; use candid::Principal; use ic_agent::{identity::DelegatedIdentity, AgentError, Identity}; use leptos::*; -use serde::{Deserialize, Serialize}; use yral_metadata_client::MetadataClient; use yral_metadata_types::UserMetadata; use crate::{ - auth::{DelegatedIdentityWire, TempRefreshToken}, + auth::DelegatedIdentityWire, canister::{ individual_user_template::{IndividualUserTemplate, Result8}, platform_orchestrator::{self, PlatformOrchestrator}, @@ -20,35 +19,6 @@ use crate::{ utils::{profile::ProfileDetails, MockPartialEq}, }; -#[derive(Serialize, Deserialize, Clone)] -pub struct AuthCanistersWire { - id: DelegatedIdentityWire, - pub user_canister: Principal, - pub profile_details: ProfileDetails, - expiry: u64, -} - -impl TryFrom for Canisters { - type Error = ServerFnError; - - fn try_from(value: AuthCanistersWire) -> Result { - let id: DelegatedIdentity = value.id.try_into()?; - let id = Arc::new(id); - Ok(Self { - agent: ic_agent::Agent::builder() - .with_url(AGENT_URL) - .with_arc_identity(id.clone()) - .build() - .unwrap(), - metadata_client: MetadataClient::with_base_url(METADATA_API_BASE.clone()), - id: Some(id), - user_canister: value.user_canister, - expiry: value.expiry, - profile_details: Some(value.profile_details), - }) - } -} - #[derive(Clone)] pub struct Canisters { agent: ic_agent::Agent, @@ -212,7 +182,7 @@ async fn create_individual_canister( pub async fn do_canister_auth( auth: DelegatedIdentityWire, -) -> Result { +) -> Result, ServerFnError> { let id: DelegatedIdentity = auth.clone().try_into()?; let mut canisters = Canisters::::authenticated(id); @@ -234,20 +204,12 @@ pub async fn do_canister_auth( Err(e) | Ok(Result8::Err(e)) => log::warn!("Failed to update last access time: {}", e), } canisters.profile_details = Some(user.get_profile_details().await?.into()); - let expiry = canisters.expiry; - Ok(AuthCanistersWire { - id: auth, - user_canister: canisters.user_canister, - profile_details: canisters.profile_details.clone().unwrap(), - expiry, - }) + Ok(canisters) } -pub type AuthCansResource = Resource< - MockPartialEq>, - Result<(AuthCanistersWire, Option), ServerFnError>, ->; +pub type AuthCansResource = + Resource>, Result, ServerFnError>>; pub fn authenticated_canisters() -> AuthCansResource { expect_context() From c31a5d19fc4728c11a5a75b41a9bb03eff25071a Mon Sep 17 00:00:00 2001 From: rupansh Date: Thu, 25 Apr 2024 00:25:37 +0530 Subject: [PATCH 9/9] fix(logout): fix logging out --- src/component/logout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/component/logout.rs b/src/component/logout.rs index 103a9366..d8e2cc12 100644 --- a/src/component/logout.rs +++ b/src/component/logout.rs @@ -14,6 +14,7 @@ use crate::{ #[component] pub fn Logout() -> impl IntoView { LogoutClicked.send_event(); + let auth = auth_state(); let auth_res = create_local_resource( || (), @@ -22,7 +23,6 @@ pub fn Logout() -> impl IntoView { LogoutConfirmation.send_event(); - let auth = auth_state(); auth.set(Some(id)); let (_, write_account_connected, _) =