1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
use chats_list_item::ChatsListItem;
use indexmap::IndexMap;
use jid::BareJID;
use leptos::prelude::*;
use tracing::debug;
use crate::{chat::{ArcMacawChat, MacawChat}, client::Client, components::{icon::IconComponent, new_chat::NewChatWidget, overlay::Overlay}, icon::Icon, message::{ArcMacawMessage, MacawMessage}, message_subscriptions::MessageSubscriptions};
mod chats_list_item;
#[component]
pub fn ChatsList() -> impl IntoView {
let (chats, set_chats) = signal(IndexMap::new());
let load_chats = LocalResource::new(move || async move {
let client = use_context::<Client>().expect("client not in context");
let chats = client
.get_chats_ordered_with_latest_messages_and_users()
.await
.map_err(|e| e.to_string());
match chats {
Ok(c) => {
let chats = c
.into_iter()
.map(|((chat, chat_user), (message, message_user))| {
(
chat.correspondent.clone(),
(
ArcMacawChat::got_chat_and_user(chat, chat_user),
ArcMacawMessage::got_message_and_user(message, message_user),
),
)
})
.collect::<IndexMap<BareJID, _>>();
set_chats.set(chats);
}
Err(_) => {
// TODO: show error message at top of chats list
}
}
});
let (open_new_chat, set_open_new_chat) = signal(false);
// TODO: filter new messages signal
let new_messages_signal: RwSignal<MessageSubscriptions> = use_context().unwrap();
let (sub_id, set_sub_id) = signal(None);
let _load_new_messages = LocalResource::new(move || async move {
load_chats.await;
let (sub_id, mut new_messages) = new_messages_signal.write().subscribe_all();
set_sub_id.set(Some(sub_id));
while let Some((to, new_message)) = new_messages.recv().await {
debug!("got new message in let");
let mut chats = set_chats.write();
if let Some((chat, _latest_message)) = chats.shift_remove(&to) {
// TODO: check if new message is actually latest message
debug!("chat existed");
debug!("new message: {}", new_message.message.get().read().body.body);
chats.insert_before(0, to, (chat.clone(), new_message));
debug!("done setting");
} else {
debug!("the chat didn't exist");
let client = use_context::<Client>().expect("client not in context");
let chat = client.get_chat(to.clone()).await.unwrap();
let user = client.get_user(to.clone()).await.unwrap();
debug!("before got chat");
let chat = ArcMacawChat::got_chat_and_user(chat, user);
debug!("after got chat");
chats.insert_before(0, to, (chat, new_message));
debug!("done setting");
}
}
debug!("set the new message");
});
on_cleanup(move || {
if let Some(sub_id) = sub_id.get_untracked() {
new_messages_signal.write().unsubscribe_all(sub_id);
}
});
view! {
<div class="chats-list panel">
// TODO: update icon, tooltip on hover.
<div class="header">
<h2>Chats</h2>
<div class="new-chat header-icon" class:open=open_new_chat >
<IconComponent icon=Icon::NewBubble24 on:click=move |_| set_open_new_chat.update(|state| *state = !*state)/>
{move || {
if *open_new_chat.read() {
view! {
<Overlay set_open=set_open_new_chat>
<NewChatWidget set_open_new_chat />
</Overlay>
}.into_any()
} else {
view! {}.into_any()
}
}}
</div>
</div>
<div class="chats-list-chats">
<For each=move || chats.get() key=|chat| chat.1.1.message.get().read().id let(chat)>
<ChatsListItem chat=chat.1.0.into() message=chat.1.1.into() />
</For>
</div>
</div>
}
}
|