Mark chat mention notifications as read when viewing the message

This commit is contained in:
Max Brunsfeld 2023-10-21 16:18:27 +01:00
parent e32aa95092
commit fce09e8c92
7 changed files with 73 additions and 9 deletions

View file

@ -370,6 +370,18 @@ impl ChannelChat {
cursor.item().unwrap() cursor.item().unwrap()
} }
pub fn rendered_message(&self, id: ChannelMessageId) {
let ChannelMessageId::Saved(id) = id else {
return;
};
self.rpc
.send(proto::AckChannelMessage {
channel_id: self.channel.id,
message_id: id,
})
.ok();
}
pub fn messages_in_range(&self, range: Range<usize>) -> impl Iterator<Item = &ChannelMessage> { pub fn messages_in_range(&self, range: Range<usize>) -> impl Iterator<Item = &ChannelMessage> {
let mut cursor = self.messages.cursor::<Count>(); let mut cursor = self.messages.cursor::<Count>();
cursor.seek(&Count(range.start), Bias::Right, &()); cursor.seek(&Count(range.start), Bias::Right, &());

View file

@ -386,7 +386,7 @@ impl Database {
} }
Ok(self Ok(self
.respond_to_notification( .mark_notification_as_read_with_response(
user_id, user_id,
&rpc::Notification::ChannelInvitation { &rpc::Notification::ChannelInvitation {
channel_id: channel_id.to_proto(), channel_id: channel_id.to_proto(),

View file

@ -321,7 +321,7 @@ impl Database {
let mut notifications = Vec::new(); let mut notifications = Vec::new();
notifications.extend( notifications.extend(
self.respond_to_notification( self.mark_notification_as_read_with_response(
responder_id, responder_id,
&rpc::Notification::ContactRequest { &rpc::Notification::ContactRequest {
sender_id: requester_id.to_proto(), sender_id: requester_id.to_proto(),

View file

@ -1,5 +1,6 @@
use super::*; use super::*;
use futures::Stream; use futures::Stream;
use rpc::Notification;
use sea_orm::TryInsertResult; use sea_orm::TryInsertResult;
use time::OffsetDateTime; use time::OffsetDateTime;
@ -326,11 +327,24 @@ impl Database {
channel_id: ChannelId, channel_id: ChannelId,
user_id: UserId, user_id: UserId,
message_id: MessageId, message_id: MessageId,
) -> Result<()> { ) -> Result<NotificationBatch> {
self.transaction(|tx| async move { self.transaction(|tx| async move {
self.observe_channel_message_internal(channel_id, user_id, message_id, &*tx) self.observe_channel_message_internal(channel_id, user_id, message_id, &*tx)
.await?; .await?;
Ok(()) let mut batch = NotificationBatch::default();
batch.extend(
self.mark_notification_as_read(
user_id,
&Notification::ChannelMessageMention {
message_id: message_id.to_proto(),
sender_id: Default::default(),
channel_id: Default::default(),
},
&*tx,
)
.await?,
);
Ok(batch)
}) })
.await .await
} }

View file

@ -129,22 +129,47 @@ impl Database {
/// Populate the response for the notification with the given kind and /// Populate the response for the notification with the given kind and
/// entity id. /// entity id.
pub async fn respond_to_notification( pub async fn mark_notification_as_read_with_response(
&self, &self,
recipient_id: UserId, recipient_id: UserId,
notification: &Notification, notification: &Notification,
response: bool, response: bool,
tx: &DatabaseTransaction, tx: &DatabaseTransaction,
) -> Result<Option<(UserId, proto::Notification)>> {
self.mark_notification_as_read_internal(recipient_id, notification, Some(response), tx)
.await
}
pub async fn mark_notification_as_read(
&self,
recipient_id: UserId,
notification: &Notification,
tx: &DatabaseTransaction,
) -> Result<Option<(UserId, proto::Notification)>> {
self.mark_notification_as_read_internal(recipient_id, notification, None, tx)
.await
}
async fn mark_notification_as_read_internal(
&self,
recipient_id: UserId,
notification: &Notification,
response: Option<bool>,
tx: &DatabaseTransaction,
) -> Result<Option<(UserId, proto::Notification)>> { ) -> Result<Option<(UserId, proto::Notification)>> {
if let Some(id) = self if let Some(id) = self
.find_notification(recipient_id, notification, tx) .find_notification(recipient_id, notification, &*tx)
.await? .await?
{ {
let row = notification::Entity::update(notification::ActiveModel { let row = notification::Entity::update(notification::ActiveModel {
id: ActiveValue::Unchanged(id), id: ActiveValue::Unchanged(id),
recipient_id: ActiveValue::Unchanged(recipient_id), recipient_id: ActiveValue::Unchanged(recipient_id),
response: ActiveValue::Set(Some(response)),
is_read: ActiveValue::Set(true), is_read: ActiveValue::Set(true),
response: if let Some(response) = response {
ActiveValue::Set(Some(response))
} else {
ActiveValue::NotSet
},
..Default::default() ..Default::default()
}) })
.exec(tx) .exec(tx)

View file

@ -3061,11 +3061,16 @@ async fn acknowledge_channel_message(
) -> Result<()> { ) -> Result<()> {
let channel_id = ChannelId::from_proto(request.channel_id); let channel_id = ChannelId::from_proto(request.channel_id);
let message_id = MessageId::from_proto(request.message_id); let message_id = MessageId::from_proto(request.message_id);
session let notifications = session
.db() .db()
.await .await
.observe_channel_message(channel_id, session.user_id, message_id) .observe_channel_message(channel_id, session.user_id, message_id)
.await?; .await?;
send_notifications(
&*session.connection_pool().await,
&session.peer,
notifications,
);
Ok(()) Ok(())
} }

View file

@ -357,8 +357,16 @@ impl ChatPanel {
let is_continuation = last_message.id != this_message.id let is_continuation = last_message.id != this_message.id
&& this_message.sender.id == last_message.sender.id; && this_message.sender.id == last_message.sender.id;
if this_message
.mentions
.iter()
.any(|(_, user_id)| Some(*user_id) == self.client.user_id())
{
active_chat.rendered_message(this_message.id);
}
( (
active_chat.message(ix).clone(), this_message.clone(),
is_continuation, is_continuation,
active_chat.message_count() == ix + 1, active_chat.message_count() == ix + 1,
is_admin, is_admin,