diff options
Diffstat (limited to 'src/components/roster_list/roster_list_item.rs')
-rw-r--r-- | src/components/roster_list/roster_list_item.rs | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/src/components/roster_list/roster_list_item.rs b/src/components/roster_list/roster_list_item.rs index 842f66c..538e664 100644 --- a/src/components/roster_list/roster_list_item.rs +++ b/src/components/roster_list/roster_list_item.rs @@ -1,11 +1,12 @@ use std::ops::Deref; use filamento::{chat::Chat, roster::{Contact, ContactStoreFields}, user::{User, UserStoreFields}}; +use jid::BareJID; use leptos::prelude::*; use reactive_stores::{ArcStore, Store}; use tracing::debug; -use crate::{chat::{ArcMacawChat, MacawChat}, components::{avatar::AvatarWithPresence, sidebar::Open}, contact::MacawContact, open_chats::{OpenChatsPanel, OpenChatsPanelStoreFields}, user::get_name}; +use crate::{chat::{ArcMacawChat, MacawChat}, client::Client, components::{avatar::AvatarWithPresence, sidebar::Open}, contact::MacawContact, open_chats::{OpenChatsPanel, OpenChatsPanelStoreFields}, state_store::StateStore, user::{fetch_avatar, get_name, ArcMacawUser}}; #[component] pub fn RosterListItem(contact: MacawContact) -> impl IntoView { @@ -14,21 +15,51 @@ pub fn RosterListItem(contact: MacawContact) -> impl IntoView { let open_chats: Store<OpenChatsPanel> = use_context().expect("no open chats panel store in context"); - // TODO: why can this not be in the closure????? - // TODO: not good, as overwrites preexisting chat state with possibly incorrect one... - let chat = Chat { - correspondent: contact.user.get().jid().get(), - have_chatted: false, - }; - let chat = ArcMacawChat::got_chat_and_user(chat, contact.user.get().get()); + let client = use_context::<Client>().expect("client not in context"); - let open_chat = move |_| { - debug!("opening chat"); - open_chats.update(|open_chats| open_chats.open(Clone::clone(&chat))); - }; + let chat_state_store: StateStore<BareJID, ArcStore<Chat>> = + use_context().expect("no chat state store"); + let user_state_store: StateStore<BareJID, (ArcStore<User>, ArcRwSignal<String>)> = + use_context().expect("no user state store"); + + let open_chat = Action::new_local(move |_| { + let client= client.clone(); + async move { + let to = contact.user.get().jid().get(); + let (chat, user) = match client.get_chat_and_user(to).await { + Ok(c) => c, + Err(e) => { + // TODO: error + // set_error.set(Some(e.into())); + // set_new_chat_pending.set(false); + return; + }, + }; + + let chat = { + // let user = MacawUser::got_user(user); + // let user = user_state_store.store(user.jid.clone(), ArcStore::new(user)); + let old_user = user_state_store.get_listener(user.jid.clone()); + let user = if let Some(old_user) = old_user { + old_user.update(|(old_user, _avatar)| { old_user.set(user); }); + old_user + } else { + let avatar = fetch_avatar(user.avatar.as_deref()).await; + let avatar = ArcRwSignal::new(avatar); + user_state_store.store(user.jid.clone(), (ArcStore::new(user), avatar)) + }; + let user = ArcMacawUser { user }; + let chat = chat_state_store.store(chat.correspondent.clone(), ArcStore::new(chat)); + ArcMacawChat { chat, user } + }; + open_chats.update(|open_chats| open_chats.open(chat.clone())); + } + }); + + let current_open_chat: Memo<Option<BareJID>> = use_context().expect("no open chat memo in context"); let open = move || { - if let Some(open_chat) = &*open_chats.chat_view().read() { + if let Some(open_chat) = &*current_open_chat.read() { debug!("got open chat: {:?}", open_chat); if *open_chat == *contact.user.get().jid().read() { return Open::Focused; @@ -47,11 +78,10 @@ pub fn RosterListItem(contact: MacawContact) -> impl IntoView { let open = move || open().is_open(); view! { - <div class="roster-list-item" class:open=move || open() class:focused=move || focused() on:click=open_chat> + <div class="roster-list-item" class:open=move || open() class:focused=move || focused() on:click=move |_| { open_chat.dispatch(()); }> {move || { - let user = contact.user.get().into(); view! { - <AvatarWithPresence user /> + <AvatarWithPresence user=contact.user /> } }} <div class="item-info"> |