Set messages' seen status when adding to vault

This commit is contained in:
Joscha 2022-08-08 14:53:13 +02:00
parent fdb8fc7bd0
commit 20ec6ef3b3
2 changed files with 81 additions and 37 deletions

View file

@ -19,8 +19,9 @@ use crate::macros::ok_or_return;
use crate::ui::UiEvent; use crate::ui::UiEvent;
use crate::vault::{EuphVault, Vault}; use crate::vault::{EuphVault, Vault};
use super::api::{Data, Log, Nick, Send, Snowflake}; use super::api::{Data, Log, Nick, Send, Snowflake, UserId};
use super::conn::{self, ConnRx, ConnTx, Status}; use super::conn::{self, ConnRx, ConnTx, Status};
use super::Joining;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum Error { pub enum Error {
@ -170,6 +171,13 @@ impl State {
Ok(()) Ok(())
} }
async fn own_user_id(&self) -> Option<UserId> {
Some(match self.conn_tx.as_ref()?.status().await.ok()? {
Status::Joining(Joining { hello, .. }) => hello?.session.id,
Status::Joined(joined) => joined.session.id,
})
}
async fn on_data(&mut self, data: Data) -> anyhow::Result<()> { async fn on_data(&mut self, data: Data) -> anyhow::Result<()> {
match data { match data {
Data::BounceEvent(_) => {} Data::BounceEvent(_) => {}
@ -202,9 +210,10 @@ impl State {
); );
} }
Data::SendEvent(d) => { Data::SendEvent(d) => {
let own_user_id = self.own_user_id().await;
if let Some(last_msg_id) = &mut self.last_msg_id { if let Some(last_msg_id) = &mut self.last_msg_id {
let id = d.0.id; let id = d.0.id;
self.vault.add_message(d.0, *last_msg_id); self.vault.add_message(d.0, *last_msg_id, own_user_id);
*last_msg_id = Some(id); *last_msg_id = Some(id);
} else { } else {
bail!("send event before snapshot event"); bail!("send event before snapshot event");
@ -214,15 +223,18 @@ impl State {
info!("e&{}: successfully joined", self.name); info!("e&{}: successfully joined", self.name);
self.vault.join(Time::now()); self.vault.join(Time::now());
self.last_msg_id = Some(d.log.last().map(|m| m.id)); self.last_msg_id = Some(d.log.last().map(|m| m.id));
self.vault.add_messages(d.log, None); let own_user_id = self.own_user_id().await;
self.vault.add_messages(d.log, None, own_user_id);
} }
Data::LogReply(d) => { Data::LogReply(d) => {
self.vault.add_messages(d.log, d.before); let own_user_id = self.own_user_id().await;
self.vault.add_messages(d.log, d.before, own_user_id);
} }
Data::SendReply(d) => { Data::SendReply(d) => {
let own_user_id = self.own_user_id().await;
if let Some(last_msg_id) = &mut self.last_msg_id { if let Some(last_msg_id) = &mut self.last_msg_id {
let id = d.0.id; let id = d.0.id;
self.vault.add_message(d.0, *last_msg_id); self.vault.add_message(d.0, *last_msg_id, own_user_id);
*last_msg_id = Some(id); *last_msg_id = Some(id);
} else { } else {
bail!("send reply before snapshot event"); bail!("send reply before snapshot event");

View file

@ -8,7 +8,7 @@ use rusqlite::{named_params, params, Connection, OptionalExtension, ToSql, Trans
use time::OffsetDateTime; use time::OffsetDateTime;
use tokio::sync::oneshot; use tokio::sync::oneshot;
use crate::euph::api::{Message, Snowflake, Time}; use crate::euph::api::{Message, Snowflake, Time, UserId};
use crate::euph::SmallMessage; use crate::euph::SmallMessage;
use crate::store::{MsgStore, Path, Tree}; use crate::store::{MsgStore, Path, Tree};
@ -99,20 +99,32 @@ impl EuphVault {
let _ = self.vault.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
} }
pub fn add_message(&self, msg: Message, prev_msg: Option<Snowflake>) { pub fn add_message(
&self,
msg: Message,
prev_msg: Option<Snowflake>,
own_user_id: Option<UserId>,
) {
let request = EuphRequest::AddMsg { let request = EuphRequest::AddMsg {
room: self.room.clone(), room: self.room.clone(),
msg: Box::new(msg), msg: Box::new(msg),
prev_msg, prev_msg,
own_user_id,
}; };
let _ = self.vault.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
} }
pub fn add_messages(&self, msgs: Vec<Message>, next_msg: Option<Snowflake>) { pub fn add_messages(
&self,
msgs: Vec<Message>,
next_msg: Option<Snowflake>,
own_user_id: Option<UserId>,
) {
let request = EuphRequest::AddMsgs { let request = EuphRequest::AddMsgs {
room: self.room.clone(), room: self.room.clone(),
msgs, msgs,
next_msg, next_msg,
own_user_id,
}; };
let _ = self.vault.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
} }
@ -280,11 +292,13 @@ pub(super) enum EuphRequest {
room: String, room: String,
msg: Box<Message>, msg: Box<Message>,
prev_msg: Option<Snowflake>, prev_msg: Option<Snowflake>,
own_user_id: Option<UserId>,
}, },
AddMsgs { AddMsgs {
room: String, room: String,
msgs: Vec<Message>, msgs: Vec<Message>,
next_msg: Option<Snowflake>, next_msg: Option<Snowflake>,
own_user_id: Option<UserId>,
}, },
GetLastSpan { GetLastSpan {
room: String, room: String,
@ -350,12 +364,14 @@ impl EuphRequest {
room, room,
msg, msg,
prev_msg, prev_msg,
} => Self::add_msg(conn, room, *msg, prev_msg), own_user_id,
} => Self::add_msg(conn, room, *msg, prev_msg, own_user_id),
EuphRequest::AddMsgs { EuphRequest::AddMsgs {
room, room,
msgs, msgs,
next_msg, next_msg,
} => Self::add_msgs(conn, room, msgs, next_msg), own_user_id,
} => Self::add_msgs(conn, room, msgs, next_msg, own_user_id),
EuphRequest::GetLastSpan { room, result } => Self::get_last_span(conn, room, result), EuphRequest::GetLastSpan { room, result } => Self::get_last_span(conn, room, result),
EuphRequest::GetPath { room, id, result } => Self::get_path(conn, room, id, result), EuphRequest::GetPath { room, id, result } => Self::get_path(conn, room, id, result),
EuphRequest::GetTree { room, root, result } => Self::get_tree(conn, room, root, result), EuphRequest::GetTree { room, root, result } => Self::get_tree(conn, room, root, result),
@ -494,16 +510,28 @@ impl EuphRequest {
Ok(()) Ok(())
} }
fn insert_msgs(tx: &Transaction<'_>, room: &str, msgs: Vec<Message>) -> rusqlite::Result<()> { fn insert_msgs(
tx: &Transaction<'_>,
room: &str,
own_user_id: &Option<UserId>,
msgs: Vec<Message>,
) -> rusqlite::Result<()> {
let mut insert_msg = tx.prepare( let mut insert_msg = tx.prepare(
" "
INSERT OR REPLACE INTO euph_msgs ( INSERT OR REPLACE INTO euph_msgs (
room, id, parent, previous_edit_id, time, content, encryption_key_id, edited, deleted, truncated, room, id, parent, previous_edit_id, time, content, encryption_key_id, edited, deleted, truncated,
user_id, name, server_id, server_era, session_id, is_staff, is_manager, client_address, real_client_address user_id, name, server_id, server_era, session_id, is_staff, is_manager, client_address, real_client_address,
seen
) )
VALUES ( VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, :room, :id, :parent, :previous_edit_id, :time, :content, :encryption_key_id, :edited, :deleted, :truncated,
?, ?, ?, ?, ?, ?, ?, ?, ? :user_id, :name, :server_id, :server_era, :session_id, :is_staff, :is_manager, :client_address, :real_client_address,
(:user_id == :own_user_id OR EXISTS(
SELECT 1
FROM euph_rooms
WHERE room = :room
AND :time < first_joined
))
) )
" "
)?; )?;
@ -528,28 +556,30 @@ impl EuphRequest {
", ",
)?; )?;
let own_user_id = own_user_id.as_ref().map(|u| &u.0);
for msg in msgs { for msg in msgs {
insert_msg.execute(params![ insert_msg.execute(named_params! {
room, ":room": room,
msg.id, ":id": msg.id,
msg.parent, ":parent": msg.parent,
msg.previous_edit_id, ":previous_edit_id": msg.previous_edit_id,
msg.time, ":time": msg.time,
msg.content, ":content": msg.content,
msg.encryption_key_id, ":encryption_key_id": msg.encryption_key_id,
msg.edited, ":edited": msg.edited,
msg.deleted, ":deleted": msg.deleted,
msg.truncated, ":truncated": msg.truncated,
msg.sender.id.0, ":user_id": msg.sender.id.0,
msg.sender.name, ":name": msg.sender.name,
msg.sender.server_id, ":server_id": msg.sender.server_id,
msg.sender.server_era, ":server_era": msg.sender.server_era,
msg.sender.session_id, ":session_id": msg.sender.session_id,
msg.sender.is_staff, ":is_staff": msg.sender.is_staff,
msg.sender.is_manager, ":is_manager": msg.sender.is_manager,
msg.sender.client_address, ":client_address": msg.sender.client_address,
msg.sender.real_client_address, ":real_client_address": msg.sender.real_client_address,
])?; ":own_user_id": own_user_id, // May be NULL
})?;
if let Some(parent) = msg.parent { if let Some(parent) = msg.parent {
delete_trees.execute(params![room, msg.id])?; delete_trees.execute(params![room, msg.id])?;
@ -641,11 +671,12 @@ impl EuphRequest {
room: String, room: String,
msg: Message, msg: Message,
prev_msg: Option<Snowflake>, prev_msg: Option<Snowflake>,
own_user_id: Option<UserId>,
) -> rusqlite::Result<()> { ) -> rusqlite::Result<()> {
let tx = conn.transaction()?; let tx = conn.transaction()?;
let end = msg.id; let end = msg.id;
Self::insert_msgs(&tx, &room, vec![msg])?; Self::insert_msgs(&tx, &room, &own_user_id, vec![msg])?;
Self::add_span(&tx, &room, prev_msg, Some(end))?; Self::add_span(&tx, &room, prev_msg, Some(end))?;
tx.commit()?; tx.commit()?;
@ -657,6 +688,7 @@ impl EuphRequest {
room: String, room: String,
msgs: Vec<Message>, msgs: Vec<Message>,
next_msg_id: Option<Snowflake>, next_msg_id: Option<Snowflake>,
own_user_id: Option<UserId>,
) -> rusqlite::Result<()> { ) -> rusqlite::Result<()> {
let tx = conn.transaction()?; let tx = conn.transaction()?;
@ -666,7 +698,7 @@ impl EuphRequest {
let first_msg_id = msgs.first().unwrap().id; let first_msg_id = msgs.first().unwrap().id;
let last_msg_id = msgs.last().unwrap().id; let last_msg_id = msgs.last().unwrap().id;
Self::insert_msgs(&tx, &room, msgs)?; Self::insert_msgs(&tx, &room, &own_user_id, msgs)?;
let end = next_msg_id.unwrap_or(last_msg_id); let end = next_msg_id.unwrap_or(last_msg_id);
Self::add_span(&tx, &room, Some(first_msg_id), Some(end))?; Self::add_span(&tx, &room, Some(first_msg_id), Some(end))?;