From 888870b7798866eb6465be2adfe490843aa306f7 Mon Sep 17 00:00:00 2001 From: Joscha Date: Mon, 8 Aug 2022 23:14:58 +0200 Subject: [PATCH] Show unseen message count in room list --- src/logger.rs | 4 ++++ src/store.rs | 1 + src/ui/room.rs | 8 +++++++ src/ui/rooms.rs | 60 +++++++++++++++++++++++++++++++++-------------- src/vault/euph.rs | 37 +++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 18 deletions(-) diff --git a/src/logger.rs b/src/logger.rs index 127811b..eb4b10b 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -139,6 +139,10 @@ impl MsgStore for Logger { None } + async fn unseen_msgs_count(&self) -> usize { + 0 + } + async fn set_seen(&self, _id: &usize, _seen: bool) {} async fn set_older_seen(&self, _id: &usize, _seen: bool) {} diff --git a/src/store.rs b/src/store.rs index 2a3c482..aba9279 100644 --- a/src/store.rs +++ b/src/store.rs @@ -133,6 +133,7 @@ pub trait MsgStore { async fn newest_unseen_msg_id(&self) -> Option; async fn older_unseen_msg_id(&self, id: &M::Id) -> Option; async fn newer_unseen_msg_id(&self, id: &M::Id) -> Option; + async fn unseen_msgs_count(&self) -> usize; async fn set_seen(&self, id: &M::Id, seen: bool); async fn set_older_seen(&self, id: &M::Id, seen: bool); } diff --git a/src/ui/room.rs b/src/ui/room.rs index 615d2f6..8bf4a2f 100644 --- a/src/ui/room.rs +++ b/src/ui/room.rs @@ -11,6 +11,7 @@ use toss::terminal::Terminal; use crate::euph::api::{SessionType, SessionView, Snowflake}; use crate::euph::{self, Joined, Status}; +use crate::store::MsgStore; use crate::vault::EuphVault; use super::chat::{ChatState, Reaction}; @@ -36,6 +37,7 @@ enum State { pub struct EuphRoom { ui_event_tx: mpsc::UnboundedSender, + vault: EuphVault, room: Option, state: State, @@ -50,6 +52,7 @@ impl EuphRoom { pub fn new(vault: EuphVault, ui_event_tx: mpsc::UnboundedSender) -> Self { Self { ui_event_tx, + vault: vault.clone(), room: None, state: State::Normal, chat: ChatState::new(vault), @@ -91,6 +94,10 @@ impl EuphRoom { } } + pub async fn unseen_msgs_count(&self) -> usize { + self.vault.unseen_msgs_count().await + } + async fn stabilize_pseudo_msg(&mut self) { if let Some(id_rx) = &mut self.last_msg_sent { match id_rx.try_recv() { @@ -169,6 +176,7 @@ impl EuphRoom { } fn status_widget(&self, status: &Option>) -> BoxedWidget { + // TODO Include unread message count let room = self.chat.store().room(); let room_style = ContentStyle::default().bold().blue(); let mut info = Styled::new(format!("&{room}"), room_style); diff --git a/src/ui/rooms.rs b/src/ui/rooms.rs index b2890af..f4b7c90 100644 --- a/src/ui/rooms.rs +++ b/src/ui/rooms.rs @@ -154,12 +154,44 @@ impl Rooms { result.join(" ") } - fn format_status(status: &Option) -> String { - match status { - None => " (connecting)".to_string(), - Some(Status::Joining(j)) if j.bounce.is_some() => " (auth required)".to_string(), - Some(Status::Joining(_)) => " (joining)".to_string(), - Some(Status::Joined(j)) => format!(" ({})", Self::format_pbln(j)), + async fn format_status(room: &EuphRoom) -> Option { + match room.status().await { + None => None, + Some(None) => Some("connecting".to_string()), + Some(Some(Status::Joining(j))) if j.bounce.is_some() => { + Some("auth required".to_string()) + } + Some(Some(Status::Joining(_))) => Some("joining".to_string()), + Some(Some(Status::Joined(joined))) => Some(Self::format_pbln(&joined)), + } + } + + async fn format_unseen_msgs(room: &EuphRoom) -> Option { + let unseen = room.unseen_msgs_count().await; + if unseen == 0 { + None + } else { + Some(format!("{unseen}")) + } + } + + async fn format_room_info(room: &EuphRoom) -> Styled { + let unseen_style = ContentStyle::default().bold().green(); + + let status = Self::format_status(room).await; + let unseen = Self::format_unseen_msgs(room).await; + + match (status, unseen) { + (None, None) => Styled::default(), + (None, Some(u)) => Styled::new_plain(" (") + .then(&u, unseen_style) + .then_plain(")"), + (Some(s), None) => Styled::new_plain(" (").then_plain(&s).then_plain(")"), + (Some(s), Some(u)) => Styled::new_plain(" (") + .then_plain(&s) + .then_plain(", ") + .then(&u, unseen_style) + .then_plain(")"), } } @@ -176,26 +208,18 @@ impl Rooms { } for room in rooms { - let bg_style = ContentStyle::default(); - let bg_sel_style = ContentStyle::default().black().on_white(); let room_style = ContentStyle::default().bold().blue(); let room_sel_style = ContentStyle::default().bold().black().on_white(); let mut normal = Styled::new(format!("&{room}"), room_style); let mut selected = Styled::new(format!("&{room}"), room_sel_style); if let Some(room) = self.euph_rooms.get(&room) { - if let Some(status) = room.status().await { - let status = Self::format_status(&status); - normal = normal.then(status.clone(), bg_style); - selected = selected.then(status, bg_sel_style); - } + let info = Self::format_room_info(room).await; + normal = normal.and_then(info.clone()); + selected = selected.and_then(info); }; - list.add_sel( - room, - Text::new(normal), - Background::new(Text::new(selected)).style(bg_sel_style), - ); + list.add_sel(room, Text::new(normal), Text::new(selected)); } } diff --git a/src/vault/euph.rs b/src/vault/euph.rs index f24ecd1..1e9df1b 100644 --- a/src/vault/euph.rs +++ b/src/vault/euph.rs @@ -305,6 +305,17 @@ impl MsgStore for EuphVault { rx.await.unwrap() } + async fn unseen_msgs_count(&self) -> usize { + // TODO vault::Error + let (tx, rx) = oneshot::channel(); + let request = EuphRequest::GetUnseenMsgsCount { + room: self.room.clone(), + result: tx, + }; + let _ = self.vault.tx.send(request.into()); + rx.await.unwrap() + } + async fn set_seen(&self, id: &Snowflake, seen: bool) { let request = EuphRequest::SetSeen { room: self.room.clone(), @@ -432,6 +443,10 @@ pub(super) enum EuphRequest { id: Snowflake, result: oneshot::Sender>, }, + GetUnseenMsgsCount { + room: String, + result: oneshot::Sender, + }, SetSeen { room: String, id: Snowflake, @@ -503,6 +518,9 @@ impl EuphRequest { EuphRequest::GetNewerUnseenMsgId { room, id, result } => { Self::get_newer_unseen_msg_id(conn, room, id, result) } + EuphRequest::GetUnseenMsgsCount { room, result } => { + Self::get_unseen_msgs_count(conn, room, result) + } EuphRequest::SetSeen { room, id, seen } => Self::set_seen(conn, room, id, seen), EuphRequest::SetOlderSeen { room, id, seen } => { Self::set_older_seen(conn, room, id, seen) @@ -1198,6 +1216,25 @@ impl EuphRequest { Ok(()) } + fn get_unseen_msgs_count( + conn: &Connection, + room: String, + result: oneshot::Sender, + ) -> rusqlite::Result<()> { + let amount = conn + .prepare( + " + SELECT COUNT(*) + FROM euph_msgs + WHERE room = ? + AND NOT seen + ", + )? + .query_row(params![room], |row| row.get(0))?; + let _ = result.send(amount); + Ok(()) + } + fn set_seen( conn: &Connection, room: String,