Show unseen message count in room list
This commit is contained in:
parent
e00ce4ebba
commit
888870b779
5 changed files with 92 additions and 18 deletions
|
|
@ -139,6 +139,10 @@ impl MsgStore<LogMsg> for Logger {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn unseen_msgs_count(&self) -> usize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
async fn set_seen(&self, _id: &usize, _seen: bool) {}
|
async fn set_seen(&self, _id: &usize, _seen: bool) {}
|
||||||
|
|
||||||
async fn set_older_seen(&self, _id: &usize, _seen: bool) {}
|
async fn set_older_seen(&self, _id: &usize, _seen: bool) {}
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,7 @@ pub trait MsgStore<M: Msg> {
|
||||||
async fn newest_unseen_msg_id(&self) -> Option<M::Id>;
|
async fn newest_unseen_msg_id(&self) -> Option<M::Id>;
|
||||||
async fn older_unseen_msg_id(&self, id: &M::Id) -> Option<M::Id>;
|
async fn older_unseen_msg_id(&self, id: &M::Id) -> Option<M::Id>;
|
||||||
async fn newer_unseen_msg_id(&self, id: &M::Id) -> Option<M::Id>;
|
async fn newer_unseen_msg_id(&self, id: &M::Id) -> Option<M::Id>;
|
||||||
|
async fn unseen_msgs_count(&self) -> usize;
|
||||||
async fn set_seen(&self, id: &M::Id, seen: bool);
|
async fn set_seen(&self, id: &M::Id, seen: bool);
|
||||||
async fn set_older_seen(&self, id: &M::Id, seen: bool);
|
async fn set_older_seen(&self, id: &M::Id, seen: bool);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ use toss::terminal::Terminal;
|
||||||
|
|
||||||
use crate::euph::api::{SessionType, SessionView, Snowflake};
|
use crate::euph::api::{SessionType, SessionView, Snowflake};
|
||||||
use crate::euph::{self, Joined, Status};
|
use crate::euph::{self, Joined, Status};
|
||||||
|
use crate::store::MsgStore;
|
||||||
use crate::vault::EuphVault;
|
use crate::vault::EuphVault;
|
||||||
|
|
||||||
use super::chat::{ChatState, Reaction};
|
use super::chat::{ChatState, Reaction};
|
||||||
|
|
@ -36,6 +37,7 @@ enum State {
|
||||||
pub struct EuphRoom {
|
pub struct EuphRoom {
|
||||||
ui_event_tx: mpsc::UnboundedSender<UiEvent>,
|
ui_event_tx: mpsc::UnboundedSender<UiEvent>,
|
||||||
|
|
||||||
|
vault: EuphVault,
|
||||||
room: Option<euph::Room>,
|
room: Option<euph::Room>,
|
||||||
|
|
||||||
state: State,
|
state: State,
|
||||||
|
|
@ -50,6 +52,7 @@ impl EuphRoom {
|
||||||
pub fn new(vault: EuphVault, ui_event_tx: mpsc::UnboundedSender<UiEvent>) -> Self {
|
pub fn new(vault: EuphVault, ui_event_tx: mpsc::UnboundedSender<UiEvent>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ui_event_tx,
|
ui_event_tx,
|
||||||
|
vault: vault.clone(),
|
||||||
room: None,
|
room: None,
|
||||||
state: State::Normal,
|
state: State::Normal,
|
||||||
chat: ChatState::new(vault),
|
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) {
|
async fn stabilize_pseudo_msg(&mut self) {
|
||||||
if let Some(id_rx) = &mut self.last_msg_sent {
|
if let Some(id_rx) = &mut self.last_msg_sent {
|
||||||
match id_rx.try_recv() {
|
match id_rx.try_recv() {
|
||||||
|
|
@ -169,6 +176,7 @@ impl EuphRoom {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn status_widget(&self, status: &Option<Option<Status>>) -> BoxedWidget {
|
fn status_widget(&self, status: &Option<Option<Status>>) -> BoxedWidget {
|
||||||
|
// TODO Include unread message count
|
||||||
let room = self.chat.store().room();
|
let room = self.chat.store().room();
|
||||||
let room_style = ContentStyle::default().bold().blue();
|
let room_style = ContentStyle::default().bold().blue();
|
||||||
let mut info = Styled::new(format!("&{room}"), room_style);
|
let mut info = Styled::new(format!("&{room}"), room_style);
|
||||||
|
|
|
||||||
|
|
@ -154,12 +154,44 @@ impl Rooms {
|
||||||
result.join(" ")
|
result.join(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_status(status: &Option<Status>) -> String {
|
async fn format_status(room: &EuphRoom) -> Option<String> {
|
||||||
match status {
|
match room.status().await {
|
||||||
None => " (connecting)".to_string(),
|
None => None,
|
||||||
Some(Status::Joining(j)) if j.bounce.is_some() => " (auth required)".to_string(),
|
Some(None) => Some("connecting".to_string()),
|
||||||
Some(Status::Joining(_)) => " (joining)".to_string(),
|
Some(Some(Status::Joining(j))) if j.bounce.is_some() => {
|
||||||
Some(Status::Joined(j)) => format!(" ({})", Self::format_pbln(j)),
|
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<String> {
|
||||||
|
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 {
|
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_style = ContentStyle::default().bold().blue();
|
||||||
let room_sel_style = ContentStyle::default().bold().black().on_white();
|
let room_sel_style = ContentStyle::default().bold().black().on_white();
|
||||||
|
|
||||||
let mut normal = Styled::new(format!("&{room}"), room_style);
|
let mut normal = Styled::new(format!("&{room}"), room_style);
|
||||||
let mut selected = Styled::new(format!("&{room}"), room_sel_style);
|
let mut selected = Styled::new(format!("&{room}"), room_sel_style);
|
||||||
if let Some(room) = self.euph_rooms.get(&room) {
|
if let Some(room) = self.euph_rooms.get(&room) {
|
||||||
if let Some(status) = room.status().await {
|
let info = Self::format_room_info(room).await;
|
||||||
let status = Self::format_status(&status);
|
normal = normal.and_then(info.clone());
|
||||||
normal = normal.then(status.clone(), bg_style);
|
selected = selected.and_then(info);
|
||||||
selected = selected.then(status, bg_sel_style);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
list.add_sel(
|
list.add_sel(room, Text::new(normal), Text::new(selected));
|
||||||
room,
|
|
||||||
Text::new(normal),
|
|
||||||
Background::new(Text::new(selected)).style(bg_sel_style),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -305,6 +305,17 @@ impl MsgStore<SmallMessage> for EuphVault {
|
||||||
rx.await.unwrap()
|
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) {
|
async fn set_seen(&self, id: &Snowflake, seen: bool) {
|
||||||
let request = EuphRequest::SetSeen {
|
let request = EuphRequest::SetSeen {
|
||||||
room: self.room.clone(),
|
room: self.room.clone(),
|
||||||
|
|
@ -432,6 +443,10 @@ pub(super) enum EuphRequest {
|
||||||
id: Snowflake,
|
id: Snowflake,
|
||||||
result: oneshot::Sender<Option<Snowflake>>,
|
result: oneshot::Sender<Option<Snowflake>>,
|
||||||
},
|
},
|
||||||
|
GetUnseenMsgsCount {
|
||||||
|
room: String,
|
||||||
|
result: oneshot::Sender<usize>,
|
||||||
|
},
|
||||||
SetSeen {
|
SetSeen {
|
||||||
room: String,
|
room: String,
|
||||||
id: Snowflake,
|
id: Snowflake,
|
||||||
|
|
@ -503,6 +518,9 @@ impl EuphRequest {
|
||||||
EuphRequest::GetNewerUnseenMsgId { room, id, result } => {
|
EuphRequest::GetNewerUnseenMsgId { room, id, result } => {
|
||||||
Self::get_newer_unseen_msg_id(conn, 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::SetSeen { room, id, seen } => Self::set_seen(conn, room, id, seen),
|
||||||
EuphRequest::SetOlderSeen { room, id, seen } => {
|
EuphRequest::SetOlderSeen { room, id, seen } => {
|
||||||
Self::set_older_seen(conn, room, id, seen)
|
Self::set_older_seen(conn, room, id, seen)
|
||||||
|
|
@ -1198,6 +1216,25 @@ impl EuphRequest {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_unseen_msgs_count(
|
||||||
|
conn: &Connection,
|
||||||
|
room: String,
|
||||||
|
result: oneshot::Sender<usize>,
|
||||||
|
) -> 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(
|
fn set_seen(
|
||||||
conn: &Connection,
|
conn: &Connection,
|
||||||
room: String,
|
room: String,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue