diff options
author | 2025-03-20 17:20:15 +0000 | |
---|---|---|
committer | 2025-03-20 17:20:15 +0000 | |
commit | 8595b2e23b2f719e83b312a28f9dc72b9b01c1b3 (patch) | |
tree | 676ec9216f0892b529fd68a451e420a4ee377cfe | |
parent | 9a38e9487c64c1887d439757bef3ceafce30535b (diff) | |
download | macaw-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.rs | 103 |
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() +} |