summaryrefslogtreecommitdiffstats
path: root/src/components/roster_list/roster_list_item.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/roster_list/roster_list_item.rs')
-rw-r--r--src/components/roster_list/roster_list_item.rs62
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">