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:
- 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.
- Message C replies to message B:
- Message B is the source message of message C.
- Message C is a child message of message B.
- Both message B and message C are child messages of message A.
- 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 onReceivePeerMessage and onReceiveGroupMessage 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 toOriginMessage
parameter and constructing a new message as the message
parameter. Then, call the replyMessage interface.
Only the following types are supported for the toOriginMessage
and message
parameters:
- Text message: ZIMTextMessage(1)
- Image message: ZIMImageMessage(11)
- File message: ZIMFileMessage(12)
- Audio message: ZIMAudioMessage(13)
- Video message: ZIMVideoMessage(14)
- Combined message: ZIMCombineMessage(100)
- Custom message: ZIMCustomMessage(200)
The following information is returned through ZIMMessageSendNotification:
- onMessageAttached: Before sending a reply, you can obtain a temporary ZIMMessage to add some business logic.
- onMediaUploadingProgress: When sending a message containing rich media, this callback provides updates on the progress of file uploading.
// Reply content
ZIMTextMessage textMessage = ZIMTextMessage(message: 'Message Content');
ZIMMessageSendConfig config = ZIMMessageSendConfig();
// Set message priority
config.priority = ZIMMessagePriority.low;
ZIMMessageSendNotification notification = ZIMMessageSendNotification();
notification.onMessageAttached = (ZIMMessage message){
// Callback before sending, where you can get a temporary object that is the same as the zimMessage object created by you. You can use this feature to add some business logic, such as displaying UI in advance.
};
notification.onMediaUploadingProgress = (ZIMMessage message, int currentFileSize, int totalFileSize){
// You can use this callback to listen for whether the message was sent successfully.
};
ZIM.getInstance()?.replyMessage(textMessage, toOriginalMessage, config, notification).then((value) {
// Sent successfully
}).catchError((onError){
// Sent failure
});
Determine if a message is a reply to another message
When receiving new messages in one-on-one and group conversations through the onReceivePeerMessage and onReceiveGroupMessage 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.
// Register ZIMEventHander callback
ZIMEventHandler.onReceivePeerMessage = (ZIM zim, List<ZIMMessage> messageList, String fromUserID) {
for (ZIMMessage message in messageList) {
if (message.repliedInfo != null) {
// Basic information of the source message referenced by this reply message, used to display the sender, sending time, and message content of the source message.
}
}
};
ZIMEventHandler.onReceiveGroupMessage = (ZIM zim, List<ZIMMessage> messageList, String fromGroupID) {
for (ZIMMessage message in messageList) {
if (message.repliedInfo != null) {
// Basic information of the source message referenced by this reply message, used to display the sender, sending time, and message content of the source message.
}
}
};
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 onMessageRepliedCountChanged event.
// 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
ZIMEventHandler.onMessageRepliedCountChanged = (ZIM zim, List<ZIMMessageRootRepliedCountInfo> infos) {
// Update the rootRepliedCount of the corresponding messageID in the conversation
};
Listen for the deletion or recall of the source message
Listen for the onMessageRepliedInfoChanged 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.
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.
// 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
ZIMEventHandler.onMessageRepliedInfoChanged = (ZIM zim, List<ZIMMessage> messageList) {
for(ZIMMessage message in messageList) {
if(message.repliedInfo == null) {
// The source message referenced by this reply message has been deleted, you can display "Message deleted" at this time
} else if (message.repliedInfo?.messageInfo.type == ZIMMessageType.revoke) {
// The source message referenced by this reply message has been recalled, you can display "Message recalled" at this time
}
}
};
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.
ZIMMessageRepliedListQueryConfig config = ZIMMessageRepliedListQueryConfig();
config.count = 10; // The number of queries, please do not exceed 100
config.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
// replyMessage can be a root message or any reply, generally obtained through the queryHistoryMessage interface or receivePeerMessage and receiveGroupMessage
ZIM.getInstance()?.queryMessageRepliedList(replyMessage, config).then((value) {
// 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
}).onError((error, stackTrace) {
if(error is PlatformException){
// Query failed
error.code;
error.message;
}
});
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.messageSeq property of the child message (which is the sequence number of the source message in the conversation).
The repliedInfo.messageSeq 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:
-
From the repliedInfo.messageSeq 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// messageSeq is the sequence number of the source message in the conversation List<int> messageSeqs = [123456]; ZIM.getInstance()?.queryMessages(messageSeqs, 'conversationID', ZIMConversationType.peer).then((value) { // Query successful }).catchError((onError){ if(onError is PlatformException){ // Query failed error.code; error.message; } });
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 ZIMMessageQueryConfig config = ZIMMessageQueryConfig(); // originalMessage is the source message obtained through queryMessages config.nextMessage = originalMessage; config.count = 20; config.reverse = false; ZIM.getInstance()?.queryHistoryMessage("YOUR_CONVERSATION_ID", ZIMConversationType.peer, config).then((value) { // Query successful }).catchError((onError){ if(onError is PlatformException){ // Query failed } });
1