Add read receipts for private messages

- Added ReadReceipt structure and .readReceipt message type
- Added .read delivery status with blue checkmarks in UI
- Send read receipts when viewing a private chat
- Send read receipts immediately for new messages if chat is open
- Update message status from delivered to read when receipt received
This commit is contained in:
jack
2025-07-06 21:49:56 +02:00
parent 2e56245a7e
commit e2b0632879
4 changed files with 143 additions and 0 deletions
+38
View File
@@ -886,12 +886,35 @@ class ChatViewModel: ObservableObject {
if privateChats[peerID] == nil {
privateChats[peerID] = []
}
// Send read receipts for unread messages from this peer
markPrivateMessagesAsRead(from: peerID)
}
func endPrivateChat() {
selectedPrivateChatPeer = nil
}
private func markPrivateMessagesAsRead(from peerID: String) {
guard let messages = privateChats[peerID] else { return }
// Find messages from the peer that haven't been read yet
for message in messages {
// Only send read receipts for messages from the other peer (not our own)
// and only if the status is delivered (not already read)
if message.senderPeerID == peerID,
case .delivered = message.deliveryStatus {
// Create and send read receipt
let receipt = ReadReceipt(
originalMessageID: message.id,
readerID: meshService.myPeerID,
readerNickname: nickname
)
meshService.sendReadReceipt(receipt, to: peerID)
}
}
}
func getPrivateChatMessages(for peerID: String) -> [BitchatMessage] {
return privateChats[peerID] ?? []
}
@@ -1754,6 +1777,16 @@ extension ChatViewModel: BitchatDelegate {
} else {
// We're viewing this chat, make sure unread is cleared
unreadPrivateMessages.remove(peerID)
// Send read receipt immediately since we're viewing the chat
if message.deliveryStatus != nil {
let receipt = ReadReceipt(
originalMessageID: message.id,
readerID: meshService.myPeerID,
readerNickname: nickname
)
meshService.sendReadReceipt(receipt, to: peerID)
}
}
} else if message.sender == nickname {
// Our own message that was echoed back - ignore it since we already added it locally
@@ -2050,6 +2083,11 @@ extension ChatViewModel: BitchatDelegate {
updateMessageDeliveryStatus(ack.originalMessageID, status: .delivered(to: ack.recipientNickname, at: ack.timestamp))
}
func didReceiveReadReceipt(_ receipt: ReadReceipt) {
// Find the message and update its read status
updateMessageDeliveryStatus(receipt.originalMessageID, status: .read(by: receipt.readerNickname, at: receipt.timestamp))
}
func didUpdateMessageDeliveryStatus(_ messageID: String, status: DeliveryStatus) {
updateMessageDeliveryStatus(messageID, status: status)
}