summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@bunny.garden>2025-06-01 20:17:57 +0100
committerLibravatar cel 🌸 <cel@bunny.garden>2025-06-01 20:17:57 +0100
commit33bb7130943b5f74b3b0f08c5e6d8f7c5e54d4c0 (patch)
tree0617888d360550508ede95aa12c00375cde4e70b
parent6ee4190a26f32bfa953302ee363ad3bb6c384ebb (diff)
downloadmacaw-web-33bb7130943b5f74b3b0f08c5e6d8f7c5e54d4c0.tar.gz
macaw-web-33bb7130943b5f74b3b0f08c5e6d8f7c5e54d4c0.tar.bz2
macaw-web-33bb7130943b5f74b3b0f08c5e6d8f7c5e54d4c0.zip
feat: switch to leptos-fetch for state management
Diffstat (limited to '')
-rw-r--r--Cargo.lock30
-rw-r--r--Cargo.toml1
-rw-r--r--src/chat.rs35
-rw-r--r--src/components/chats_list.rs2
-rw-r--r--src/components/message_history_buffer.rs2
-rw-r--r--src/components/new_chat.rs69
-rw-r--r--src/components/personal_status.rs2
-rw-r--r--src/components/roster_list/contact_request_manager.rs3
-rw-r--r--src/message.rs34
-rw-r--r--src/state_store.rs237
-rw-r--r--src/user.rs44
-rw-r--r--src/views/macaw.rs51
12 files changed, 218 insertions, 292 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 01baf20..e4f6991 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1510,6 +1510,26 @@ dependencies = [
]
[[package]]
+name = "leptos-fetch"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "094fee918af2bd8c6d67e9765db107e2b5d6306ca7f03bd63314eb5920e10142"
+dependencies = [
+ "chrono",
+ "chrono-humanize",
+ "codee",
+ "futures",
+ "leptos",
+ "parking_lot",
+ "paste",
+ "rustc_version",
+ "send_wrapper",
+ "task-local",
+ "tracing",
+ "web-sys",
+]
+
+[[package]]
name = "leptos_config"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1715,6 +1735,7 @@ dependencies = [
"indexmap",
"jid",
"leptos",
+ "leptos-fetch",
"reactive_stores",
"serde",
"stylance",
@@ -3075,6 +3096,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
+name = "task-local"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2c821daee0efdf6414970c8185a1c22e259a7ed87b2fd9f7d3c5f5503fd2863"
+dependencies = [
+ "pin-project-lite",
+]
+
+[[package]]
name = "tempfile"
version = "3.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 4e894ed..a9a6319 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,6 +16,7 @@ futures = "0.3.31"
indexmap = "2.9.0"
jid = { path = "../luz/jid" }
leptos = { version = "0.8.2", features = ["csr"] }
+leptos-fetch = "0.4.2"
# leptos-use = "0.15.7"
# leptos_meta = "0.8.2"
# reactive_graph = "0.2.2"
diff --git a/src/chat.rs b/src/chat.rs
index 6785b06..a1ced32 100644
--- a/src/chat.rs
+++ b/src/chat.rs
@@ -2,30 +2,49 @@ use std::ops::{Deref, DerefMut};
use filamento::{chat::Chat, user::User};
use jid::BareJID;
+use leptos_fetch::QueryClient;
use reactive_stores::ArcStore;
use leptos::prelude::*;
-use crate::{state_store::{StateListener, StateStore}, user::MacawUser};
+use crate::{client::Client, user::MacawUser};
+
+async fn get_chat(jid: BareJID) -> ArcStore<Chat> {
+ let client: Client = use_context().expect("no client in context");
+ ArcStore::new(client.get_chat(jid).await.unwrap())
+}
#[derive(Clone)]
pub struct MacawChat {
- pub chat: StateListener<BareJID, ArcStore<Chat>>,
+ pub chat: ArcStore<Chat>,
pub user: MacawUser,
// user: StateListener<BareJID, ArcStore<User>>,
}
impl MacawChat {
pub fn got_chat_and_user(chat: Chat, user: User) -> Self {
- let chat_state_store: StateStore<BareJID, ArcStore<Chat>> =
- use_context().expect("no chat state store");
- let chat = chat_state_store.store(chat.correspondent.clone(), ArcStore::new(chat));
- let user = MacawUser::got_user(user);
- Self { chat, user }
+ let query_client: QueryClient = expect_context();
+
+ let jid = chat.correspondent.clone();
+ let chat_store = query_client.subscribe_value_local(get_chat, move || jid.clone());
+ if let Some(chat_store) = chat_store.get() {
+ chat_store.set(chat);
+ let user = MacawUser::got_user(user);
+ Self { chat: chat_store, user }
+ } else {
+ let jid = chat.correspondent.clone();
+ let chat_store = ArcStore::new(chat);
+ query_client.set_query_local(get_chat, jid, chat_store.clone());
+ let user = MacawUser::got_user(user);
+ Self {
+ chat: chat_store,
+ user,
+ }
+ }
}
}
impl Deref for MacawChat {
- type Target = StateListener<BareJID, ArcStore<Chat>>;
+ type Target = ArcStore<Chat>;
fn deref(&self) -> &Self::Target {
&self.chat
diff --git a/src/components/chats_list.rs b/src/components/chats_list.rs
index b8cf34c..d520f56 100644
--- a/src/components/chats_list.rs
+++ b/src/components/chats_list.rs
@@ -73,7 +73,7 @@ pub fn ChatsList() -> impl IntoView {
debug!("set the new message");
});
on_cleanup(move || {
- if let Some(sub_id) = sub_id.get() {
+ if let Some(sub_id) = sub_id.get_untracked() {
new_messages_signal.write().unsubscribe_all(sub_id);
}
});
diff --git a/src/components/message_history_buffer.rs b/src/components/message_history_buffer.rs
index 36439a8..632209d 100644
--- a/src/components/message_history_buffer.rs
+++ b/src/components/message_history_buffer.rs
@@ -123,7 +123,7 @@ pub fn MessageHistoryBuffer(chat: MacawChat) -> impl IntoView {
if let Some(sub_id) = sub_id.get() {
new_messages_signal
.write()
- .unsubscribe_chat(sub_id, chat_chat.correspondent().get());
+ .unsubscribe_chat(sub_id, chat_chat.correspondent().get_untracked());
}
});
diff --git a/src/components/new_chat.rs b/src/components/new_chat.rs
index 8047afb..6d64c96 100644
--- a/src/components/new_chat.rs
+++ b/src/components/new_chat.rs
@@ -3,10 +3,11 @@ use std::str::FromStr;
use filamento::{chat::Chat, error::{CommandError, DatabaseError}, user::User};
use jid::{BareJID, JID};
use leptos::{html::Input, prelude::*};
+use leptos_fetch::QueryClient;
use reactive_stores::{ArcStore, Store};
use thiserror::Error;
-use crate::{chat::MacawChat, client::Client, open_chats::OpenChatsPanel, state_store::StateStore, user::MacawUser};
+use crate::{chat::MacawChat, client::Client, open_chats::OpenChatsPanel, user::MacawUser};
#[derive(Clone, Debug, Error)]
pub enum NewChatError {
@@ -18,6 +19,17 @@ pub enum NewChatError {
Db(#[from] CommandError<DatabaseError>),
}
+// TODO: remove
+async fn get_chat(jid: BareJID) -> ArcStore<Chat> {
+ let client: Client = use_context().expect("no client in context");
+ ArcStore::new(client.get_chat(jid).await.unwrap())
+}
+
+async fn get_user(jid: BareJID) -> ArcStore<User> {
+ let client: Client = use_context().expect("no client in context");
+ ArcStore::new(client.get_user(jid).await.unwrap())
+}
+
#[component]
pub fn NewChatWidget(set_open_new_chat: WriteSignal<bool>) -> impl IntoView {
let jid = RwSignal::new("".to_string());
@@ -39,10 +51,7 @@ pub fn NewChatWidget(set_open_new_chat: WriteSignal<bool>) -> impl IntoView {
use_context().expect("no open chats panel store in context");
let client = use_context::<Client>().expect("client not in context");
- let chat_state_store: StateStore<BareJID, ArcStore<Chat>> =
- use_context().expect("no chat state store");
- let user_state_store: StateStore<BareJID, ArcStore<User>> =
- use_context().expect("no user state store");
+ let query_client: QueryClient = expect_context();
let open_chat = Action::new_local(move |_| {
let client = client.clone();
@@ -77,10 +86,52 @@ pub fn NewChatWidget(set_open_new_chat: WriteSignal<bool>) -> impl IntoView {
let chat = {
// let user = MacawUser::got_user(user);
- let user = user_state_store.store(user.jid.clone(), ArcStore::new(user));
- let user = MacawUser { user };
- let chat = chat_state_store.store(chat.correspondent.clone(), ArcStore::new(chat));
- MacawChat { chat, user }
+ let jid = chat.correspondent.clone();
+ let chat_store = query_client.subscribe_value_local(get_chat, move || jid.clone());
+ if let Some(chat_store) = chat_store.get() {
+ chat_store.set(chat);
+ let user = {
+ let jid = user.jid.clone();
+ let user_store = query_client.subscribe_value_local(get_user, move || jid.clone());
+ if let Some(user_store) = user_store.get() {
+ user_store.set(user);
+ MacawUser { user: user_store }
+ } else {
+ let jid = user.jid.clone();
+ let user_store = ArcStore::new(user);
+ query_client.set_query_local(get_user, jid, user_store.clone());
+ MacawUser {
+ user: user_store,
+ }
+ }
+
+ };
+ MacawChat { chat: chat_store, user }
+ } else {
+ let jid = chat.correspondent.clone();
+ let chat_store = ArcStore::new(chat);
+ query_client.set_query_local(get_chat, jid, chat_store.clone());
+ let user = {
+ let jid = user.jid.clone();
+ let user_store = query_client.subscribe_value_local(get_user, move || jid.clone());
+ if let Some(user_store) = user_store.get() {
+ user_store.set(user);
+ MacawUser { user: user_store }
+ } else {
+ let jid = user.jid.clone();
+ let user_store = ArcStore::new(user);
+ query_client.set_query_local(get_user, jid, user_store.clone());
+ MacawUser {
+ user: user_store,
+ }
+ }
+
+ };
+ MacawChat {
+ chat: chat_store,
+ user,
+ }
+ }
};
open_chats.update(|open_chats| open_chats.open(chat.clone()));
set_open_new_chat.set(false);
diff --git a/src/components/personal_status.rs b/src/components/personal_status.rs
index f830a1b..81a27b5 100644
--- a/src/components/personal_status.rs
+++ b/src/components/personal_status.rs
@@ -11,7 +11,7 @@ pub fn PersonalStatus() -> impl IntoView {
let (open, set_open) = signal(false);
move || if let Some(user) = user.get() {
- let user: Store<User> = <ArcStore<filamento::user::User> as Clone>::clone(&(*user.user)).into();
+ let user: Store<User> = <ArcStore<filamento::user::User> as Clone>::clone(&user.user).into();
view! {
<div class="dock-item" class:focused=move || *open.read() on:click=move |_| {
debug!("set open to true");
diff --git a/src/components/roster_list/contact_request_manager.rs b/src/components/roster_list/contact_request_manager.rs
index 174e677..31dff91 100644
--- a/src/components/roster_list/contact_request_manager.rs
+++ b/src/components/roster_list/contact_request_manager.rs
@@ -109,7 +109,8 @@ pub fn AddContact() -> impl IntoView {
let jid = jid.clone();
async move {
// TODO: error
- client.accept_buddy_request(jid).await;
+ client.accept_buddy_request(jid.clone()).await;
+ set_requests.write().remove(&jid);
}
});
diff --git a/src/message.rs b/src/message.rs
index e5caed1..a47c75f 100644
--- a/src/message.rs
+++ b/src/message.rs
@@ -1,30 +1,48 @@
use std::ops::{Deref, DerefMut};
use filamento::{chat::Message, user::User};
+use leptos_fetch::QueryClient;
use reactive_stores::ArcStore;
use uuid::Uuid;
use leptos::prelude::*;
-use crate::{state_store::{StateListener, StateStore}, user::MacawUser};
+use crate::{client::Client, user::MacawUser};
+
+async fn get_message(id: Uuid) -> ArcStore<Message> {
+ let client: Client = use_context().expect("no client in context");
+ ArcStore::new(client.get_message(id).await.unwrap())
+}
#[derive(Clone)]
pub struct MacawMessage {
- pub message: StateListener<Uuid, ArcStore<Message>>,
+ pub message: ArcStore<Message>,
pub user: MacawUser,
}
impl MacawMessage {
pub fn got_message_and_user(message: Message, user: User) -> Self {
- let message_state_store: StateStore<Uuid, ArcStore<Message>> =
- use_context().expect("no message state store");
- let message = message_state_store.store(message.id, ArcStore::new(message));
- let user = MacawUser::got_user(user);
- Self { message, user }
+ let query_client: QueryClient = expect_context();
+
+ let id = message.id;
+ let message_store = query_client.subscribe_value_local(get_message, move || id);
+ if let Some(message_store) = message_store.get() {
+ message_store.set(message);
+ let user = MacawUser::got_user(user);
+ Self { message: message_store, user }
+ } else {
+ let message_store = ArcStore::new(message);
+ query_client.set_query_local(get_message, id, message_store.clone());
+ let user = MacawUser::got_user(user);
+ Self {
+ message: message_store,
+ user,
+ }
+ }
}
}
impl Deref for MacawMessage {
- type Target = StateListener<Uuid, ArcStore<Message>>;
+ type Target = ArcStore<Message>;
fn deref(&self) -> &Self::Target {
&self.message
diff --git a/src/state_store.rs b/src/state_store.rs
index 2536cda..8b13789 100644
--- a/src/state_store.rs
+++ b/src/state_store.rs
@@ -1,238 +1 @@
-use std::{collections::HashMap, ops::{Deref, DerefMut}, sync::{Arc, RwLock}};
-use leptos::prelude::*;
-
-// TODO: get rid of this
-// V has to be an arc signal
-#[derive(Debug)]
-pub struct ArcStateStore<K, V> {
- store: Arc<RwLock<HashMap<K, (V, usize)>>>,
-}
-
-impl<K, V> PartialEq for ArcStateStore<K, V> {
- fn eq(&self, other: &Self) -> bool {
- Arc::ptr_eq(&self.store, &other.store)
- }
-}
-
-impl<K, V> Clone for ArcStateStore<K, V> {
- fn clone(&self) -> Self {
- Self {
- store: Arc::clone(&self.store),
- }
- }
-}
-
-impl<K, V> Eq for ArcStateStore<K, V> {}
-
-impl<K, V> ArcStateStore<K, V> {
- pub fn new() -> Self {
- Self {
- store: Arc::new(RwLock::new(HashMap::new())),
- }
- }
-}
-
-#[derive(Debug)]
-pub struct StateStore<K, V, S = SyncStorage> {
- inner: ArenaItem<ArcStateStore<K, V>, S>,
-}
-
-impl<K, V, S> Dispose for StateStore<K, V, S> {
- fn dispose(self) {
- self.inner.dispose()
- }
-}
-
-impl<K, V> StateStore<K, V>
-where
- K: Send + Sync + 'static,
- V: Send + Sync + 'static,
-{
- pub fn new() -> Self {
- Self::new_with_storage()
- }
-}
-
-impl<K, V, S> StateStore<K, V, S>
-where
- K: 'static,
- V: 'static,
- S: Storage<ArcStateStore<K, V>>,
-{
- pub fn new_with_storage() -> Self {
- Self {
- inner: ArenaItem::new_with_storage(ArcStateStore::new()),
- }
- }
-}
-
-impl<K, V> StateStore<K, V, LocalStorage>
-where
- K: 'static,
- V: 'static,
-{
- pub fn new_local() -> Self {
- Self::new_with_storage()
- }
-}
-
-impl<
- K: std::marker::Send + std::marker::Sync + 'static,
- V: std::marker::Send + std::marker::Sync + 'static,
-> From<ArcStateStore<K, V>> for StateStore<K, V>
-{
- fn from(value: ArcStateStore<K, V>) -> Self {
- Self {
- inner: ArenaItem::new_with_storage(value),
- }
- }
-}
-
-impl<K: 'static, V: 'static> FromLocal<ArcStateStore<K, V>> for StateStore<K, V, LocalStorage> {
- fn from_local(value: ArcStateStore<K, V>) -> Self {
- Self {
- inner: ArenaItem::new_with_storage(value),
- }
- }
-}
-
-impl<K, V, S> Copy for StateStore<K, V, S> {}
-
-impl<K, V, S> Clone for StateStore<K, V, S> {
- fn clone(&self) -> Self {
- *self
- }
-}
-
-impl<K: Eq + std::hash::Hash + Clone, V: Clone> StateStore<K, V>
-where
- K: Send + Sync + 'static,
- V: Send + Sync + 'static,
-{
- pub fn store(&self, key: K, value: V) -> StateListener<K, V> {
- {
- let store = self.inner.try_get_value().unwrap();
- let mut store = store.store.write().unwrap();
- if let Some((v, count)) = store.get_mut(&key) {
- *v = value.clone();
- *count += 1;
- } else {
- store.insert(key.clone(), (value.clone(), 1));
- }
- };
- StateListener {
- value,
- cleaner: StateCleaner {
- key,
- state_store: self.clone(),
- },
- }
- }
-}
-
-impl<K, V> StateStore<K, V>
-where
- K: Eq + std::hash::Hash + Send + Sync + 'static,
- V: Send + Sync + 'static,
-{
- pub fn update(&self, key: &K, value: V) {
- let store = self.inner.try_get_value().unwrap();
- let mut store = store.store.write().unwrap();
- if let Some((v, _)) = store.get_mut(key) {
- *v = value;
- }
- }
-
- pub fn modify(&self, key: &K, modify: impl Fn(&mut V)) {
- let store = self.inner.try_get_value().unwrap();
- let mut store = store.store.write().unwrap();
- if let Some((v, _)) = store.get_mut(key) {
- modify(v);
- }
- }
-
- fn remove(&self, key: &K) {
- // let store = self.inner.try_get_value().unwrap();
- // let mut store = store.store.write().unwrap();
- // if let Some((_v, count)) = store.get_mut(key) {
- // *count -= 1;
- // if *count == 0 {
- // store.remove(key);
- // debug!("dropped item from store");
- // }
- // }
- }
-}
-
-#[derive(Clone)]
-pub struct StateListener<K, V>
-where
- K: Eq + std::hash::Hash + 'static + std::marker::Send + std::marker::Sync,
- V: 'static + std::marker::Send + std::marker::Sync,
-{
- value: V,
- cleaner: StateCleaner<K, V>,
-}
-
-impl<
- K: std::cmp::Eq + std::hash::Hash + std::marker::Send + std::marker::Sync,
- V: std::marker::Send + std::marker::Sync,
-> Deref for StateListener<K, V>
-{
- type Target = V;
-
- fn deref(&self) -> &Self::Target {
- &self.value
- }
-}
-
-impl<K: std::cmp::Eq + std::hash::Hash + Send + Sync, V: Send + Sync> DerefMut
- for StateListener<K, V>
-{
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.value
- }
-}
-
-struct ArcStateCleaner<K, V> {
- key: K,
- state_store: ArcStateStore<K, V>,
-}
-
-struct StateCleaner<K, V>
-where
- K: Eq + std::hash::Hash + Send + Sync + 'static,
- V: Send + Sync + 'static,
-{
- key: K,
- state_store: StateStore<K, V>,
-}
-
-impl<K, V> Clone for StateCleaner<K, V>
-where
- K: Eq + std::hash::Hash + Clone + Send + Sync,
- V: Send + Sync,
-{
- fn clone(&self) -> Self {
- {
- let store = self.state_store.inner.try_get_value().unwrap();
- let mut store = store.store.write().unwrap();
- if let Some((_v, count)) = store.get_mut(&self.key) {
- *count += 1;
- }
- }
- Self {
- key: self.key.clone(),
- state_store: self.state_store.clone(),
- }
- }
-}
-
-impl<K: Eq + std::hash::Hash + Send + Sync + 'static, V: Send + Sync + 'static> Drop
- for StateCleaner<K, V>
-{
- fn drop(&mut self) {
- self.state_store.remove(&self.key);
- }
-}
diff --git a/src/user.rs b/src/user.rs
index f55c0dd..d92ba4f 100644
--- a/src/user.rs
+++ b/src/user.rs
@@ -2,28 +2,46 @@ use std::ops::{Deref, DerefMut};
use filamento::user::{User, UserStoreFields};
use jid::BareJID;
+use leptos_fetch::QueryClient;
use reactive_stores::{ArcStore, Store};
use leptos::prelude::*;
-use crate::{client::Client, roster::{Roster, RosterStoreFields}, state_store::{StateListener, StateStore}};
+use crate::{client::Client, roster::{Roster, RosterStoreFields}};
+
+async fn get_user(jid: BareJID) -> ArcStore<User> {
+ let client: Client = use_context().expect("no client in context");
+ ArcStore::new(client.get_user(jid).await.unwrap())
+}
#[derive(Clone)]
pub struct MacawUser {
- pub user: StateListener<BareJID, ArcStore<User>>,
+ pub user: ArcStore<User>,
}
impl MacawUser {
pub fn got_user(user: User) -> Self {
-
- let user_state_store: StateStore<BareJID, ArcStore<User>> =
- use_context().expect("no user state store");
- let user = user_state_store.store(user.jid.clone(), ArcStore::new(user));
- Self { user }
+ // let avatar = fetch_avatar(&user);
+ // user.avatar = avatar;
+ let query_client: QueryClient = expect_context();
+
+ let jid = user.jid.clone();
+ let user_store = query_client.subscribe_value_local(get_user, move || jid.clone());
+ if let Some(user_store) = user_store.get() {
+ user_store.set(user);
+ Self { user: user_store }
+ } else {
+ let jid = user.jid.clone();
+ let user_store = ArcStore::new(user);
+ query_client.set_query_local(get_user, jid, user_store.clone());
+ Self {
+ user: user_store,
+ }
+ }
}
}
impl Deref for MacawUser {
- type Target = StateListener<BareJID, ArcStore<User>>;
+ type Target = ArcStore<User>;
fn deref(&self) -> &Self::Target {
&self.user
@@ -38,6 +56,15 @@ impl DerefMut for MacawUser {
pub const NO_AVATAR: &str = "/assets/no-avatar.png";
+pub async fn fetch_avatar(user: &User) -> Option<String> {
+ if let Some(avatar) = &user.avatar {
+ let client = use_context::<Client>().expect("client not in context");
+ client.file_store.get_src(avatar).await
+ } else {
+ None
+ }
+}
+
pub async fn get_avatar(user: Store<User>) -> String {
if let Some(avatar) = &user.read().avatar {
let client = use_context::<Client>().expect("client not in context");
@@ -46,6 +73,7 @@ pub async fn get_avatar(user: Store<User>) -> String {
} else {
NO_AVATAR.to_string()
}
+ // avatar.clone()
// TODO: enable avatar fetching
// format!("/files/{}", avatar)
} else {
diff --git a/src/views/macaw.rs b/src/views/macaw.rs
index 18e0ad3..e6ec66c 100644
--- a/src/views/macaw.rs
+++ b/src/views/macaw.rs
@@ -1,8 +1,9 @@
use std::collections::HashSet;
-use filamento::{chat::{Chat, Message, MessageStoreFields}, user::User, UpdateMessage};
+use filamento::{chat::{Chat, Message, MessageStoreFields}, user::{User, UserStoreFields}, UpdateMessage};
use jid::BareJID;
use leptos::{prelude::*, task::spawn_local};
+use leptos_fetch::QueryClient;
use open_chats_panel::OpenChatsPanelView;
use reactive_stores::{ArcStore, Store};
use settings::{Settings, SettingsPage};
@@ -10,13 +11,25 @@ use tokio::sync::mpsc::Receiver;
use tracing::debug;
use uuid::Uuid;
-use crate::{client::Client, components::sidebar::Sidebar, contact::MacawContact, message::MacawMessage, message_subscriptions::MessageSubscriptions, open_chats::OpenChatsPanel, roster::{Roster, RosterStoreFields}, state_store::StateStore, user::MacawUser, user_presences::{Presences, UserPresences}};
+use crate::{client::Client, components::sidebar::Sidebar, contact::MacawContact, message::MacawMessage, message_subscriptions::MessageSubscriptions, open_chats::OpenChatsPanel, roster::{Roster, RosterStoreFields}, user::MacawUser, user_presences::{Presences, UserPresences}};
use super::AppState;
pub mod settings;
mod open_chats_panel;
+// TODO: remove
+async fn get_message(id: Uuid) -> ArcStore<Message> {
+ let client: Client = use_context().expect("no client in context");
+ ArcStore::new(client.get_message(id).await.unwrap())
+}
+
+async fn get_user(jid: BareJID) -> ArcStore<User> {
+ let client: Client = use_context().expect("no client in context");
+ ArcStore::new(client.get_user(jid).await.unwrap())
+}
+
+
#[component]
pub fn Macaw(
// TODO: logout
@@ -34,12 +47,8 @@ pub fn Macaw(
let message_subscriptions = RwSignal::new(MessageSubscriptions::new());
provide_context(message_subscriptions);
- let messages_store: StateStore<Uuid, ArcStore<Message>> = StateStore::new();
- provide_context(messages_store);
- let chats_store: StateStore<BareJID, ArcStore<Chat>> = StateStore::new();
- provide_context(chats_store);
- let users_store: StateStore<BareJID, ArcStore<User>> = StateStore::new();
- provide_context(users_store);
+ QueryClient::new().provide();
+ let query_client: QueryClient = expect_context();
let open_chats = Store::new(OpenChatsPanel::default());
provide_context(open_chats);
@@ -102,7 +111,7 @@ pub fn Macaw(
}
UpdateMessage::Presence { from, presence } => {
let bare_jid = from.to_bare();
- if let Some(presences) = user_presences.read().user_presences.get(&bare_jid) {
+ if let Some(presences) = user_presences.read_untracked().user_presences.get(&bare_jid) {
if let Some(resource) = from.resourcepart() {
presences.write().update_presence(resource.clone(), presence);
}
@@ -127,22 +136,28 @@ pub fn Macaw(
debug!("after set message");
}
UpdateMessage::MessageDelivery { id, chat, delivery } => {
- messages_store.modify(&id, |message| {
- <ArcStore<filamento::chat::Message> as Clone>::clone(&message)
- .delivery()
- .set(Some(delivery))
- });
+ query_client.update_query(get_message, id, |message| {
+ if let Some(message) = message {
+ <ArcStore<filamento::chat::Message> as Clone>::clone(&message).delivery().set(Some(delivery))
+ }
+ })
}
UpdateMessage::SubscriptionRequest(jid) => {
set_subscription_requests.update(|req| { req.insert(jid); });
}
UpdateMessage::NickChanged { jid, nick } => {
- users_store.modify(&jid, |user| {
- user.update(|user| *&mut user.nick = nick.clone())
- });
+ query_client.update_query(get_user, jid, |user| {
+ if let Some(user) = user {
+ <ArcStore<filamento::user::User> as Clone>::clone(&user).nick().set(nick)
+ }
+ })
}
UpdateMessage::AvatarChanged { jid, id } => {
- users_store.modify(&jid, |user| *&mut user.write().avatar = id.clone());
+ query_client.update_query(get_user, jid, |user| {
+ if let Some(user) = user {
+ <ArcStore<filamento::user::User> as Clone>::clone(&user).avatar().set(id)
+ }
+ })
}
}
}