[Feature] Implement per-participant read receipt sync and UI

Question

Grade: Education Subject: timurgilfanov messenger
[Feature] Implement per-participant read receipt sync and UI
Asked by:
60 Viewed 60 Answers

Answer (60)

Best Answer
(526)

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

(4287)

[Solution]

To implement per-participant read receipt sync and UI, follow these steps:

  1. 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()
  1. 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)
        }
    }
}
  1. 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) });
            }
        });
}
  1. 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>
    );
}
  1. 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.