summaryrefslogtreecommitdiffstats
path: root/src/views/macaw.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/views/macaw.rs')
-rw-r--r--src/views/macaw.rs111
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()
+ }
}}
}
}
-