From 37c5ce933d225b49fad29519e5b37b90e0e83ca1 Mon Sep 17 00:00:00 2001 From: otsmr Date: Mon, 20 Apr 2026 11:38:25 +0200 Subject: [PATCH] fix receipts are getting deleted if message was removed --- lib/src/database/daos/messages.dao.dart | 30 ++++++++++++++++--- lib/src/services/api/messages.dart | 24 ++++++++------- .../chat_list_components/group_list_item.dart | 7 +++-- lib/src/views/chats/chat_messages.view.dart | 2 +- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/lib/src/database/daos/messages.dao.dart b/lib/src/database/daos/messages.dao.dart index 7a1c36a..7255ca7 100644 --- a/lib/src/database/daos/messages.dao.dart +++ b/lib/src/database/daos/messages.dao.dart @@ -64,18 +64,39 @@ class MessagesDao extends DatabaseAccessor with _$MessagesDaoMixin { return query.map((row) => row.readTable(messages)).watch(); } - Stream watchLastMessage(String groupId) { + Future> watchLastMessage(String groupId) async { + final group = await twonlyDB.groupsDao.getGroup(groupId); + final deletionTime = clock.now().subtract( + Duration( + milliseconds: group!.deleteMessagesAfterMilliseconds, + ), + ); return (select(messages) - ..where((t) => t.groupId.equals(groupId)) + ..where( + (t) => + t.groupId.equals(groupId) & + // messages in groups will only be removed in case all members have received it... + // so ensuring that this message is not shown in the messages anymore + t.openedAt.isBiggerThanValue(deletionTime), + ) ..orderBy([(t) => OrderingTerm.desc(t.createdAt)]) ..limit(1)) .watchSingleOrNull(); } - Stream> watchByGroupId(String groupId) { + Future>> watchByGroupId(String groupId) async { + final group = await twonlyDB.groupsDao.getGroup(groupId); + final deletionTime = clock.now().subtract( + Duration( + milliseconds: group!.deleteMessagesAfterMilliseconds, + ), + ); return ((select(messages)..where( (t) => t.groupId.equals(groupId) & + // messages in groups will only be removed in case all members have received it... + // so ensuring that this message is not shown in the messages anymore + t.openedAt.isBiggerThanValue(deletionTime) & (t.isDeletedFromSender.equals(true) | (t.type.equals(MessageType.text.name).not() | t.type.equals(MessageType.media.name).not()) | @@ -127,7 +148,8 @@ class MessagesDao extends DatabaseAccessor with _$MessagesDaoMixin { (m.mediaStored.equals(true) & m.isDeletedFromSender.equals(true) | m.mediaStored.equals(false)) & - (m.openedAt.isSmallerThanValue(deletionTime) | + // Only remove the message when ALL members have seen it. Otherwise the receipt will also be deleted which could cause issues in case a member opens the image later.. + (m.openedByAll.isSmallerThanValue(deletionTime) | (m.isDeletedFromSender.equals(true) & m.createdAt.isSmallerThanValue(deletionTime))), )) diff --git a/lib/src/services/api/messages.dart b/lib/src/services/api/messages.dart index 07865ec..e678e46 100644 --- a/lib/src/services/api/messages.dart +++ b/lib/src/services/api/messages.dart @@ -102,21 +102,23 @@ Future<(Uint8List, Uint8List?)?> tryToSendCompleteMessage({ message.encryptedContent, ); - final pushNotification = await getPushNotificationFromEncryptedContent( - receipt.contactId, - receipt.messageId, - encryptedContent, - ); - - Log.info('Uploading $receiptId. (${pushNotification?.kind})'); + Log.info('Uploading $receiptId.'); Uint8List? pushData; - if (pushNotification != null && receipt.retryCount <= 1) { - // Only show the push notification the first two time. - pushData = await encryptPushNotification( + if (receipt.retryCount == 0) { + final pushNotification = await getPushNotificationFromEncryptedContent( receipt.contactId, - pushNotification, + receipt.messageId, + encryptedContent, ); + + if (pushNotification != null) { + // Only show the push notification the first two time. + pushData = await encryptPushNotification( + receipt.contactId, + pushNotification, + ); + } } if (message.type == pb.Message_Type.TEST_NOTIFICATION) { diff --git a/lib/src/views/chats/chat_list_components/group_list_item.dart b/lib/src/views/chats/chat_list_components/group_list_item.dart index 361a476..d14aa3e 100644 --- a/lib/src/views/chats/chat_list_components/group_list_item.dart +++ b/lib/src/views/chats/chat_list_components/group_list_item.dart @@ -63,9 +63,10 @@ class _UserListItem extends State { } Future initStreams() async { - _lastMessageStream = twonlyDB.messagesDao - .watchLastMessage(widget.group.groupId) - .listen((update) { + _lastMessageStream = + (await twonlyDB.messagesDao.watchLastMessage( + widget.group.groupId, + )).listen((update) { protectUpdateState.protect(() async { await updateState(update, _messagesNotOpened); }); diff --git a/lib/src/views/chats/chat_messages.view.dart b/lib/src/views/chats/chat_messages.view.dart index dcb1c2b..8b30c0b 100644 --- a/lib/src/views/chats/chat_messages.view.dart +++ b/lib/src/views/chats/chat_messages.view.dart @@ -107,7 +107,7 @@ class _ChatMessagesViewState extends State { }); }); - final msgStream = twonlyDB.messagesDao.watchByGroupId(widget.groupId); + final msgStream = await twonlyDB.messagesDao.watchByGroupId(widget.groupId); messageSub = msgStream.listen((update) async { allMessages = update; await protectMessageUpdating.protect(() async {