diff options
Diffstat (limited to 'src/views/macaw.rs')
| -rw-r--r-- | src/views/macaw.rs | 111 |
1 files changed, 74 insertions, 37 deletions
diff --git a/src/views/macaw.rs b/src/views/macaw.rs index 1b7051f..e91e08a 100644 --- a/src/views/macaw.rs +++ b/src/views/macaw.rs @@ -1,6 +1,14 @@ -use std::collections::HashSet; +// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden> +// +// SPDX-License-Identifier: AGPL-3.0-or-later -use filamento::{chat::{Chat, Message, MessageStoreFields}, user::User, UpdateMessage}; +use std::collections::{HashMap, HashSet}; + +use filamento::{ + UpdateMessage, + chat::{Chat, Message, MessageStoreFields}, + user::User, +}; use jid::BareJID; use leptos::{prelude::*, task::spawn_local}; use open_chats_panel::OpenChatsPanelView; @@ -10,12 +18,23 @@ use tokio::sync::mpsc::Receiver; use tracing::debug; use uuid::Uuid; -use crate::{client::Client, components::sidebar::Sidebar, contact::{ArcMacawContact, MacawContact}, message::{ArcMacawMessage, MacawMessage}, message_subscriptions::MessageSubscriptions, open_chats::OpenChatsPanel, roster::{Roster, RosterStoreFields}, state_store::StateStore, user::{ArcMacawUser, MacawUser}, user_presences::{Presences, UserPresences}}; +use crate::{ + client::Client, + components::sidebar::Sidebar, + contact::{ArcMacawContact, MacawContact}, + message::{ArcMacawMessage, MacawMessage}, + message_subscriptions::MessageSubscriptions, + open_chats::OpenChatsPanel, + roster::{Roster, RosterStoreFields}, + state_store::StateStore, + user::{ArcMacawUser, MacawUser, fetch_avatar}, + user_presences::{Presences, UserPresences}, +}; use super::AppState; -pub mod settings; mod open_chats_panel; +pub mod settings; #[component] pub fn Macaw( @@ -25,6 +44,7 @@ pub fn Macaw( mut updates: Receiver<UpdateMessage>, set_app: WriteSignal<AppState>, ) -> impl IntoView { + let (updates, set_updates) = signal(Some(updates)); provide_context(set_app); provide_context(client); @@ -38,46 +58,45 @@ pub fn Macaw( 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(); + let users_store: StateStore<BareJID, (ArcStore<User>, ArcRwSignal<String>)> = StateStore::new(); provide_context(users_store); let open_chats = Store::new(OpenChatsPanel::default()); provide_context(open_chats); - let show_settings = RwSignal::new(None::<SettingsPage>); + let show_settings = RwSignal::new(None::<SettingsPage>); provide_context(show_settings); let user_presences = Store::new(UserPresences::new()); provide_context(user_presences); - let client_user: LocalResource<MacawUser> = LocalResource::new(move || { - async move { - let client = use_context::<Client>().expect("client not in context"); - let user = client.get_user((*client.jid).clone()).await.unwrap(); - ArcMacawUser::got_user(user).into() - } + let client_user: LocalResource<MacawUser> = LocalResource::new(move || async move { + let client = use_context::<Client>().expect("client not in context"); + let user = client.get_user((*client.jid).clone()).await.unwrap(); + ArcMacawUser::got_user(user).await.into() }); provide_context(client_user); // TODO: timestamp incoming/outgoing subscription requests - let (subscription_requests, set_subscription_requests)= signal(HashSet::<BareJID>::new()); + let (subscription_requests, set_subscription_requests) = signal(HashSet::<BareJID>::new()); provide_context(subscription_requests); provide_context(set_subscription_requests); // TODO: get cached contacts on login before getting the updated contacts - OnceResource::new(async move { + LocalResource::new(move || async move { + let mut updates = set_updates.write().take().expect("main loop ran twice"); while let Some(update) = updates.recv().await { match update { UpdateMessage::Online(online, items) => { - let contacts = items - .into_iter() - .map(|(contact, user)| { - ( - contact.user_jid.clone(), - ArcMacawContact::got_contact_and_user(contact, user).into(), - ) - }) - .collect(); + let mut contacts = HashMap::new(); + for (contact, user) in items { + contacts.insert( + contact.user_jid.clone(), + ArcMacawContact::got_contact_and_user(contact, user) + .await + .into(), + ); + } roster.contacts().set(contacts); } UpdateMessage::Offline(offline) => { @@ -85,13 +104,15 @@ pub fn Macaw( user_presences.write().clear(); } UpdateMessage::RosterUpdate(contact, user) => { + let new_contact = ArcMacawContact::got_contact_and_user(contact.clone(), user) + .await + .into(); roster.contacts().update(|roster| { if let Some(macaw_contact) = roster.get_mut(&contact.user_jid) { macaw_contact.set(contact); } else { let jid = contact.user_jid.clone(); - let contact = ArcMacawContact::got_contact_and_user(contact, user).into(); - roster.insert(jid, contact); + roster.insert(jid, new_contact); } }); } @@ -102,21 +123,30 @@ 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); + presences + .write() + .update_presence(resource.clone(), presence); } } else { if let Some(resource) = from.resourcepart() { let mut presences = Presences::new(); presences.update_presence(resource.clone(), presence); - user_presences.write().user_presences.insert(bare_jid, ArcRwSignal::new(presences)); + user_presences + .write() + .user_presences + .insert(bare_jid, ArcRwSignal::new(presences)); } } } UpdateMessage::Message { to, from, message } => { debug!("before got message"); - let new_message = ArcMacawMessage::got_message_and_user(message, from); + let new_message = ArcMacawMessage::got_message_and_user(message, from).await; debug!("after got message"); spawn_local(async move { message_subscriptions @@ -134,15 +164,21 @@ pub fn Macaw( }); } UpdateMessage::SubscriptionRequest(jid) => { - set_subscription_requests.update(|req| { req.insert(jid); }); + set_subscription_requests.update(|req| { + req.insert(jid); + }); } UpdateMessage::NickChanged { jid, nick } => { - users_store.modify(&jid, |user| { + users_store.modify(&jid, |(user, _avatar)| { user.update(|user| *&mut user.nick = nick.clone()) }); } UpdateMessage::AvatarChanged { jid, id } => { - users_store.modify(&jid, |user| *&mut user.write().avatar = id.clone()); + let new_avatar = fetch_avatar(id.as_deref()).await; + users_store.modify(&jid, |(user, avatar)| { + *&mut user.write().avatar = id.clone(); + *&mut avatar.set(new_avatar.clone()) + }); } } } @@ -152,11 +188,12 @@ pub fn Macaw( <Sidebar /> // <ChatsList /> <OpenChatsPanelView /> - {move || if let Some(_) = *show_settings.read() { - view! { <Settings /> }.into_any() - } else { - view! {}.into_any() + {move || { + if let Some(_) = *show_settings.read() { + view! { <Settings /> }.into_any() + } else { + view! {}.into_any() + } }} } } - |
