summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@bunny.garden>2025-04-29 20:58:02 +0100
committerLibravatar cel 🌸 <cel@bunny.garden>2025-04-29 20:58:02 +0100
commit22141aa6d7b0f97441a60111046d1ef7260b68dc (patch)
tree68667672a2777aec2cfcf36575b973fb3e64e7f8
parent0e902e1f0a56e2f59cb91065a0ad8600631a1e49 (diff)
downloadmacaw-web-22141aa6d7b0f97441a60111046d1ef7260b68dc.tar.gz
macaw-web-22141aa6d7b0f97441a60111046d1ef7260b68dc.tar.bz2
macaw-web-22141aa6d7b0f97441a60111046d1ef7260b68dc.zip
fix: use_context works
-rw-r--r--Cargo.lock149
-rw-r--r--Cargo.toml3
-rw-r--r--src/lib.rs363
3 files changed, 307 insertions, 208 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 471b27e..62a6def 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,14 +4,14 @@ version = 4
[[package]]
name = "accessory"
-version = "2.0.0"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb3791c4beae5b827e93558ac83a88e63a841aad61759a05d9b577ef16030470"
+checksum = "28e416a3ab45838bac2ab2d81b1088d738d7b2d2c5272a54d39366565a29bd80"
dependencies = [
"macroific",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -90,7 +90,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -118,7 +118,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -129,7 +129,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -143,7 +143,7 @@ dependencies = [
"manyhow",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -159,7 +159,7 @@ dependencies = [
"proc-macro2",
"quote",
"quote-use",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -259,9 +259,9 @@ checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
[[package]]
name = "bytemuck"
-version = "1.22.0"
+version = "1.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
+checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c"
[[package]]
name = "byteorder-lite"
@@ -310,9 +310,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
-version = "0.4.40"
+version = "0.4.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
+checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
dependencies = [
"android-tzdata",
"iana-time-zone",
@@ -545,7 +545,7 @@ dependencies = [
"macroific",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -556,7 +556,7 @@ checksum = "2364b9aa47e460ce9bca6ac1777d14c98eef7e274eb077beed49f3adc94183ed"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -576,7 +576,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
"unicode-xid",
]
@@ -599,7 +599,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -715,7 +715,7 @@ dependencies = [
"macroific",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -868,7 +868,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -1243,7 +1243,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -1325,14 +1325,14 @@ checksum = "0ab604ee7085efba6efc65e4ebca0e9533e3aff6cb501d7d77b211e3a781c6d5"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
name = "indexed_db_futures"
-version = "0.6.1"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94eebf0199c01a1560770d964efb1fb09183a3afc0b1c1397fac1bfdbfa7d6cf"
+checksum = "ac6179b8a3ef894b4645271be8131a444679c8d39b8307d70cbb34e471b68ea4"
dependencies = [
"accessory",
"cfg-if",
@@ -1359,7 +1359,7 @@ dependencies = [
"macroific",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -1380,7 +1380,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -1579,7 +1579,7 @@ dependencies = [
"quote",
"rstml",
"serde",
- "syn 2.0.100",
+ "syn 2.0.101",
"walkdir",
]
@@ -1601,7 +1601,7 @@ dependencies = [
"quote",
"rstml",
"server_fn_macro",
- "syn 2.0.100",
+ "syn 2.0.101",
"uuid",
]
@@ -1760,6 +1760,7 @@ dependencies = [
"futures",
"getrandom 0.2.16",
"jid",
+ "js-sys",
"lazy_static",
"peanuts",
"pin-project",
@@ -1790,6 +1791,7 @@ dependencies = [
"leptos",
"leptos_meta",
"leptos_reactive",
+ "reactive_stores",
"serde",
"stylance",
"thiserror 2.0.12",
@@ -1819,7 +1821,7 @@ dependencies = [
"proc-macro2",
"quote",
"sealed",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -1831,7 +1833,7 @@ dependencies = [
"proc-macro2",
"quote",
"sealed",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -1844,7 +1846,7 @@ dependencies = [
"macroific_core",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -1856,7 +1858,7 @@ dependencies = [
"manyhow-macros",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -1982,7 +1984,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -2082,7 +2084,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -2162,7 +2164,7 @@ dependencies = [
[[package]]
name = "peanuts"
version = "0.1.0"
-source = "git+https://bunny.garden/peanuts#a0cc279551267dfa7a17fe4b449dd1a1fcd3526f"
+source = "git+https://bunny.garden/peanuts#9aa337bd703426f737c5d4f94fe84c4a646b7836"
dependencies = [
"async-recursion",
"circular",
@@ -2201,7 +2203,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -2251,7 +2253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6"
dependencies = [
"proc-macro2",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -2273,7 +2275,7 @@ dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -2304,7 +2306,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
"version_check",
"yansi",
]
@@ -2325,7 +2327,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30"
dependencies = [
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -2371,7 +2373,7 @@ dependencies = [
"proc-macro-utils",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -2526,7 +2528,7 @@ dependencies = [
"proc-macro-error2",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -2610,7 +2612,7 @@ dependencies = [
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
"syn_derive",
"thiserror 2.0.12",
]
@@ -2706,7 +2708,7 @@ checksum = "22f968c5ea23d555e670b449c1c5e7b2fc399fdaec1d304a17cd48e288abc107"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -2775,7 +2777,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -2850,7 +2852,7 @@ dependencies = [
"convert_case 0.6.0",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
"xxhash-rust",
]
@@ -2861,7 +2863,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb8b274f568c94226a8045668554aace8142a59b8bca5414ac5a79627c825568"
dependencies = [
"server_fn_macro",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -3044,7 +3046,7 @@ dependencies = [
"proc-macro2",
"quote",
"stylance-core",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -3066,9 +3068,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.100"
+version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
+checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [
"proc-macro2",
"quote",
@@ -3084,7 +3086,7 @@ dependencies = [
"proc-macro-error2",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -3095,7 +3097,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -3196,7 +3198,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -3207,7 +3209,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -3289,7 +3291,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -3323,14 +3325,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee80eb7e23abaa636caa9afe6042c6d8a8c0686165b8165f4fbf2988f0dd347f"
dependencies = [
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
name = "toml"
-version = "0.8.20"
+version = "0.8.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
+checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae"
dependencies = [
"serde",
"serde_spanned",
@@ -3340,27 +3342,34 @@ dependencies = [
[[package]]
name = "toml_datetime"
-version = "0.6.8"
+version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
+checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
-version = "0.22.24"
+version = "0.22.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
+checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
+ "toml_write",
"winnow 0.7.7",
]
[[package]]
+name = "toml_write"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076"
+
+[[package]]
name = "tracing"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3379,7 +3388,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -3481,7 +3490,7 @@ checksum = "3c36781cc0e46a83726d9879608e4cf6c2505237e263a8eb8c24502989cfdb28"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -3646,7 +3655,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
"wasm-bindgen-shared",
]
@@ -3681,7 +3690,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -3760,7 +3769,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -3771,7 +3780,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -4027,7 +4036,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
"synstructure",
]
@@ -4048,7 +4057,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
@@ -4068,7 +4077,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
"synstructure",
]
@@ -4091,7 +4100,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.100",
+ "syn 2.0.101",
]
[[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 5dc98c9..06662d9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,9 +9,10 @@ filamento = { path = "../luz/filamento", features = ["serde"] }
futures = "0.3.31"
indexmap = "2.9.0"
jid = { path = "../luz/jid" }
-leptos = { version = "0.7.8", features = ["csr"] }
+leptos = { version = "0.7.5", features = ["csr"] }
leptos_meta = "0.7.8"
leptos_reactive = { version = "0.6.15", features = ["csr"] }
+reactive_stores = "0.1.8"
serde = "1.0.219"
stylance = "0.6.0"
thiserror = "2.0.12"
diff --git a/src/lib.rs b/src/lib.rs
index b6e7cea..11ebc54 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,16 +1,36 @@
-use std::{ops::{Deref, DerefMut}, str::FromStr, sync::Arc, thread::sleep, time::{self, Duration}};
-
-use filamento::{chat::{Chat, Message}, db::Db, error::{CommandError, ConnectionError, DatabaseError}, files::FilesMem, user::User, UpdateMessage};
+use std::{
+ borrow::Borrow,
+ cell::RefCell,
+ collections::HashMap,
+ marker::PhantomData,
+ ops::{Deref, DerefMut},
+ rc::Rc,
+ str::FromStr,
+ sync::{atomic::AtomicUsize, Arc},
+ thread::sleep,
+ time::{self, Duration},
+};
+
+use filamento::{
+ chat::{Chat, Message},
+ db::Db,
+ error::{CommandError, ConnectionError, DatabaseError},
+ files::FilesMem,
+ user::User,
+ UpdateMessage,
+};
+use futures::stream::StreamExt;
use indexmap::IndexMap;
use jid::JID;
-use leptos::{prelude::*, task::spawn_local};
-use futures::stream::StreamExt;
+use leptos::{
+ prelude::*,
+ task::{spawn, spawn_local},
+};
use leptos_meta::Stylesheet;
-use leptos_query::{create_query, provide_query_client, provide_query_client_with_options, DefaultQueryOptions, QueryOptions, QueryResult, QueryScope};
-use leptos_reactive::{SignalGetUntracked, SignalStream};
+use reactive_stores::Store;
use stylance::import_style;
use thiserror::Error;
-use tokio::{sync::mpsc::Receiver};
+use tokio::sync::{mpsc::Receiver, Mutex};
use tracing::debug;
use uuid::Uuid;
@@ -43,7 +63,7 @@ impl DerefMut for Client {
#[component]
pub fn App() -> impl IntoView {
let (app, set_app) = signal(AppState::LoggedOut);
- let client: RwSignal<Option<(Client, Receiver<UpdateMessage>)>, LocalStorage> = RwSignal::new_local(None);
+ let client: RwSignal<Option<(Client, Receiver<UpdateMessage>)>> = RwSignal::new(None);
view! {
{move || match &*app.read() {
@@ -73,13 +93,13 @@ pub enum LoginError {
}
#[component]
-fn LoginPage(set_app: WriteSignal<AppState>, set_client: RwSignal<Option<(Client, Receiver<UpdateMessage>)>, LocalStorage>) -> impl IntoView {
+fn LoginPage(set_app: WriteSignal<AppState>, set_client: RwSignal<Option<(Client, Receiver<UpdateMessage>)>>) -> impl IntoView {
let jid = RwSignal::new("".to_string());
let password = RwSignal::new("".to_string());
let remember_me = RwSignal::new(false);
let connect_on_login = RwSignal::new(true);
- let (error, set_error) = signal_local(None::<LoginError>);
+ let (error, set_error) = signal(None::<LoginError>);
let error_message = move || {
error.with(|error| {
if let Some(error) = error {
@@ -128,7 +148,7 @@ fn LoginPage(set_app: WriteSignal<AppState>, set_client: RwSignal<Option<(Client
jid: Arc::new(jid),
file_store: files_mem,
};
- // TODO: connect on login
+
if *connect_on_login.read_untracked() {
match client.connect().await {
Ok(_) => {},
@@ -211,19 +231,26 @@ fn Macaw(
client: Client,
mut updates: Receiver<UpdateMessage>,
) -> impl IntoView {
- // TODO: is there some kind of context_local?
- let client = RwSignal::new_local(client);
provide_context(client);
let (new_messages, set_new_messages) = signal(None::<(JID, MacawMessage)>);
provide_context(new_messages);
- provide_query_client_with_options(DefaultQueryOptions {
- resource_option: leptos_query::ResourceOption::Local,
- ..Default::default()
- });
+ let messages_store: StateStore<Uuid, Store<Message>> = StateStore::new();
+ provide_context(RwSignal::new_local(messages_store));
+ let chats_store: StateStore<JID, Store<Chat>> = StateStore::new();
+ provide_context(RwSignal::new_local(chats_store));
+ let users_store: StateStore<JID, Store<User>> = StateStore::new();
+ provide_context(RwSignal::new_local(users_store));
- let updates_routine = OnceResource::new(async move {
+ // // here we create a signal in the root that can be consumed
+ // // anywhere in the app.
+ // let (count, set_count) = signal(0);
+ // // we'll pass the setter to specific components,
+ // // but provide the count itself to the whole app via context
+ // provide_context(count);
+
+ OnceResource::new(async move {
while let Some(update) = updates.recv().await {
match update {
UpdateMessage::Online(online, items) => {},
@@ -243,85 +270,148 @@ fn Macaw(
}
});
- view! {
- "logged in"
- <ChatsList />
+ view! { <ChatsList /> }
+}
+
+// V has to be an arc signal
+struct StateStore<K, V> {
+ store: Rc<RefCell<HashMap<K, (V, usize)>>>,
+}
+
+impl<K, V> Clone for StateStore<K, V> {
+ fn clone(&self) -> Self {
+ Self {
+ store: self.store.clone(),
+ }
}
}
-fn chat_query() -> QueryScope<JID, Result<Chat, String>> {
- create_query(get_chat, QueryOptions::default())
+impl<K, V> StateStore<K, V> {
+ pub fn new() -> Self {
+ Self {
+ store: Rc::new(RefCell::new(HashMap::new())),
+ }
+ }
+}
+
+impl<K: Eq + std::hash::Hash + Clone, V: Clone> StateStore<K, V> {
+ pub fn store(&self, key: K, value: V) -> StateListener<K, V> {
+ let mut store = self.store.borrow_mut();
+ if let Some((v, count)) = store.get_mut(&key) {
+ *v = value.clone();
+ *count += 1;
+ StateListener {
+ value,
+ cleaner: StateCleaner { key, _ty: PhantomData },
+ }
+ } else {
+ store.insert(key.clone(), (value.clone(), 1));
+ StateListener {
+ value,
+ cleaner: StateCleaner {
+ key,
+ _ty: PhantomData,
+ }
+ }
+ }
+ }
+
+ pub fn init() {
+
+ }
+}
+
+impl<K: Eq + std::hash::Hash , V> StateStore<K, V> {
+ pub fn update(&self, key: &K, value: V) {
+ if let Some((v, _)) = self.store.borrow_mut().get_mut(key) {
+ *v = value;
+ }
+ }
+
+ pub fn modify(&self, key: &K, modify: impl Fn(&mut V)) {
+ if let Some((v, _)) = self.store.borrow_mut().get_mut(key) {
+ modify(v);
+ }
+ }
+
+ fn remove(&self, key: &K) {
+ let mut store = self.store.borrow_mut();
+ if let Some((_v, count)) = store.get_mut(key) {
+ *count -= 1;
+ if *count == 0 {
+ store.remove(key);
+ }
+ }
+ }
}
-async fn get_chat(jid: JID) -> Result<Chat, String> {
- let client: Client = use_context::<RwSignal<Client, LocalStorage>>().unwrap().read_untracked().clone();
- client.get_chat(jid).await.map_err(|e| e.to_string())
+#[derive(Clone)]
+struct StateListener<K, V> where K: Eq + std::hash::Hash + 'static, V: 'static {
+ value: V,
+ cleaner: StateCleaner<K, V>
}
-fn user_query() -> QueryScope<JID, Result<User, String>> {
- create_query(get_user, QueryOptions::default())
+impl<K: std::cmp::Eq + std::hash::Hash, V> Deref for StateListener<K, V> {
+ type Target = V;
+
+ fn deref(&self) -> &Self::Target {
+ &self.value
+ }
}
-async fn get_user(jid: JID) -> Result<User, String> {
- let client: Client = use_context::<RwSignal<Client, LocalStorage>>().unwrap().read_untracked().clone();
- client.get_user(jid).await.map_err(|e| e.to_string())
+impl<K: std::cmp::Eq + std::hash::Hash, V> DerefMut for StateListener<K, V> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.value
+ }
}
-fn message_query() -> QueryScope<Uuid, Result<Message, String>> {
- create_query(get_message, QueryOptions::default())
+struct StateCleaner<K, V> where K: Eq + std::hash::Hash + 'static, V: 'static {
+ key: K,
+ _ty: PhantomData<V>,
+ // state_store: StateStore<K, V>,
}
-async fn get_message(id: Uuid) -> Result<Message, String> {
- let client: Client = use_context::<RwSignal<Client, LocalStorage>>().unwrap().read_untracked().clone();
- client.get_message(id).await.map_err(|e| e.to_string())
+impl<K, V> Clone for StateCleaner<K, V> where K: Eq + std::hash::Hash + Clone {
+ fn clone(&self) -> Self {
+ let state_store = use_context::<RwSignal<StateStore<K, V>, LocalStorage>>().unwrap();
+ if let Some((_v, count)) = state_store.read_untracked().store.borrow_mut().get_mut(&self.key) {
+ *count += 1;
+ }
+ Self {
+ key: self.key.clone(),
+ _ty: PhantomData,
+ }
+ }
}
-// fn got_chat(chat: Chat) -> QueryScope<JID, MacawChat> {
-// let fetcher = move |_| {
-// let chat = (&chat).clone();
-// async {
-// MacawChat {
-// chat
-// }
-// }};
-// create_query(fetcher, QueryOptions::default())
-// }
+impl<K: Eq + std::hash::Hash + 'static, V: 'static> Drop for StateCleaner<K, V> {
+ fn drop(&mut self) {
+ let state_store = use_context::<RwSignal<StateStore<K, V>, LocalStorage>>().unwrap();
+ state_store.read_untracked().remove(&self.key)
+ }
+}
#[derive(Clone)]
struct MacawChat {
- chat: ReadSignal<Option<Option<Result<Chat, String>>>>,
- user: ReadSignal<Option<Option<Result<User, String>>>>,
+ chat: StateListener<JID, Store<Chat>>,
+ user: StateListener<JID, Store<User>>,
}
impl MacawChat {
fn got_chat_and_user(chat: Chat, user: User) -> Self {
- let correspondent = chat.correspondent.clone();
- let chat_query = chat_query();
- chat_query.set_query_data(correspondent.clone(), Ok(chat));
- let chat = chat_query.use_query(move || correspondent.clone());
- let jid = user.jid.clone();
- let user_query = user_query();
- user_query.set_query_data(jid.clone(), Ok(user));
- let user = user_query.use_query(move || jid.clone());
+ let chat_state_store: RwSignal<StateStore<JID, Store<Chat>>, LocalStorage> = use_context().expect("no chat state store");
+ let user_state_store: RwSignal<StateStore<JID, Store<User>>, LocalStorage> = use_context().expect("no user state store");
+ let user = user_state_store.read_untracked().store(user.jid.clone(), Store::new(user));
+ let chat = chat_state_store.read_untracked().store(chat.correspondent.clone(), Store::new(chat));
Self {
- chat: ReadSignal::from_stream_unsync(chat.data.to_stream()),
- user: ReadSignal::from_stream_unsync(user.data.to_stream()),
- }
- }
-
- fn get(jid: JID) -> Self {
- let jid1 = jid.clone();
- let chat = chat_query().use_query(move || (&jid1).clone());
- let user = user_query().use_query(move || (&jid).clone());
- Self {
- chat: ReadSignal::from_stream_unsync(chat.data.to_stream()),
- user: ReadSignal::from_stream_unsync(user.data.to_stream()),
+ chat,
+ user,
}
}
}
impl Deref for MacawChat {
- type Target = ReadSignal<Option<Option<Result<Chat, String>>>>;
+ type Target = StateListener<JID, Store<Chat>>;
fn deref(&self) -> &Self::Target {
&self.chat
@@ -336,30 +426,25 @@ impl DerefMut for MacawChat {
#[derive(Clone)]
struct MacawMessage {
- message: ReadSignal<Option<Option<Result<Message, String>>>>,
- user: ReadSignal<Option<Option<Result<User, String>>>>,
+ message: StateListener<Uuid, Store<Message>>,
+ user: StateListener<JID, Store<User>>,
}
impl MacawMessage {
fn got_message_and_user(message: Message, user: User) -> Self {
- debug!("executing the got message");
- let message_id = message.id;
- let message_query = message_query();
- message_query.set_query_data(message.id, Ok(message));
- let message = message_query.use_query(move || message_id);
- let jid = user.jid.clone();
- let user_query = user_query();
- user_query.set_query_data(jid.clone(), Ok(user));
- let user = user_query.use_query(move || jid.clone());
+ let message_state_store: RwSignal<StateStore<Uuid, Store<Message>>, LocalStorage> = use_context().expect("no message state store");
+ let user_state_store: RwSignal<StateStore<JID, Store<User>>, LocalStorage> = use_context().expect("no user state store");
+ let message = message_state_store.read_untracked().store(message.id, Store::new(message));
+ let user = user_state_store.read_untracked().store(user.jid.clone(), Store::new(user));
Self {
- message: ReadSignal::from_stream_unsync(message.data.to_stream()),
- user: ReadSignal::from_stream_unsync(user.data.to_stream()),
+ message,
+ user,
}
}
}
impl Deref for MacawMessage {
- type Target = ReadSignal<Option<Option<Result<Message, String>>>>;
+ type Target = StateListener<Uuid, Store<Message>>;
fn deref(&self) -> &Self::Target {
&self.message
@@ -372,73 +457,77 @@ impl DerefMut for MacawMessage {
}
}
+struct MacawUser {
+ user: StateListener<JID, Store<User>>,
+}
+
+impl Deref for MacawUser {
+ type Target = StateListener<JID, Store<User>>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.user
+ }
+}
+
+impl DerefMut for MacawUser {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.user
+ }
+}
+
+#[component]
fn ChatsList() -> impl IntoView {
- let chats: LocalResource<std::result::Result<(ReadSignal<IndexMap<JID, (MacawChat, MacawMessage)>, LocalStorage>, WriteSignal<IndexMap<JID, (MacawChat, MacawMessage)>, LocalStorage>), String>> = LocalResource::new(move || async move || -> Result<_, _> {
- let client: Client = use_context::<RwSignal<Client, LocalStorage>>().unwrap().read().clone();
- let chats = client.get_chats_ordered_with_latest_messages_and_users().await.map_err(|e| e.to_string())?;
- let chats = chats.into_iter().map(|((chat, chat_user), (message, message_user))| {
- (chat.correspondent.clone(), (MacawChat::got_chat_and_user(chat, chat_user), MacawMessage::got_message_and_user(message, message_user)))
-
- }).collect::<IndexMap<JID, _>>();
- let (chats, set_chats) = signal_local(chats);
- Ok((chats, set_chats))
- }());
+ let client = use_context::<Client>().expect("client not in context");
+ let (chats, set_chats) = signal(IndexMap::new());
+
+ let load_chats = LocalResource::new(move || async move {
+ let client = use_context::<Client>().expect("client not in context");
+ let chats = client.get_chats_ordered_with_latest_messages_and_users().await.map_err(|e| e.to_string());
+ match chats {
+ Ok(c) => {
+ let chats = c.into_iter().map(|((chat, chat_user), (message, message_user))| {
+ (chat.correspondent.clone(), (MacawChat::got_chat_and_user(chat, chat_user), MacawMessage::got_message_and_user(message, message_user)))
+ }).collect::<IndexMap<JID, _>>();
+ set_chats.set(chats);
+ },
+ Err(_) => {
+ // TODO: show error message at top of chats list
+ },
+ }
+ });
// TODO: filter new messages signal
let new_messages_signal: ReadSignal<Option<(JID, MacawMessage)>> = use_context().unwrap();
- OnceResource::new(async move {
+ spawn_local(async move {
let mut new_message = new_messages_signal.to_stream();
- match chats.await {
- Ok((c, set_c)) => {
- while let Some(new_message) = new_message.next().await {
- debug!("got new message in let");
- if let Some((to, new_message)) = new_message {
- if let Some((chat, _latest_message)) = set_c.write().shift_remove(&to) {
- debug!("chat existed");
- set_c.write().insert_before(0, to, (chat, new_message));
- debug!("done setting");
- } else {
- debug!("the chat didn't exist");
- let chat = MacawChat::get(to.clone());
- set_c.write().insert_before(0, to, (chat, new_message));
- debug!("done setting");
- }
- }
+ load_chats.await;
+ while let Some(new_message) = new_message.next().await {
+ debug!("got new message in let");
+ if let Some((to, new_message)) = new_message {
+ if let Some((chat, _latest_message)) = set_chats.write().shift_remove(&to) {
+ debug!("chat existed");
+ set_chats.write().insert_before(0, to, (chat, new_message));
+ debug!("done setting");
+ } else {
+ debug!("the chat didn't exist");
+ let chat = client.get_chat(to.clone()).await.unwrap();
+ let user = client.get_user(to.clone()).await.unwrap();
+ let chat = MacawChat::got_chat_and_user(chat, user);
+ set_chats.write().insert_before(0, to, (chat, new_message));
+ debug!("done setting");
}
- debug!("set the new message");
}
- Err(_) => {},
}
+ debug!("set the new message");
});
view! {
<div class="chats-list panel">
<h2>Chats</h2>
<div>
- {move || {
- if let Some(chats) = &*chats.read() {
- match &**chats {
- Ok((chats, _)) => {
- let chats = chats.clone();
- view! {
- <For
- each=move || chats.get()
- key=|chat| chat.0.clone()
- let(chat)
- >
- <p>{chat.0.to_string()}</p>
- </For>
- }
- .into_any()
- }
- Err(e) => {
- view! { <div class="error">{format!("{}", e)}</div> }.into_any()
- }
- }
- } else {
- None::<String>.into_any()
- }
- }}
+ <For each=move || chats.get() key=|chat| chat.0.clone() let(chat)>
+ <p>{chat.0.to_string()}</p>
+ </For>
</div>
</div>
}