# Synchronization of delivery status When we send a message to a conversation, the delivery status must be explicit and understandable for the end user. So, Jami must offer the possibility to know if the message was delivered to the other members of a conversation and synchronize this status (sent and displayed) across devices. # How it works (backend) The status of messages is stored in the conversation layer via the variable `messagesStatus (map)` with the following structure: ``` {uri, { {"fetch", "commitId"}, {"fetched_ts", "timestamp"}, {"read", "commitId"}, {"read_ts", "timestamp"} } } ``` The `fetch` status is the commitId of the last message fetched by the member. The `fetched_ts` is the timestamp of the last message fetched by the member. The `read` status is the commitId of the last message read by the member. The `read_ts` is the timestamp of the last message read by the member. When a member fetches a message, the `fetch` status is updated with the commitId of the message and the `fetched_ts` is updated with the timestamp of the message. When a member reads a message, the `read` status is updated with the commitId of the message and the `read_ts` is updated with the timestamp of the message. This information is synced across devices and other devices will update their internal structure if the timestamp is newer. This information is stored in `conversation_data/xxxxxxxxx/status`. # Client API The client should get status from the current **SwarmMessage** structure when loading conversation and update the status via `AccountMessageStatusChanged`. In `AccountMessageStatusChanged` the client will have the commitId, peer uri and new status. So, this will correspond to `message.status[uri]`. SwarmMessage's status structure is: ``` { {uri, status}, {uri2, status2} } ``` Where `uri` is the peer uri and `status` is the status of the message for this peer (from the `MessageStates` enum). When sending a new message, the `status` map can be empty (because no one fetched). By default, if there is no fetch/read information for a message, the message MUST be considered as sending. The global status of a message is the maximum of the status of all members except ourselves. For example, if Alice sends a message and we have: ``` status = {alice: displayed, bob: sending, carl: sent} ``` The global status is `sent`. # Notes for client + If the client wants to show which message is the last read message for a member, they must check the index when responding to `AccountMessageStatusChanged`. Because this signal can emit that a previous message is displayed later. + The status of a message can be used to create a detailed view of who received/displayed a specific message. However, timestamps of those events are not stored, because this would represent too much data.