aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@bunny.garden>2025-03-20 17:20:15 +0000
committerLibravatar cel 🌸 <cel@bunny.garden>2025-03-20 17:20:15 +0000
commit8595b2e23b2f719e83b312a28f9dc72b9b01c1b3 (patch)
tree676ec9216f0892b529fd68a451e420a4ee377cfe
parent9a38e9487c64c1887d439757bef3ceafce30535b (diff)
downloadmacaw-8595b2e23b2f719e83b312a28f9dc72b9b01c1b3.tar.gz
macaw-8595b2e23b2f719e83b312a28f9dc72b9b01c1b3.tar.bz2
macaw-8595b2e23b2f719e83b312a28f9dc72b9b01c1b3.zip
feat: 'proper' chats list with latest message timestamps and previews
-rw-r--r--src/main.rs103
1 files changed, 64 insertions, 39 deletions
diff --git a/src/main.rs b/src/main.rs
index 6b1b2fe..bc60f0a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6,18 +6,20 @@ use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;
+use chrono::Local;
+use iced::alignment::Horizontal::Right;
use iced::futures::{SinkExt, Stream, StreamExt};
use iced::theme::palette::{
Background, Danger, Extended, Pair, Primary, Secondary, Success, Warning,
};
use iced::theme::{Custom, Palette};
use iced::widget::button::Status;
-use iced::widget::text::{Fragment, IntoFragment};
+use iced::widget::text::{Fragment, IntoFragment, Wrapping};
use iced::widget::{
- button, center, checkbox, column, container, mouse_area, opaque, row, scrollable, stack, text,
- text_input, toggler, Column, Text, Toggler,
+ button, center, checkbox, column, container, horizontal_space, mouse_area, opaque, row,
+ scrollable, stack, text, text_input, toggler, Column, Text, Toggler,
};
-use iced::Length::Fill;
+use iced::Length::{self, Fill, Shrink};
use iced::{color, stream, Color, Element, Subscription, Task, Theme};
use indexmap::{indexmap, IndexMap};
use jid::JID;
@@ -333,10 +335,9 @@ pub enum Message {
Roster(HashMap<JID, Contact>),
Connect,
Disconnect,
- OpenChat(JID),
GotChats(Vec<Chat>),
GotMessageHistory(Chat, IndexMap<Uuid, ChatMessage>),
- CloseChat(JID),
+ ToggleChat(JID),
MessageCompose(String),
SendMessage(JID, String),
Error(Error),
@@ -537,7 +538,16 @@ impl Macaw {
}
Account::LoggedOut(login_modal) => Task::none(),
},
- Message::OpenChat(jid) => {
+ Message::ToggleChat(jid) => {
+ match &self.open_chat {
+ Some(message_view) => {
+ if message_view.jid == jid {
+ self.open_chat = None;
+ return Task::none();
+ }
+ }
+ None => {}
+ }
self.open_chat = Some(MessageView::new(jid.clone()));
let jid1 = jid.clone();
match &self.client {
@@ -681,10 +691,6 @@ impl Macaw {
}
Task::none()
}
- Message::CloseChat(jid) => {
- self.open_chat = None;
- Task::none()
- }
Message::MessageCompose(m) => {
if let Some(open_chat) = &mut self.open_chat {
open_chat.new_message = m;
@@ -727,26 +733,19 @@ impl Macaw {
fn view(&self) -> Element<Message> {
let mut ui: Element<Message> = {
let mut chats_list: Column<Message> = column![];
- for (jid, chat) in &self.chats {
- let cow_jid: Cow<'_, str> = (jid).into();
- let mut toggler: Toggler<Message> = iced::widget::toggler(false);
+ for (jid, (chat, latest_message)) in &self.chats {
+ let mut open = false;
if let Some(open_chat) = &self.open_chat {
if open_chat.jid == *jid {
- toggler = iced::widget::toggler(true)
+ open = true;
}
}
- let toggler = toggler
- .on_toggle(|open| {
- if open {
- Message::OpenChat(jid.clone())
- } else {
- Message::CloseChat(jid.clone())
- }
- })
- .label(cow_jid);
- chats_list = chats_list.push(toggler);
+ let chat_list_item = chat_list_item(chat, latest_message, open);
+ chats_list = chats_list.push(chat_list_item);
}
- let chats_list = scrollable(chats_list).height(Fill);
+ let chats_list = scrollable(chats_list.spacing(8).padding(8))
+ .spacing(1)
+ .height(Fill);
let connection_status = self.client.connection_status();
let client_jid: Cow<'_, str> = match &self.client {
@@ -769,7 +768,8 @@ impl Macaw {
.label(connection_status),
];
- let sidebar = column![chats_list, account_view].height(Fill);
+ // TODO: config width/resizing
+ let sidebar = column![chats_list, account_view].height(Fill).width(300);
let message_view;
if let Some(open_chat) = &self.open_chat {
@@ -779,18 +779,6 @@ impl Macaw {
}
row![sidebar, container(message_view).width(Fill)]
-
- // old
-
- // let mut contacts: Vec<Element<Message>> = Vec::new();
- // for (_, contact) in &self.roster {
- // let jid: Cow<'_, str> = (&contact.user_jid).into();
- // contacts.push(
- // button(text(jid))
- // .on_press(Message::OpenChat(contact.user_jid.clone()))
- // .into(),
- // );
- // }
}
.into();
@@ -951,3 +939,40 @@ where
}
stack![base.into(), opaque(mouse_area)].into()
}
+
+fn chat_list_item<'a>(
+ chat: &'a Chat,
+ latest_message: &'a Option<ChatMessage>,
+ open: bool,
+) -> Element<'a, Message> {
+ let mut content: Column<Message> = column![text(chat.correspondent.to_string())];
+ if let Some(latest_message) = latest_message {
+ let date = latest_message.timestamp.naive_local();
+ let now = Local::now().naive_local();
+ let timeinfo;
+ if date.date() == now.date() {
+ // TODO: localisation/config
+ timeinfo = text(date.time().format("%H:%M").to_string())
+ } else {
+ timeinfo = text(date.date().format("%d/%m").to_string())
+ }
+ content = content.push(
+ row![
+ container(text(latest_message.body.body.clone()).wrapping(Wrapping::None))
+ .clip(true)
+ .width(Fill),
+ timeinfo
+ ]
+ .spacing(8)
+ .width(Fill),
+ );
+ }
+ let mut button = button(content).on_press(Message::ToggleChat(chat.correspondent.clone()));
+ if open {
+ button = button.style(|theme: &Theme, status| {
+ let palette = theme.extended_palette();
+ button::Style::default().with_background(palette.primary.weak.color)
+ });
+ }
+ button.width(Fill).into()
+}