Question
[Feature] Implement per-participant read receipt sync and UI
Asked by: USER9671
60 Viewed
60 Answers
Answer (60)
Problem statement
Users cannot see whether their messages have been read by other participants. The DeliveryStatus domain entity exists but there is no sync mechanism or UI indicator.
Proposed solution
Implement read receipt sync: when a user views a message, send a read receipt to the server. Display read indicators (e.g., double checkmarks) on sent messages. Show per-participant read status in group chats on tap.
Affected layer
Multiple
Estimated effort
L
[Solution]
To implement per-participant read receipt sync and UI, follow these steps:
- Backend: Update the server to send a read receipt to the server whenever a user views a message.
# server.py
def mark_message_as_read(user_id, message_id):
message = Message.objects.get(id=message_id)
message.read_by.add(user_id)
message.save()
- Frontend (Mobile): Implement the logic to send a read receipt to the server when a user views a message.
// MessageListViewController.swift
func messageTapped(message: Message) {
// Send read receipt to the server
ApiManager.sharedInstance.markMessageAsRead(messageId: message.id) { (success) in
if success {
// Update UI
message.isRead = true
self.tableView.reloadRows(at: [IndexPath(row: self.messages.firstIndex(of: message)!, section: 0)], with: UITableViewRowAnimation.automatic)
}
}
}
- Frontend (Web): Implement the logic to send a read receipt to the server when a user views a message.
// MessageController.js
function messageClicked(message) {
// Send read receipt to the server
fetch(`/api/messages/${message.id}/mark_as_read`, { method: 'POST' })
.then(response => response.json())
.then(data => {
if (data.success) {
// Update UI
message.is_read = true;
this.setState({ messages: this.state.messages.map(m => m.id === message.id ? message : m) });
}
});
}
- Frontend (Mobile & Web): Display read indicators (e.g., double checkmarks) on sent messages.
// MessageListViewController.swift
func configureMessageCell(cell: MessageTableViewCell, message: Message) {
cell.messageLabel.text = message.content
cell.messageTimeLabel.text = formatDate(message.created_at)
cell.messageIsRead = message.isRead
}
// MessageController.js
function renderMessage(message) {
return (
<tr key={message.id}>
<td>{message.content}</td>
<td>{formatDate(message.created_at)}</td>
<td>{message.is_read ? <strong>Read</strong> : <i>Unread</i>}</td>
</tr>
);
}
- Frontend (Mobile & Web): Show per-participant read status in group chats on tap.
// MessageListViewController.swift
func showParticipantReadStatus(message: Message) {
let alertController = UIAlertController(title: "Participant Read Status", message: "", preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
let seeAllAction = UIAlertAction(title: "See All", style: .default, handler: { (_) in
// Navigate to the page showing per-participant read status
})
var participants: [String] = []
for participant in message.participants {
if participant.id != StorageManager.currentUser.id {
participants.append(participant.username)
}
}
alertController.addAction(cancelAction)
alertController.addAction(seeAllAction)
alertController.setValue("Participants: \(participants.join(", "))", forKey: "message")
self.present(alertController, animated: true, completion: nil)
}
// MessageController.js
function showParticipantReadStatus(message) {
let participants = message.participants.map(p => p.username).join(', ');
let alert = new Alert('Participant Read Status', `Participants: ${participants}`);
alert.show();
}
[End]
The proposed solution aims to implement read receipt sync and per-participant read status UI indicators to improve communication between users. This solution affects both the frontend and backend, and the estimated effort is considered low.