aboutsummaryrefslogtreecommitdiffstats
path: root/src/message_view.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/message_view.rs')
-rw-r--r--src/message_view.rs169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/message_view.rs b/src/message_view.rs
new file mode 100644
index 0000000..4709dd6
--- /dev/null
+++ b/src/message_view.rs
@@ -0,0 +1,169 @@
+use std::borrow::Cow;
+
+use chrono::NaiveDate;
+use iced::{
+ alignment::Horizontal::{self, Right},
+ border::Radius,
+ color,
+ theme::Palette,
+ widget::{button, column, container, row, scrollable, text, text_input, Column},
+ Border, Color, Element,
+ Length::{Fill, Shrink},
+ Theme,
+};
+use indexmap::IndexMap;
+use jid::JID;
+use luz::chat::Message as ChatMessage;
+use uuid::Uuid;
+
+pub struct MessageView {
+ pub jid: JID,
+ pub message_history: IndexMap<Uuid, ChatMessage>,
+ pub new_message: String,
+}
+
+#[derive(Debug, Clone)]
+pub enum Message {
+ MessageHistory(Vec<ChatMessage>),
+ Message(ChatMessage),
+ MessageCompose(String),
+ SendMessage(String),
+}
+
+pub enum Action {
+ None,
+ SendMessage(String),
+}
+
+impl MessageView {
+ pub fn new(jid: JID) -> Self {
+ Self {
+ jid,
+ // TODO: save position in message history
+ message_history: IndexMap::new(),
+ // TODO: save draft (as part of chat struct?)
+ new_message: String::new(),
+ }
+ }
+ pub fn update(&mut self, message: Message) -> Action {
+ match message {
+ Message::MessageHistory(messages) => {
+ if self.message_history.is_empty() {
+ self.message_history = messages
+ .into_iter()
+ .map(|message| (message.id.clone(), message))
+ .collect();
+ }
+ Action::None
+ }
+ Message::Message(message) => {
+ let i = self
+ .message_history
+ .iter()
+ .position(|(_id, m)| m.timestamp > message.timestamp);
+ if let Some(i) = i {
+ self.message_history.insert_before(i, message.id, message);
+ } else {
+ self.message_history.insert(message.id, message);
+ }
+ Action::None
+ }
+ Message::MessageCompose(s) => {
+ self.new_message = s;
+ Action::None
+ }
+ Message::SendMessage(m) => {
+ self.new_message = String::new();
+ Action::SendMessage(m)
+ }
+ }
+ }
+ pub fn view(&self) -> Element<Message> {
+ let mut messages_view = column![].spacing(8);
+ let mut latest_date = NaiveDate::MIN;
+ for (_id, message) in &self.message_history {
+ let message_date = message.timestamp.naive_local().date();
+ if message_date > latest_date {
+ latest_date = message_date;
+ messages_view = messages_view.push(date(latest_date));
+ }
+ messages_view = messages_view.push(self.message(message));
+ }
+ let message_send_input = row![
+ text_input("new message", &self.new_message).on_input(Message::MessageCompose),
+ button("send").on_press(Message::SendMessage(self.new_message.clone()))
+ ];
+ column![
+ scrollable(messages_view)
+ .height(Fill)
+ .width(Fill)
+ .spacing(1)
+ .anchor_bottom(),
+ message_send_input
+ ]
+ .into()
+ }
+
+ pub fn message<'a>(&'a self, message: &'a ChatMessage) -> Element<'a, Message> {
+ let timestamp = message.timestamp.naive_local();
+ let timestamp = timestamp.time().format("%H:%M").to_string();
+
+ if self.jid == message.from.as_bare() {
+ container(
+ container(
+ column![
+ text(message.body.body.as_str()),
+ container(text(timestamp).wrapping(text::Wrapping::None).size(12))
+ .align_right(Fill)
+ ]
+ .width(Shrink)
+ .max_width(500),
+ )
+ .padding(16)
+ .style(|theme: &Theme| {
+ let palette = theme.extended_palette();
+ container::Style::default()
+ .background(palette.primary.weak.color)
+ .border(Border {
+ color: Color::BLACK,
+ width: 4.,
+ radius: Radius::new(16),
+ })
+ }),
+ )
+ .align_left(Fill)
+ .into()
+ } else {
+ let element: Element<Message> = container(
+ container(
+ column![
+ text(message.body.body.as_str()),
+ container(text(timestamp).wrapping(text::Wrapping::None).size(12))
+ .align_right(Fill)
+ ]
+ .width(Shrink)
+ .max_width(500),
+ )
+ .padding(16)
+ .style(|theme: &Theme| {
+ let palette = theme.extended_palette();
+ container::Style::default()
+ .background(palette.primary.base.color)
+ .border(Border {
+ color: Color::BLACK,
+ width: 4.,
+ radius: Radius::new(16),
+ })
+ }),
+ )
+ .align_right(Fill)
+ .into();
+ // element.explain(Color::BLACK)
+ element
+ }
+ }
+}
+
+pub fn date(date: NaiveDate) -> Element<'static, Message> {
+ container(text(date.to_string())).center_x(Fill).into()
+}