diff options
author | 2025-06-01 20:17:57 +0100 | |
---|---|---|
committer | 2025-06-01 20:17:57 +0100 | |
commit | 33bb7130943b5f74b3b0f08c5e6d8f7c5e54d4c0 (patch) | |
tree | 0617888d360550508ede95aa12c00375cde4e70b | |
parent | 6ee4190a26f32bfa953302ee363ad3bb6c384ebb (diff) | |
download | macaw-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.lock | 30 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/chat.rs | 35 | ||||
-rw-r--r-- | src/components/chats_list.rs | 2 | ||||
-rw-r--r-- | src/components/message_history_buffer.rs | 2 | ||||
-rw-r--r-- | src/components/new_chat.rs | 69 | ||||
-rw-r--r-- | src/components/personal_status.rs | 2 | ||||
-rw-r--r-- | src/components/roster_list/contact_request_manager.rs | 3 | ||||
-rw-r--r-- | src/message.rs | 34 | ||||
-rw-r--r-- | src/state_store.rs | 237 | ||||
-rw-r--r-- | src/user.rs | 44 | ||||
-rw-r--r-- | src/views/macaw.rs | 51 |
12 files changed, 218 insertions, 292 deletions
@@ -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" @@ -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) + } + }) } } } |