logo
In-app Chat
SDK Error Codes
Powered Byspreading
On this page

Reply to a message


Introduction

The ZIM SDK supports the functionality of replying to messages within a session, which means quoting a received message to provide a targeted response and forming a tree-like structure of message replies starting from that message. With this feature, users can ask questions, provide feedback, or provide additional background information in response to a specific message.

Concepts

This feature involves the following concepts:

  • Root message: The starting point of a reply tree, usually the initial message of a specific discussion.
  • Child message: A direct or indirect reply to a certain message.
  • Source message: The previous level message of a reply.
  • Reply count: The number of replies received by the root message.

Using messages A, B, and C in group chat as examples:

  1. Message B replies to message A:
    • Message A is the root message.
    • Message A is the source message of message B.
    • Message B is a child message of message A.
  2. Message C replies to message B:
    • Message B is the source message of message C.
    • Message C is a child message of message B.
  3. Both message B and message C are child messages of message A.
  4. The reply count of message A is 2. Message B does not have a reply count.

Reply to a message

After logging in to ZIM, users can listen to the peerMessageReceived and groupMessageReceived callback to receive new messages from one-on-one and group conversations, or call the queryHistoryMessage interface to fetch historical messages.

At this point, users can choose a message to reply to by using that message as the toOriginalMessage parameter and constructing a new message as the message parameter. Then, call the replyMessage interface.

Note

Only the following types are supported for the toOriginalMessage and message parameters:

In addition to the required parameters mentioned above, you can also construct a notification object based on your business needs and listen to the following callbacks:

  • onMessageAttached: This callback is triggered before sending the reply, allowing you to obtain a temporary ZIMMessage object. You can use this object to add some logic, such as displaying UI in advance.
  • onMediaUploadingProgress: This callback provides updates on the progress of file uploads when sending messages with rich media.

The sending result will be returned through the ZIMMessageSentResult.

Untitled
// The source message object, obtained through queryHistoryMessage or peerMessageReceived and receiveGroupMessage.
var toOriginalMessage = {};

var config = { 
    priority: 1, // Set message priority, values are low: 1 (default), medium: 2, high: 3
};

var messageTextObj = { type: 1, message: 'Reply message content' };
var notification = {
    onMessageAttached: function(message) {
        // todo: Loading
    },
    onMediaUploadingProgress: (message, currentFileSize, totalFileSize) => {
        // If the reply is a media message, you can use this to display the file upload progress.
    },
}

zim.replyMessage(messageTextObj, toOriginalMessage, config, notification)
    .then(function ({ message }) {
        // Sent successfully
    })
    .catch(function (err) {
        // Failed to send
    });
1
Copied!

Determine if a message is a reply to another message

When receiving new messages in one-on-one and group conversations through the peerMessageReceived and groupMessageReceived callbacks, you need to determine if the message has repliedInfo (basic information of the source message):

  • If it exists, it means that this message is a reply to another message.
  • If it doesn't exist, it means that this message is an independent message.

When you have the repliedInfo, you can use it to display the sender, sending time, and message content of the source message.

Untitled
// Receive a message in a one-to-one conversation
zim.on('peerMessageReceived', function (zim, { messageList, info, fromConversationID }) {
    messageList.forEach((msg) => {
        if (msg.repliedInfo) {
            // Basic information of the source message referenced by this reply, used to display the sender, sending time, and message content of the source message.
        }
    });
});

// Receive a message in a group conversation
zim.on('groupMessageReceived', function (zim, { messageList, info, fromConversationID }) {
    messageList.forEach((msg) => {
        if (msg.repliedInfo) {
            // Basic information of the source message referenced by this reply, used to display the sender, sending time, and message content of the source message.
        }
    });
});
1
Copied!

Get the number of replies to a root message

ZIM supports actively or passively obtaining the number of replies to a root message.

Active retrieval

To actively retrieve the number of replies to a root message, you can directly use ZIMMessage > rootRepliedCount to get it.

Passive retrieval

To get real-time updates on how many replies a root message has received, you can listen for the messageRepliedCountChanged event.

Untitled
// Listen for changes in the number of replies to a root message
// Event trigger: When a new message replied to another message successfully, the number of replies to the root message of its reply tree will increase by 1
zim.on('messageRepliedCountChanged', function (zim, { infos }) {
    infos.forEach(({ count, messageID, conversationID, conversationType }) => {
        // Update the rootRepliedCount of the corresponding messageID in the conversation
    });
});
1
Copied!

Listen for the deletion or recall of the source message

Listen for the messageRepliedInfoChanged callback to get the list of child messages of a message when it is deleted or recalled. You can display relevant prompts on the UI of the corresponding child messages.

Note

