Message displayed status

Every client generally must be able to show what peer read what message and get how many unread messages there is.

For this, the daemon provides some APIs:

Set a message displayed

The Configuration manager provides:

<method name="setMessageDisplayed" tp:name-for-bindings="setMessageDisplayed">
    <tp:added version="8.1.0"/>
    <tp:docstring>
        <p>Informs that a message have been read</p>
    </tp:docstring>
    <arg type="s" name="accountId" direction="in">
        <tp:docstring>
        The account ID
        </tp:docstring>
    </arg>
    <arg type="s" name="conversationUri" direction="in">
        <tp:docstring>
        A conversation uri (swarm:xxxx or jami:xxxx)
        </tp:docstring>
    </arg>
    <arg type="s" name="messageId" direction="in">
        <tp:docstring>
        The message ID
        </tp:docstring>
    </arg>
    <arg type="i" name="status" direction="in">
        <tp:docstring>
        The message status, 3 for displayed
        </tp:docstring>
    </arg>
    <arg type="b" name="success" direction="out">
        <tp:docstring>
        True if the message status was set, false if account, contact or message is unknown.
        </tp:docstring>
    </arg>
</method>

to set a message as displayed. Should be done when the interaction is shown and the conversation selected.

This sends a SIP messages to connected peers with the following format:

std::string
getDisplayed(const std::string& conversationId, const std::string& messageId)
{
    // implementing https://tools.ietf.org/rfc/rfc5438.txt
    return fmt::format(
        "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
        "<imdn><message-id>{}</message-id>\n"
        "{}"
        "<display-notification><status><displayed/></status></display-notification>\n"
        "</imdn>",
        messageId,
        conversationId.empty() ? "" : "<conversation>" + conversationId + "</conversation>");
}

Then the peer will know this via onMessageDisplayed and emit a signal to the client (DRing::ConfigurationSignal::AccountMessageStatusChanged with status 3 (DRing::Account::MessageStates::DISPLAYED))

Get unread messages

By knowing the lastDisplayedMessage for our account, we can use this informations and ConfigrationManager::countInteractionsSince which count interaction since last message to a given message (typically last displayed interaction)

To get last displayed message for a member, in Configuration::getConversationMembers each member will have the last displayed interaction available via memberInfo["lastDisplayed"]

How this information is stored

In src/jamidht/conversation.cpp each conversation store the last displayed messages in a map<string, string> (uri, interactionId) and this structure is serialized in fileutils::get_data_dir()/getAccountID()/conversation_data/repository_->id()/lastDisplayed