diff options
| author | 2025-06-07 17:36:22 +0100 | |
|---|---|---|
| committer | 2025-06-07 17:36:22 +0100 | |
| commit | 36e87b708ed3a2b0d6f2e932509b0fdf10fe0089 (patch) | |
| tree | 5f3fc5a3d863f52a82a204a7746532202103d7cc /src/components/roster_list | |
| parent | 4a5aa6579f5184c443ffbe80ce93e0daa0926826 (diff) | |
| download | macaw-web-36e87b708ed3a2b0d6f2e932509b0fdf10fe0089.tar.gz macaw-web-36e87b708ed3a2b0d6f2e932509b0fdf10fe0089.tar.bz2 macaw-web-36e87b708ed3a2b0d6f2e932509b0fdf10fe0089.zip  | |
fix: avatar flashing from avatar load
Diffstat (limited to 'src/components/roster_list')
| -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">  | 