Even if the source message is deleted by the user on a device, causing the repliedInfo.state (the state of the source message) of its child message to be ZIMMessageRepliedInfoState.DELETED, you can still get the brief content of the source message in the repliedInfo.messageInfo of the child message. Therefore, you can choose whether to display the content of the source message on that device as needed.

Untitled
// Listen for changes in the source message of a reply message
// Event trigger: When the source message is "deleted" or "recalled", the repliedInfo property of the reply referencing it will change
zim.on('messageRepliedInfoChanged', function (zim, { messageList }) {
    messageList.forEach((msg) => {
        if (msg.repliedInfo) {
            if (msg.repliedInfo.state != 0) {
                // The source message referenced by this reply message has been deleted, you can display "Message deleted" at this time
            } else if (msg.repliedInfo.messageInfo.type == 31) {
                // The source message referenced by this reply message has been recalled, you can display "Message recalled" at this time
            }
        }
    });
});
1
Copied!

Query the reply list

Call queryMessageRepliedList and pass in the root message or any reply to view the complete list of replies and get the complete message list related to the replies.

The results returned by this interface will distinguish between the root message (rootRepliedInfo) and the reply list (messageList), and the reply list will be sorted in chronological order based on the sending time of the replies.

Untitled
var replyMessage = {}; // replyMessage can be a root message or any reply, generally obtained through the queryHistoryMessage interface or peerMessageReceived and receiveGroupMessage

var config = {
    count: 10, // The number of queries, please do not exceed 100
    nextFlag: 0, // Pagination flag, fill in 0 for the first query, and subsequent queries will be based on the nextFlag returned by the query result
};

zim.queryMessageRepliedList(replyMessage, config)
    .then(({ nextFlag, rootRepliedInfo, messageList }) => {
        // Query successful
        // If nextFlag is not 0, it means there is more data to be queried
        // rootRepliedInfo is the information of the root message
        // messageList represents the reply list to the root message
    })
    .catch((err) => {
        // Query failed
    });
1
Copied!
Note
  • When querying the reply list, no matter the message passed is the root message or not, as long as the nextFlag is set to 0, it means querying in ascending order of message sending time starting from the root message.
  • Since the message in rootRepliedInfo is a nullable object, when state is ZIMMessageRepliedInfoState.Deleted, it means the root message has been deleted. At this time, developers should prompt "The root message has been deleted" on the UI. When state is ZIMMessageRepliedInfoState.NotFound, it means that the root message cannot be found anymore. The possible reasons are that the message exceeded the server storage time, or the group users query the reply list after joining the group but the root message was sent before they joined the group, so the message may not be able to be required anymore. At this time, developers should prompt "The root message cannot be located" or other informative statements on the UI.

View the context of the source message

Since the repliedInfo of a child message (i.e., a reply message) only contains basic source message data that can be used for UI display, users may need to go to the original location of the source message to read other messages near the source message.

Therefore, to implement this scenario, you need to use the repliedInfo.messageInfo property of the child message (which is the sequence number of the source message in the conversation).

Note

The repliedInfo.messageInfo property of a child message (which is the sequence number of the source message in the conversation) corresponds to the messageSeq of the source message.

Depending on whether the source message and its surrounding messages are cached in the application's memory, ZIM provides two options.

Both the source message and its surrounding messages are cached in the application's memory

When a source message and its surrounding messages are saved in your application's memory (for example, by calling queryHistoryMessage to retrieve and cache the conversation's message history), you can search the messageSeq of the source message in the memory and implement the business logic to go to the original location of the source message to view the context.

The source message or its surrounding messages are not cached in the application's memory

When the source message or its surrounding messages are not cached in the application's memory, if another user replies to the source message in the conversation, you can:

  1. From the repliedInfo.messageInfo of the reply, get the messageSeq of the source message. Pass it as a parameter to call the queryMessages interface to get the complete ZIMMessage object of the source message.
Untitled
var messageSeqs = []; // messageSeq is the sequence number of the source message in the conversation

var conversationID = '';
var conversationType = 0; // Conversation Type: ono-to-onr: 0; group: 2

zim.queryMessages(messageSeqs, conversationID, conversationType)
    .then(({ messageList }) => {
        // Query successful
    })
    .catch((err) => {
        // Query failed
    });
1
Copied!
  1. Pass the source message object as the nextMessage parameter to queryHistoryMessage, so that you can use the source message as an anchor point to retrieve messages from the messages forward or backward.
Untitled
// This example demonstrates querying forward from the source message
var originalMessage = {};
var config = {
    // originalMessage is the source message obtained through queryMessages
    nextMessage: originalMessage,
    count: 20,
    reverse: false,
};

var conversationID = '';
var conversationType = 0;

zim.queryHistoryMessage(conversationID, conversationType, config)
    .then((res) => {
        // Query successful
    })
    .catch((err) => {
        // Query failed
    });
1
Copied!

Previous

Geofencing

Next

Call invitation (signaling)