Mentions
Overview
The sender listens for the characters in the input box. When the user enters @, the group member selection UI will pop up. After the target group members are selected, the message will be displayed in the input box in the format of
"@A @B @C......"
, which can be further edited before sent.
In the group chat list of the receiver's conversation UI, the identifier "someone@me"
or "@ all"
will be displayed to remind the user that the user was mentioned by someone in the group chat.Note
Currently, only text @ messages are supported.
Feature Demonstration
Listening for the @ character for group member selection | Editing and sending the group @ message | Receiving the group @ message |
| | |
Figure 1: When the @ character is detected in the input box on the chat UI, the user is redirected to the group member selection UI to select the target group members.
Figure 2: After selecting the target group members, the user goes back to the chat UI to edit and send the group @ message.
Figure 3: If a user is mentioned, the user receives the conversation update, and the "someone@me" information is displayed in the conversation
Cell
.Sending a Group @ Message
1. The sender listens for the text input box on the chat UI and launches the group member selection UI. After group members are selected, the ID and nickname information of the members is called back. The ID is used to create the
V2TIMMessage
object, while the nickname is to be displayed in the text box.2. The sender calls the
createAtSignedGroupMessage
API (Android / iOS & Mac / Windows) to create a group @ message, get the V2TIMMessage
object, and specify the target group members.3. The sender calls
sendMessage
(Android / iOS and macOS / Windows) to send the created @ message object.Sample code:
// Create a original text messageV2TIMMessage textMsg = V2TIMManager.getMessageManager().createTextMessage("text");// Create a group @ message using the original text message, @ group members `user1` and `user2`List<String> atUserList = new ArrayList<>();atUserList.add("user1");atUserList.add("user2");V2TIMMessage atMsg = V2TIMManager.getMessageManager().createAtSignedGroupMessage(textMsg, atUserList);// Send the group @ messageV2TIMManager.getMessageManager().sendMessage(atMsg, null, "toGroupID", V2TIMMessage.V2TIM_PRIORITY_DEFAULT, false, null, new V2TIMSendCallback<V2TIMMessage>() {@Overridepublic void onError(int code, String desc) {// The group @ message failed to be sent}@Overridepublic void onSuccess(V2TIMMessage v2TIMMessage) {// Group @ message sent successfully}@Overridepublic void onProgress(int progress) {}});
// Create a original text messageV2TIMMessage *textMsg = [[V2TIMManager sharedInstance] createTextMessage:@"text"];// Create a group @ message using the original text message, @ group members `user1` and `user2`V2TIMMessage *atMsg = [[V2TIMManager sharedInstance] createAtSignedGroupMessage:textMsg atUserList:@[@"xixi", @"yahaha"]];// Send the group @ message[[V2TIMManager sharedInstance] sendMessage:atMsg receiver:nil groupID:@"groupA" priority:V2TIM_PRIORITY_NORMAL onlineUserOnly:NO offlinePushInfo:nil progress:nil succ:nil fail:nil];
class SendCallback final : public V2TIMSendCallback {public:using SuccessCallback = std::function<void(const V2TIMMessage&)>;using ErrorCallback = std::function<void(int, const V2TIMString&)>;using ProgressCallback = std::function<void(uint32_t)>;SendCallback() = default;~SendCallback() override = default;void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback,ProgressCallback progress_callback) {success_callback_ = std::move(success_callback);error_callback_ = std::move(error_callback);progress_callback_ = std::move(progress_callback);}void OnSuccess(const V2TIMMessage& message) override {if (success_callback_) {success_callback_(message);}}void OnError(int error_code, const V2TIMString& error_message) override {if (error_callback_) {error_callback_(error_code, error_message);}}void OnProgress(uint32_t progress) override {if (progress_callback_) {progress_callback_(progress);}}private:SuccessCallback success_callback_;ErrorCallback error_callback_;ProgressCallback progress_callback_;};V2TIMStringVector atUserList;atUserList.PushBack("user1");atUserList.PushBack("user2");V2TIMMessage message = V2TIMManager::GetInstance()->GetMessageManager()->CreateTextMessage(u8"text");V2TIMMessage at_message = V2TIMManager::GetInstance()->GetMessageManager()->CreateAtSignedGroupMessage(message, atUserList);auto callback = new SendCallback{};callback->SetCallback([=](const V2TIMMessage& message) {// The group @ message failed to be sentdelete callback;},[=](int error_code, const V2TIMString& error_message) {// Group @ message sent successfullydelete callback;},[=](uint32_t progress) {});V2TIMManager::GetInstance()->GetMessageManager()->SendMessage(at_message, "denny", {}, V2TIMMessagePriority::V2TIM_PRIORITY_NORMAL, false, {}, callback);
Receiving a Group @ Message
1. When the conversation is loaded and updated, call the
groupAtInfolist
API (Android / iOS and macOS / Windows) of V2TIMConversation
to get the @ data list of the conversation.2. Call the
atType
API (Android / iOS and macOS / Windows) of the V2TIMGroupAtInfo
object in the list to get the @ data type and update it to the @ information of the conversation.Sample code:
// Obtain the group @ data listList<V2TIMGroupAtInfo> atInfoList = conversation.getGroupAtInfoList();// Parse the @ type (@me, @all members, @me and @all members)boolean atMe = false;boolean atAll = false;String atTips = "";for(V2TIMGroupAtInfo atInfo : atInfoList){if (atInfo.getAtType() == V2TIMGroupAtInfo.TIM_AT_ME){atMe = true;continue;}if (atInfo.getAtType() == V2TIMGroupAtInfo.TIM_AT_ALL){atAll = true;continue;}}// Based on the @ type, prompt:if (atMe && !atAll) {atTips = "[Someone@me]";} else if (!atMe && atAll) {atTips = "[@all]";} else if (atMe && atAll) {atTips = "[someone@me][@all members]";}
// Obtain the group @ data listNSArray<V2TIMGroupAtInfo *> *atInfoList = conversation.groupAtInfolist;// Parse the @ type (@me, @all members, @me and @all members)BOOL atMe = NO; // Whether it's @meBOOL atAll = NO; // Whether it's @all membersNSString *atTipsStr = @"";for (V2TIMGroupAtInfo *atInfo in atInfoList) {switch (atInfo.atType) {case V2TIM_AT_ME:atMe = YES;break;case V2TIM_AT_ALL:atAll = YES;break;case V2TIM_AT_ALL_AT_ME:atMe = YES;atAll = YES;break;default:break;}}// Based on the @ type, prompt:if (atMe && !atAll) {atTipsStr = @"[someone@me]";}if (!atMe && atAll) {atTipsStr = @"[@all members]";}if (atMe && atAll) {atTipsStr = @"[someone@me][@all members]";}
// Obtain the group @ data listV2TIMGroupAtInfoVector groupAtInfolist = conversation.groupAtInfolist;// Parse the @ type (@me, @all members, @me and @all members)bool atMe = false;bool atAll = false;std::string atTips = "";for (size_t i = 0; i < groupAtInfolist.Size(); ++i) {const V2TIMGroupAtInfo& atInfo = groupAtInfolist[i];switch (atInfo.atType) {case V2TIM_AT_ME:atMe = true;break;case V2TIM_AT_ALL:atAll = true;break;case V2TIM_AT_ALL_AT_ME:atMe = true;atAll = true;break;default:break;}}// Based on the @ type, prompt:if (atMe && !atAll) {atTips = u8"[someone@me]";} else if (!atMe && atAll) {atTips = u8"[@all members]";} else if (atMe && atAll) {atTips = u8"[someone@me][@all members]";}