From 0596c6ef6602509a8747d9db73ba67b81115275d Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Mon, 15 Aug 2022 12:09:10 +0800 Subject: [PATCH 01/49] rename unSubscribe to unsubscribe. --- lib/src/em_presence_manager.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/em_presence_manager.dart b/lib/src/em_presence_manager.dart index 823bbaea..3f6fdf17 100644 --- a/lib/src/em_presence_manager.dart +++ b/lib/src/em_presence_manager.dart @@ -103,7 +103,7 @@ class EMPresenceManager { /// /// **Throws** A description of the exception. See {@link EMError}. /// - Future unSubscribe({ + Future unsubscribe({ required List members, }) async { Map req = {'members': members}; From a04b3a960dc2292f196cbb3ff4b5913dde6b1d31 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Wed, 10 May 2023 15:50:30 +0800 Subject: [PATCH 02/49] add chinese api doc. --- android/build.gradle | 2 +- example/lib/main.dart | 24 +- ios/im_flutter_sdk.podspec | 2 +- lib/im_flutter_sdk.dart | 2 - lib/src/em_chat_manager.dart | 654 ++++++++++++--- lib/src/em_chat_room_manager.dart | 629 ++++++++++---- lib/src/em_chat_thread_manager.dart | 287 +++++-- lib/src/em_client.dart | 517 +++++++----- lib/src/em_contact_manager.dart | 117 +-- lib/src/em_group_manager.dart | 378 +++------ lib/src/em_listeners.dart | 790 ----------------- lib/src/em_message_status_callback.dart | 27 - lib/src/em_presence_manager.dart | 41 - lib/src/em_push_manager.dart | 216 +---- lib/src/em_userInfo_manager.dart | 21 +- .../event_handler/manager_event_handler.dart | 792 ++++++++++++++++-- lib/src/internal/em_push_config.dart | 2 + lib/src/internal/inner_headers.dart | 3 +- lib/src/models/chat_silent_mode.dart | 135 ++- lib/src/models/em_chat_enums.dart | 647 +++++++++++++- lib/src/models/em_chat_room.dart | 128 ++- lib/src/models/em_chat_thread.dart | 84 +- lib/src/models/em_conversation.dart | 241 +++++- lib/src/models/em_cursor_result.dart | 27 +- lib/src/models/em_deviceInfo.dart | 24 +- lib/src/models/em_download_callback.dart | 30 +- lib/src/models/em_error.dart | 18 +- lib/src/models/em_group.dart | 227 ++++- lib/src/models/em_group_message_ack.dart | 51 +- lib/src/models/em_group_options.dart | 61 +- lib/src/models/em_group_shared_file.dart | 43 +- lib/src/models/em_message.dart | 734 ++++++++++++++-- lib/src/models/em_message_reaction.dart | 66 +- lib/src/models/em_options.dart | 410 +++++++-- lib/src/models/em_page_result.dart | 22 +- lib/src/models/em_presence.dart | 54 +- lib/src/models/em_push_configs.dart | 46 +- lib/src/models/em_translate_language.dart | 26 +- lib/src/models/em_userInfo.dart | 107 ++- 39 files changed, 5292 insertions(+), 2393 deletions(-) delete mode 100644 lib/src/em_listeners.dart delete mode 100644 lib/src/em_message_status_callback.dart diff --git a/android/build.gradle b/android/build.gradle index 9f84577a..6aebee0a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -48,5 +48,5 @@ tasks.withType(JavaCompile){ dependencies { api 'androidx.appcompat:appcompat:1.1.0' - implementation 'io.hyphenate:hyphenate-chat:4.0.1' + implementation 'io.hyphenate:hyphenate-chat:4.0.2' } diff --git a/example/lib/main.dart b/example/lib/main.dart index c312b78d..bb41c847 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,9 +1,13 @@ import 'package:flutter/material.dart'; import 'package:im_flutter_sdk/im_flutter_sdk.dart'; -var appKey = "<#Your AppKey#>"; +var appKey = "easemob-demo#flutter"; -void main() { +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + EMOptions options = + EMOptions(appKey: appKey, autoLogin: false, debugModel: true); + await EMClient.getInstance.init(options); runApp(const MyApp()); } @@ -43,7 +47,6 @@ class _MyHomePageState extends State { @override void initState() { super.initState(); - _initSDK(); _addChatListener(); } @@ -150,18 +153,6 @@ class _MyHomePageState extends State { super.dispose(); } - void _initSDK() async { - EMOptions options = EMOptions( - appKey: appKey, - autoLogin: false, - debugModel: true, - ); - - await EMClient.getInstance.init( - options, - ); - } - void _addChatListener() { EMClient.getInstance.chatManager.addMessageEvent( "UNIQUE_HANDLER_ID", @@ -254,6 +245,7 @@ class _MyHomePageState extends State { } try { + _addLogToConsole("sign in..."); await EMClient.getInstance.login(_userId, _password); _addLogToConsole("sign in succeed, username: $_userId"); } on EMError catch (e) { @@ -263,6 +255,7 @@ class _MyHomePageState extends State { void _signOut() async { try { + _addLogToConsole("sign out..."); await EMClient.getInstance.logout(true); _addLogToConsole("sign out succeed"); } on EMError catch (e) { @@ -278,6 +271,7 @@ class _MyHomePageState extends State { } try { + _addLogToConsole("sign up..."); await EMClient.getInstance.createAccount(_userId, _password); _addLogToConsole("sign up succeed, username: $_userId"); } on EMError catch (e) { diff --git a/ios/im_flutter_sdk.podspec b/ios/im_flutter_sdk.podspec index ec550ad6..d4803d2a 100644 --- a/ios/im_flutter_sdk.podspec +++ b/ios/im_flutter_sdk.podspec @@ -21,7 +21,7 @@ A new flutter plugin project. s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' - s.dependency 'HyphenateChat','4.0.0' + s.dependency 'HyphenateChat','4.0.2' s.ios.deployment_target = '11.0' end diff --git a/lib/im_flutter_sdk.dart b/lib/im_flutter_sdk.dart index 95de2dff..95dab0cc 100644 --- a/lib/im_flutter_sdk.dart +++ b/lib/im_flutter_sdk.dart @@ -12,7 +12,6 @@ export 'src/em_chat_room_manager.dart'; export 'src/em_push_manager.dart'; export 'src/em_userInfo_manager.dart'; export 'src/em_presence_manager.dart'; -export 'src/em_listeners.dart'; export 'src/models/em_group_message_ack.dart' show EMGroupMessageAck; export 'src/models/em_chat_room.dart' show EMChatRoom; @@ -38,5 +37,4 @@ export 'src/models/em_message_reaction.dart'; export 'src/models/em_chat_thread.dart'; export 'src/models/chat_silent_mode.dart'; export 'src/event_handler/manager_event_handler.dart'; -export 'src/em_message_status_callback.dart' show MessageStatusCallBack; export 'src/tools/area_code.dart'; diff --git a/lib/src/em_chat_manager.dart b/lib/src/em_chat_manager.dart index 777c4604..1d5e93d8 100644 --- a/lib/src/em_chat_manager.dart +++ b/lib/src/em_chat_manager.dart @@ -5,7 +5,7 @@ import "dart:async"; import 'package:flutter/services.dart'; import 'internal/inner_headers.dart'; -/// +/// ~english /// The chat manager class, responsible for sending and receiving messages, loading and deleting conversations, and downloading attachments. /// /// The sample code for sending a text message: @@ -15,12 +15,22 @@ import 'internal/inner_headers.dart'; /// username: toChatUsername, content: content); /// await EMClient.getInstance.chatManager.sendMessage(msg); /// ``` +/// ~end +/// +/// ~chinese +/// 聊天管理类,该类负责管理会话(加载,删除等)、发送消息、下载消息附件等。 /// +/// 比如,发送一条文本消息: +/// +/// ```dart +/// EMMessage msg = EMMessage.createTxtSendMessage( +/// targetId: toChatUsername, content: content); +/// await EMClient.getInstance.chatManager.sendMessage(msg); +/// ``` +/// ~end class EMChatManager { final Map _eventHandlesMap = {}; - final List _listeners = []; - /// @nodoc EMChatManager() { ChatChannel.setMethodCallHandler((MethodCall call) async { @@ -50,13 +60,21 @@ class EMChatManager { }); } - /// + /// ~english /// Adds the chat event handler. After calling this method, you can handle for chat event when they arrive. /// /// Param [identifier] The custom handler identifier, is used to find the corresponding handler. /// /// Param [handler] The handler for chat event. See [EMChatEventHandler]. + /// ~end + /// + /// ~chinese + /// 添加事件监听。 /// + /// Param [identifier] 事件监听对应的 ID。 + /// + /// Param [handler] 事件监听. 请见 [EMChatEventHandler]. + /// ~end void addEventHandler( String identifier, EMChatEventHandler handler, @@ -64,34 +82,52 @@ class EMChatManager { _eventHandlesMap[identifier] = handler; } - /// + /// ~english /// Remove the chat event handler. /// /// Param [identifier] The custom handler identifier. + /// ~end /// + /// ~chinese + /// 移除事件监听。 + /// + /// Param [identifier] 要移除监听对应的 ID。 + /// ~end void removeEventHandler(String identifier) { _eventHandlesMap.remove(identifier); } - /// + /// ~english /// Get the chat event handler. /// /// Param [identifier] The custom handler identifier. /// /// **Return** The chat event handler. + /// ~end + /// + /// ~chinese + /// 获取事件监听。 /// + /// Param [identifier] 要获取监听对应的 ID。 + /// + /// **Return** 事件监听。 + /// ~end EMChatEventHandler? getEventHandler(String identifier) { return _eventHandlesMap[identifier]; } - /// + /// ~english /// Clear all chat event handlers. + /// ~end /// + /// ~chinese + /// 清除所有事件监听。 + /// ~end void clearEventHandlers() { _eventHandlesMap.clear(); } - /// + /// ~english /// Sends a message. /// /// **Note** @@ -103,7 +139,21 @@ class EMChatManager { /// Param [message] The message object to be sent: [EMMessage]. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 发消息 + /// + /// **Note** + /// 对于语音、图片、视频等附件消息,SDK会自动上传附件。 + /// 可以使用 [EMOptions.serverTransfer] 设置是否将附件上传到聊天服务器。 + /// + /// 添加发送状态监听使用 [EMChatManager.addMessageEvent]. /// + /// Param [message] 需要发送的消息 [EMMessage]. + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future sendMessage( EMMessage message, { void Function( @@ -128,11 +178,19 @@ class EMChatManager { } } - /// + /// ~english /// Resend a message. /// /// Param [message] The message object to be resent: [EMMessage]. + /// ~end + /// + /// ~chinese + /// 重发消息。 + /// + /// Param [message] 需要重发的消息。 /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future resendMessage(EMMessage message) async { message.status = MessageStatus.PROGRESS; Map result = await ChatChannel.invokeMethod( @@ -149,7 +207,7 @@ class EMChatManager { } } - /// + /// ~english /// Sends the read receipt to the server. /// /// This method applies to one-to-one chats only. @@ -165,7 +223,23 @@ class EMChatManager { /// Param [message] The message body: [EMMessage]. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 发送消息的已读回执,该方法只针对单聊会话。 /// + /// **Warning** + /// 该方法只有在 [EMOptions.requireAck] 为 `true` 时才生效。 + /// + /// **Note** + /// 群消息已读回执,详见 [sendGroupMessageReadAck]。 + /// + /// 推荐进入会话页面时调用 [sendConversationReadAck],其他情况下调用该方法以减少调用频率。 + /// + /// Param [message] 需要发送已读回执的消息。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future sendMessageReadAck(EMMessage message) async { Map req = {"to": message.from, "msg_id": message.msgId}; Map result = @@ -178,7 +252,7 @@ class EMChatManager { } } - /// + /// ~english /// Sends the group message receipt to the server. /// /// You can call the method only after setting the following method: [EMOptions.requireAck] and [EMMessage.needGroupAck]. @@ -195,7 +269,25 @@ class EMChatManager { /// Param [content] The extension information, which is a custom keyword that specifies a custom action or command. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 发送群消息已读回执。 /// + /// 前提条件:设置了[EMOptions.requireAck] 和 [EMMessage.needGroupAck] 都为 `true`。 + /// + /// **Note** + /// 发送单聊消息已读回执,详见 [sendMessageReadAck]; + /// 会话已读回执,详见 [sendConversationReadAck]; + /// + /// Param [msgId] 消息 ID。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [content] 扩展信息。用户自己定义的关键字,接收后,解析出自定义的字符串,可以自行处理。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future sendGroupMessageReadAck( String msgId, String groupId, { @@ -216,7 +308,7 @@ class EMChatManager { } } - /// + /// ~english /// Sends the conversation read receipt to the server. This method is only for one-to-one chat conversations. /// /// This method informs the server to set the unread message count of the conversation to 0. In multi-device scenarios, all the devices receive the [EMChatEventHandler.onConversationRead] callback. @@ -227,7 +319,21 @@ class EMChatManager { /// Param [conversationId] The conversation ID. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end /// + /// ~chinese + /// 发送会话的已读回执,该方法只针对单聊会话。 + /// + /// 该方法会通知服务器将此会话未读数设置为 0,对话方(包含多端多设备)将会在下面这个回调方法中接收到回调: + /// [EMChatEventHandler.onConversationRead]。 + /// + /// **Note** + /// 发送群组消息已读回执见 [sendGroupMessageReadAck]。 + /// + /// Param [conversationId] 会话 ID。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future sendConversationReadAck(String conversationId) async { Map req = {"con_id": conversationId}; Map result = @@ -240,13 +346,21 @@ class EMChatManager { } } - /// + /// ~english /// Recalls the sent message. /// /// Param [messageId] The message ID. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 撤回发送成功的消息。 /// + /// Param [messageId] 消息 ID。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future recallMessage(String messageId) async { Map req = {"msg_id": messageId}; Map result = @@ -258,7 +372,7 @@ class EMChatManager { } } - /// + /// ~english /// Loads a message from the local database by message ID. /// /// Param [messageId] The message ID. @@ -266,7 +380,17 @@ class EMChatManager { /// **Return** The message object specified by the message ID. Returns null if the message does not exist. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 从本地数据库获取指定 ID 的消息对象。 + /// + /// Param [messageId] 消息 ID。 /// + /// **Return** 根据指定 ID 获取的消息对象,如果消息不存在会返回空值。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future loadMessage(String messageId) async { Map req = {"msg_id": messageId}; Map result = @@ -283,7 +407,7 @@ class EMChatManager { } } - /// + /// ~english /// Gets the conversation by conversation ID and conversation type. /// /// Param [conversationId] The conversation ID. @@ -297,7 +421,26 @@ class EMChatManager { /// **Return** The conversation object found according to the ID and type. Returns null if the conversation is not found. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 根据指定会话 ID 和会话类型获取会话对象。 /// + /// 没有找到会返回空值。 + /// + /// Param [conversationId] 会话 ID。 + /// + /// Param [type] 会话类型,详见 [EMConversationType]。 + /// + /// Param [createIfNeed] 没找到相应会话时是否自动创建。 + /// - (Default)`true` 表示没有找到相应会话时会自动创建会话; + /// - `false` 表示没有找到相应会话时不创建会话。 + /// + /// + /// **Return** 根据指定 ID 以及会话类型找到的会话对象,如果没有找到会返回空值。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future getConversation( String conversationId, { EMConversationType type = EMConversationType.Chat, @@ -322,7 +465,7 @@ class EMChatManager { } } - /// + /// ~english /// Gets the thread conversation by thread ID. /// /// Param [threadId] The thread ID. @@ -330,7 +473,17 @@ class EMChatManager { /// **Return** The conversation object. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end /// + /// ~chinese + /// 根据threadId 获取 thread 会话。 + /// + /// Param [threadId] Thread ID. + /// + /// **Return** 会话对象. + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future getThreadConversation(String threadId) async { Map result = await ChatChannel.invokeMethod( ChatMethodKeys.getThreadConversation, @@ -346,12 +499,21 @@ class EMChatManager { } } + /// ~english /// Marks all messages as read. /// /// This method is for the local conversations only. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 把所有的会话都设成已读。 /// + /// 这里针对的是本地会话。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future markAllConversationsAsRead() async { Map result = await ChatChannel.invokeMethod(ChatMethodKeys.markAllChatMsgAsRead); @@ -362,13 +524,21 @@ class EMChatManager { } } - /// + /// ~english /// Gets the count of the unread messages. /// /// **Return** The count of the unread messages. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 获取未读消息数。 /// + /// **Return** 未读消息数。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future getUnreadMessageCount() async { Map result = await ChatChannel.invokeMethod(ChatMethodKeys.getUnreadMessageCount); @@ -384,13 +554,21 @@ class EMChatManager { } } - /// + /// ~english /// Updates the local message. /// /// The message will be updated both in the cache and local database. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 更新本地消息。 + /// + /// 会同时更新本地内存和数据库。 /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future updateMessage(EMMessage message) async { Map req = {"message": message.toJson()}; Map result = @@ -402,7 +580,7 @@ class EMChatManager { } } - /// + /// ~english /// Imports messages to the local database. /// /// Before importing, ensure that the sender or receiver of the message is the current user. @@ -412,7 +590,18 @@ class EMChatManager { /// Param [messages] The message list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 将消息导入本地数据库。 + /// + /// 只能将当前用户发送或接收的消息导入本地数据库。 + /// 已经对函数做过速度优化,推荐一次导入 1,000 条以内的数据。 /// + /// Param [messages] 需要导入数据库的消息。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future importMessages(List messages) async { List list = []; messages.forEach((element) { @@ -428,7 +617,7 @@ class EMChatManager { } } - /// + /// ~english /// Downloads the attachment files from the server. /// /// You can call the method again if the attachment download fails. @@ -436,7 +625,17 @@ class EMChatManager { /// Param [message] The message with the attachment that is to be downloaded. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 下载消息的附件。 + /// + /// 若附件自动下载失败,也可以调用此方法下载。 /// + /// Param [message] 要下载附件的消息。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future downloadAttachment(EMMessage message) async { Map result = await ChatChannel.invokeMethod( ChatMethodKeys.downloadAttachment, {"message": message.toJson()}); @@ -447,13 +646,21 @@ class EMChatManager { } } - /// + /// ~english /// Downloads the thumbnail if the message has not been downloaded before or if the download fails. /// /// Param [message] The message object. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 下载消息的缩略图。 /// + /// Param [message] 要下载缩略图的消息,一般图片消息和视频消息有缩略图。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future downloadThumbnail(EMMessage message) async { Map result = await ChatChannel.invokeMethod( ChatMethodKeys.downloadThumbnail, {"message": message.toJson()}); @@ -464,7 +671,7 @@ class EMChatManager { } } - /// + /// ~english /// Gets all conversations from the local database. /// /// Conversations will be first loaded from the cache. If no conversation is found, the SDK loads from the local database. @@ -472,7 +679,17 @@ class EMChatManager { /// **Return** All the conversations from the cache or local database. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 获取本地数据库中所有会话。 + /// + /// 会先从内存中获取,如果没有会从本地数据库获取。 /// + /// **Return** 返回获取的会话。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> loadAllConversations() async { Map result = await ChatChannel.invokeMethod(ChatMethodKeys.loadAllConversations); @@ -488,7 +705,7 @@ class EMChatManager { } } - /// + /// ~english /// Gets the conversation list from the server. /// /// To use this function, you need to contact our business manager to activate it. After this function is activated, users can pull 10 conversations within 7 days by default (each conversation contains the latest historical message). If you want to adjust the number of conversations or time limit, please contact our business manager. @@ -496,7 +713,17 @@ class EMChatManager { /// **Return** The conversation list of the current user. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 从服务器获取会话列表。 /// + /// 该功能需联系商务开通,开通后,用户默认可拉取 7 天内的 10 个会话(每个会话包含最新一条历史消息),如需调整会话数量或时间限制请联系商务经理。 + /// + /// **Return** 返回获取的会话列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> getConversationsFromServer() async { Map result = await ChatChannel.invokeMethod( ChatMethodKeys.getConversationsFromServer); @@ -512,6 +739,7 @@ class EMChatManager { } } + /// ~english /// fetch the conversations from the server. /// /// Param [pageNum] The current page number. @@ -521,6 +749,19 @@ class EMChatManager { /// **Return** The conversation list of the current user. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 获取服务器会话。 + /// + /// Param [pageNum] 获取的页码。 + /// + /// Param [pageSize] 获取页中返回数量。 + /// + /// **Return** 当前用户的会话列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> fetchConversationListFromServer({ int pageNum = 1, int pageSize = 20, @@ -546,6 +787,7 @@ class EMChatManager { } } + /// ~english /// Unidirectionally removes historical message by message ID from the server. /// /// Param [conversationId] The conversation ID. @@ -553,6 +795,17 @@ class EMChatManager { /// Param [type] The conversation type. /// /// Param [msgIds] The list of IDs of messages to be removed. + /// ~end + /// + /// ~chinese + /// 根据消息ID 单向删除服务器会话中的消息和本地消息。 + /// + /// Param [conversationId] 会话 ID。 + /// + /// Param [type] 会话类型。 + /// + /// Param [msgIds] 需要删除的消息 ID。 + /// ~end Future deleteRemoteMessagesWithIds( {required String conversationId, required EMConversationType type, @@ -573,6 +826,7 @@ class EMChatManager { } } + /// ~english /// Unidirectionally removes historical message by timestamp from the server. /// /// Param [conversationId] The conversation ID. @@ -580,6 +834,16 @@ class EMChatManager { /// Param [type] The conversation type. /// /// Param [timestamp] The UNIX timestamp in millisecond. Messages with a timestamp smaller than the specified one will be removed. + /// ~end + /// + /// ~chinese + /// 根据时间 单向删除服务器会话中的消息和本地消息。 + /// Param [conversationId] 会话 ID。 + /// + /// Param [type] 会话类型。 + /// + /// Param [timestamp] 以毫秒为单位的UNIX时间戳。时间戳小于指定时间戳的消息将被删除。 + /// ~end Future deleteRemoteMessagesBefore( {required String conversationId, required EMConversationType type, @@ -600,6 +864,7 @@ class EMChatManager { } } + /// ~english /// Deletes a conversation and its related messages from the local database. /// /// If you set [deleteMessages] to `true`, the local historical messages are deleted when the conversation is deleted. @@ -615,7 +880,21 @@ class EMChatManager { /// - `false`: No. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end /// + /// ~chinese + /// 删除本地会话。 + /// + /// Param [deleteMessages] 删除会话时是否同时删除本地的聊天记录。 + /// - `true` 表示删除; + /// - `false` 表示不删除。 + /// + /// **Return** 删除会话结果。 + /// - `true` 代表删除成功; + /// - `false` 代表删除失败。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future deleteConversation( String conversationId, { bool deleteMessages = true, @@ -631,7 +910,7 @@ class EMChatManager { } } - /// + /// ~english /// Gets historical messages of the conversation from the server with pagination. /// /// Param [conversationId] The conversation ID. @@ -645,7 +924,23 @@ class EMChatManager { /// **Return** The obtained messages and the cursor for the next fetch action. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 从服务器分页获取历史消息。 + /// + /// Param [conversationId] 会话 ID。 + /// + /// Param [type] 会话类型,详见 {@link EMConversationType}。 /// + /// Param [pageSize] 每页获取的消息数量。 + /// + /// Param [startMsgId] 获取历史消息的开始消息 ID,如果为空,从最新的消息向前开始获取。 + /// + /// **Return** 返回消息列表和用于继续获取历史消息的 [EMCursorResult] + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> fetchHistoryMessages({ required String conversationId, EMConversationType type = EMConversationType.Chat, @@ -671,7 +966,7 @@ class EMChatManager { } } - /// + /// ~english /// Retrieves messages from the database according to the parameters. /// /// **Note** @@ -688,7 +983,25 @@ class EMChatManager { /// **Return** The list of messages. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 根据传入的参数从本地存储中搜索指定数量的消息。 + /// + /// 注意:当 maxCount 非常大时,需要考虑内存消耗,目前限制一次最多搜索 400 条数据。 + /// + /// Param [keywords] 关键词。 /// + /// Param [timestamp] 搜索消息的时间点,Unix 时间戳。 + /// + /// Param [maxCount] 搜索结果的最大条数。 + /// + /// Param [from] 搜索来自某人或者某群的消息,一般是指会话 ID。 + /// + /// **Return** 获取的消息列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> searchMsgFromDB( String keywords, { int timestamp = -1, @@ -717,7 +1030,7 @@ class EMChatManager { } } - /// + /// ~english /// Gets read receipts for group messages from the server with pagination. /// /// See also: @@ -732,7 +1045,26 @@ class EMChatManager { /// **Return** The list of obtained read receipts and the cursor for next query. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 从服务器获取群组消息回执详情。 + /// + /// 分页获取。 /// + /// **Note** + /// 发送群组消息回执,详见 [sendConversationReadAck]。 + /// + /// Param [msgId] 消息 ID。 + /// + /// Param [startAckId] 已读回执的 ID,如果为空,从最新的回执向前开始获取。 + /// + /// Param [pageSize] 每页获取群消息已读回执的条数。 + /// + /// **Return** 返回回执列表和用于下次获取群消息回执的 [EMCursorResult] + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> fetchGroupAcks( String msgId, String groupId, { @@ -761,7 +1093,7 @@ class EMChatManager { } } - /// + /// ~english /// Deletes the specified conversation and the related historical messages from the server. /// /// Param [conversationId] The conversation ID. @@ -774,7 +1106,22 @@ class EMChatManager { /// /// /// **Throws** A description of the exception. See [EMError]. + /// ~end /// + /// ~chinese + /// 删除服务端的指定 ID 的会话和聊天记录。 + /// + /// Param [conversationId] 会话 ID。 + /// + /// Param [conversationType] 会话类型,详见 [EMConversationType]。 + /// + /// Param [isDeleteMessage] 删除会话时是否同时删除历史消息记录。 + /// + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future deleteRemoteConversation( String conversationId, { EMConversationType conversationType = EMConversationType.Chat, @@ -800,13 +1147,21 @@ class EMChatManager { } } - /// + /// ~english /// Deletes messages with timestamp that is before the specified one. /// /// Param [timestamp] The specified Unix timestamp(milliseconds). /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 根据时间删除本地消息。 /// + /// Param [timestamp] 指定的Unix时间戳(毫秒)。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future deleteMessagesBefore(int timestamp) async { Map result = await ChatChannel.invokeMethod( ChatMethodKeys.deleteMessagesBeforeTimestamp, {"timestamp": timestamp}); @@ -826,11 +1181,6 @@ class EMChatManager { for (var item in _eventHandlesMap.values) { item.onMessagesReceived?.call(messageList); } - - // deprecated(3.9.5) - for (var listener in _listeners) { - listener.onMessagesReceived(messageList); - } } Future _onCmdMessagesReceived(List messages) async { @@ -842,11 +1192,6 @@ class EMChatManager { for (var item in _eventHandlesMap.values) { item.onCmdMessagesReceived?.call(list); } - - // deprecated(3.9.5) - for (var listener in _listeners) { - listener.onCmdMessagesReceived(list); - } } Future _onMessagesRead(List messages) async { @@ -858,11 +1203,6 @@ class EMChatManager { for (var item in _eventHandlesMap.values) { item.onMessagesRead?.call(list); } - - // deprecated(3.9.5) - for (var listener in _listeners) { - listener.onMessagesRead(list); - } } Future _onGroupMessageRead(List messages) async { @@ -874,22 +1214,12 @@ class EMChatManager { for (var item in _eventHandlesMap.values) { item.onGroupMessageRead?.call(list); } - - // deprecated(3.9.5) - for (var listener in _listeners) { - listener.onGroupMessageRead(list); - } } Future _onReadAckForGroupMessageUpdated(List messages) async { for (var item in _eventHandlesMap.values) { item.onReadAckForGroupMessageUpdated?.call(); } - - // deprecated(3.9.5) - for (var listener in _listeners) { - listener.onReadAckForGroupMessageUpdated(); - } } Future _onMessagesDelivered(List messages) async { @@ -901,11 +1231,6 @@ class EMChatManager { for (var item in _eventHandlesMap.values) { item.onMessagesDelivered?.call(list); } - - // deprecated(3.9.5) - for (var listener in _listeners) { - listener.onMessagesDelivered(list); - } } Future _onMessagesRecalled(List messages) async { @@ -917,22 +1242,12 @@ class EMChatManager { for (var item in _eventHandlesMap.values) { item.onMessagesRecalled?.call(list); } - - // deprecated(3.9.5) - for (var listener in _listeners) { - listener.onMessagesRecalled(list); - } } Future _onConversationsUpdate(dynamic obj) async { for (var item in _eventHandlesMap.values) { item.onConversationsUpdate?.call(); } - - // deprecated(3.9.5) - for (var listener in _listeners) { - listener.onConversationsUpdate(); - } } Future _onConversationHasRead(dynamic obj) async { @@ -942,11 +1257,6 @@ class EMChatManager { for (var item in _eventHandlesMap.values) { item.onConversationRead?.call(from, to); } - - // deprecated(3.9.5) - for (var listener in _listeners) { - listener.onConversationRead(from, to); - } } Future _messageReactionDidChange(List reactionChangeList) async { @@ -958,24 +1268,31 @@ class EMChatManager { for (var item in _eventHandlesMap.values) { item.onMessageReactionDidChange?.call(list); } - - // deprecated(3.9.5) - for (var listener in _listeners) { - listener.onMessageReactionDidChange(list); - } } + /// ~english + /// Reports an inappropriate message. /// - /// Report violation message + /// Param [messageId] The ID of the message to report. /// - /// Param [messageId] Violation Message ID + /// Param [tag] The tag of the inappropriate message. You need to type a custom tag, like `porn` or `ad`. /// - /// Param [tag] The report type (For example: involving pornography and terrorism). - /// - /// Param [reason] The reason for reporting. + /// Param [reason] The reporting reason. You need to type a specific reason. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 举报消息。 + /// + /// Param [messageId] 要举报的消息 ID。 + /// + /// Param [tag] 非法消息的标签。你需要填写自定义标签,例如`涉政`或`广告`。 /// + /// Param [reason] 举报原因。你需要自行填写举报原因。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future reportMessage({ required String messageId, required String tag, @@ -991,7 +1308,7 @@ class EMChatManager { } } - /// + /// ~english /// Adds a reaction. /// /// Param [messageId] The message ID. @@ -999,7 +1316,17 @@ class EMChatManager { /// Param [reaction] The reaction content. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 添加 Reaction。 /// + /// Param [messageId] 要添加 Reaction 的消息 ID。 + /// + /// Param [reaction] Reaction 的内容。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 详见 [EMError]。 + /// ~end Future addReaction({ required String messageId, required String reaction, @@ -1014,7 +1341,7 @@ class EMChatManager { } } - /// + /// ~english /// Deletes a reaction. /// /// Param [messageId] The message ID. @@ -1022,7 +1349,17 @@ class EMChatManager { /// Param [reaction] The reaction content. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 删除 Reaction。 /// + /// Param [messageId] 添加了该 Reaction 的消息 ID。 + /// + /// Param [reaction] 要删除的 Reaction。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future removeReaction({ required String messageId, required String reaction, @@ -1037,7 +1374,7 @@ class EMChatManager { } } - /// + /// ~english /// Gets the list of Reactions. /// /// Param [messageIds] The message IDs. @@ -1049,7 +1386,21 @@ class EMChatManager { /// **Return** The Reaction list under the specified message ID([EMMessageReaction.userList] is the summary data, which only contains the information of the first three users). /// /// **Throws** A description of the exception. See [EMError]. + /// ~end /// + /// ~chinese + /// 获取 Reaction 列表。 + /// + /// Param [messageIds] 消息 ID 列表。 + /// + /// Param [chatType] 会话类型。 + /// + /// Param [groupId] 群组 ID,该参数仅在会话类型为群聊时有效。 + /// + /// **Return** 若调用成功,返回 Reaction 列表;失败则抛出异常。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future>> fetchReactionList({ required List messageIds, required ChatType chatType, @@ -1081,7 +1432,7 @@ class EMChatManager { } } - /// + /// ~english /// Gets the reaction details. /// /// Param [messageId] The message ID. @@ -1095,7 +1446,23 @@ class EMChatManager { /// **Return** The result callback, which contains the reaction list obtained from the server and the cursor for the next query. Returns null if all the data is fetched. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 获取 Reaction 详情。 /// + /// Param [messageId] 消息 ID。 + /// + /// Param [reaction] Reaction 内容。 + /// + /// Param [cursor] 开始获取 Reaction 的游标位置, 首次可以不传。 + /// + /// Param [pageSize] 每页期望返回的 Reaction 数量。 + /// + /// **Return** 若调用成功,返回 Reaction 详情。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future> fetchReactionDetail({ required String messageId, required String reaction, @@ -1123,7 +1490,7 @@ class EMChatManager { } } - /// + /// ~english /// Translate a message. /// /// Param [msg] The message object @@ -1133,7 +1500,19 @@ class EMChatManager { /// **Return** Translated Message /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 翻译一条文本消息。 /// + /// Param [msg] 要翻译的文本消息。 + /// + /// Param [languages] 目标语言。 + /// + /// **Return** 译文。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future translateMessage({ required EMMessage msg, required List languages, @@ -1151,13 +1530,21 @@ class EMChatManager { } } - /// + /// ~english /// Fetch all languages what the translate service support /// /// **Return** Supported languages /// /// **Throws** A description of the exception. See [EMError]. + /// ~end /// + /// ~chinese + /// 查询翻译服务支持的语言。 + /// + /// **Return** 翻译服务支持的语言列表。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future> fetchSupportedLanguages() async { Map result = await ChatChannel.invokeMethod(ChatMethodKeys.fetchSupportLanguages); @@ -1173,31 +1560,61 @@ class EMChatManager { } } + /// ~english /// Adds a message status listener. /// /// Param [identifier] The ID of the message status listener. The ID is required when you delete a message status listener. /// /// Param [event] The message status event. + /// ~end + /// + /// ~chinese + /// 添加消息状态监听。 + /// + /// Param [identifier] 消息状态监听 ID, 删除监听时需提供。 + /// + /// Param [event] 消息状态事件。 + /// ~end void addMessageEvent(String identifier, ChatMessageEvent event) { MessageCallBackManager.getInstance.addMessageEvent(identifier, event); } + /// ~english /// Removes a message status listener. /// /// Param [identifier] The ID of the message status listener. The ID is set when you add a message status listener. + /// ~end + /// + /// ~chinese + /// 移除消息状态监听。 + /// + /// Param [identifier] 消息状态监听 ID, 在添加时设置。 + /// ~end void removeMessageEvent(String identifier) { MessageCallBackManager.getInstance.removeMessageEvent(identifier); } + /// ~english /// Clears all message status listeners. + /// ~end + /// + /// ~chinese + /// 清空所有消息状态监听。 + /// ~end void clearMessageEvent() { MessageCallBackManager.getInstance.clearAllMessageEvents(); } } +/// ~english /// The message status event class. /// During message delivery, the message ID will be changed from a local uuid to a global unique ID that is generated by the server to uniquely identify a message on all devices using the SDK. /// This API should be implemented in the chat page widget to listen for message status changes. +/// ~end +/// +/// ~chinese +/// 消息状态事件类。 +/// ~end class ChatMessageEvent { ChatMessageEvent({ this.onSuccess, @@ -1205,61 +1622,55 @@ class ChatMessageEvent { this.onProgress, }); + /// ~english /// Occurs when a message is successfully sent or downloaded. /// /// Param [msgId] The pre-sending message ID or the ID of the message that is successfully downloaded. /// /// Param [msg] The message that is successfully sent or downloaded. + /// ~end + /// + /// ~chinese + /// 消息发送或下载成功回调。 + /// ~end final void Function(String msgId, EMMessage msg)? onSuccess; + /// ~english /// Occurs when a message fails to be sent or downloaded. /// /// Param [msgId] The pre-sending message ID or the ID of the message that fails to be downloaded. /// /// Param [msg] The message that fails to be sent or downloaded. + /// ~end + /// + /// ~chinese + /// 消息发送或下载失败回调。 + /// + /// Param [msgId] 发送前或下载失败的消息 ID。 + /// + /// Param [msg] 发送或下载失败的消息。 + /// ~end final void Function(String msgId, EMMessage msg, EMError error)? onError; + /// ~english /// Occurs when there is a progress for message upload or download. This event is triggered when a message is being uploaded or downloaded. /// /// Param [msgId] The ID of the message that is being uploaded or downloaded. /// /// Param [progress] The upload or download progress. - final void Function(String msgId, int progress)? onProgress; -} - -extension ChatManagerDeprecated on EMChatManager { - /// - /// Adds the chat manager listener. After calling this method, you can listen for new messages when they arrive. + /// ~end /// - /// Param [listener] The chat manager listener that listens for new messages. See [EMChatManagerListener]. + /// ~chinese + /// 消息上传或下载进度的回调。 /// - @Deprecated("Use addEventHandler to instead") - void addChatManagerListener(EMChatManagerListener listener) { - _listeners.remove(listener); - _listeners.add(listener); - } - - /// - /// Removes the chat manager listener. - /// - /// After adding a chat manager listener, you can remove this listener if you do not want to listen for it. - /// - /// Param [listener] The chat manager listener to be removed. See [EMChatManagerListener]. - /// - @Deprecated("Use [removeEventHandler] to instead") - void removeChatManagerListener(EMChatManagerListener listener) { - _listeners.remove(listener); - } - - /// - /// Removes all chat manager listeners. + /// Param [msgId] 正在上传或下载的消息的 ID。 /// - @Deprecated("Use [clearEventHandlers] to instead") - void clearAllChatManagerListeners() { - _listeners.clear(); - } + /// Param [progress] 上传或下载进度。 + /// ~end + final void Function(String msgId, int progress)? onProgress; } +/// @nodoc class MessageCallBackManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _emMessageChannel = @@ -1292,16 +1703,19 @@ class MessageCallBackManager { }); } + /// @nodoc void addMessageEvent(String key, ChatMessageEvent event) { cacheHandleMap[key] = event; } + /// @nodoc void removeMessageEvent(String key) { if (cacheHandleMap.containsKey(key)) { cacheHandleMap.remove(key); } } + /// @nodoc void clearAllMessageEvents() { cacheHandleMap.clear(); } diff --git a/lib/src/em_chat_room_manager.dart b/lib/src/em_chat_room_manager.dart index ad746a6c..e06cec7b 100644 --- a/lib/src/em_chat_room_manager.dart +++ b/lib/src/em_chat_room_manager.dart @@ -5,9 +5,21 @@ import "dart:async"; import 'package:flutter/services.dart'; import 'internal/inner_headers.dart'; +/// ~english +/// The chat room manager class, which manages user joining and exiting the chat room, retrieving the chat room list, and managing member privileges. +/// The sample code for joining a chat room: +/// ```dart +/// try { +/// await EMClient.getInstance.chatRoomManager.joinChatRoom(chatRoomId); +/// } on EMError catch (e) { +/// debugPrint(e.toString()); +// } +/// ``` +/// ~end /// -/// The chat room manager class, which manages user joining and exiting the chat room, retrieving the chat room list, and managing member privileges. -/// The sample code for joining a chat room: +/// ~chinese +/// 聊天室管理类,负责聊天室加入和退出、聊天室列表获取以及成员权限管理等。 +/// 比如,加入聊天室: /// ```dart /// try { /// await EMClient.getInstance.chatRoomManager.joinChatRoom(chatRoomId); @@ -15,6 +27,7 @@ import 'internal/inner_headers.dart'; /// debugPrint(e.toString()); /// } /// ``` +/// ~end class EMChatRoomManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( @@ -33,8 +46,6 @@ class EMChatRoomManager { final Map _eventHandlesMap = {}; - final List _listeners = []; - Future _chatRoomChange(Map event) async { String? type = event['type']; @@ -136,89 +147,23 @@ class EMChatRoomManager { break; } } - // deprecated (3.9.5) - for (var listener in _listeners) { - switch (type) { - case EMChatRoomEvent.ON_CHAT_ROOM_DESTROYED: - String roomId = event['roomId']; - String? roomName = event['roomName']; - listener.onChatRoomDestroyed(roomId, roomName); - break; - case EMChatRoomEvent.ON_MEMBER_JOINED: - String roomId = event['roomId']; - String participant = event['participant']; - listener.onMemberJoinedFromChatRoom(roomId, participant); - break; - case EMChatRoomEvent.ON_MEMBER_EXITED: - String roomId = event['roomId']; - String? roomName = event['roomName']; - String participant = event['participant']; - listener.onMemberExitedFromChatRoom(roomId, roomName, participant); - break; - case EMChatRoomEvent.ON_REMOVED_FROM_CHAT_ROOM: - String roomId = event['roomId']; - String? roomName = event['roomName']; - String participant = event['participant']; - listener.onRemovedFromChatRoom(roomId, roomName, participant); - break; - case EMChatRoomEvent.ON_MUTE_LIST_ADDED: - String roomId = event['roomId']; - List mutes = List.from(event['mutes'] ?? []); - String? expireTime = event['expireTime']; - listener.onMuteListAddedFromChatRoom(roomId, mutes, expireTime); - break; - case EMChatRoomEvent.ON_MUTE_LIST_REMOVED: - String roomId = event['roomId']; - List mutes = List.from(event['mutes'] ?? []); - listener.onMuteListRemovedFromChatRoom(roomId, mutes); - break; - case EMChatRoomEvent.ON_ADMIN_ADDED: - String roomId = event['roomId']; - String admin = event['admin']; - listener.onAdminAddedFromChatRoom(roomId, admin); - break; - case EMChatRoomEvent.ON_ADMIN_REMOVED: - String roomId = event['roomId']; - String admin = event['admin']; - listener.onAdminRemovedFromChatRoom(roomId, admin); - break; - case EMChatRoomEvent.ON_OWNER_CHANGED: - String roomId = event['roomId']; - String newOwner = event['newOwner']; - String oldOwner = event['oldOwner']; - listener.onOwnerChangedFromChatRoom(roomId, newOwner, oldOwner); - break; - case EMChatRoomEvent.ON_ANNOUNCEMENT_CHANGED: - String roomId = event['roomId']; - String announcement = event['announcement']; - listener.onAnnouncementChangedFromChatRoom(roomId, announcement); - break; - case EMChatRoomEvent.ON_WHITE_LIST_ADDED: - String roomId = event['roomId']; - List members = List.from(event["whitelist"] ?? []); - listener.onAllowListAddedFromChatRoom(roomId, members); - break; - case EMChatRoomEvent.ON_WHITE_LIST_REMOVED: - String roomId = event['roomId']; - List members = List.from(event["whitelist"] ?? []); - listener.onAllowListRemovedFromChatRoom(roomId, members); - break; - case EMChatRoomEvent.ON_ALL_MEMBER_MUTE_STATE_CHANGED: - String roomId = event['roomId']; - bool isAllMuted = event['isMuted']; - listener.onAllChatRoomMemberMuteStateChanged(roomId, isAllMuted); - break; - } - } } - /// + /// ~english /// Adds the room event handler. After calling this method, you can handle for new room event when they arrive. /// /// Param [identifier] The custom handler identifier, is used to find the corresponding handler. /// /// Param [handler] The handle for room event. See [EMChatRoomEventHandler]. + /// ~end + /// + /// ~chinese + /// 添加房间事件处理程序。调用此方法后,您可以在新的房间事件到达时处理它们。 /// + /// Param [identifier] 自定义聊天室事件 ID,用于查找相应的处理程序。 + /// + /// Param [handler] 聊天室事件 请参见 [EMChatRoomEventHandler]. + /// ~end void addEventHandler( String identifier, EMChatRoomEventHandler handler, @@ -226,34 +171,52 @@ class EMChatRoomManager { _eventHandlesMap[identifier] = handler; } - /// + /// ~english /// Remove the room event handler. /// /// Param [identifier] The custom handler identifier. + /// ~end /// + /// ~chinese + /// 移除聊天室事件 + /// + /// Param [identifier] 聊天室事件 ID。 + /// ~end void removeEventHandler(String identifier) { _eventHandlesMap.remove(identifier); } - /// + /// ~english /// Get the room event handler. /// /// Param [identifier] The custom handler identifier. /// /// **Return** The room event handler. + /// ~end /// + /// ~chinese + /// 获取聊天室事件。 + /// + /// Param [identifier] 要获取的事件 ID。 + /// + /// **Return** 聊天室事件。 + /// ~end EMChatRoomEventHandler? getEventHandler(String identifier) { return _eventHandlesMap[identifier]; } - /// + /// ~english /// Clear all room event handlers. + /// ~end /// + /// ~chinese + /// 清除所有聊天室事件。 + /// ~end void clearEventHandlers() { _eventHandlesMap.clear(); } - /// + /// ~english /// Joins the chat room. /// /// To exit the chat room, call [leaveChatRoom]. @@ -261,7 +224,17 @@ class EMChatRoomManager { /// Param [roomId] The ID of the chat room to join. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 加入聊天室 /// + /// 退出聊天室,调用 [leaveChatRoom]. + /// + /// Param [roomId] 要加入的聊天室ID。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future joinChatRoom(String roomId) async { Map result = await _channel .invokeMethod(ChatMethodKeys.joinChatRoom, {"roomId": roomId}); @@ -272,13 +245,21 @@ class EMChatRoomManager { } } - /// + /// ~english /// Leaves the chat room. /// /// Param [roomId] The ID of the chat room to leave. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 离开聊天室。 /// + /// Param [roomId] 聊天室 ID。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future leaveChatRoom(String roomId) async { Map result = await _channel .invokeMethod(ChatMethodKeys.leaveChatRoom, {"roomId": roomId}); @@ -289,7 +270,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Gets chat room data from the server with pagination. /// /// Param [pageNum] The page number, starting from 1. @@ -299,7 +280,19 @@ class EMChatRoomManager { /// **Return** Chat room data. See [EMPageResult]. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 以分页的方式从服务器获取聊天室数据。 + /// + /// Param [pageNum] 当前页码,从 1 开始。 /// + /// Param [pageSize] 每页返回的记录数。 + /// + /// **Return** 分页获取结果,详见 {@link EMPageResult}。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> fetchPublicChatRoomsFromServer({ int pageNum = 1, int pageSize = 200, @@ -319,7 +312,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Gets the details of the chat room from the server. /// By default, the details do not include the chat room member list. /// @@ -328,7 +321,17 @@ class EMChatRoomManager { /// **Return** The chat room instance. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 从服务器获取聊天室详情,默认不取成员列表。 /// + /// Param [roomId] 聊天室 ID。 + /// + /// **Return** 返回聊天室对象。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future fetchChatRoomInfoFromServer( String roomId, { bool fetchMembers = false, @@ -345,7 +348,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Gets the chat room in the cache. /// /// Param [roomId] The chat room ID. @@ -353,7 +356,17 @@ class EMChatRoomManager { /// **Return** The chat room instance. Returns null if the chat room is not found in the cache. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 从内存中获取聊天室。 /// + /// Param [roomId] 聊天室 ID。 + /// + /// **Return** 返回聊天室对象。如果内存中不存在聊天室对象,返回 null。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future getChatRoomWithId(String roomId) async { Map result = await _channel .invokeMethod(ChatMethodKeys.getChatRoom, {"roomId": roomId}); @@ -369,7 +382,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Creates a chat room. /// /// Param [name] The chat room name. @@ -385,7 +398,25 @@ class EMChatRoomManager { /// **Return** The chat room instance. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 创建聊天室。 /// + /// Param [name] 聊天室名称。 + /// + /// Param [desc] 聊天室描述。 + /// + /// Param [welcomeMsg] 邀请成员加入聊天室的消息。 + /// + /// Param [maxUserCount] 允许加入聊天室的最大成员数。 + /// + /// Param [members] 邀请加入聊天室的成员列表。 + /// + /// **Return** 创建成功的聊天室对象。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future createChatRoom( String name, { String? desc, @@ -409,7 +440,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Destroys a chat room. /// /// Only the chat room owner can call this method. @@ -417,7 +448,17 @@ class EMChatRoomManager { /// Param [roomId] The chat room ID. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 销毁聊天室。 /// + /// 仅聊天室所有者可调用此方法。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future destroyChatRoom( String roomId, ) async { @@ -431,7 +472,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Changes the chat room name. /// /// Only the chat room owner can call this method. @@ -441,7 +482,19 @@ class EMChatRoomManager { /// Param [name] The new name of the chat room. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 修改聊天室标题。 + /// + /// 仅聊天室所有者可调用此方法。 /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [name] 新的聊天室名称。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future changeChatRoomName( String roomId, String name, @@ -456,7 +509,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Modifies the chat room description. /// /// Only the chat room owner can call this method. @@ -466,7 +519,19 @@ class EMChatRoomManager { /// Param [description] The new description of the chat room. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 修改聊天室描述信息。 /// + /// 仅聊天室所有者可调用此方法。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [description] The new description of the chat room. + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future changeChatRoomDescription( String roomId, String description, @@ -481,7 +546,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Gets the chat room member list. /// /// Param [roomId] The chat room ID. @@ -493,7 +558,23 @@ class EMChatRoomManager { /// **Return** The list of chat room members. See [EMCursorResult]. If [EMCursorResult.cursor] is an empty string (""), all data is fetched. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 获取聊天室成员列表。 + /// + /// 返回的结果中,当 EMCursorResult.cursor 为空字符串 ("") 时,表示没有更多数据。 + /// + /// Param [roomId] 聊天室 ID。 /// + /// Param [cursor] 从这个游标位置开始取数据。 + /// + /// Param [pageSize] 每页返回的成员数。 + /// + /// **Return** 分页获取结果 {@link EMCursorResult}。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> fetchChatRoomMembers( String roomId, { String? cursor, @@ -513,7 +594,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Mutes the specified members in a chat room. /// /// Only the chat room owner or admin can call this method. @@ -525,7 +606,21 @@ class EMChatRoomManager { /// Param [duration] The mute duration in milliseconds. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 禁止聊天室成员发言。 + /// + /// 仅聊天室所有者和管理员可调用此方法。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [muteMembers] 禁言的用户列表。 /// + /// Param [duration] 禁言时长,单位是毫秒。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future muteChatRoomMembers( String roomId, List muteMembers, { @@ -545,7 +640,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Unmutes the specified members in a chat room. /// /// Only the chat room owner or admin can call this method. @@ -555,7 +650,19 @@ class EMChatRoomManager { /// Param [unMuteMembers] The list of members to be unmuted. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 解除禁言。 + /// + /// 仅聊天室所有者和管理员可调用此方法。 /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [unMuteMembers] 解除禁言的用户列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future unMuteChatRoomMembers( String roomId, List unMuteMembers, @@ -570,7 +677,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Transfers the chat room ownership. /// /// Only the chat room owner can call this method. @@ -580,7 +687,19 @@ class EMChatRoomManager { /// Param [newOwner] The ID of the new chat room owner. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 转移聊天室的所有权。 /// + /// 仅聊天室所有者可调用此方法。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [newOwner] 新的聊天室所有者 ID。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future changeOwner( String roomId, String newOwner, @@ -595,7 +714,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Adds a chat room admin. /// /// Only the chat room owner can call this method. @@ -605,7 +724,19 @@ class EMChatRoomManager { /// Param [admin] The ID of the chat room admin to be added. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 添加聊天室管理员。 /// + /// 仅聊天室所有者可调用此方法。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [admin] 要设置的管理员 ID。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future addChatRoomAdmin( String roomId, String admin, @@ -620,7 +751,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Removes privileges of a chat room admin. /// /// Param [roomId] The chat room ID. @@ -628,7 +759,17 @@ class EMChatRoomManager { /// Param [admin] The ID of admin whose privileges are to be removed. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end /// + /// ~chinese + /// 移除聊天室管理员权限。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [admin] 要移除管理员权限的 ID。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future removeChatRoomAdmin( String roomId, String admin, @@ -643,7 +784,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Gets the list of members who are muted in the chat room from the server. /// /// Only the chat room owner or admin can call this method. @@ -657,7 +798,23 @@ class EMChatRoomManager { /// **Return** The muted member list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 获取聊天室禁言列表。 + /// + /// 仅聊天室所有者和管理员可调用此方法。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [pageNum] 当前页码,从 1 开始。 /// + /// Param [pageSize] 每页返回的禁言成员数。 + /// + /// **Return** 返回的包含禁言成员 ID 列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> fetchChatRoomMuteList( String roomId, { int pageNum = 1, @@ -674,7 +831,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Removes the specified members from a chat room. /// /// Only the chat room owner or admin can call this method. @@ -684,7 +841,19 @@ class EMChatRoomManager { /// Param [members] The list of the members to be removed. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 将成员移出聊天室。 /// + /// 仅聊天室所有者和管理员可调用此方法。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [members] 要移出聊天室的用户列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future removeChatRoomMembers( String roomId, List members, @@ -699,7 +868,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Adds the specified members to the block list of the chat room. /// /// Only the chat room owner or admin can call this method. @@ -713,7 +882,24 @@ class EMChatRoomManager { /// Param [members] The list of members to be added to block list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end /// + /// ~chinese + /// 将成员添加到聊天室黑名单。 + /// + /// 仅聊天室所有者和管理员可调用此方法。 + /// + /// 对于添加到聊天室黑名单的成员,请注意以下几点: + /// 1. 成员添加到黑名单的同时,将被服务器移出聊天室。 + /// 2. 可通过 [EMChatRoomEventHandler.onRemovedFromChatRoom] 回调通知。 + /// 3. 添加到黑名单的成员禁止再次加入到聊天室。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [members] 要加入黑名单的成员列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future blockChatRoomMembers( String roomId, List members, @@ -728,7 +914,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Removes the specified members from the block list of the chat room. /// /// Only the chat room owner or admin can call this method. @@ -738,7 +924,19 @@ class EMChatRoomManager { /// Param [members] The list of members to be removed from the block list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 从聊天室黑名单中移除成员。 + /// + /// 仅聊天室所有者和管理员可调用此方法。 /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [members] 要移除黑名单的成员列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future unBlockChatRoomMembers( String roomId, List members, @@ -753,7 +951,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Gets the chat room block list with pagination. /// /// Only the chat room owner or admin can call this method. @@ -767,7 +965,23 @@ class EMChatRoomManager { /// **Return** The list of the blocked chat room members. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 以分页的形式获取聊天室黑名单列表。 + /// + /// 仅聊天室所有者和管理员可调用此方法。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [pageNum] 当前页码,从 1 开始。 + /// + /// Param [pageSize] 每页返回的黑名单中的用户数。 + /// + /// **Return** 返回聊天室黑名单列表。 /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> fetchChatRoomBlockList( String roomId, { int pageNum = 1, @@ -785,7 +999,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Updates the chat room announcement. /// /// Only the chat room owner or admin can call this method. @@ -795,7 +1009,19 @@ class EMChatRoomManager { /// Param [announcement] The announcement content. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 更新聊天室公告。 + /// + /// 仅聊天室所有者和管理员可调用此方法。 + /// + /// Param [roomId] 聊天室 ID。 /// + /// Param [announcement] 公告内容。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future updateChatRoomAnnouncement( String roomId, String announcement, @@ -810,7 +1036,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Gets the chat room announcement from the server. /// /// Param [roomId] The chat room ID. @@ -818,7 +1044,17 @@ class EMChatRoomManager { /// **Return** The chat room announcement. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 从服务器获取聊天室公告内容。 + /// + /// Param [roomId] 聊天室 ID。 /// + /// **Return** 聊天室公告。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future fetchChatRoomAnnouncement( String roomId, ) async { @@ -833,7 +1069,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Gets the allow list from the server. /// /// Only the chat room owner or admin can call this method. @@ -843,7 +1079,19 @@ class EMChatRoomManager { /// **Return** The chat room allow list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 从服务器获取白名单列表。 + /// + /// 仅聊天室所有者和管理员可调用此方法。 /// + /// Param [roomId] 聊天室 ID。 + /// + /// **Return** 聊天室白名单列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> fetchChatRoomAllowListFromServer(String roomId) async { Map req = {"roomId": roomId}; Map result = await _channel.invokeMethod( @@ -864,7 +1112,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Checks whether the member is on the allow list. /// /// Param [roomId] The chat room ID. @@ -873,7 +1121,18 @@ class EMChatRoomManager { /// - `true`: Yes; /// - `false`: No. /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 检查成员自己是否加入了白名单。 /// + /// Param [roomId] 聊天室 ID。 + /// + /// **Return** 返回是否在白名单中: + /// - `true`: 是; + /// - `false`: 否。 + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future isMemberInChatRoomAllowList(String roomId) async { Map req = {"roomId": roomId}; Map result = await _channel.invokeMethod( @@ -888,7 +1147,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Adds members to the allowlist. /// /// Only the chat room owner or admin can call this method. @@ -898,7 +1157,19 @@ class EMChatRoomManager { /// Param [members] The list of members to be added to the allow list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 将成员添加到白名单。 + /// + /// 仅聊天室所有者和管理员可调用此方法。 /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [members] 要加入白名单的成员列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future addMembersToChatRoomAllowList( String roomId, List members, @@ -919,7 +1190,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Removes members from the allow list. /// /// Only the chat room owner or admin can call this method. @@ -929,7 +1200,19 @@ class EMChatRoomManager { /// Param [members] The list of members to be removed from the allow list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 将成员从白名单移除。 /// + /// 仅聊天室所有者和管理员可调用此方法。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [members] 移除白名单的用户列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future removeMembersFromChatRoomAllowList( String roomId, List members, @@ -949,7 +1232,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Mutes all members. /// /// Only the chat room owner or admin can call this method. @@ -959,7 +1242,19 @@ class EMChatRoomManager { /// Param [roomId] The chat room ID. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 设置全员禁言。 /// + /// 仅聊天室所有者和管理员可调用此方法。 + /// + /// 聊天室所有者、管理员及加入白名单的用户不受影响。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future muteAllChatRoomMembers(String roomId) async { Map req = {"roomId": roomId}; Map result = await _channel.invokeMethod( @@ -973,7 +1268,7 @@ class EMChatRoomManager { } } - /// + /// ~english /// Unmutes all members. /// /// Only the chat room owner or admin can call this method. @@ -981,7 +1276,17 @@ class EMChatRoomManager { /// Param [roomId] The chat room ID. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end /// + /// ~chinese + /// 解除所有成员的禁言状态。 + /// + /// 仅聊天室所有者和管理员可调用此方法。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future unMuteAllChatRoomMembers(String roomId) async { Map req = {"roomId": roomId}; Map result = await _channel.invokeMethod( @@ -995,11 +1300,29 @@ class EMChatRoomManager { } } + /// ~english /// Gets the list of custom chat room attributes based on the attribute key list. + /// /// Param [roomId] The chat room ID. + /// /// Param [keys] The key list of attributes to get. If you set it as `null` or leave it empty, this method retrieves all custom attributes. + /// /// **Return** The chat room attributes in key-value pairs. + /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 根据属性键列表获取自定义聊天室属性的列表。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [keys] 要获取的属性的键列表。如果将其设置为“null”或留空,此方法将检索所有自定义属性。 + /// + /// **Return** 键值对应的聊天室属性。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future?> fetchChatRoomAttributes( String roomId, List? keys, @@ -1022,9 +1345,13 @@ class EMChatRoomManager { } } + /// ~english /// Sets custom chat room attributes. + /// /// Param [roomId] The chat room ID. + /// /// Param [attributes] The chat room attributes to add. The attributes are in key-value format. + /// /// Note: /// In a key-value pair, the key is the attribute name that can contain 128 characters at most; the value is the attribute value that cannot exceed 4096 characters. /// A chat room can have a maximum of 100 custom attributes and the total length of custom chat room attributes cannot exceed 10 GB for each app. Attribute keys support the following character sets: @@ -1034,9 +1361,30 @@ class EMChatRoomManager { /// * - "_", "-", "." /// /// Param [deleteWhenLeft] Whether to delete the chat room attributes set by the member when he or she exits the chat room. + /// /// Param [overwrite] Whether to overwrite the attributes with same key set by others. + /// /// **Return** `failureKeys map` is returned in key-value format, where the key is the attribute key and the value is the reason for the failure. + /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 设置自定义聊天室属性。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [attributes] 要添加的聊天室属性。属性采用键值格式。 + /// + /// Param [deleteWhenLeft] 退出聊天室时是否删除该成员设置的聊天室属性。 + /// + /// Param [overwrite] 是否覆盖其他人设置的相同键的属性。 + /// + /// **Return** ' failureKeys map '以键值格式返回,其中键是属性键,值是失败的原因。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// + /// ~end Future?> addAttributes( String roomId, { required Map attributes, @@ -1062,12 +1410,35 @@ class EMChatRoomManager { } } + /// ~english /// Removes custom chat room attributes. + /// /// Param [roomId] The chat room ID. + /// /// Param [keys] The keys of the custom chat room attributes to remove. + /// /// Param [force] Whether to remove the attributes with same key set by others. + /// /// **Return** `failureKeys map` is returned in key-value format, where the key is the attribute key and the value is the reason for the failure. + /// /// **Throws** A description of the exception. See [EMError]. + /// + /// ~end + /// + /// ~chinese + /// 删除自定义聊天室属性。 + /// + /// Param [roomId] 聊天室 ID。 + /// + /// Param [keys] 要删除的自定义聊天室属性的键。 + /// + /// Param [force] 是否删除其他人设置的键值相同的属性。 + /// + /// **Return** 'failureKeys map'以键值格式返回,其中键是属性键,值是失败的原因。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// + /// ~end Future?> removeAttributes( String roomId, { required List keys, @@ -1092,41 +1463,3 @@ class EMChatRoomManager { } } } - -extension ChatRoomManagerDeprecated on EMChatRoomManager { - /// - /// Registers a chat room manager listener. - /// - /// After registering the chat room manager listener, you can listen for events in [EMChatRoomManagerListener], for example, users joining and exiting the chat room, adding the specified member to the chat group mute list, updating the chat room allow list, and destroying the chat room. - /// - /// To stop listening for chat room manager, call [removeChatRoomManagerListener]. - /// - /// Param [listener] A chat room listener. See [EMChatRoomManagerListener]. - /// - @Deprecated("Use [EMChatRoomManager.addEventHandler] to instead") - void addChatRoomManagerListener(EMChatRoomManagerListener listener) { - _listeners.remove(listener); - _listeners.add(listener); - } - - /// - /// Removes a chat room manager listener. - /// This method removes the chat room manager listener registered with [addChatRoomManagerListener]. - /// - /// Param [listener] The chat room manager listener to be removed. - /// - @Deprecated("Use [EMChatRoomManager.removeEventHandler] to instead") - void removeChatRoomManagerListener(EMChatRoomManagerListener listener) { - if (_listeners.contains(listener)) { - _listeners.remove(listener); - } - } - - /// - /// Removes all chat room manager listener. - /// - @Deprecated("Use [clearEventHandlers] to instead") - void clearAllChatRoomManagerListeners() { - _listeners.clear(); - } -} diff --git a/lib/src/em_chat_thread_manager.dart b/lib/src/em_chat_thread_manager.dart index 9ba05fb6..04e6ea98 100644 --- a/lib/src/em_chat_thread_manager.dart +++ b/lib/src/em_chat_thread_manager.dart @@ -3,9 +3,13 @@ import 'package:flutter/services.dart'; import 'internal/inner_headers.dart'; -/// +/// ~english /// The chat thread manager class. +/// ~end /// +/// ~chinese +/// 子区管理类。 +/// ~end class EMChatThreadManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( @@ -13,8 +17,6 @@ class EMChatThreadManager { final Map _eventHandlesMap = {}; - final List _listeners = []; - EMChatThreadManager() { _channel.setMethodCallHandler((MethodCall call) async { Map? argMap = call.arguments; @@ -31,13 +33,21 @@ class EMChatThreadManager { }); } - /// + /// ~english /// Adds the chat thread event handler. After calling this method, you can handle for chat thread event when they arrive. /// /// Param [identifier] The custom handler identifier, is used to find the corresponding handler. /// /// Param [handler] The handle for chat thread event. See [EMChatThreadEventHandler]. + /// ~end + /// + /// ~chinese + /// 添加 Thread 事件监听。 /// + /// Param [identifier] 自定义事件 ID,用于查找事件监听。 + /// + /// Param [handler] 事件监听. 请见 [EMChatThreadEventHandler]. + /// ~end void addEventHandler( String identifier, EMChatThreadEventHandler handler, @@ -45,34 +55,52 @@ class EMChatThreadManager { _eventHandlesMap[identifier] = handler; } - /// + /// ~english /// Remove the chat thread event handler. /// /// Param [identifier] The custom handler identifier. + /// ~end + /// + /// ~chinese + /// 移除 Thread 事件。 /// + /// Param [identifier] 需要移除事件监听的 ID。 + /// ~end void removeEventHandler(String identifier) { _eventHandlesMap.remove(identifier); } - /// + /// ~english /// Get the chat thread event handler. /// /// Param [identifier] The custom handler identifier. /// /// **Return** The chat thread event handler. + /// ~end + /// + /// ~chinese + /// 获取指定 ID 的事件监听。 + /// + /// Param [identifier] 需要获取的事件监听 ID。 /// + /// **Return** Thread 事件监听。 + /// ~end EMChatThreadEventHandler? getEventHandler(String identifier) { return _eventHandlesMap[identifier]; } - /// + /// ~english /// Clear all chat thread event handlers. + /// ~end /// + /// ~chinese + /// 清除所有 Thread 监听。 + /// ~end void clearEventHandlers() { _eventHandlesMap.clear(); } - /// + /// ~english /// Get Chat Thread details from server. /// /// Param [chatThreadId] Chat Thread ID. @@ -80,7 +108,17 @@ class EMChatThreadManager { /// **Return** The chat thread object. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 从服务器获取子区详情。 /// + /// Param [chatThreadId] 子区 ID。 + /// + /// **Return** 若调用成功,返回子区详情;失败则抛出异常。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future fetchChatThread({ required String chatThreadId, }) async { @@ -98,7 +136,7 @@ class EMChatThreadManager { } } - /// + /// ~english /// Paging to get the list of Chat Threads that the current user has joined from the server /// /// Param [cursor] The initial value can be empty or empty string. @@ -108,7 +146,19 @@ class EMChatThreadManager { /// **Return** Returns the result of [EMCursorResult], including the cursor for getting data next time and the chat thread object list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 分页从服务器获取当前用户加入的子区列表。 + /// + /// Param [cursor] 开始获取数据的游标位置。首次调用方法时可以不传,按用户加入子区时间的倒序获取数据。 + /// + /// Param [limit] 每页期望返回的子区数。取值范围为 (1,50]。 /// + /// **Return** 若调用成功,返回子区列表;失败则抛出异常。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future> fetchJoinedChatThreads({ String? cursor, int limit = 20, @@ -129,7 +179,7 @@ class EMChatThreadManager { } } - /// + /// ~english /// Get the subareas under a group from the server /// /// Param [parentId] Parent ID, generally refers to group ID. @@ -141,7 +191,21 @@ class EMChatThreadManager { /// **Return** result of [EMCursorResult], including the cursor for getting data next time and the chat thread object list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 分页从服务器端获取指定群组的子区列表。 + /// + /// Param [parentId] 群组 ID。 + /// + /// Param [cursor] 开始取数据的游标位置。首次获取数据时可以不传,按子区创建时间的倒序获取数据。 + /// + /// Param [limit] 每页期望返回的子区数。取值范围为 (1,50]。 /// + /// **Return** 若调用成功,返回子区列表;失败则抛出异常。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future> fetchChatThreadsWithParentId({ required String parentId, String? cursor, @@ -166,7 +230,7 @@ class EMChatThreadManager { } } - /// + /// ~english /// Paging to get the list of Chat Threads that the current user has joined the specified group from the server。 /// /// Param [parentId] The session id of the upper level of the sub-area @@ -178,7 +242,21 @@ class EMChatThreadManager { /// **Return** The result of [EMCursorResult], including the cursor for getting data next time and the chat thread object list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 分页从服务器获取当前用户加入指定群组的子区列表。 + /// + /// Param [parentId] 群组 ID。 + /// + /// Param [cursor] 开始取数据的游标位置。首次调用方法时可以不传,按用户加入子区时间的倒序获取数据。 + /// + /// Param [limit] 每页期望返回的子区数。取值范围为 (1,50]。 + /// + /// **Return** 若调用成功,返回子区列表;失败则抛出异常。 /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future> fetchJoinedChatThreadsWithParentId({ required String parentId, String? cursor, @@ -203,7 +281,7 @@ class EMChatThreadManager { } } - /// + /// ~english /// Paging to get Chat Thread members. /// /// The members of the group to which Chat Thread belongs have permission. @@ -217,7 +295,24 @@ class EMChatThreadManager { /// **Return** The result of [EMCursorResult], including the cursor for getting data next time and the chat thread member list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 分页获取子区成员。 + /// + /// @note + /// 子区所属群组的所有成员均可调用该方法。 + /// + /// Param [chatThreadId] 子区 ID。 + /// + /// Param [cursor] 开始获取数据的游标位置,首次调用方法时传 `null` 或空字符串,按成员加入子区时间的正序获取数据。 + /// + /// Param [limit] 每页期望返回的成员数。取值范围为 (1,50]。 /// + /// **Return** 若调用成功,返回子区成员列表;失败则抛出异常。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future> fetchChatThreadMembers({ required String chatThreadId, String? cursor, @@ -246,7 +341,7 @@ class EMChatThreadManager { } } - /// + /// ~english /// Get the latest news of the specified Chat Thread list from the server. /// /// Param [chatThreadIds] Chat Thread id list. The list length is not greater than 20. @@ -254,7 +349,17 @@ class EMChatThreadManager { /// **Return** returns a Map collection, the key is the chat thread ID, and the value is the latest message object of the chat thread. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 从服务器批量获取指定子区中的最新一条消息。 /// + /// Param [chatThreadIds] 要查询的子区 ID 列表,每次最多可传 20 个子区。 + /// + /// **Return** 若调用成功,返回子区的最新一条消息列表;失败则抛出异常。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future> fetchLatestMessageWithChatThreads({ required List chatThreadIds, }) async { @@ -283,7 +388,7 @@ class EMChatThreadManager { } } - /// + /// ~english /// Remove member from Chat Thread. /// /// Param [memberId] The ID of the member that was removed from Chat Thread. @@ -291,7 +396,22 @@ class EMChatThreadManager { /// Param [chatThreadId] Chat Thread ID. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end /// + /// ~chinese + /// 移除子区成员。 + /// + /// @note + /// 只有子区所属群主、群管理员及子区创建者可调用该方法。 + /// + /// 被移出的成员会收到 [EMChatThreadEventHandler.onUserKickOutOfChatThread] 回调。 + /// + /// Param [memberId] 被移出子区的成员的用户 ID。 + /// + /// Param [chatThreadId] 子区 ID。 + /// + /// **Throws** A description of the exception. See [EMError]. + /// ~end Future removeMemberFromChatThread({ required String memberId, required String chatThreadId, @@ -311,19 +431,34 @@ class EMChatThreadManager { } } - /// + /// ~english /// Change Chat Thread name. /// /// The group owner, group administrator and Thread creator have permission. /// After modifying chat thread name, members of the organization (group) to which chat thread belongs will receive the update notification event. - /// You can set [EMChatThreadEvent] to listen on the event. + /// You can set [EMChatThreadEventHandler.onChatThreadUpdate] to listen on the event. /// /// Param [chatThreadId] Chat Thread ID. /// /// Param [newName] New Chat Thread name. No more than 64 characters in length. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 修改子区名称。 + /// + /// @note + /// 只有子区所属群主、群管理员及子区创建者可调用该方法。 + /// + /// 子区所属群组的所有成员均会收到 [EMChatThreadEventHandler.onChatThreadUpdate]。 /// + /// Param [chatThreadId] 子区 ID。 + /// + /// Param [newName] 子区的新名称。长度不超过 64 个字符。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future updateChatThreadName({ required String chatThreadId, required String newName, @@ -343,7 +478,7 @@ class EMChatThreadManager { } } - /// + /// ~english /// Create Chat Thread. /// /// Group members have permission. @@ -364,7 +499,29 @@ class EMChatThreadManager { /// **Return** EMChatThread object /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 创建子区。 + /// + /// @note + /// 所有群成员都可以调用。 + /// 子区创建成功后,会出现如下情况: + /// + /// - 单设备登录时,子区所属群组的所有成员均会收到 [EMChatThreadEventHandler.onChatThreadCreate] 。 + /// + /// - 多端多设备登录时,各设备会收到 [EMMultiDeviceEventHandler.onChatThreadEvent] 回调。 + /// + /// Param [name] 要创建的子区的名称。长度不超过 64 个字符。 + /// + /// Param [messageId] 父消息 ID。 /// + /// Param [parentId] 群组 ID。 + /// + /// **Return** 调用成功时,返回创建的子区对象;失败则抛出异常。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future createChatThread({ required String name, required String messageId, @@ -387,7 +544,7 @@ class EMChatThreadManager { } } - /// + /// ~english /// Join Chat Thread. /// /// Group members have permission. @@ -403,7 +560,22 @@ class EMChatThreadManager { /// **Return** The joined chat thread object; /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 加入子区。 + /// + /// @note + /// 子区所属群组的所有成员均可调用该方法。 + /// + /// 加入成功后,多端多设备登录情况下,其他设备会收到 [EMMultiDeviceEventHandler.onChatThreadEvent],Event 的值为 [EMMultiDevicesEvent.CHAT_THREAD_JOIN]。 /// + /// Param [chatThreadId] 子区 ID。 + /// + /// **Return** 若调用成功,返回子区详情 [EMChatThread],详情中不含成员数量;失败则抛出异常。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future joinChatThread({ required String chatThreadId, }) async { @@ -422,7 +594,7 @@ class EMChatThreadManager { } } - /// + /// ~english /// Leave Chat Thread. /// /// The operation is available to Chat Thread members. @@ -434,7 +606,19 @@ class EMChatThreadManager { /// Param [chatThreadId] Chat Thread ID. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 退出子区。 + /// + /// @note + /// 子区中的所有成员均可调用该方法。 + /// 多端多设备登录情况下,其他设备会收到 [EMMultiDeviceEventHandler.onChatThreadEvent] 回调,Event 的值为 [EMMultiDevicesEvent.CHAT_THREAD_LEAVE]。 + /// + /// Param [chatThreadId] 要退出的子区 ID。 /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future leaveChatThread({ required String chatThreadId, }) async { @@ -452,7 +636,7 @@ class EMChatThreadManager { } } - /// + /// ~english /// Disband Chat Thread. /// /// Group owner and group administrator to which the Chat Thread belongs have permission. @@ -467,7 +651,20 @@ class EMChatThreadManager { /// Param [chatThreadId] Chat Thread ID. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 解散子区。 + /// + /// @note + /// 只有子区所属群组的群主及管理员可调用该方法。 + /// 单设备登录时,子区所在群的所有成员均会收到 [EMChatThreadEventHandler.onChatThreadDestroy] 。 + /// 多端多设备登录时,其他设备会收到 [EMMultiDeviceEventHandler.onChatThreadEvent] 回调,Event 的值为 [EMMultiDevicesEvent.CHAT_THREAD_DESTROY]。 + /// + /// Param [chatThreadId] 子区 ID。 /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future destroyChatThread({ required String chatThreadId, }) async { @@ -489,8 +686,8 @@ class EMChatThreadManager { if (event == null) { return; } - _listeners.forEach((element) { - element.onChatThreadCreate.call(EMChatThreadEvent.fromJson(event)); + _eventHandlesMap.values.forEach((element) { + element.onChatThreadCreate?.call(EMChatThreadEvent.fromJson(event)); }); } @@ -498,8 +695,8 @@ class EMChatThreadManager { if (event == null) { return; } - _listeners.forEach((element) { - element.onChatThreadUpdate.call(EMChatThreadEvent.fromJson(event)); + _eventHandlesMap.values.forEach((element) { + element.onChatThreadUpdate?.call(EMChatThreadEvent.fromJson(event)); }); } @@ -507,8 +704,8 @@ class EMChatThreadManager { if (event == null) { return; } - _listeners.forEach((element) { - element.onChatThreadDestroy.call(EMChatThreadEvent.fromJson(event)); + _eventHandlesMap.values.forEach((element) { + element.onChatThreadDestroy?.call(EMChatThreadEvent.fromJson(event)); }); } @@ -522,43 +719,5 @@ class EMChatThreadManager { EMChatThreadEvent.fromJson(event), ); }); - - // deprecated(3.9.5) - _listeners.forEach((element) { - element.onUserKickOutOfChatThread.call(EMChatThreadEvent.fromJson(event)); - }); - } -} - -extension ChatThreadManagerDeprecated on EMChatThreadManager { - /// - /// Adds the chat thread manager listener. After calling this method, you can listen for new chat threads when they arrive. - /// - /// Param [listener] The chat thread manager listener that listens for new chat thread. See [EMChatThreadManagerListener]. - /// - @Deprecated("Use addEventHandler to instead") - void addChatThreadManagerListener(EMChatThreadManagerListener listener) { - _listeners.remove(listener); - _listeners.add(listener); - } - - /// - /// Removes the chat thread listener. - /// - /// After adding a chat thread manager listener, you can remove this listener if you do not want to listen for it. - /// - /// Param [listener] The chat thread listener to be removed. See [EMChatThreadManagerListener]. - /// - @Deprecated("Use [removeEventHandler] to instead") - void removeChatThreadManagerListener(EMChatThreadManagerListener listener) { - _listeners.remove(listener); - } - - /// - /// Removes all chat thread listeners. - /// - @Deprecated("Use [clearEventHandlers] to instead") - void clearAllChatThreadManagerListeners() { - _listeners.clear(); } } diff --git a/lib/src/em_client.dart b/lib/src/em_client.dart index 25187ed9..dc925c3c 100644 --- a/lib/src/em_client.dart +++ b/lib/src/em_client.dart @@ -5,9 +5,14 @@ import 'dart:async'; import 'package:flutter/services.dart'; import 'internal/inner_headers.dart'; +/// ~english +/// The EMClient class, which is the entry point of the Chat SDK. +/// With this class, you can log in, log out, and access other functionalities such as group and chatroom. +/// ~end /// -/// The EMClient class, which is the entry point of the Chat SDK. With this class, you can log in, log out, and access other functionalities such as group and chatroom. -/// +/// ~chinese +/// 该类是 Chat SDK 的入口,负责登录、退出及连接管理等,由此可以获得其他模块的入口。 +/// ~end class EMClient { static EMClient? _instance; final EMChatManager _chatManager = EMChatManager(); @@ -23,30 +28,49 @@ class EMClient { final Map _connectionEventHandler = {}; final Map _multiDeviceEventHandler = {}; - final List _connectionListeners = []; - final List _multiDeviceListeners = []; - @deprecated - final List _customListeners = []; // ignore: unused_field EMProgressManager? _progressManager; EMOptions? _options; + /// ~english /// Gets the configurations. + /// ~end + /// + /// ~chinese + /// 获取配置信息。 + /// ~end EMOptions? get options => _options; String? _currentUserId; + /// ~english + /// Obtain instance. + /// ~end + /// + /// ~chinese + /// 获取SDK实例 + /// ~end static EMClient get getInstance => _instance ??= EMClient._internal(); - /// + /// ~english /// Set a custom event handle to receive data from iOS or Android devices. /// /// Param [customEventHandler] The custom event handler. + /// ~end /// + /// ~chinese + /// 设置一个自定义事件句柄来接收来自iOS或Android设备的数据。 + /// ~end void Function(Map map)? customEventHandler; - /// Gets the current logged-in username. + /// ~english + /// Gets the current logged-in userId. + /// ~end + /// + /// ~chinese + /// 当前登录用户id + /// ~end String? get currentUserId => _currentUserId; EMClient._internal() { @@ -91,13 +115,21 @@ class EMClient { }); } - /// + /// ~english /// Adds the connection event handler. After calling this method, you can handle for new room event when they arrive. /// /// Param [identifier] The custom handler identifier, is used to find the corresponding handler. /// /// Param [handler] The handler for connection event. See [EMConnectionEventHandler]. + /// ~end /// + /// ~chinese + /// 添加连接状态监听事件。 + /// + /// Param [identifier] 监听事件对应 ID。 + /// + /// Param [handler] 监听的事件。 请见 [EMConnectionEventHandler]。 + /// ~end void addConnectionEventHandler( String identifier, EMConnectionEventHandler handler, @@ -105,40 +137,66 @@ class EMClient { _connectionEventHandler[identifier] = handler; } - /// + /// ~english /// Remove the connection event handler. /// /// Param [identifier] The custom handler identifier. + /// ~end /// + /// ~chinese + /// 移除连接状态监听事件。 + /// + /// Param [identifier] 监听事件对应 ID。 + /// ~end void removeConnectionEventHandler(String identifier) { _connectionEventHandler.remove(identifier); } - /// + /// ~english /// Get the connection event handler. /// /// Param [identifier] The custom handler identifier. /// /// **Return** The connection event handler. + /// ~end /// + /// ~chinese + /// 获取连接状态监听事件。 + /// + /// Param [identifier] 监听事件对应 ID。 + /// + /// **Return** 连接状态监听。 + /// ~end EMConnectionEventHandler? getConnectionEventHandler(String identifier) { return _connectionEventHandler[identifier]; } - /// + /// ~english /// Clear all connection event handlers. + /// ~end /// + /// ~chinese + /// 清除所以连接状态监听。 + /// ~end void clearConnectionEventHandles() { _connectionEventHandler.clear(); } - /// + /// ~english /// Adds the multi-device event handler. After calling this method, you can handle for new room event when they arrive. /// /// Param [identifier] The custom handler identifier, is used to find the corresponding handler. /// /// Param [handler] The handler multi-device event. See [EMMultiDeviceEventHandler]. + /// ~end + /// + /// ~chinese + /// 添加多设备事件监听。 + /// + /// Param [identifier] 多设备事件监听对应 ID。 /// + /// Param [handler] 多设备事件监听。 请见 [EMMultiDeviceEventHandler]。 + /// ~end void addMultiDeviceEventHandler( String identifier, EMMultiDeviceEventHandler handler, @@ -146,39 +204,64 @@ class EMClient { _multiDeviceEventHandler[identifier] = handler; } - /// + /// ~english /// Remove the multi-device event handler. /// /// Param [identifier] The custom handler identifier. + /// ~end + /// + /// ~chinese + /// 移除多设备事件监听。 /// + /// Param [identifier] 要移除多设备事件监听对应的 ID。 + /// ~end void removeMultiDeviceEventHandler(String identifier) { _multiDeviceEventHandler.remove(identifier); } - /// + /// ~english /// Get the multi-device event handler. /// /// Param [identifier] The custom handler identifier. /// /// **Return** The multi-device event handler. + /// ~end + /// + /// ~chinese + /// 获取多设备事件监听。 + /// + /// Param [identifier] 多设备事件监听对应的 ID。 /// + /// **Return** 多设备事件监听。 + /// ~end EMMultiDeviceEventHandler? getMultiDeviceEventHandler(String identifier) { return _multiDeviceEventHandler[identifier]; } - /// + /// ~english /// Clear all multi-device event handlers. + /// ~end /// + /// ~chinese + /// 清除所有多设备事件监听。 + /// ~end void clearMultiDeviceEventHandles() { _multiDeviceEventHandler.clear(); } - /// + /// ~english /// Start contact and group, chatroom callback. /// /// Reference: /// Call this method when you ui is ready, then will receive [EMChatRoomEventHandler], [EMContactEventHandler], [EMGroupEventHandler] event. + /// ~end + /// + /// ~chinese + /// /// 开始回调通知。 /// + /// Reference: + /// 当UI准备好后调用,调用之后才能收到 [EMChatRoomEventHandler], [EMContactEventHandler], [EMGroupEventHandler] 监听。 + /// ~end Future startCallback() async { Map result = await ClientChannel.invokeMethod(ChatMethodKeys.startCallback); try { @@ -188,12 +271,20 @@ class EMClient { } } - /// + /// ~english /// Checks whether the SDK is connected to the chat server. /// /// **Return** the result whether the SDK is connected to the chat server. /// `true`: means that the SDK is connected to the chat server. /// `false`: means not. + /// ~end + /// + /// ~chinese + /// 检查 SDK 是否连接到 Chat 服务器。 + /// **Return** SDK 是否连接到 Chat 服务器。 + /// - `true`:是; + /// - `false`:否。 + /// ~end Future isConnected() async { Map result = await ClientChannel.invokeMethod(ChatMethodKeys.isConnected); try { @@ -204,7 +295,7 @@ class EMClient { } } - /// + /// ~english /// Checks whether the user has logged in before and did not log out. /// /// Reference: @@ -213,7 +304,15 @@ class EMClient { /// **Return** The result of whether the user has logged in before. /// `true`: means that the user has logged in before, /// `false`: means that the user has not login before or has called [logout] method. + /// ~end /// + /// ~chinese + /// 检查用户是否已登录 Chat 服务。 + /// + /// **Return** 用户是否已经登录 Chat 服务。 + /// - `true`:是; + /// - `false`:否。 + /// ~end Future isLoginBefore() async { Map result = await ClientChannel.invokeMethod(ChatMethodKeys.isLoggedInBefore); @@ -225,11 +324,17 @@ class EMClient { } } - /// + /// ~english /// Gets the current login user ID. /// /// **Return** The current login user ID. + /// ~end + /// + /// ~chinese + /// 获取当前登录的用户 ID。 /// + /// **Return** 当前登录的用户 ID。 + /// ~end Future getCurrentUserId() async { Map result = await ClientChannel.invokeMethod(ChatMethodKeys.getCurrentUser); @@ -247,7 +352,15 @@ class EMClient { } } + /// ~english /// Gets the token of the current logged-in user. + /// ~end + /// + /// ~chinese + /// 获取当前登录账号的 Token。 + /// + /// **Return** 当前登录账号的 Token。 + /// ~end Future getAccessToken() async { Map result = await ClientChannel.invokeMethod(ChatMethodKeys.getToken); try { @@ -258,19 +371,25 @@ class EMClient { } } - /// + /// ~english /// Initializes the SDK. /// /// Param [options] The configurations: [EMOptions]. Ensure that you set this parameter. + /// ~end + /// + /// ~chinese + /// 初始化 SDK。 /// + /// Param [options] 配置,不可为空。 + /// ~end Future init(EMOptions options) async { _options = options; EMLog.v('init: $options'); await ClientChannel.invokeMethod(ChatMethodKeys.init, options.toJson()); - _currentUserId = await getCurrentUsername(); + _currentUserId = await getCurrentUserId(); } - /// + /// ~english /// Register a new user. /// /// Param [userId] The userId. The maximum length is 64 characters. Ensure that you set this parameter. @@ -281,7 +400,17 @@ class EMClient { /// Param [password] The password. The maximum length is 64 characters. Ensure that you set this parameter. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 创建账号。 + /// + /// Param [userId] 用户 ID,长度不超过 64 个字符。请确保你对该参数设值。支持的字符包括英文字母(a-z),数字(0-9),下划线(_),英文横线(-),英文句号(.)。该参数不区分大小写,大写字母会被自动转为小写字母。如果使用正则表达式设置该参数,则可以将表达式写为:^[a-zA-Z0-9_-]+$。请确保同一个 app 下,userId 唯一;`userId` 用户 ID 是会公开的信息,请勿使用 UUID、邮箱地址、手机号等敏感信息。 /// + /// Param [password] 密码,长度不超过 64 个字符。请确保你对该参数设值。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future createAccount(String userId, String password) async { EMLog.v('create account: $userId : $password'); Map req = {'username': userId, 'password': password}; @@ -294,7 +423,7 @@ class EMClient { } } - /// + /// ~english /// An app user logs in to the chat server with a password or token. /// /// Param [userId] The username. @@ -306,7 +435,21 @@ class EMClient { /// `false`: Log in with token. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 使用密码或 Token 登录服务器。 + /// + /// Param [userId] 用户 ID。 + /// + /// Param [pwdOrToken] 登录密码或 Token。 /// + /// Param [isPassword] 是否用密码登录。 + /// - (默认)`true`:是。 + /// - `false`:否。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future login(String userId, String pwdOrToken, [bool isPassword = true]) async { EMLog.v('login: $userId : $pwdOrToken, isPassword: $isPassword'); @@ -324,7 +467,7 @@ class EMClient { } } - /// + /// ~english /// An app user logs in to the chat server by username and Agora token. This method supports automatic login. /// /// See also: Another method to login to chat server is to login with user ID and token, See [login]. @@ -334,7 +477,20 @@ class EMClient { /// Param [agoraToken] The Agora token. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 用声网 Token 登录服务器,该方法支持自动登录。 + /// + /// **Note** + /// 通过 token 登录服务器的方法见 {@link #login(String, String, bool)}。 + /// + /// Param [userId] 用户 ID。 + /// + /// Param [agoraToken] 声网 Token。 /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future loginWithAgoraToken(String userId, String agoraToken) async { Map req = { "username": userId, @@ -351,7 +507,7 @@ class EMClient { } } - /// + /// ~english /// Renews the Agora token. /// /// If a user is logged in with an Agora token, when the token expires, you need to call this method to update the token. @@ -359,7 +515,15 @@ class EMClient { /// Param [agoraToken] The new Agora token. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 当用户在声网 token 登录状态时,且在 [EMConnectionEventHandler.onTokenWillExpire] 实现类中收到 token 即将过期事件的回调通知可以调用这个 API 来更新 token,避免因 token 失效产生的未知问题。 + /// + /// Param [agoraToken] 新声网 Token. /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future renewAgoraToken(String agoraToken) async { Map req = {"agora_token": agoraToken}; @@ -372,7 +536,7 @@ class EMClient { } } - /// + /// ~english /// An app user logs out. /// /// Param [unbindDeviceToken] Whether to unbind the token when logout. @@ -381,7 +545,17 @@ class EMClient { /// `false` No. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 退出登录。 /// + /// Param [unbindDeviceToken] 退出时是否解绑设备 token。 + /// - (默认)`true`:是。 + /// - `false`:否。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future logout([ bool unbindDeviceToken = true, ]) async { @@ -396,7 +570,7 @@ class EMClient { } } - /// + /// ~english /// Updates the App Key, which is the unique identifier to access Agora Chat. /// /// You can retrieve the new App Key from Agora Console. @@ -406,7 +580,18 @@ class EMClient { /// Param [newAppKey] The App Key. Ensure that you set this parameter. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 修改 App Key。 + /// + /// @note + /// 只有在未登录状态才能修改 App Key。 + /// + /// Param [newAppKey] App Key,请确保设置该参数。 /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future changeAppKey({required String newAppKey}) async { EMLog.v('changeAppKey: $newAppKey'); Map req = {'appKey': newAppKey}; @@ -420,7 +605,7 @@ class EMClient { } } - /// + /// ~english /// Compresses the debug log into a gzip archive. /// /// Best practice is to delete this debug archive as soon as it is no longer used. @@ -428,7 +613,15 @@ class EMClient { /// **Return** The path of the compressed gzip file. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 压缩 log 文件,并返回压缩后的文件路径。强烈建议方法完成之后删除该压缩文件。 + /// + /// **Return** 压缩后的 log 文件路径。 /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future compressLogs() async { EMLog.v('compressLogs:'); Map result = await ClientChannel.invokeMethod(ChatMethodKeys.compressLogs); @@ -440,7 +633,7 @@ class EMClient { } } - /// + /// ~english /// Gets all the information about the logged in devices under the specified account. /// /// Param [userId] The username you want to get the device information. @@ -450,7 +643,19 @@ class EMClient { /// **Return** TThe list of the logged-in devices. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 获取指定账号下登录的在线设备列表。 /// + /// Param [userId] 用户 ID。 + /// + /// Param [password] 密码。 + /// + /// **Return** 获取到到设备列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> getLoggedInDevicesFromServer( {required String userId, required String password}) async { EMLog.v('getLoggedInDevicesFromServer: $userId, "******"'); @@ -469,7 +674,7 @@ class EMClient { } } - /// + /// ~english /// Forces the specified account to log out from the specified device. /// /// Param [userId] The account you want to force logout. @@ -479,7 +684,19 @@ class EMClient { /// Param [resource] The device ID. For how to fetch the device ID, See [EMDeviceInfo.resource]. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 在指定账号下,根据设备 ID,将指定设备下线,设备 ID:{@link EMDeviceInfo#resource}。 + /// + /// Param [userId] 用户 ID。 /// + /// Param [password] 密码。 + /// + /// Param [resource] 设备 ID,详见 {@link EMDeviceInfo#resource}。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future kickDevice( {required String userId, required String password, @@ -496,7 +713,7 @@ class EMClient { } } - /// + /// ~english /// Kicks out all the devices logged in under the specified account. /// /// Param [userId] The account you want to log out from all the devices. @@ -504,7 +721,17 @@ class EMClient { /// Param [password] The password. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 将指定用户 ID 下的所有设备都踢下线。 + /// + /// Param [userId] 用户 ID。 /// + /// Param [password] 密码。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future kickAllDevices( {required String userId, required String password}) async { EMLog.v('kickAllDevices: $userId, "******"'); @@ -522,108 +749,66 @@ class EMClient { for (var handler in _connectionEventHandler.values) { handler.onConnected?.call(); } - - for (var listener in _connectionListeners) { - listener.onConnected(); - } } Future _onDisconnected() async { for (var handler in _connectionEventHandler.values) { handler.onDisconnected?.call(); } - - for (var listener in _connectionListeners) { - listener.onDisconnected(); - } } Future _onUserDidLoginFromOtherDevice() async { for (var handler in _connectionEventHandler.values) { handler.onUserDidLoginFromOtherDevice?.call(); } - - for (var listener in _connectionListeners) { - listener.onUserDidLoginFromOtherDevice(); - } } Future _onUserDidRemoveFromServer() async { for (var handler in _connectionEventHandler.values) { handler.onUserDidRemoveFromServer?.call(); } - - for (var listener in _connectionListeners) { - listener.onUserDidRemoveFromServer(); - } } Future _onUserDidForbidByServer() async { for (var handler in _connectionEventHandler.values) { handler.onUserDidForbidByServer?.call(); } - - for (var listener in _connectionListeners) { - listener.onUserDidForbidByServer(); - } } Future _onUserDidChangePassword() async { for (var handler in _connectionEventHandler.values) { handler.onUserDidChangePassword?.call(); } - - for (var listener in _connectionListeners) { - listener.onUserDidChangePassword(); - } } Future _onUserDidLoginTooManyDevice() async { for (var handler in _connectionEventHandler.values) { handler.onUserDidLoginTooManyDevice?.call(); } - - for (var listener in _connectionListeners) { - listener.onUserDidLoginTooManyDevice(); - } } Future _onUserKickedByOtherDevice() async { for (var handler in _connectionEventHandler.values) { handler.onUserKickedByOtherDevice?.call(); } - for (var listener in _connectionListeners) { - listener.onUserKickedByOtherDevice(); - } } Future _onUserAuthenticationFailed() async { for (var handler in _connectionEventHandler.values) { handler.onDisconnected?.call(); } - for (var listener in _connectionListeners) { - listener.onDisconnected(); - } } void _onTokenWillExpire(Map? map) { for (var item in _connectionEventHandler.values) { item.onTokenWillExpire?.call(); } - - for (EMConnectionListener listener in _connectionListeners) { - listener.onTokenWillExpire(); - } } void _onTokenDidExpire(Map? map) { for (var item in _connectionEventHandler.values) { item.onTokenDidExpire?.call(); } - - for (EMConnectionListener listener in _connectionListeners) { - listener.onTokenDidExpire(); - } } Future _onMultiDeviceGroupEvent(Map map) async { @@ -634,10 +819,6 @@ class EMClient { for (var handler in _multiDeviceEventHandler.values) { handler.onGroupEvent?.call(event, target, users); } - - for (var listener in _multiDeviceListeners) { - listener.onGroupEvent(event, target, users); - } } Future _onMultiDeviceContactEvent(Map map) async { @@ -648,10 +829,6 @@ class EMClient { for (var handler in _multiDeviceEventHandler.values) { handler.onContactEvent?.call(event, target, ext); } - - for (var listener in _multiDeviceListeners) { - listener.onContactEvent(event, target, ext); - } } Future _onMultiDeviceThreadEvent(Map map) async { @@ -662,88 +839,128 @@ class EMClient { for (var handler in _multiDeviceEventHandler.values) { handler.onChatThreadEvent?.call(event, target, users); } - - for (var listener in _multiDeviceListeners) { - listener.onChatThreadEvent( - convertIntToEMMultiDevicesEvent(map['event'])!, - map['target'], - map['users'], - ); - } } void _onReceiveCustomData(Map map) { customEventHandler?.call(map); } - /// + /// ~english /// Gets the [EMChatManager] class. Make sure to call it after EMClient has been initialized. /// /// **Return** The `EMChatManager` class. + /// ~end + /// + /// ~chinese + /// 获取 [EMChatManager] 类。请确保在 EMClient 初始化之后调用本方法,详见 [EMClient.init]。 /// + /// **Return** `EMChatManager` 类。 + /// ~end EMChatManager get chatManager { return _chatManager; } - /// + /// ~english /// Gets the [EMContactManager] class. Make sure to call it after the EMClient has been initialized. /// /// **Return** The `EMContactManager` class. + /// ~end /// + /// ~chinese + /// 获取 [EMContactManager] 类。请确保在 EMClient 初始化之后调用本方法,详见 [EMClient.init]。 + /// + /// **Return** `EMContactManager` 类。 + /// ~end EMContactManager get contactManager { return _contactManager; } - /// + /// ~english /// Gets the [EMChatRoomManager] class. Make sure to call it after the EMClient has been initialized. /// /// **Return** The `EMChatRoomManager` class. + /// ~end /// + /// ~chinese + /// 获取 [EMChatRoomManager] 类。请确保在 EMClient 初始化之后调用本方法,详见 [EMClient.init]。 + /// + /// **Return** `EMChatRoomManager` 类。 + /// ~end EMChatRoomManager get chatRoomManager { return _chatRoomManager; } - /// + /// ~english /// Gets the [EMGroupManager] class. Make sure to call it after the EMClient has been initialized. /// /// **Return** The `EMGroupManager` class. + /// ~end + /// + /// ~chinese + /// 获取 [EMGroupManager] 类。请确保在 EMClient 初始化之后调用本方法,详见 [EMClient.init]。 /// + /// **Return** `EMGroupManager` 类。 + /// ~end EMGroupManager get groupManager { return _groupManager; } - /// + /// ~english /// Gets the [EMPushManager] class. Make sure to call it after the EMClient has been initialized. /// /// **Return** The `EMPushManager` class. + /// ~end + /// + /// ~chinese + /// 获取 [EMPushManager] 类。请确保在 EMClient 初始化之后调用本方法,详见 [EMClient.init]。 /// + /// **Return** `EMPushManager` 类。 + /// ~end EMPushManager get pushManager { return _pushManager; } - /// + /// ~english /// Gets the [EMUserInfoManager] class. Make sure to call it after the EMClient has been initialized. /// /// **Return** The `EMUserInfoManager` class. + /// ~end /// + /// ~chinese + /// 获取 [EMUserInfoManager] 类。请确保在 EMClient 初始化之后调用本方法,详见 [EMClient.init]。 + /// + /// **Return** `EMUserInfoManager` 类。 + /// ~end EMUserInfoManager get userInfoManager { return _userInfoManager; } - /// + /// ~english /// Gets the [EMChatThreadManager] class. Make sure to call it after the EMClient has been initialized. /// /// **Return** The `EMChatThreadManager` class. + /// ~end + /// + /// ~chinese + /// 获取 [EMChatThreadManager] 类。请确保在 EMClient 初始化之后调用本方法,详见 [EMClient.init]。 /// + /// **Return** `EMChatThreadManager` 类。 + /// ~end EMChatThreadManager get chatThreadManager { return _chatThreadManager; } - /// + /// ~english /// Gets the [EMPresenceManager] class. Make sure to call it after the EMClient has been initialized. /// /// **Return** The `EMPresenceManager` class. + /// ~end + /// + /// ~chinese + /// 获取 [EMPresenceManager] 类。请确保在 EMClient 初始化之后调用本方法,详见 [EMClient.init]。 /// + /// **Return** `EMPresenceManager` 类。 + /// ~end EMPresenceManager get presenceManager { return _presenceManager; } @@ -753,107 +970,3 @@ class EMClient { _userInfoManager.clearUserInfoCache(); } } - -extension EMClientDeprecated on EMClient { - /// - /// Adds the multi-device listener. - /// - /// Param [listener] The listener to be added: {EMMultiDeviceListener}. - /// - @Deprecated("Use [addMultiDeviceEventHandler] to instead") - void addMultiDeviceListener(EMMultiDeviceListener listener) { - _multiDeviceListeners.add(listener); - } - - /// - /// Removes the multi-device listener. - /// - /// Param [listener] The listener to be removed: {EMMultiDeviceListener}. - /// - @Deprecated("Use [removeMultiDeviceEventHandler] to instead") - void removeMultiDeviceListener(EMMultiDeviceListener listener) { - if (_multiDeviceListeners.contains(listener)) { - _multiDeviceListeners.remove(listener); - } - } - - /// - /// Removes all multi-device listener. - /// - @Deprecated("Use [clearMultiDeviceEventHandles] to instead") - void clearAllMultiDeviceListeners() { - _multiDeviceListeners.clear(); - } - - /// - /// Adds the connection listener of chat server. - /// - /// Param [listener] The chat server connection listener to be added. - /// - @Deprecated("Use [addConnectionEventHandler] to instead") - void addConnectionListener(EMConnectionListener listener) { - _connectionListeners.add(listener); - } - - /// - /// Removes the chat server connection listener. - /// - /// Param [listener] The chat server connection listener to be removed. - /// - @Deprecated("Use [removeConnectionEventHandler] to instead") - void removeConnectionListener(EMConnectionListener listener) { - if (_connectionListeners.contains(listener)) { - _connectionListeners.remove(listener); - } - } - - /// - /// Removes all chat server connection listeners. - /// - @Deprecated("Use [clearConnectionEventHandles] to instead") - void clearAllConnectionListeners() { - _connectionListeners.clear(); - } - - /// - /// Adds a custom listener to receive data from iOS or Android devices. - /// - /// Param [listener] The custom native listener to be added. - /// - @Deprecated("Use [customEventHandler] to instead") - void addCustomListener(EMCustomListener listener) { - _customListeners.add(listener); - } - - /// - /// Removes the custom listener. - /// - /// Param [listener] The custom native listener. - /// - @deprecated - void removeCustomListener(EMCustomListener listener) { - if (_customListeners.contains(listener)) { - _customListeners.remove(listener); - } - } - - /// Removes all custom listeners. - @deprecated - void clearAllCustomListeners() { - _customListeners.clear(); - } - - /// - /// Gets the current login user ID. - /// - /// **Return** The current login user ID. - /// - @Deprecated("Use [getCurrentUserId] to instead") - Future getCurrentUsername() async { - return getCurrentUserId(); - } - - /// Gets the current logged-in username. - @Deprecated("Use [currentUserId] to instead") - String? get currentUsername => _currentUserId; -} diff --git a/lib/src/em_contact_manager.dart b/lib/src/em_contact_manager.dart index d80757c3..39e1e60f 100644 --- a/lib/src/em_contact_manager.dart +++ b/lib/src/em_contact_manager.dart @@ -5,9 +5,9 @@ import 'dart:async'; import 'package:flutter/services.dart'; import 'internal/inner_headers.dart'; -/// +/// ~english /// The contact manager class, which manages chat contacts such as adding, deleting, retrieving, and modifying contacts. -/// +/// ~end class EMContactManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( @@ -26,8 +26,6 @@ class EMContactManager { final Map _eventHandlesMap = {}; - final List _listeners = []; - Future _onContactChanged(Map event) async { var type = event['type']; String username = event['username']; @@ -53,37 +51,15 @@ class EMContactManager { default: } }); - - // deprecated(3.9.5) - for (var listener in _listeners) { - switch (type) { - case EMContactChangeEvent.CONTACT_ADD: - listener.onContactAdded(username); - break; - case EMContactChangeEvent.CONTACT_DELETE: - listener.onContactDeleted(username); - break; - case EMContactChangeEvent.INVITED: - listener.onContactInvited(username, reason); - break; - case EMContactChangeEvent.INVITATION_ACCEPTED: - listener.onFriendRequestAccepted(username); - break; - case EMContactChangeEvent.INVITATION_DECLINED: - listener.onFriendRequestDeclined(username); - break; - default: - } - } } - /// + /// ~english /// Adds the contact event handler. After calling this method, you can handle for new contact event when they arrive. /// /// Param [identifier] The custom handler identifier, is used to find the corresponding handler. /// /// Param [handler] The handle for contact event. See [EMContactEventHandler]. - /// + /// ~end void addEventHandler( String identifier, EMContactEventHandler handler, @@ -91,34 +67,34 @@ class EMContactManager { _eventHandlesMap[identifier] = handler; } - /// + /// ~english /// Remove the contact event handler. /// /// Param [identifier] The custom handler identifier. - /// + /// ~end void removeEventHandler(String identifier) { _eventHandlesMap.remove(identifier); } - /// + /// ~english /// Get the contact event handler. /// /// Param [identifier] The custom handler identifier. /// /// **Return** The contact event handler. - /// + /// ~end EMContactEventHandler? getEventHandler(String identifier) { return _eventHandlesMap[identifier]; } - /// + /// ~english /// Clear all contact event handlers. /// void clearEventHandlers() { _eventHandlesMap.clear(); } - /// + /// ~english /// Adds a new contact. /// /// Param [userId] The user to be added. @@ -126,7 +102,7 @@ class EMContactManager { /// Param [reason] (optional) The invitation message. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future addContact( String userId, { String? reason, @@ -144,7 +120,7 @@ class EMContactManager { } } - /// + /// ~english /// Deletes a contact and all the related conversations. /// /// Param [username] The contact to be deleted. @@ -154,7 +130,7 @@ class EMContactManager { /// - `false`: (default) No. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future deleteContact( String username, { bool keepConversation = false, @@ -168,13 +144,13 @@ class EMContactManager { } } - /// + /// ~english /// Gets all the contacts from the server. /// /// **Return** The list of contacts. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> getAllContactsFromServer() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getAllContactsFromServer); @@ -192,13 +168,13 @@ class EMContactManager { } } - /// + /// ~english /// Gets the contact list from the local database. /// /// **Return** The contact list. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> getAllContactsFromDB() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getAllContactsFromDB); @@ -217,14 +193,14 @@ class EMContactManager { } } - /// + /// ~english /// Adds a user to the block list. /// You can send messages to the users on the block list, but cannot receive messages from them. /// /// Param [username] The user to be added to the block list. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future addUserToBlockList( String username, ) async { @@ -240,13 +216,13 @@ class EMContactManager { } } - /// + /// ~english /// Removes the contact from the block list. /// /// Param [username] The contact to be removed from the block list. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future removeUserFromBlockList(String username) async { Map req = {'username': username}; Map result = await _channel.invokeMethod( @@ -258,13 +234,13 @@ class EMContactManager { } } - /// + /// ~english /// Gets the block list from the server. /// /// **Return** The block list obtained from the server. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> getBlockListFromServer() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getBlockListFromServer); @@ -282,13 +258,13 @@ class EMContactManager { } } - /// + /// ~english /// Gets the block list from the local database. /// /// **Return** The block list obtained from the local database. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> getBlockListFromDB() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getBlockListFromDB); try { @@ -305,13 +281,13 @@ class EMContactManager { } } - /// + /// ~english /// Accepts a friend invitation。 /// /// Param [username] The user who sends the friend invitation. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future acceptInvitation(String username) async { Map req = {'username': username}; Map result = @@ -323,13 +299,13 @@ class EMContactManager { } } - /// + /// ~english /// Declines a friend invitation. /// /// Param [username] The user who sends the friend invitation. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future declineInvitation(String username) async { Map req = {'username': username}; Map result = @@ -341,13 +317,13 @@ class EMContactManager { } } - /// + /// ~english /// Gets the unique IDs of the current user on the other devices. The ID is in the format of username + "/" + resource. /// /// **Return** The list of unique IDs of users on the other devices if the method succeeds. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> getSelfIdsOnOtherPlatform() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getSelfIdsOnOtherPlatform); @@ -363,34 +339,3 @@ class EMContactManager { } } } - -extension EMContactManagerDeprecated on EMContactManager { - /// - /// Registers a new contact manager listener. - /// - /// Param [listener] The contact manager listener to be registered: [EMContactManagerListener]. - /// - @Deprecated("Use addEventHandler to instead") - void addContactManagerListener(EMContactManagerListener listener) { - _listeners.remove(listener); - _listeners.add(listener); - } - - /// - /// Removes the contact manager listener. - /// - /// Param [listener] The contact manager listener to be removed. - /// - @Deprecated("Use [removeEventHandler] to instead") - void removeContactManagerListener(EMContactManagerListener listener) { - _listeners.remove(listener); - } - - /// - /// Removes all contact manager listeners. - /// - @Deprecated("Use [clearEventHandlers] to instead") - void clearContactManagerListeners() { - _listeners.clear(); - } -} diff --git a/lib/src/em_group_manager.dart b/lib/src/em_group_manager.dart index 79097dbb..2b665361 100644 --- a/lib/src/em_group_manager.dart +++ b/lib/src/em_group_manager.dart @@ -5,19 +5,19 @@ import 'dart:async'; import 'package:flutter/services.dart'; import 'internal/inner_headers.dart'; -/// +/// ~english /// The group manager class, which manages group creation and deletion, user joining and exiting the group, etc. -/// +/// ~end class EMGroupManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( '$_channelPrefix/chat_group_manager', JSONMethodCodec()); final Map _eventHandlesMap = {}; - // deprecated(3.9.5) - final List _listeners = []; + /// ~english /// group shared file download callback. + /// ~end EMDownloadCallback? downloadCallback; /// @nodoc @@ -31,13 +31,13 @@ class EMGroupManager { }); } - /// + /// ~english /// Adds the group event handler. After calling this method, you can handle for new group event when they arrive. /// /// Param [identifier] The custom handler identifier, is used to find the corresponding handler. /// /// Param [handler] The handle for group event. See [EMGroupEventHandler]. - /// + /// ~end void addEventHandler( String identifier, EMGroupEventHandler handler, @@ -45,34 +45,34 @@ class EMGroupManager { _eventHandlesMap[identifier] = handler; } - /// + /// ~english /// Remove the group event handler. /// /// Param [identifier] The custom handler identifier. - /// + /// ~end void removeEventHandler(String identifier) { _eventHandlesMap.remove(identifier); } - /// + /// ~english /// Get the group event handler. /// /// Param [identifier] The custom handler identifier. /// /// **Return** The group event handler. - /// + /// ~end EMGroupEventHandler? getEventHandler(String identifier) { return _eventHandlesMap[identifier]; } - /// + /// ~english /// Clear all group event handlers. - /// + /// ~end void clearEventHandlers() { _eventHandlesMap.clear(); } - /// + /// ~english /// Gets the group instance from the cache by group ID. /// /// Param [groupId] The group ID. @@ -80,7 +80,7 @@ class EMGroupManager { /// **Return** The group instance. Returns null if the group does not exist. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future getGroupWithId(String groupId) async { Map req = {'groupId': groupId}; Map result = @@ -97,13 +97,13 @@ class EMGroupManager { } } - /// + /// ~english /// Gets all groups of the current user from the cache. /// /// **Return** The group list. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> getJoinedGroups() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getJoinedGroups); try { @@ -117,7 +117,7 @@ class EMGroupManager { } } - /// + /// ~english /// Gets all groups of the current user from the server. /// /// This method returns a group list which does not contain member information. If you want to update information of a group to include its member information, call [fetchGroupInfoFromServer]. @@ -133,7 +133,7 @@ class EMGroupManager { /// **Return** The list of groups that the current user joins. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> fetchJoinedGroupsFromServer({ int pageSize = 20, int pageNum = 0, @@ -159,7 +159,7 @@ class EMGroupManager { } } - /// + /// ~english /// Gets public groups from the server with pagination. /// /// Param [pageSize] The number of public groups per page. @@ -170,7 +170,7 @@ class EMGroupManager { /// If [EMCursorResult.cursor] is an empty string (""), all data is fetched. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> fetchPublicGroupsFromServer({ int pageSize = 200, String? cursor, @@ -191,7 +191,7 @@ class EMGroupManager { } } - /// + /// ~english /// Creates a group instance. /// /// After the group is created, the data in the cache and database will be updated and multiple devices will receive the notification event and update the group data to the cache and database. @@ -217,7 +217,7 @@ class EMGroupManager { /// **Return** The created group instance. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future createGroup({ String? groupName, String? desc, @@ -240,7 +240,7 @@ class EMGroupManager { } } - /// + /// ~english /// Gets the group information from the server. /// /// This method does not get member information. If member information is required, call [fetchMemberListFromServer]. @@ -252,7 +252,7 @@ class EMGroupManager { /// **Return** The group instance. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future fetchGroupInfoFromServer( String groupId, { bool fetchMembers = false, @@ -269,7 +269,7 @@ class EMGroupManager { } } - /// + /// ~english /// Gets the member list of the group with pagination. /// /// For example: @@ -288,7 +288,7 @@ class EMGroupManager { /// If [EMCursorResult.cursor] is an empty string (""), all data is fetched. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> fetchMemberListFromServer( String groupId, { int pageSize = 200, @@ -313,7 +313,7 @@ class EMGroupManager { } } - /// + /// ~english /// Gets the group block list from server with pagination. /// /// Only the group owner or admin can call this method. @@ -327,7 +327,7 @@ class EMGroupManager { /// **Return** The group block list. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> fetchBlockListFromServer( String groupId, { int pageSize = 200, @@ -346,7 +346,7 @@ class EMGroupManager { } } - /// + /// ~english /// Gets the mute list of the group from the server. /// /// Only the group owner or admin can call this method. @@ -360,7 +360,7 @@ class EMGroupManager { /// **Return** The group mute map, key is memberId and value is mute time. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> fetchMuteListFromServer( String groupId, { int pageSize = 200, @@ -386,7 +386,7 @@ class EMGroupManager { } } - /// + /// ~english /// Gets the allow list of the group from the server. /// /// Only the group owner or admin can call this method. @@ -396,7 +396,7 @@ class EMGroupManager { /// **Return** The allow list of the group. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> fetchAllowListFromServer(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod( @@ -415,7 +415,7 @@ class EMGroupManager { } } - /// + /// ~english /// Gets whether the member is on the allow list of the group. /// /// Param [groupId] The group ID. @@ -423,7 +423,7 @@ class EMGroupManager { /// **Return** A Boolean value to indicate whether the current user is on the allow list of the group; /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future isMemberInAllowListFromServer(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod( @@ -436,7 +436,7 @@ class EMGroupManager { } } - /// + /// ~english /// Gets the shared files of the group from the server. /// /// Param [groupId] The group ID. @@ -448,7 +448,7 @@ class EMGroupManager { /// **Return** The shared files. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> fetchGroupFileListFromServer( String groupId, { int pageSize = 200, @@ -469,7 +469,7 @@ class EMGroupManager { } } - /// + /// ~english /// Gets the group announcement from the server. /// /// Group members can call this method. @@ -479,7 +479,7 @@ class EMGroupManager { /// **Return** The group announcement. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future fetchAnnouncementFromServer(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod( @@ -492,7 +492,7 @@ class EMGroupManager { } } - /// + /// ~english /// Adds users to the group. /// /// Only the group owner or admin can call this method. @@ -504,7 +504,7 @@ class EMGroupManager { /// Param [welcome] The welcome message. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future addMembers( String groupId, List members, { @@ -520,7 +520,7 @@ class EMGroupManager { } } - /// + /// ~english /// Invites users to join the group. /// /// This method works only for groups with the style of [EMGroupStyle.PrivateOnlyOwnerInvite], [EMGroupStyle.PrivateMemberCanInvite], or [EMGroupStyle.PublicJoinNeedApproval]. @@ -534,7 +534,7 @@ class EMGroupManager { /// Param [reason] The invitation reason. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future inviterUser( String groupId, List members, { @@ -558,7 +558,7 @@ class EMGroupManager { } } - /// + /// ~english /// Removes a member from the group. /// /// Only the group owner or admin can call this method. @@ -568,7 +568,7 @@ class EMGroupManager { /// Param [members] The username of the member to be removed. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future removeMembers( String groupId, List members, @@ -582,7 +582,7 @@ class EMGroupManager { } } - /// + /// ~english /// Adds the user to the block list of the group. /// /// Users will be first removed from the group they have joined before being added to the block list of the group. The users on the group block list cannot join the group again. @@ -594,7 +594,7 @@ class EMGroupManager { /// Param [members] The list of users to be added to the block list. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future blockMembers( String groupId, List members, @@ -608,7 +608,7 @@ class EMGroupManager { } } - /// + /// ~english /// Removes users from the group block list. /// /// Only the group owner or admin can call this method. @@ -618,7 +618,7 @@ class EMGroupManager { /// Param [members] The users to be removed from the group block list. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future unblockMembers( String groupId, List members, @@ -633,7 +633,7 @@ class EMGroupManager { } } - /// + /// ~english /// Changes the group name. /// /// Only the group owner or admin can call this method. @@ -643,7 +643,7 @@ class EMGroupManager { /// Param [name] The new group name. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future changeGroupName( String groupId, String name, @@ -658,7 +658,7 @@ class EMGroupManager { } } - /// + /// ~english /// Changes the group description. /// /// Only the group owner or admin can call this method. @@ -668,7 +668,7 @@ class EMGroupManager { /// Param [desc] The new group description. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future changeGroupDescription( String groupId, String desc, @@ -683,13 +683,13 @@ class EMGroupManager { } } - /// + /// ~english /// Leaves a group. /// /// Param [groupId] The group ID. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future leaveGroup(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.leaveGroup, req); @@ -700,7 +700,7 @@ class EMGroupManager { } } - /// + /// ~english /// Destroys the group instance. /// /// Only the group owner can call this method. @@ -708,7 +708,7 @@ class EMGroupManager { /// Param [groupId] The group ID. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future destroyGroup(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.destroyGroup, req); @@ -719,7 +719,7 @@ class EMGroupManager { } } - /// + /// ~english /// Blocks group messages. /// /// The user that blocks group messages is still a group member, but can't receive group messages. @@ -727,7 +727,7 @@ class EMGroupManager { /// Param [groupId] The group ID. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future blockGroup(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.blockGroup, req); @@ -738,13 +738,13 @@ class EMGroupManager { } } - /// + /// ~english /// Unblocks group messages. /// /// Param [groupId] The group ID. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future unblockGroup(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.unblockGroup, req); @@ -755,7 +755,7 @@ class EMGroupManager { } } - /// + /// ~english /// Transfers the group ownership. /// /// Only the group owner can call this method. @@ -765,7 +765,7 @@ class EMGroupManager { /// Param [newOwner] The new owner ID. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future changeOwner( String groupId, String newOwner, @@ -780,7 +780,7 @@ class EMGroupManager { } } - /// + /// ~english /// Adds a group admin. /// /// Only the group owner can call this method and group admins cannot. @@ -790,7 +790,7 @@ class EMGroupManager { /// Param [memberId] The username of the admin to add. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future addAdmin( String groupId, String memberId, @@ -804,7 +804,7 @@ class EMGroupManager { } } - /// + /// ~english /// Removes a group admin. /// /// Only the group owner can call this method. @@ -814,7 +814,7 @@ class EMGroupManager { /// Param [adminId] The username of the admin to remove. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future removeAdmin( String groupId, String adminId, @@ -828,7 +828,7 @@ class EMGroupManager { } } - /// + /// ~english /// Mutes group members. /// /// Only the group owner or admin can call this method. @@ -840,7 +840,7 @@ class EMGroupManager { /// Param [duration] The mute duration in milliseconds. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future muteMembers( String groupId, List members, { @@ -855,7 +855,7 @@ class EMGroupManager { } } - /// + /// ~english /// Unmutes group members. /// /// Only the group owner or admin can call this method. @@ -865,7 +865,7 @@ class EMGroupManager { /// Param [members] The list of members to be muted. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future unMuteMembers( String groupId, List members, @@ -879,7 +879,7 @@ class EMGroupManager { } } - /// + /// ~english /// Mutes all members. /// /// Only the group owner or admin can call this method. @@ -887,7 +887,7 @@ class EMGroupManager { /// Param [groupId] The group ID. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future muteAllMembers(String groupId) async { Map req = {'groupId': groupId}; Map result = @@ -899,7 +899,7 @@ class EMGroupManager { } } - /// + /// ~english /// Unmutes all members. /// /// Only the group owner or admin can call this method. @@ -907,7 +907,7 @@ class EMGroupManager { /// Param [groupId] The group ID. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future unMuteAllMembers(String groupId) async { Map req = {'groupId': groupId}; Map result = @@ -919,7 +919,7 @@ class EMGroupManager { } } - /// + /// ~english /// Adds members to the allow list of the group. /// /// Only the group owner or admin can call this method. @@ -929,7 +929,7 @@ class EMGroupManager { /// Param [members] The members to be added to the allow list of the group. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future addAllowList( String groupId, List members, @@ -943,7 +943,7 @@ class EMGroupManager { } } - /// + /// ~english /// Removes members from the allow list of the group. /// /// Only the group owner or admin can call this method. @@ -953,7 +953,7 @@ class EMGroupManager { /// Param [members] The members to be removed from the allow list of the group. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future removeAllowList( String groupId, List members, @@ -968,7 +968,7 @@ class EMGroupManager { } } - /// + /// ~english /// Uploads the shared file to the group. /// /// When a shared file is uploaded, the upload progress callback will be triggered. @@ -978,7 +978,7 @@ class EMGroupManager { /// Param [filePath] The local path of the shared file. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future uploadGroupSharedFile( String groupId, String filePath, @@ -993,7 +993,7 @@ class EMGroupManager { } } - /// + /// ~english /// Downloads the shared file of the group. /// /// Note: The callback is only used for progress callback. @@ -1005,7 +1005,7 @@ class EMGroupManager { /// Param [savePath] The local path of the shared file. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future downloadGroupSharedFile({ required String groupId, required String fileId, @@ -1021,7 +1021,7 @@ class EMGroupManager { } } - /// + /// ~english /// Removes a shared file of the group. /// /// Group members can delete their own uploaded files. The group owner or admin can delete all shared files. @@ -1031,7 +1031,7 @@ class EMGroupManager { /// Param [fileId] The ID of the shared file. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future removeGroupSharedFile( String groupId, String fileId, @@ -1046,7 +1046,7 @@ class EMGroupManager { } } - /// + /// ~english /// Updates the group announcement. /// /// Only the group owner or admin can call this method. @@ -1056,7 +1056,7 @@ class EMGroupManager { /// Param [announcement] The group announcement. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future updateGroupAnnouncement( String groupId, String announcement, @@ -1071,7 +1071,7 @@ class EMGroupManager { } } - /// + /// ~english /// Updates the group extension field. /// /// Only the group owner or admin can call this method. @@ -1081,7 +1081,7 @@ class EMGroupManager { /// Param [extension] The group extension field. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future updateGroupExtension( String groupId, String extension, @@ -1096,7 +1096,7 @@ class EMGroupManager { } } - /// + /// ~english /// Joins a public group. /// /// For a group that requires no authentication,users can join it freely without obtaining permissions from the group owner. @@ -1105,7 +1105,7 @@ class EMGroupManager { /// Param [groupId] The group ID. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future joinPublicGroup( String groupId, ) async { @@ -1119,7 +1119,7 @@ class EMGroupManager { } } - /// + /// ~english /// Requests to join a group. /// /// This method works only for public groups requiring authentication, i.e., groups with the style of [EMGroupStyle.PublicJoinNeedApproval]. @@ -1129,7 +1129,7 @@ class EMGroupManager { /// Param [reason] The reason for requesting to join the group. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future requestToJoinPublicGroup( String groupId, { String? reason, @@ -1145,7 +1145,7 @@ class EMGroupManager { } } - /// + /// ~english /// Approves a group request. /// /// Only the group owner or admin can call this method. @@ -1155,7 +1155,7 @@ class EMGroupManager { /// Param [username] The username of the user who sends a request to join the group. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future acceptJoinApplication( String groupId, String username, @@ -1170,7 +1170,7 @@ class EMGroupManager { } } - /// + /// ~english /// Declines a group request. /// /// Only the group owner or admin can call this method. @@ -1182,7 +1182,7 @@ class EMGroupManager { /// Param [reason] The reason of declining. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future declineJoinApplication( String groupId, String username, { @@ -1200,7 +1200,7 @@ class EMGroupManager { } } - /// + /// ~english /// Accepts a group invitation. /// /// Param [groupId] The group ID. @@ -1210,7 +1210,7 @@ class EMGroupManager { /// **Return** The group instance which the user has accepted the invitation to join. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future acceptInvitation( String groupId, String inviter, @@ -1226,7 +1226,7 @@ class EMGroupManager { } } - /// + /// ~english /// Declines a group invitation. /// /// Param [groupId] The group ID. @@ -1236,7 +1236,7 @@ class EMGroupManager { /// Param [reason] The reason of declining. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future declineInvitation({ required String groupId, required String inviter, @@ -1396,183 +1396,5 @@ class EMGroupManager { break; } }); - - // deprecated (3.9.5) - for (var listener in _listeners) { - switch (type) { - case EMGroupChangeEvent.ON_INVITATION_RECEIVED: - String groupId = map['groupId']; - String? groupName = map['groupName']; - String inviter = map['inviter']; - String? reason = map['reason']; - listener.onInvitationReceivedFromGroup( - groupId, groupName, inviter, reason); - break; - case EMGroupChangeEvent.ON_INVITATION_ACCEPTED: - String groupId = map['groupId']; - String invitee = map['invitee']; - String? reason = map['reason']; - listener.onInvitationAcceptedFromGroup(groupId, invitee, reason); - break; - case EMGroupChangeEvent.ON_INVITATION_DECLINED: - String groupId = map['groupId']; - String invitee = map['invitee']; - String? reason = map['reason']; - listener.onInvitationDeclinedFromGroup(groupId, invitee, reason); - break; - case EMGroupChangeEvent.ON_AUTO_ACCEPT_INVITATION: - String groupId = map['groupId']; - String inviter = map['inviter']; - String? inviteMessage = map['inviteMessage']; - listener.onAutoAcceptInvitationFromGroup( - groupId, inviter, inviteMessage); - break; - case EMGroupChangeEvent.ON_USER_REMOVED: - String groupId = map['groupId']; - String? groupName = map['groupName']; - listener.onUserRemovedFromGroup(groupId, groupName); - break; - case EMGroupChangeEvent.ON_REQUEST_TO_JOIN_RECEIVED: - String groupId = map['groupId']; - String? groupName = map['groupName']; - String applicant = map['applicant']; - String? reason = map['reason']; - listener.onRequestToJoinReceivedFromGroup( - groupId, groupName, applicant, reason); - break; - case EMGroupChangeEvent.ON_REQUEST_TO_JOIN_DECLINED: - String groupId = map['groupId']; - String? groupName = map['groupName']; - String decliner = map['decliner']; - String? reason = map['reason']; - listener.onRequestToJoinDeclinedFromGroup( - groupId, groupName, decliner, reason); - break; - case EMGroupChangeEvent.ON_REQUEST_TO_JOIN_ACCEPTED: - String groupId = map['groupId']; - String? groupName = map['groupName']; - String accepter = map['accepter']; - listener.onRequestToJoinAcceptedFromGroup( - groupId, groupName, accepter); - break; - case EMGroupChangeEvent.ON_GROUP_DESTROYED: - String groupId = map['groupId']; - String? groupName = map['groupName']; - listener.onGroupDestroyed(groupId, groupName); - break; - case EMGroupChangeEvent.ON_MUTE_LIST_ADDED: - String groupId = map['groupId']; - List mutes = List.from(map['mutes'] ?? []); - int? muteExpire = map['muteExpire']; - listener.onMuteListAddedFromGroup(groupId, mutes, muteExpire); - break; - case EMGroupChangeEvent.ON_MUTE_LIST_REMOVED: - String groupId = map['groupId']; - List mutes = List.from(map['mutes'] ?? []); - listener.onMuteListRemovedFromGroup(groupId, mutes); - break; - case EMGroupChangeEvent.ON_ADMIN_ADDED: - String groupId = map['groupId']; - String administrator = map['administrator']; - listener.onAdminAddedFromGroup(groupId, administrator); - break; - case EMGroupChangeEvent.ON_ADMIN_REMOVED: - String groupId = map['groupId']; - String administrator = map['administrator']; - listener.onAdminRemovedFromGroup(groupId, administrator); - break; - case EMGroupChangeEvent.ON_OWNER_CHANGED: - String groupId = map['groupId']; - String newOwner = map['newOwner']; - String oldOwner = map['oldOwner']; - listener.onOwnerChangedFromGroup(groupId, newOwner, oldOwner); - break; - case EMGroupChangeEvent.ON_MEMBER_JOINED: - String groupId = map['groupId']; - String member = map['member']; - listener.onMemberJoinedFromGroup(groupId, member); - break; - case EMGroupChangeEvent.ON_MEMBER_EXITED: - String groupId = map['groupId']; - String member = map['member']; - listener.onMemberExitedFromGroup(groupId, member); - break; - case EMGroupChangeEvent.ON_ANNOUNCEMENT_CHANGED: - String groupId = map['groupId']; - String announcement = map['announcement']; - listener.onAnnouncementChangedFromGroup(groupId, announcement); - break; - case EMGroupChangeEvent.ON_SHARED_FILE_ADDED: - String groupId = map['groupId']; - EMGroupSharedFile sharedFile = - EMGroupSharedFile.fromJson(map['sharedFile']); - listener.onSharedFileAddedFromGroup(groupId, sharedFile); - break; - case EMGroupChangeEvent.ON_SHARED_FILE__DELETED: - String groupId = map['groupId']; - String fileId = map['fileId']; - listener.onSharedFileDeletedFromGroup(groupId, fileId); - break; - case EMGroupChangeEvent.ON_WHITE_LIST_ADDED: - String groupId = map["groupId"]; - List members = List.from(map['whitelist'] ?? []); - listener.onAllowListAddedFromGroup(groupId, members); - break; - case EMGroupChangeEvent.ON_WHITE_LIST_REMOVED: - String groupId = map["groupId"]; - List members = List.from(map['whitelist'] ?? []); - listener.onAllowListRemovedFromGroup(groupId, members); - break; - case EMGroupChangeEvent.ON_ALL_MEMBER_MUTE_STATE_CHANGED: - String groupId = map["groupId"]; - bool isAllMuted = map["isMuted"] as bool; - listener.onAllGroupMemberMuteStateChanged(groupId, isAllMuted); - break; - case EMGroupChangeEvent.ON_SPECIFICATION_DID_UPDATE: - EMGroup group = EMGroup.fromJson(map["group"]); - listener.onSpecificationDidUpdate(group); - break; - case EMGroupChangeEvent.ON_STATE_CHANGED: - String groupId = map["groupId"]; - bool isDisable = map["isDisable"] as bool; - listener.onDisableChange(groupId, isDisable); - break; - } - } - } -} - -extension EMGroupManagerDeprecated on EMGroupManager { - /// - /// Registers a group manager listener. - /// - /// The registered listener needs to be used together with [removeGroupManagerListener]. - /// - /// Param [listener] The group manager listener to be registered. - /// - @Deprecated("Use addEventHandler to instead") - void addGroupManagerListener(EMGroupManagerListener listener) { - _listeners.remove(listener); - _listeners.add(listener); - } - - /// - /// Removes a group manager listener. - /// - /// This method removes a group manager listener registered with [addGroupManagerListener]. - /// - /// Param [listener] The group manager listener to be removed. - /// - @Deprecated("Use [removeEventHandler] to instead") - void removeGroupManagerListener(EMGroupManagerListener listener) { - _listeners.remove(listener); - } - - /// - /// Removes all group manager listener. - /// - @Deprecated("Use [clearEventHandlers] to instead") - void clearAllGroupManagerListeners() { - _listeners.clear(); } } diff --git a/lib/src/em_listeners.dart b/lib/src/em_listeners.dart deleted file mode 100644 index 83090475..00000000 --- a/lib/src/em_listeners.dart +++ /dev/null @@ -1,790 +0,0 @@ -import 'internal/inner_headers.dart'; - -/// -/// The chat connection listener. -/// -/// For the occasion of onDisconnected during unstable network condition, you don't need to reconnect manually, -/// the chat SDK will handle it automatically. -/// -/// There are only two states: onConnected, onDisconnected. -/// -/// Note: We recommend not to update UI based on those methods, because this method is called on worker thread. If you update UI in those methods, other UI errors might be invoked. -/// Also do not insert heavy computation work here, which might invoke other listeners to handle this connection event. -/// -/// Register: -/// ```dart -/// EMClient.getInstance.addConnectionListener(mConnectionListener); -/// ``` -/// -/// Unregister: -/// ```dart -/// EMClient.getInstance.removeConnectionListener(mConnectionListener); -/// ``` -/// -@Deprecated("Use EMConnectionEventHandler to instead") -abstract class EMConnectionListener { - /// - /// Occurs when the SDK connects to the chat server successfully. - /// - void onConnected(); - - /// - /// Occurs when the SDK disconnect from the chat server. - /// - /// Note that the logout may not be performed at the bottom level when the SDK is disconnected. - /// - void onDisconnected(); - - /// - /// Occurs when the current user account is logged in to another device. - /// - void onUserDidLoginFromOtherDevice(); - - /// - /// Occurs when the current chat user is removed from the server. - /// - void onUserDidRemoveFromServer(); - - /// - /// Occurs when the current chat user is forbid from the server. - /// - void onUserDidForbidByServer(); - - /// - /// Occurs when the current chat user is changed password. - /// - void onUserDidChangePassword(); - - /// - /// Occurs when the current chat user logged to many devices. - /// - void onUserDidLoginTooManyDevice(); - - /// - /// Occurs when the current chat user kicked by other device. - /// - void onUserKickedByOtherDevice(); - - /// - /// Occurs when the current chat user authentication failed. - /// - void onUserAuthenticationFailed(); - - /// - /// Occurs when the token is about to expire. - /// - void onTokenWillExpire(); - - /// - /// Occurs when the token has expired. - /// - void onTokenDidExpire(); -} - -/// -/// The multi-device event listener. -/// Listens for callback for the current user's actions on other devices, including contact changes and group changes. -/// -/// Registers a multi-device event listener: -/// ```dart -/// EMClient.getInstance.addMultiDeviceListener(mMultiDeviceListener); -/// ``` -/// -/// Removes a multi-device event listener: -/// ```dart -/// EMClient.getInstance.removeMultiDeviceListener(mMultiDeviceListener); -/// ``` -@Deprecated("Use EMMultiDeviceEventHandler to instead") -abstract class EMMultiDeviceListener { - /// - /// The multi-device event callback of contact. - /// - /// Param [event] The event type. - /// - /// Param [username] The username. - /// - /// Param [ext] The extended Information. - /// - void onContactEvent( - EMMultiDevicesEvent event, - String username, - String? ext, - ); - - /// - /// The multi-device event callback of group. - /// - /// Param [event] The event type. - /// - /// Param [groupId] The group ID. - /// - /// Param [usernames] The array of usernames. - /// - void onGroupEvent( - EMMultiDevicesEvent event, - String groupId, - List? usernames, - ); - - /// - /// The multi-device event callback of thread. - /// - /// Param [event] The event type. - /// - /// Param [chatThreadId] subregion id. - /// - /// Param [usernames] The array of usernames. - /// - void onChatThreadEvent( - EMMultiDevicesEvent event, - String chatThreadId, - List usernames, - ); -} - -/// -/// The custom event listener. -/// -@Deprecated("Use [EMClient.customEventHandler] instead") -abstract class EMCustomListener { - void onDataReceived(Map map); -} - -/// -/// The contact updates listener. -/// -/// Occurs when the contact changes, including requests to add friends, notifications to delete friends, -/// requests to accept friends, and requests to reject friends. -/// -/// Register the listener: -/// ```dart -/// EMClient.getInstance.contactManager.addContactManagerListener(contactListener); -/// ``` -/// -/// Unregister the listener: -/// ```dart -/// EMClient.getInstance.contactManager.removeContactManagerListener(contactListener); -/// ``` -/// -@Deprecated("Use EMContactEventHandler to instead") -abstract class EMContactManagerListener { - /// - /// Occurs when user is added as a contact by another user. - /// - /// Param [userName] The new contact to be added. - /// - void onContactAdded(String userName); - - /// - /// Occurs when a user is removed from the contact list by another user. - /// - /// Param [userName] The user who is removed from the contact list by another user. - /// - void onContactDeleted(String userName); - - /// - /// Occurs when a user receives a friend request. - /// - /// Param [userName] The user who initiated the friend request. - /// - /// Param [reason] The invitation message. - /// - void onContactInvited(String userName, String? reason); - - /// - /// Occurs when a friend request is approved. - /// - /// Param [userName] The user who initiated the friend request. - /// - void onFriendRequestAccepted(String userName); - - /// - /// Occurs when a friend request is declined. - /// - /// Param [userName] The user who initiated the friend request. - /// - void onFriendRequestDeclined(String userName); -} - -/// -/// The chat room manager listener. -/// -/// Register the listener: -/// ```dart -/// EMClient.getInstance.chatRoomManager.addChatRoomManagerListener(listener); -/// ``` -/// -/// Unregister the listener: -/// ```dart -/// EMClient.getInstance.chatRoomManager.removeChatRoomManagerListener(listener); -/// ``` -/// -@Deprecated("Use EMChatRoomEventHandler to instead") -abstract class EMChatRoomManagerListener { - /// - /// Occurs when the chat room is destroyed. - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [roomName] The chatroom name. - /// - void onChatRoomDestroyed(String roomId, String? roomName); - - /// - /// Occurs when a member join the chatroom. - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [participant] The new member's username. - /// - void onMemberJoinedFromChatRoom(String roomId, String participant); - - /// - /// Occurs when a member leaves the chatroom. - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [participant] The exited member's username. - /// - void onMemberExitedFromChatRoom( - String roomId, String? roomName, String participant); - - /// - /// Occurs when a member is dismissed from a chat room. - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [roomName] The chatroom name. - /// - /// Param [participant] The member is dismissed from a chat room. - /// - void onRemovedFromChatRoom( - String roomId, - String? roomName, - String? participant, - ); - - /// - /// Occurs when there are chat room member(s) muted (added to mute list). - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [mutes] The members to be muted. - /// - /// Param [expireTime] The mute duration. - /// - void onMuteListAddedFromChatRoom( - String roomId, - List mutes, - String? expireTime, - ); - - /// - /// Occurs when there are chat room member(s) unmuted (removed from mute list). - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [mutes] The member(s) muted is removed from the mute list. - /// - void onMuteListRemovedFromChatRoom( - String roomId, - List mutes, - ); - - /// - /// Occurs when a member has been changed to an admin. - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [admin] The member who has been changed to an admin. - /// - void onAdminAddedFromChatRoom(String roomId, String admin); - - /// - /// Occurs when an admin is been removed. - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [admin] The member whose admin permission is removed. - /// - void onAdminRemovedFromChatRoom(String roomId, String admin); - - /// - /// Occurs when the chat room ownership has been transferred. - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [newOwner] The new owner. - /// - /// Param [oldOwner] The previous owner. - /// - void onOwnerChangedFromChatRoom( - String roomId, String newOwner, String oldOwner); - - /// - /// Occurs when the announcement changed. - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [announcement] The changed announcement. - /// - void onAnnouncementChangedFromChatRoom(String roomId, String announcement); - - /// - /// Occurs when the chat room member(s) is added to the allowlist. - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [members] The member(s) to be added to the allowlist. - /// - void onAllowListAddedFromChatRoom(String roomId, List members); - - /// - /// Occurs when the chat room member(s) is removed from the allowlist. - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [members] The member(s) is removed from the allowlist. - /// - void onAllowListRemovedFromChatRoom(String roomId, List members); - - /// - /// Occurs when all members in the chat room are muted or unmuted. - /// - /// Param [roomId] The chatroom ID. - /// - /// Param [isAllMuted] Whether all chat room members is muted or unmuted. - /// - `true`: Yes; - /// - `false`: No. - /// - void onAllChatRoomMemberMuteStateChanged(String roomId, bool isAllMuted); -} - -/// -/// The group change listener. -/// -/// Occurs when the following group events happens: requesting to join a group, approving or declining a group request, and kicking a user out of a group. -/// -/// Register a group change listener: -/// ```dart -/// EMClient.getInstance.groupManager.addGroupManagerListener(listener); -/// ``` -/// -/// Unregister a group change listener: -/// ```dart -/// EMClient.getInstance.groupManager.removeGroupManagerListener(listener); -/// ``` -@Deprecated("Use EMGroupEventHandler to instead") -abstract class EMGroupManagerListener { - /// - /// Occurs when the user receives a group invitation. - /// - /// Param [groupId] The group ID. - /// - /// Param [groupName] The group name. - /// - /// Param [inviter] The invitee ID. - /// - /// Param [reason] The reason for invitation. - /// - void onInvitationReceivedFromGroup( - String groupId, String? groupName, String inviter, String? reason); - - /// - /// Occurs when the group owner or administrator receives a group request from a user. - /// - /// Param [groupId] The group ID. - /// - /// Param [groupName] The group name. - /// - /// Param [applicant] The ID of the user requesting to join the group. - /// - /// Param [reason] The reason for requesting to join the group. - /// - void onRequestToJoinReceivedFromGroup( - String groupId, String? groupName, String applicant, String? reason); - - /// - /// Occurs when a group request is accepted. - /// - /// Param [groupId] The group ID. - /// - /// Param [groupName] The group name. - /// - /// Param [accepter] The ID of the user that accepts the group request. - /// - void onRequestToJoinAcceptedFromGroup( - String groupId, String? groupName, String accepter); - - /// - /// Occurs when a group request is declined. - /// - /// Param [groupId] The group ID. - /// - /// Param [groupName] The group name. - /// - /// Param [decliner] The ID of the user that declines the group request. - /// - /// Param [reason] The reason for declining. - /// - void onRequestToJoinDeclinedFromGroup( - String groupId, - String? groupName, - String decliner, - String? reason, - ); - - /// - /// Occurs when a group invitation is accepted. - /// - /// Param [groupId] The group ID. - /// - /// Param [invitee] The invitee ID. - /// - /// Param [reason] The reason for acceptance. - /// - void onInvitationAcceptedFromGroup( - String groupId, - String invitee, - String? reason, - ); - - /// - /// Occurs when a group invitation is declined. - /// - /// Param [groupId] The group ID. - /// - /// Param [invitee] The invitee ID. - /// - /// Param [reason] The reason for declining. - /// - void onInvitationDeclinedFromGroup( - String groupId, String invitee, String? reason); - - /// - /// Occurs when the current user is removed from the group by the group admin. - /// - /// Param [groupId] The group ID. - /// - /// Param [groupName] The group name. - /// - void onUserRemovedFromGroup(String groupId, String? groupName); - - /// - /// Occurs when a group is destroyed. - /// - /// Param [groupId] The group ID. - /// - /// Param [groupName] The group name. - /// - void onGroupDestroyed(String groupId, String? groupName); - - /// - /// Occurs when the group invitation is accepted automatically. - /// For settings, see [EMOptions.autoAcceptGroupInvitation]. - /// The SDK will join the group before notifying the app of the acceptance of the group invitation. - /// - /// Param [groupId] The group ID. - /// - /// Param [inviter] The inviter ID. - /// - /// Param [inviteMessage] The invitation message. - /// - void onAutoAcceptInvitationFromGroup( - String groupId, String inviter, String? inviteMessage); - - /// - /// Occurs when one or more group members are muted. - /// - /// Note: The mute function is different from a block list. - /// A user, when muted, can still see group messages, but cannot send messages in the group. - /// However, a user on the block list can neither see nor send group messages. - /// - /// Param [groupId] The group ID. - /// - /// Param [mutes] The member(s) added to the mute list. - /// - /// Param [muteExpire] The mute duration in milliseconds. - /// - void onMuteListAddedFromGroup( - String groupId, List mutes, int? muteExpire); - - /// - /// Occurs when one or more group members are unmuted. - /// - /// Param [groupId] The group ID. - /// - /// Param [mutes] The member(s) added to the mute list. - /// - void onMuteListRemovedFromGroup(String groupId, List mutes); - - /// - /// Occurs when a member is set as an admin. - /// - /// Param [groupId] The group ID. - /// - /// Param [admin] The member that is set as an admin. - /// - void onAdminAddedFromGroup(String groupId, String admin); - - /// - /// Occurs when a member's admin privileges are removed. - /// - /// Param [groupId] The group ID. - /// - /// Param [admin] The member whose admin privileges are removed. - /// - void onAdminRemovedFromGroup(String groupId, String admin); - - /// - /// Occurs when the group ownership is transferred. - /// - /// Param [groupId] The group ID. - /// - /// Param [newOwner] The new owner. - /// - /// Param [oldOwner] The previous owner. - /// - void onOwnerChangedFromGroup( - String groupId, String newOwner, String oldOwner); - - /// - /// Occurs when a member joins a group. - /// - /// Param [groupId] The group ID. - /// - /// Param [member] The ID of the new member. - /// - void onMemberJoinedFromGroup(String groupId, String member); - - /// - /// Occurs when a member proactively leaves the group. - /// - /// Param [groupId] The group ID. - /// - /// Param [member] The member leaving the group. - /// - void onMemberExitedFromGroup(String groupId, String member); - - /// - /// Occurs when the announcement is updated. - /// - /// Param [groupId] The group ID. - /// - /// Param [announcement] The updated announcement content. - /// - void onAnnouncementChangedFromGroup(String groupId, String announcement); - - /// - /// Occurs when a shared file is added to a group. - /// - /// Param [groupId] The group ID. - /// - /// Param [sharedFile] The new shared file. - /// - void onSharedFileAddedFromGroup(String groupId, EMGroupSharedFile sharedFile); - - /// - /// Occurs when a shared file is removed from a group. - /// - /// Param [groupId] The group ID. - /// - /// Param [fileId] The ID of the removed shared file. - /// - void onSharedFileDeletedFromGroup(String groupId, String fileId); - - /// - /// Occurs when one or more group members are added to the allowlist. - /// - /// Param [groupId] The group ID. - /// - /// Param [members] The member(s) removed from the allowlist. - /// - void onAllowListAddedFromGroup(String groupId, List members); - - /// - /// Occurs when one or more members are removed from the allowlist. - /// - /// Param [groupId] The group ID. - /// - /// Param [members] The member(s) added to the allowlist. - /// - void onAllowListRemovedFromGroup(String groupId, List members); - - /// - /// Occurs when all group members are muted or unmuted. - /// - /// Param [groupId] The group ID. - /// - /// Param [isAllMuted] Whether all group members are muted or unmuted. - /// - `true`: Yes; - /// - `false`: No. - /// - void onAllGroupMemberMuteStateChanged(String groupId, bool isAllMuted); - - /// Occurs when the group detail information is updated. - void onSpecificationDidUpdate(EMGroup group); - - /// Occurs when the group is enabled or disabled. - void onDisableChange(String groupId, bool isDisable); -} - -/// -/// The message event listener. -/// -/// This listener is used to check whether messages are received. If messages are sent successfully, a delivery receipt will be returned (delivery receipt needs to be enabled: [EMOptions.requireDeliveryAck]. -/// If the peer reads the received message, a read receipt will be returned (read receipt needs to be enabled: [EMOptions.requireAck]. -/// During message delivery, the message ID will be changed from a local uuid to a global unique ID that is generated by the server to uniquely identify a message on all devices using the SDK. -/// This API should be implemented in the app to listen for message status changes. -/// -/// Adds the message listener: -/// ```dart -/// EMClient.getInstance.chatManager.addChatManagerListener(listener); -/// ``` -/// -/// Removes the message listener: -/// ```dart -/// EMClient.getInstance.chatManager.removeChatManagerListener(listener); -/// ``` -/// -@Deprecated("Use EMChatEventHandler to instead") -class EMChatManagerListener { - /// - /// Occurs when a message is received. - /// - /// This callback is triggered to notify the user when a message such as texts or an image, video, voice, location, or file is received. - /// - /// Param [messages] The received messages. - /// - void onMessagesReceived(List messages) {} - - /// - /// Occurs when a command message is received. - /// - /// This callback only contains a command message body that is usually invisible to users. - /// - /// Param [messages]The received cmd messages. - /// - void onCmdMessagesReceived(List messages) {} - - /// - /// Occurs when a read receipt is received for a message. - /// - /// Param [messages] The has read messages. - /// - void onMessagesRead(List messages) {} - - /// - /// Occurs when a read receipt is received for a group message. - /// - /// Param [groupMessageAcks] The group message acks. - /// - void onGroupMessageRead(List groupMessageAcks) {} - - /// - /// Occurs when the update for the group message read status is received. - /// - void onReadAckForGroupMessageUpdated() {} - - /// - /// Occurs when a delivery receipt is received. - /// - /// Param [messages] The has delivered messages. - /// - void onMessagesDelivered(List messages) {} - - /// - /// Occurs when a received message is recalled. - /// - /// Param [messages] The recalled messages. - /// - void onMessagesRecalled(List messages) {} - - /// - /// Occurs when the conversation updated. - /// - void onConversationsUpdate() {} - - /// - /// Occurs when a conversation read receipt is received. - /// - /// Occurs in the following scenarios: - /// (1) The message is read by the receiver (The conversation receipt is sent). - /// Upon receiving this event, the SDK sets the [EMMessage.hasReadAck] property of the message in the conversation to `true` in the local database. - /// (2) In the multi-device login scenario, when one device sends a Conversation receipt, - /// the server will set the number of unread messages to 0, and the callback occurs on the other devices. - /// and sets the [EMMessage.hasReadAck] property of the message in the conversation to `true` in the local database. - /// - /// Param [from] The user who sends the read receipt. - /// Param [to] The user who receives the read receipt. - /// - void onConversationRead(String from, String to) {} - - /// - /// Occurs when the Reaction data changes. - /// - /// Param [list] The Reaction which is changed - /// - void onMessageReactionDidChange(List list) {} -} - -/// -/// The presence manager listener. -/// -@Deprecated("Use EMPresenceEventHandler to instead") -class EMPresenceManagerListener { - /// - /// Occurs when the presence state of a subscribed user changes. - /// - /// Param [list] The new presence state of a subscribed user. - /// - void onPresenceStatusChanged(List list) {} -} - -/// -/// The message thread listener interface, which listens for message thread events such as creating or leaving a message thread. -/// -/// Adds a message thread event listener: -/// EMClient.getInstance.chatThreadManager.addChatThreadManagerListener(listener); -/// -/// Removes a message thread event listener: -/// EMClient.getInstance.chatThreadManager.removeChatThreadManagerListener(listener); -/// -@Deprecated("Use EMChatThreadEventHandler to instead") -class EMChatThreadManagerListener { - /// - /// Occurs when a message thread is created. - /// - /// Each member of the group to which the message thread belongs can receive the callback. - /// - /// Param [event] The event; - /// - void onChatThreadCreate(EMChatThreadEvent event) {} - - /// - /// Occurs when a message thread is updated. - /// - /// This callback is triggered when the message thread name is changed or a threaded reply is added or recalled. - /// - /// Each member of the group to which the message thread belongs can receive the callback. - /// - /// Param [event] The event; - /// - void onChatThreadUpdate(EMChatThreadEvent event) {} - - /// - /// Occurs when a message thread is destroyed. - /// - /// Each member of the group to which the message thread belongs can receive the callback. - /// - /// Param [event] The event; - /// - void onChatThreadDestroy(EMChatThreadEvent event) {} - - /// - /// Occurs when the current user is removed from the message thread by the group owner or a group admin to which the message thread belongs. - /// - /// Param [event] The event; - /// - void onUserKickOutOfChatThread(EMChatThreadEvent event) {} -} diff --git a/lib/src/em_message_status_callback.dart b/lib/src/em_message_status_callback.dart deleted file mode 100644 index 12d2ea2b..00000000 --- a/lib/src/em_message_status_callback.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:flutter/foundation.dart'; - -import 'internal/inner_headers.dart'; - -@Deprecated('Switch [ChatManager.addMessageEvent] to instead.') -class MessageStatusCallBack { - final void Function(int progress)? onProgress; - - final void Function(EMError error)? onError; - - final VoidCallback? onSuccess; - - final VoidCallback? onReadAck; - - final VoidCallback? onDeliveryAck; - - final VoidCallback? onStatusChanged; - - MessageStatusCallBack({ - this.onProgress, - this.onError, - this.onSuccess, - this.onReadAck, - this.onDeliveryAck, - this.onStatusChanged, - }); -} diff --git a/lib/src/em_presence_manager.dart b/lib/src/em_presence_manager.dart index 6e19d675..250a78ab 100644 --- a/lib/src/em_presence_manager.dart +++ b/lib/src/em_presence_manager.dart @@ -12,8 +12,6 @@ class EMPresenceManager { '$_channelPrefix/chat_presence_manager', JSONMethodCodec()); final Map _eventHandlesMap = {}; - // will deprecated - final List _listeners = []; /// @nodoc EMPresenceManager() { @@ -210,44 +208,5 @@ class EMPresenceManager { for (var handle in _eventHandlesMap.values) { handle.onPresenceStatusChanged?.call(pList); } - - _forward(pList); - } -} - -extension PresenceDeprecated on EMPresenceManager { - /// - /// Registers a new presence manager listener. - /// - /// Param [listener] The presence manager listener to be registered: [EMPresenceManagerListener]. - /// - @Deprecated("Use addEventHandler to instead") - void addPresenceManagerListener(EMPresenceManagerListener listener) { - _listeners.remove(listener); - _listeners.add(listener); - } - - /// - /// Removes the contact listener. - /// - /// Param [listener] The presence manager listener to be removed. - /// - @Deprecated("Use [removeEventHandler] to instead") - void removePresenceManagerListener(EMPresenceManagerListener listener) { - if (_listeners.contains(listener)) { - _listeners.remove(listener); - } - } - - @Deprecated("Use [clearEventHandlers] to instead") - void clearAllPresenceManagerListener() { - _listeners.clear(); - } - - @deprecated - void _forward(List pList) { - for (var listener in _listeners) { - listener.onPresenceStatusChanged(pList); - } } } diff --git a/lib/src/em_push_manager.dart b/lib/src/em_push_manager.dart index 1fbb4502..90e3a8b8 100644 --- a/lib/src/em_push_manager.dart +++ b/lib/src/em_push_manager.dart @@ -2,24 +2,13 @@ import 'dart:io'; import 'internal/inner_headers.dart'; -/// +/// ~english /// The message push configuration options. -/// +/// ~end class EMPushManager { - @deprecated - Future getPushConfigsFromCache() async { - Map result = await PushChannel.invokeMethod(ChatMethodKeys.getImPushConfig); - try { - EMError.hasErrorFromResult(result); - return EMPushConfigs.fromJson(result[ChatMethodKeys.getImPushConfig]); - } on EMError catch (e) { - throw e; - } - } - - /// + /// ~english /// Gets the push configurations from the server. - /// + /// ~end Future fetchPushConfigsFromServer() async { Map result = await PushChannel.invokeMethod( ChatMethodKeys.getImPushConfigFromServer); @@ -32,50 +21,7 @@ class EMPushManager { } } - /// - /// Sets whether to turn on or turn off the push notification for the the specified groups. - /// - /// [groupIds] The list of groups to be set. - /// - /// [enablePush] enable push notification. - /// `true`: Turns on the notification; - /// `false`: Turns off the notification; - /// - /// **Throws** A description of the issue that caused this exception. See [EMError] - /// - @deprecated - Future updatePushServiceForGroup({ - required List groupIds, - required bool enablePush, - }) async { - Map req = {'noPush': !enablePush, 'group_ids': groupIds}; - Map result = await PushChannel.invokeMethod( - ChatMethodKeys.updateGroupPushService, req); - try { - EMError.hasErrorFromResult(result); - } on EMError catch (e) { - throw e; - } - } - - /// - /// Gets the list of users which have blocked the push notification. - /// - /// **return** The list of user that blocked the push notification. - /// - /// **Throws** A description of the issue that caused this exception. See [EMError] - /// - @Deprecated('') - Future> getNoPushUsersFromCache() async { - Map result = await PushChannel.invokeMethod(ChatMethodKeys.getNoPushUsers); - List list = []; - if (result.containsKey(ChatMethodKeys.getNoPushUsers)) { - list = result[ChatMethodKeys.getNoPushUsers]?.cast(); - } - return list; - } - - /// + /// ~english /// Updates the push display nickname of the current user. /// /// This method can be used to set a push display nickname, the push display nickname will be used to show for offline push notification. @@ -85,7 +31,7 @@ class EMPushManager { /// Param [nickname] The push display nickname, which is different from the nickname in the user profile. /// /// **Throws** A description of the issue that caused this exception. See [EMError] - /// + /// ~end Future updatePushNickname(String nickname) async { Map req = {'nickname': nickname}; Map result = @@ -97,13 +43,13 @@ class EMPushManager { } } - /// + /// ~english /// Updates the push message style. The default value is [DisplayStyle.Simple]. /// /// Param [displayStyle] The push message display style. /// /// **Throws** A description of the issue that caused this exception. See [EMError] - /// + /// ~end Future updatePushDisplayStyle(DisplayStyle displayStyle) async { Map req = {'pushStyle': displayStyle == DisplayStyle.Simple ? 0 : 1}; Map result = @@ -115,13 +61,13 @@ class EMPushManager { } } - /// + /// ~english /// Updates the HMS push token. /// /// Param [token] The HMS push token. /// /// **Throws** A description of the issue that caused this exception. See [EMError] - /// + /// ~end Future updateHMSPushToken(String token) async { if (Platform.isAndroid) { Map req = {'token': token}; @@ -135,13 +81,13 @@ class EMPushManager { } } - /// + /// ~english /// Updates the FCM push token. /// /// Param [token] The FCM push token. /// /// **Throws** A description of the issue that caused this exception. See [EMError] - /// + /// ~end Future updateFCMPushToken(String token) async { if (Platform.isAndroid) { Map req = {'token': token}; @@ -155,13 +101,13 @@ class EMPushManager { } } - /// + /// ~english /// Updates the APNs push token. /// /// Param [token] The APNs push token. /// /// **Throws** A description of the issue that caused this exception. See [EMError] - /// + /// ~end Future updateAPNsDeviceToken(String token) async { if (Platform.isIOS) { Map req = {'token': token}; @@ -175,15 +121,7 @@ class EMPushManager { } } - // Future reportPushAction( - // {String taskId, - // String provider, - // String action,} - // ) async { - // Map req = {}; - // } - - /// + /// ~english /// Set offline push notification type for the special conversation. /// /// Param [conversationId] The conversation id. @@ -194,7 +132,7 @@ class EMPushManager { /// /// **Throws** A description of the exception. See [EMError]. /// - /// + /// ~end Future setConversationSilentMode({ required String conversationId, required EMConversationType type, @@ -214,7 +152,7 @@ class EMPushManager { } } - /// + /// ~english /// Remove the setting of offline push notification type for the special conversation. /// After clearing, the session follows the Settings of the current logged-in user [EMPushManager.setSilentModeForAll]. /// @@ -223,7 +161,7 @@ class EMPushManager { /// Param [type] The conversation type. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future removeConversationSilentMode({ required String conversationId, required EMConversationType type, @@ -240,7 +178,7 @@ class EMPushManager { } } - /// + /// ~english /// Gets the DND setting of the special conversation. /// /// Param [conversationId] The conversation id. @@ -250,7 +188,7 @@ class EMPushManager { /// **Return** The conversation silent mode. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future fetchConversationSilentMode({ required String conversationId, required EMConversationType type, @@ -269,13 +207,13 @@ class EMPushManager { } } - /// + /// ~english /// Set the DND normal settings for the current login user. /// /// Param [param] Push DND parameters offline. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future setSilentModeForAll({ required ChatSilentModeParam param, }) async { @@ -292,13 +230,13 @@ class EMPushManager { } } - /// + /// ~english /// Gets the DND normal settings of the current login user. /// /// **Return** The normal silent mode. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future fetchSilentModeForAll() async { Map result = await PushChannel.invokeMethod(ChatMethodKeys.fetchSilentModeForAll); @@ -312,7 +250,7 @@ class EMPushManager { } } - /// + /// ~english /// Obtain the DND Settings of specified conversations in batches. /// /// Param [conversations] The conversation list. @@ -320,7 +258,7 @@ class EMPushManager { /// **Return** key is conversation id and the value is silent mode. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> fetchSilentModeForConversations( List conversations, ) async { @@ -349,13 +287,13 @@ class EMPushManager { } } - /// + /// ~english /// Set user push translation language. /// /// Param [languageCode] language code. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future setPreferredNotificationLanguage(String languageCode) async { Map req = {"code": languageCode}; Map result = await PushChannel.invokeMethod( @@ -369,13 +307,13 @@ class EMPushManager { } } - /// + /// ~english /// Gets the push translation language set by the user. /// /// **Return** has set language code. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future fetchPreferredNotificationLanguage() async { Map result = await PushChannel.invokeMethod( ChatMethodKeys.fetchPreferredNotificationLanguage, @@ -389,13 +327,13 @@ class EMPushManager { } } - /// + /// ~english /// Set the push template for offline push. /// /// Param [pushTemplateName] push template name. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future setPushTemplate(String pushTemplateName) async { Map result = await PushChannel.invokeMethod(ChatMethodKeys.setPushTemplate, { @@ -408,13 +346,13 @@ class EMPushManager { } } - /// + /// ~english /// Gets the offline push template for Settings. /// /// **Return** The push template name. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future getPushTemplate() async { Map result = await PushChannel.invokeMethod(ChatMethodKeys.getPushTemplate); try { @@ -426,89 +364,3 @@ class EMPushManager { } } } - -extension EMPushManagerDeprecated on EMPushManager { - /// - /// Turns on the push notification. - /// - /// **Throws** A description of the issue that caused this exception. See [EMError] - /// - @Deprecated("Use [setSilentModeForAll] to instead") - Future enableOfflinePush() async { - Map result = - await PushChannel.invokeMethod(ChatMethodKeys.enableOfflinePush); - try { - EMError.hasErrorFromResult(result); - } on EMError catch (e) { - throw e; - } - } - - /// - /// Do not push the offline messages within the specified time period (24-hour clock). - /// - /// Param [start] The start hour(24-hour clock). - /// - /// Param [end] The end hour(24-hour clock). - /// - /// **Throws** A description of the issue that caused this exception. See [EMError] - /// - @Deprecated("Use [setSilentModeForAll] to instead") - Future disableOfflinePush({ - required int start, - required int end, - }) async { - Map req = {'start': start, 'end': end}; - Map result = - await PushChannel.invokeMethod(ChatMethodKeys.disableOfflinePush, req); - try { - EMError.hasErrorFromResult(result); - } on EMError catch (e) { - throw e; - } - } - - /// - /// Gets the list of groups which have blocked the push notification. - /// - /// **return** The list of groups that blocked the push notification. - /// - /// **Throws** A description of the issue that caused this exception. See [EMError] - /// - - @deprecated - Future> getNoPushGroupsFromCache() async { - Map result = await PushChannel.invokeMethod(ChatMethodKeys.getNoPushGroups); - List list = []; - if (result.containsKey(ChatMethodKeys.getNoPushGroups)) { - list = result[ChatMethodKeys.getNoPushGroups]?.cast(); - } - return list; - } - - /// - /// Sets whether to turn on or turn off the push notification for the the specified users. - /// - /// [userIds] The list of users to be set. - /// - /// [enablePush] enable push notification. - /// `true`: Turns on the notification; - /// `false`: Turns off the notification; - /// - /// **Throws** A description of the issue that caused this exception. See [EMError] - /// - @Deprecated('Use [EMPushManager.setConversationSilentMode] to instead') - Future updatePushServiceFroUsers({ - required List userIds, - required bool enablePush, - }) async { - Map req = {'noPush': !enablePush, 'user_ids': userIds}; - Map result = await PushChannel.invokeMethod( - ChatMethodKeys.updateUserPushService, req); - try { - EMError.hasErrorFromResult(result); - } on EMError catch (e) { - throw e; - } - } -} diff --git a/lib/src/em_userInfo_manager.dart b/lib/src/em_userInfo_manager.dart index 5f7dd3a6..b7a14940 100644 --- a/lib/src/em_userInfo_manager.dart +++ b/lib/src/em_userInfo_manager.dart @@ -5,9 +5,9 @@ import 'package:flutter/services.dart'; import 'internal/inner_headers.dart'; -/// +/// ~english /// The user attribute manager class, which gets and sets the user attributes. -/// +/// ~end class EMUserInfoManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( @@ -16,7 +16,7 @@ class EMUserInfoManager { // The map of effective contacts. Map _effectiveUserInfoMap = Map(); - /// + /// ~english /// Modifies the user attributes of the current user. /// /// Param [nickname] The nickname of the user. @@ -40,7 +40,7 @@ class EMUserInfoManager { /// **Return** The user info. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future updateUserInfo({ String? nickname, String? avatarUrl, @@ -74,7 +74,7 @@ class EMUserInfoManager { } } - /// + /// ~english /// Gets the current user's attributes from the server. /// /// Param [expireTime] The time period(seconds) when the user attributes in the cache expire. If the interval between two callers is less than or equal to the value you set in the parameter, user attributes are obtained directly from the local cache; otherwise, they are obtained from the server. For example, if you set this parameter to 120(2 minutes), once this method is called again within 2 minutes, the SDK returns the attributes obtained last time. @@ -82,9 +82,9 @@ class EMUserInfoManager { /// **Return** The user properties that are obtained. See [EMUserInfo]. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future fetchOwnInfo({int expireTime = 0}) async { - String? currentUser = await EMClient.getInstance.getCurrentUsername(); + String? currentUser = await EMClient.getInstance.getCurrentUserId(); if (currentUser != null) { try { Map ret = await fetchUserInfoById( @@ -100,7 +100,7 @@ class EMUserInfoManager { return null; } - /// + /// ~english /// Gets user attributes of the specified users. /// /// Param [userIds] The username array. @@ -110,7 +110,7 @@ class EMUserInfoManager { /// **Return** A map that contains key-value pairs where the key is the user ID and the value is user attributes. /// /// **Throws** A description of the exception. See [EMError]. - /// + /// ~end Future> fetchUserInfoById( List userIds, { int expireTime = 0, @@ -151,6 +151,9 @@ class EMUserInfoManager { } } + /// ~english + /// clear all userInfo cache. + /// ~end void clearUserInfoCache() { _effectiveUserInfoMap.clear(); } diff --git a/lib/src/event_handler/manager_event_handler.dart b/lib/src/event_handler/manager_event_handler.dart index c895fbd7..b5c8872a 100644 --- a/lib/src/event_handler/manager_event_handler.dart +++ b/lib/src/event_handler/manager_event_handler.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:im_flutter_sdk/im_flutter_sdk.dart'; -/// +/// ~english /// The connection event handler. /// /// For the occasion of onDisconnected during unstable network condition, you don't need to reconnect manually, @@ -19,66 +19,127 @@ import 'package:im_flutter_sdk/im_flutter_sdk.dart'; /// ```dart /// EMClient.getInstance.removeConnectionEventHandler(UNIQUE_HANDLER_ID); /// ``` +/// ~end +/// +/// ~chinese +/// 服务器连接监听类。 +/// +/// 对于不稳定网络条件下的onDisconnected情况,您不需要手动重新连接, +/// SDK会自动处理。 +/// +/// 添加 connection event handler: +/// ```dart +/// EMClient.getInstance.addConnectionEventHandler(UNIQUE_HANDLER_ID, EMConnectionEventHandler()); +/// ``` /// +/// 移除 connection event handler: +/// ```dart +/// EMClient.getInstance.removeConnectionEventHandler(UNIQUE_HANDLER_ID); +/// ``` +/// ~end class EMConnectionEventHandler { - /// + /// ~english /// Occurs when the SDK connects to the chat server successfully. + /// ~end /// + /// ~chinese + /// 成功连接到 chat 服务器时触发的回调。 + /// ~end final VoidCallback? onConnected; - /// + /// ~english /// Occurs when the SDK disconnect from the chat server. /// /// Note that the logout may not be performed at the bottom level when the SDK is disconnected. + /// ~end /// + /// ~chinese + /// 与 chat 服务器断开连接时触发的回调。 + /// ~end final VoidCallback? onDisconnected; - /// + /// ~english /// Occurs when the current user account is logged in to another device. + /// ~end /// + /// ~chinese + /// 其他设备登录回调。 + /// ~end final VoidCallback? onUserDidLoginFromOtherDevice; - /// + /// ~english /// Occurs when the current chat user is removed from the server. + /// ~end /// + /// ~chinese + /// 被服务器移除回调。 + /// ~end final VoidCallback? onUserDidRemoveFromServer; - /// + /// ~english /// Occurs when the current chat user is forbid from the server. + /// ~end /// + /// ~chinese + /// 被服务器禁止连接回调。 + /// ~end final VoidCallback? onUserDidForbidByServer; - /// + /// ~english /// Occurs when the current chat user is changed password. + /// ~end /// + /// ~chinese + /// 用户密码变更回调。 + /// ~end final VoidCallback? onUserDidChangePassword; - /// + /// ~english /// Occurs when the current chat user logged to many devices. + /// ~end /// + /// ~chinese + /// 登录设备过多回调。 + /// ~end final VoidCallback? onUserDidLoginTooManyDevice; - /// + /// ~english /// Occurs when the current chat user kicked by other device. + /// ~end /// + /// ~chinese + /// 被其他设备踢掉回调。 + /// ~end final VoidCallback? onUserKickedByOtherDevice; - /// + /// ~english /// Occurs when the current chat user authentication failed. + /// ~end /// + /// ~chinese + /// 鉴权失败回调。 + /// ~end final VoidCallback? onUserAuthenticationFailed; - /// + /// ~english /// Occurs when the token is about to expire. + /// ~end /// + /// ~chinese + /// Agora token 即将过期时触发。 + /// ~end final VoidCallback? onTokenWillExpire; - /// + /// ~english /// Occurs when the token has expired. + /// ~end /// + /// ~chinese + /// Agora token 已过期时触发。 + /// ~end final VoidCallback? onTokenDidExpire; - /// + /// ~english /// The chat connection listener callback. /// /// Param [onConnected] The SDK connects to the chat server successfully callback. @@ -102,7 +163,33 @@ class EMConnectionEventHandler { /// Param [onTokenWillExpire] The token is about to expire callback. /// /// Param [onTokenDidExpire] The token has expired callback. + /// ~end + /// + /// ~chinese + /// 连接状态监听。 + /// + /// Param [onConnected] 成功连接到 chat 服务器时触发的回调。 + /// + /// Param [onDisconnected] 和 chat 服务器断开连接时触发的回调。 + /// + /// Param [onUserDidLoginFromOtherDevice] 其他设备登录回调。 + /// + /// Param [onUserDidRemoveFromServer] 被服务器移除回调。 + /// + /// Param [onUserDidForbidByServer] 被服务器禁止连接回调。 + /// + /// Param [onUserDidChangePassword] 用户密码变更回调。 /// + /// Param [onUserDidLoginTooManyDevice] 登录设备过多回调。 + /// + /// Param [onUserKickedByOtherDevice] 被其他设备踢掉回调。 + /// + /// Param [onUserAuthenticationFailed] 鉴权失败回调。 + /// + /// Param [onTokenWillExpire] Agora token 即将过期时回调。 + /// + /// Param [onTokenDidExpire] Agora token 已过期时回调。 + /// ~end EMConnectionEventHandler({ this.onConnected, this.onDisconnected, @@ -118,7 +205,7 @@ class EMConnectionEventHandler { }); } -/// +/// ~english /// The multi-device event handler. /// Listens for callback for the current user's actions on other devices, including contact changes and group changes. /// @@ -131,29 +218,63 @@ class EMConnectionEventHandler { /// ```dart /// EMClient.getInstance.removeMultiDeviceEventHandler(UNIQUE_HANDLER_ID); /// ``` +/// ~end +/// +/// ~chinese +/// 多设备事件监听 +/// 监听当前用户在其他设备上的操作的回调,包括联系人更改和组,thread等更改。 /// +/// 添加监听: +/// ```dart +/// EMClient.getInstance.addMultiDeviceEventHandler((UNIQUE_HANDLER_ID, EMMultiDeviceEventHandler()); +/// ``` +/// +/// 移除监听: +/// ```dart +/// EMClient.getInstance.removeMultiDeviceEventHandler(UNIQUE_HANDLER_ID); +/// ``` +/// ~end class EMMultiDeviceEventHandler { + /// ~english /// The multi-device event of contact. + /// ~end + /// + /// ~chinese + /// 多设备联系人事件。 + /// ~end final void Function( EMMultiDevicesEvent event, String userId, String? ext, )? onContactEvent; + /// ~english /// The multi-device event of group. + /// ~end + /// + /// ~chinese + /// 多设备群组事件。 + /// ~end final void Function( EMMultiDevicesEvent event, String groupId, List? userIds, )? onGroupEvent; + /// ~english /// The multi-device event of thread. + /// ~end + /// + /// ~chinese + /// 多设备Thread 事件。 + /// ~end final void Function( EMMultiDevicesEvent event, String chatThreadId, List userIds, )? onChatThreadEvent; + /// ~english /// The multi-device event handler. /// /// Param [onContactEvent] The multi-device event of contact. @@ -161,7 +282,17 @@ class EMMultiDeviceEventHandler { /// Param [onGroupEvent] The multi-device event of group. /// /// Param [onChatThreadEvent] The multi-device event of thread. + /// ~end + /// + /// ~chinese + /// 多设备事件。 + /// + /// Param [onContactEvent] 多设备联系人事件。 + /// + /// Param [onGroupEvent] 多设备群组事件。 /// + /// Param [onChatThreadEvent] 多设备 Thread 事件。 + /// ~end EMMultiDeviceEventHandler({ this.onContactEvent, this.onGroupEvent, @@ -169,7 +300,7 @@ class EMMultiDeviceEventHandler { }); } -/// +/// ~english /// The chat event handler. /// /// This handler is used to check whether messages are received. If messages are sent successfully, a delivery receipt will be returned (delivery receipt needs to be enabled: [EMOptions.requireDeliveryAck]. @@ -185,54 +316,104 @@ class EMMultiDeviceEventHandler { /// ```dart /// EMClient.getInstance.chatManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` +/// ~end +/// +/// ~chinese +/// Chat 事件监听。 +/// +/// 用于监听收消息,已读回执,等回调。 +/// +/// 添加监听: +/// ```dart +/// EMClient.getInstance.chatManager.addEventHandler(UNIQUE_HANDLER_ID, EMChatEventHandler()); +/// ``` /// +/// 移除监听: +/// ```dart +/// EMClient.getInstance.chatManager.removeEventHandler(UNIQUE_HANDLER_ID); +/// ``` +/// ~end class EMChatEventHandler { - /// + /// ~english /// Occurs when a message is received callback. /// /// This callback is triggered to notify the user when a message such as texts or an image, video, voice, location, or file is received. + /// ~end /// + /// ~chinese + /// 收到消息回调。 + /// 在收到文本、图片、视频、语音、地理位置和文件等消息时,通过此回调通知用户。 + /// ~end final void Function(List messages)? onMessagesReceived; - /// + /// ~english /// Occurs when a command message is received. /// /// This callback only contains a command message body that is usually invisible to users. + /// ~end /// + /// ~chinese + /// 收到命令消息回调。 + /// 与 [onMessagesReceived] 不同, 这个回调只包含命令的消息,命令消息通常不对用户展示。 + /// ~end final void Function(List messages)? onCmdMessagesReceived; - /// + /// ~english /// Occurs when a read receipt is received for a message. + /// ~end /// + /// ~chinese + /// 收到单聊消息已读回执的回调。 + /// ~end final void Function(List messages)? onMessagesRead; - /// + /// ~english /// Occurs when a read receipt is received for a group message. + /// ~end /// + /// ~chinese + /// 收到群组消息的已读回执的回调。 + /// ~end final void Function(List groupMessageAcks)? onGroupMessageRead; - /// + /// ~english /// Occurs when the update for the group message read status is received. + /// ~end /// + /// ~chinese + /// 群消息已读变更。 + /// ~end final VoidCallback? onReadAckForGroupMessageUpdated; - /// + /// ~english /// Occurs when a delivery receipt is received. + /// ~end /// + /// ~chinese + /// 收到消息已送达回执的回调。 + /// ~end final void Function(List messages)? onMessagesDelivered; - /// + /// ~english /// Occurs when a received message is recalled. + /// ~end /// + /// ~chinese + /// 已收到的消息被撤回的回调。 + /// ~end final void Function(List messages)? onMessagesRecalled; - /// + /// ~english /// Occurs when the conversation updated. + /// ~end /// + /// ~chinese + /// 会话更新事件回调。 + /// ~end final VoidCallback? onConversationsUpdate; - /// + /// ~english /// Occurs when a conversation read receipt is received. /// /// Occurs in the following scenarios: @@ -241,16 +422,30 @@ class EMChatEventHandler { /// (2) In the multi-device login scenario, when one device sends a Conversation receipt, /// the server will set the number of unread messages to 0, and the callback occurs on the other devices. /// and sets the [EMMessage.hasReadAck] property of the message in the conversation to `true` in the local database. + /// ~end + /// + /// ~chinese + /// 收到会话已读回执的回调。 /// + /// 回调此方法的场景: + /// (1)消息被接收方阅读,即接收方发送了会话已读回执。 + /// SDK 在接收到此事件时,会将本地数据库中该会话中消息的 `isAcked` 属性置为 `true`。 + /// (2)多端多设备登录场景下,一端发送会话已读回执,服务器端会将会话的未读消息数置为 0, + /// 同时其他端会回调此方法,并将本地数据库中该会话中消息的 `isRead` 属性置为 `true`。 + /// ~end final void Function(String from, String to)? onConversationRead; - /// + /// ~english /// Occurs when the Reaction data changes. + /// ~end /// + /// ~chinese + /// 消息表情回复(Reaction)变化监听器。 + /// ~end final void Function(List events)? onMessageReactionDidChange; - /// + /// ~english /// The chat event handler. /// /// Param [onMessagesReceived] Message is received callback. @@ -272,7 +467,31 @@ class EMChatEventHandler { /// Param [onConversationRead] Conversation read receipt is received callback. /// /// Param [onMessageReactionDidChange] Reaction data changes callback. + /// ~end + /// + /// ~chinese + /// 消息事件监听。 + /// + /// Param [onMessagesReceived] 在收到文本、图片、视频、语音、地理位置和文件等消息时,通过此回调通知用户。 + /// + /// Param [onCmdMessagesReceived] 收到命令消息回调。 /// + /// Param [onMessagesRead] 收到单聊消息已读回执的回调。 + /// + /// Param [onGroupMessageRead] 收到群组消息的已读回执的回调。 + /// + /// Param [onReadAckForGroupMessageUpdated] 群消息已读变更。 + /// + /// Param [onMessagesDelivered] 收到消息已送达回执的回调。 + /// + /// Param [onMessagesRecalled] 已收到的消息被撤回的回调。 + /// + /// Param [onConversationsUpdate] 会话更新事件回调。 + /// + /// Param [onConversationRead] 收到会话已读回执的回调。 + /// + /// Param [onMessageReactionDidChange] 消息表情回复(Reaction)变化监听器。 + /// ~end EMChatEventHandler({ this.onMessagesReceived, this.onCmdMessagesReceived, @@ -287,7 +506,7 @@ class EMChatEventHandler { }); } -/// +/// ~english /// The chat room event handler. /// /// Adds chat event handler: @@ -299,132 +518,216 @@ class EMChatEventHandler { /// ```dart /// EMClient.getInstance.chatRoomManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` +/// ~end +/// +/// ~chinese +/// 聊天室事件监听。 /// +/// 添加监听: +/// ```dart +/// EMClient.getInstance.chatRoomManager.addEventHandler(UNIQUE_HANDLER_ID, EMChatRoomEventHandler()); +/// ``` +/// +/// Remove a chat room event handler: +/// ```dart +/// EMClient.getInstance.chatRoomManager.removeEventHandler(UNIQUE_HANDLER_ID); +/// ``` +/// ~end class EMChatRoomEventHandler { - /// + /// ~english /// Occurs when a member has been changed to an admin. + /// ~end /// + /// ~chinese + /// 有成员设置为聊天室管理员的回调。 + /// ~end final void Function( String roomId, String admin, )? onAdminAddedFromChatRoom; - /// + /// ~english /// Occurs when an admin is been removed. + /// ~end /// + /// ~chinese + /// 移除聊天室管理员权限的回调。 + /// ~end final void Function( String roomId, String admin, )? onAdminRemovedFromChatRoom; - /// + /// ~english /// Occurs when all members in the chat room are muted or unmuted. + /// ~end /// + /// ~chinese + /// 聊天室全员禁言状态变化回调。 + /// ~end final void Function( String roomId, bool isAllMuted, )? onAllChatRoomMemberMuteStateChanged; - /// + /// ~english /// Occurs when the chat room member(s) is added to the allowlist. + /// ~end /// + /// ~chinese + /// 有成员被加入聊天室白名单的回调。 + /// ~end final void Function( String roomId, List members, )? onAllowListAddedFromChatRoom; - /// + /// ~english /// Occurs when the chat room member(s) is removed from the allowlist. + /// ~end /// + /// ~chinese + /// 有成员被移出聊天室白名单的回调。 + /// ~end final void Function( String roomId, List members, )? onAllowListRemovedFromChatRoom; - /// + /// ~english /// Occurs when the announcement changed. + /// ~end /// + /// ~chinese + /// 聊天室公告更新回调。 + /// ~end final void Function( String roomId, String announcement, )? onAnnouncementChangedFromChatRoom; - /// + /// ~english /// Occurs when the chat room is destroyed. + /// ~end /// + /// ~chinese + /// 聊天室解散的回调。 + /// ~end final void Function( String roomId, String? roomName, )? onChatRoomDestroyed; - /// + /// ~english /// Occurs when a member leaves the chatroom. + /// ~end /// + /// ~chinese + /// 聊天室成员主动退出回调。 + /// ~end final void Function( String roomId, String? roomName, String participant, )? onMemberExitedFromChatRoom; - /// + /// ~english /// Occurs when a member join the chatroom. + /// ~end /// + /// ~chinese + /// 聊天室加入新成员回调。 + /// ~end final void Function(String roomId, String participant)? onMemberJoinedFromChatRoom; - /// + /// ~english /// Occurs when there are chat room member(s) muted (added to mute list), + /// ~end /// + /// ~chinese + /// 有成员被禁言回调。 + /// ~end final void Function( String roomId, List mutes, String? expireTime, )? onMuteListAddedFromChatRoom; - /// + /// ~english /// Occurs when there are chat room member(s) unmuted (removed from mute list). + /// ~end /// + /// ~chinese + /// 有成员从禁言列表中移除回调。 + /// ~end final void Function( String roomId, List mutes, )? onMuteListRemovedFromChatRoom; + /// ~english + /// Occurs when the chat room ownership has been transferred. + /// ~end /// - /// Occurs when the chat room ownership has been transferred. - /// + /// ~chinese + /// 转移聊天室的所有权的回调。 + /// ~end final void Function( String roomId, String newOwner, String oldOwner, )? onOwnerChangedFromChatRoom; - /// + /// ~english /// Occurs when a member is dismissed from a chat room. + /// ~end /// + /// ~chinese + /// 聊天室成员被移出聊天室回调。 + /// ~end final void Function( String roomId, String? roomName, String? participant, )? onRemovedFromChatRoom; + /// ~english /// Occurs when the chat room specifications changes. All chat room members receive this event. + /// ~end + /// + /// ~chinese + /// 聊天室详情变更。 + /// ~end final void Function(EMChatRoom room)? onSpecificationChanged; + /// ~english /// Occurs when the custom chat room attributes (key-value) are updated. + /// ~end + /// + /// ~chinese + /// 聊天室属性变更。 + /// ~end final void Function( String roomId, Map attributes, String from, )? onAttributesUpdated; + /// ~english /// Occurs when the custom chat room attributes (key-value) are removed. + /// ~end + /// + /// ~chinese + /// 聊天室属性被删除。 + /// ~end final void Function( String roomId, List removedKeys, String from, )? onAttributesRemoved; - /// + /// ~english /// The chat room manager listener callback. /// /// Param [onAdminAddedFromChatRoom] A member has been changed to an admin callback. @@ -458,7 +761,43 @@ class EMChatRoomEventHandler { /// Param [onAttributesUpdated] The chat room attributes updated callback. /// /// Param [onAttributesRemoved] The chat room attributes removed callback. + /// ~end + /// + /// ~chinese + /// 聊天室事件监听。 + /// + /// Param [onAdminAddedFromChatRoom] 有成员设置为聊天室管理员的回调。 + /// + /// Param [onAdminRemovedFromChatRoom] 移除聊天室管理员权限的回调。 + /// + /// Param [onAllChatRoomMemberMuteStateChanged] 聊天室全员禁言状态变化回调。 + /// + /// Param [onAllowListAddedFromChatRoom] 有成员被加入聊天室白名单的回调。 + /// + /// Param [onAllowListRemovedFromChatRoom] 有成员被移出聊天室白名单的回调。 + /// + /// Param [onAnnouncementChangedFromChatRoom] 聊天室公告更新回调。 + /// + /// Param [onChatRoomDestroyed] 聊天室解散的回调。 /// + /// Param [onMemberExitedFromChatRoom] 聊天室成员主动退出回调。 + /// + /// Param [onMemberJoinedFromChatRoom] 聊天室加入新成员回调。 + /// + /// Param [onMuteListAddedFromChatRoom] 有成员被禁言回调。 + /// + /// Param [onMuteListRemovedFromChatRoom] 有成员从禁言列表中移除回调。 + /// + /// Param [onOwnerChangedFromChatRoom] 转移聊天室的所有权的回调。 + /// + /// Param [onRemovedFromChatRoom] 聊天室成员被移出聊天室回调。 + /// + /// Param [onSpecificationChanged] 聊天室详情变更。 + /// + /// Param [onAttributesUpdated] 聊天室属性变更。 + /// + /// Param [onAttributesRemoved] 聊天室属性被删除。 + /// ~end EMChatRoomEventHandler({ this.onAdminAddedFromChatRoom, this.onAdminRemovedFromChatRoom, @@ -479,7 +818,7 @@ class EMChatRoomEventHandler { }); } -/// +/// ~english /// The message thread event handler. which handle for message thread events such as creating or leaving a message thread. /// /// Adds a message thread event handler: @@ -491,45 +830,77 @@ class EMChatRoomEventHandler { /// ```dart /// EMClient.getInstance.chatThreadManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` +/// ~end +/// +/// ~chinese +/// Thread 事件监听 /// +/// 添加监听: +/// ```dart +/// EMClient.getInstance.chatThreadManager.addEventHandler(UNIQUE_HANDLER_ID, EMChatThreadEventHandler()); +/// ``` +/// +/// 移除监听: +/// ```dart +/// EMClient.getInstance.chatThreadManager.removeEventHandler(UNIQUE_HANDLER_ID); +/// ``` +/// ~end class EMChatThreadEventHandler { - /// + /// ~english /// Occurs when a message thread is created. /// /// Each member of the group to which the message thread belongs can receive the callback. + /// ~end /// + /// ~chinese + /// 子区创建回调。 + /// ~end final void Function( EMChatThreadEvent event, )? onChatThreadCreate; - /// + /// ~english /// Occurs when a message thread is destroyed. /// /// Each member of the group to which the message thread belongs can receive the callback. + /// ~end /// + /// ~chinese + /// 子区解散事件。 + /// 子区所属群组的所有成员均可调用该方法。 + /// ~end final void Function( EMChatThreadEvent event, )? onChatThreadDestroy; - /// + /// ~english /// Occurs when a message thread is updated. /// /// This callback is triggered when the message thread name is changed or a threaded reply is added or recalled. /// /// Each member of the group to which the message thread belongs can receive the callback. + /// ~end /// + /// ~chinese + /// 子区更新回调。 + /// 子区所属群组的所有成员均可调用该方法。 + /// ~end final void Function( EMChatThreadEvent event, )? onChatThreadUpdate; - /// + /// ~english /// Occurs when the current user is removed from the message thread by the group owner or a group admin to which the message thread belongs. + /// ~end /// + /// ~chinese + /// 管理员移除子区用户的回调。 + /// ~end final void Function( EMChatThreadEvent event, )? onUserKickOutOfChatThread; - /// + /// ~english /// The message thread listener callback /// /// Param [onChatThreadCreate] A message thread is created callback. @@ -539,7 +910,19 @@ class EMChatThreadEventHandler { /// Param [onChatThreadUpdate] A message thread is updated callback. /// /// Param [onUserKickOutOfChatThread] Current user is removed from the message thread by the group owner or a group admin to which the message thread belongs callback. + /// ~end /// + /// ~chinese + /// Thread 事件监听 + /// + /// Param [onChatThreadCreate] 子区创建回调。 + /// + /// Param [onChatThreadDestroy] 子区解散事件, 子区所属群组的所有成员均可调用该方法。 + /// + /// Param [onChatThreadUpdate] 子区更新回调, 子区所属群组的所有成员均可调用该方法。 + /// + /// Param [onUserKickOutOfChatThread] 管理员移除子区用户的回调。 + /// ~end EMChatThreadEventHandler({ this.onChatThreadCreate, this.onChatThreadDestroy, @@ -548,7 +931,7 @@ class EMChatThreadEventHandler { }); } -/// +/// ~english /// The contact event handler. /// /// Occurs when the contact changes, including requests to add friends, notifications to delete friends, @@ -563,45 +946,79 @@ class EMChatThreadEventHandler { /// ```dart /// EMClient.getInstance.contactManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` +/// ~end +/// +/// ~chinese +/// 联系人事件监听 +/// +/// 添加监听: +/// ```dart +/// EMClient.getInstance.contactManager.addEventHandler(UNIQUE_HANDLER_ID, EMContactEventHandler()); +/// ``` /// +/// 移除监听: +/// ```dart +/// EMClient.getInstance.contactManager.removeEventHandler(UNIQUE_HANDLER_ID); +/// ``` +/// ~end class EMContactEventHandler { - /// + /// ~english /// Occurs when user is added as a contact by another user. + /// ~end /// + /// ~chinese + /// 添加好友回调。 + /// ~end final void Function( String userId, )? onContactAdded; - /// + /// ~english /// Occurs when a user is removed from the contact list by another user. + /// ~end /// + /// ~chinese + /// 删除好友回调。 + /// ~end final void Function( String userId, )? onContactDeleted; - /// + /// ~english /// Occurs when a user receives a friend request. + /// ~end /// + /// ~chinese + /// 好友申请回调。 + /// ~end final void Function( String userId, String? reason, )? onContactInvited; - /// + /// ~english /// Occurs when a friend request is approved. + /// ~end /// + /// ~chinese + /// 发出的好友申请被对方同意。 + /// ~end final void Function( String userId, )? onFriendRequestAccepted; - /// + /// ~english /// Occurs when a friend request is declined. + /// ~end /// + /// ~chinese + /// 发出的好友申请被对方拒绝。 + /// ~end final void Function( String userId, )? onFriendRequestDeclined; - /// + /// ~english /// The contact updates listener callback. /// /// Param [onContactAdded] Current user is added as a contact by another user callback. @@ -613,7 +1030,21 @@ class EMContactEventHandler { /// Param [onFriendRequestAccepted] A friend request is approved callback. /// /// Param [onFriendRequestDeclined] A friend request is declined callback. + /// ~end + /// + /// ~chinese + /// 联系人事件监听。 + /// + /// Param [onContactAdded] 添加好友回调。 + /// + /// Param [onContactDeleted] 删除好友回调。 /// + /// Param [onContactInvited] 好友申请回调。 + /// + /// Param [onFriendRequestAccepted] 发出的好友申请被对方同意。 + /// + /// Param [onFriendRequestDeclined] 发出的好友申请被对方拒绝。 + /// ~end EMContactEventHandler({ this.onContactAdded, this.onContactDeleted, @@ -623,7 +1054,7 @@ class EMContactEventHandler { }); } -/// +/// ~english /// The group event handler. /// /// Occurs when the following group events happens: requesting to join a group, approving or declining a group request, and kicking a user out of a group. @@ -637,96 +1068,156 @@ class EMContactEventHandler { /// ```dart /// EMClient.getInstance.groupManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` +/// ~end +/// +/// ~chinese +/// 群组事件监听 +/// +/// 添加监听: +/// ```dart +/// EMClient.getInstance.groupManager.addEventHandler(UNIQUE_HANDLER_ID, EMGroupEventHandler()); +/// ``` /// +/// 移除监听: +/// ```dart +/// EMClient.getInstance.groupManager.removeEventHandler(UNIQUE_HANDLER_ID); +/// ``` +/// ~end class EMGroupEventHandler { - /// + /// ~english /// Occurs when a member is set as an admin. + /// ~end /// + /// ~chinese + /// 成员设置为管理员的回调。 + /// ~end final void Function( String groupId, String admin, )? onAdminAddedFromGroup; - /// + /// ~english /// Occurs when a member's admin privileges are removed. + /// ~end /// + /// ~chinese + /// 取消成员的管理员权限的回调。 + /// ~end final void Function( String groupId, String admin, )? onAdminRemovedFromGroup; - /// + /// ~english /// Occurs when all group members are muted or unmuted. + /// ~end /// + /// ~chinese + /// 全员禁言状态变化回调。 + /// ~end final void Function( String groupId, bool isAllMuted, )? onAllGroupMemberMuteStateChanged; - /// + /// ~english /// Occurs when one or more group members are added to the allowlist. + /// ~end /// + /// ~chinese + /// 成员加入群组白名单回调。 + /// ~end final void Function( String groupId, List members, )? onAllowListAddedFromGroup; - /// + /// ~english /// Occurs when one or more members are removed from the allowlist. + /// ~end /// + /// ~chinese + /// 成员移出群组白名单回调。 + /// ~end final void Function( String groupId, List members, )? onAllowListRemovedFromGroup; - /// + /// ~english /// Occurs when the announcement is updated. + /// ~end /// + /// ~chinese + /// 群公告更新回调。 + /// ~end final void Function( String groupId, String announcement, )? onAnnouncementChangedFromGroup; - /// + /// ~english /// Occurs when the group invitation is accepted automatically. /// For settings, See [EMOptions.autoAcceptGroupInvitation]. /// The SDK will join the group before notifying the app of the acceptance of the group invitation. + /// ~end /// + /// ~chinese + /// 当前用户自动同意入群邀请的回调。 + /// 设置请见 [EMOptions.autoAcceptGroupInvitation]. + /// ~end final void Function( String groupId, String inviter, String? inviteMessage, )? onAutoAcceptInvitationFromGroup; - /// + /// ~english /// Occurs when a group is destroyed. + /// ~end /// + /// ~chinese + /// 当前用户收到群组被解散的回调。 + /// ~end final void Function( String groupId, String? groupName, )? onGroupDestroyed; - /// + /// ~english /// Occurs when a group invitation is accepted. + /// ~end /// + /// ~chinese + /// 当前用户收到对端用户同意入群邀请触发的回调。 + /// ~end final void Function( String groupId, String invitee, String? reason, )? onInvitationAcceptedFromGroup; - /// + /// ~english /// Occurs when a group invitation is declined. + /// ~end /// + /// ~chinese + /// 当前用户收到群组邀请被拒绝的回调。 + /// 该回调是由当前用户收到对端用户拒绝入群邀请触发的。例如,用户 B 拒绝了用户 A 的群组邀请,用户 A 会收到该回调。 + /// ~end final void Function( String groupId, String invitee, String? reason, )? onInvitationDeclinedFromGroup; - /// + /// ~english /// Occurs when the user receives a group invitation. + /// ~end /// + /// ~chinese + /// 当前用户收到入群邀请的回调。 + /// ~end final void Function( String groupId, String? groupName, @@ -734,64 +1225,93 @@ class EMGroupEventHandler { String? reason, )? onInvitationReceivedFromGroup; - /// + /// ~english /// Occurs when a member proactively leaves the group. + /// ~end /// + /// ~chinese + /// 群组成员主动退出回调。 + /// ~end final void Function( String groupId, String member, )? onMemberExitedFromGroup; - /// + /// ~english /// Occurs when a member joins a group. + /// ~end /// + /// ~chinese + /// 新成员加入群组的回调。 + /// ~end final void Function( String groupId, String member, )? onMemberJoinedFromGroup; - /// + /// ~english /// Occurs when one or more group members are muted. /// /// Note: The mute function is different from a block list. /// A user, when muted, can still see group messages, but cannot send messages in the group. /// However, a user on the block list can neither see nor send group messages. + /// ~end /// + /// ~chinese + /// 有成员被禁言回调。 + /// 用户禁言后,将无法在群中发送消息,但可查看群组中的消息,而黑名单中的用户无法查看和发送群组消息。 + /// ~end final void Function( String groupId, List mutes, int? muteExpire, )? onMuteListAddedFromGroup; - /// + /// ~english /// Occurs when one or more group members are unmuted. + /// ~end /// + /// ~chinese + /// 有成员被解除禁言的回调。 + /// ~end final void Function( String groupId, List mutes, )? onMuteListRemovedFromGroup; - /// + /// ~english /// Occurs when the group ownership is transferred. + /// ~end /// + /// ~chinese + /// 转移群主权限的回调。 + /// ~end final void Function( String groupId, String newOwner, String oldOwner, )? onOwnerChangedFromGroup; - /// + /// ~english /// Occurs when a group request is accepted. + /// ~end /// + /// ~chinese + /// 对端用户接受当前用户发送的群组申请的回调。 + /// ~end final void Function( String groupId, String? groupName, String accepter, )? onRequestToJoinAcceptedFromGroup; - /// + /// ~english /// Occurs when a group request is declined. + /// ~end /// + /// ~chinese + /// 对端用户拒绝群组申请的回调。 + /// ~end final void Function( String groupId, String? groupName, @@ -799,9 +1319,13 @@ class EMGroupEventHandler { String? reason, )? onRequestToJoinDeclinedFromGroup; - /// + /// ~english /// Occurs when the group owner or administrator receives a group request from a user. + /// ~end /// + /// ~chinese + /// 对端用户接收群组申请的回调。 + /// ~end final void Function( String groupId, String? groupName, @@ -809,42 +1333,66 @@ class EMGroupEventHandler { String? reason, )? onRequestToJoinReceivedFromGroup; - /// + /// ~english /// Occurs when a shared file is added to a group. + /// ~end /// + /// ~chinese + /// 群组添加共享文件回调。 + /// ~end final void Function( String groupId, EMGroupSharedFile sharedFile, )? onSharedFileAddedFromGroup; + /// ~english /// Occurs when the group detail information is updated. + /// ~end + /// + /// ~chinese + /// 群详情变更回调。 + /// ~end final void Function( EMGroup group, )? onSpecificationDidUpdate; + /// ~english /// Occurs when the group is enabled or disabled. + /// ~end + /// + /// ~chinese + /// 群是禁用状态变更。 + /// ~end final void Function( String groupId, bool isDisable, )? onDisableChanged; - /// + /// ~english /// Occurs when a shared file is removed from a group. + /// ~end /// + /// ~chinese + /// 群组删除共享文件回调。 + /// ~end final void Function( String groupId, String fileId, )? onSharedFileDeletedFromGroup; - /// + /// ~english /// Occurs when the current user is removed from the group by the group admin. + /// ~end /// + /// ~chinese + /// 当前用户被移出群组时的回调。 + /// ~end final void Function( String groupId, String? groupName, )? onUserRemovedFromGroup; - /// + /// ~english /// The group manager listener callback. /// /// Param [onAdminAddedFromGroup] A member is set as an admin callback. @@ -853,9 +1401,9 @@ class EMGroupEventHandler { /// /// Param [onAllGroupMemberMuteStateChanged] All group members are muted or unmuted callback. /// - /// Param [onAllowListAddedFromGroup] Ane or more group members are muted callback. + /// Param [onAllowListAddedFromGroup] One or more group members are muted callback. /// - /// Param [onAllowListRemovedFromGroup] Ane or more group members are unmuted callback. + /// Param [onAllowListRemovedFromGroup] One or more group members are unmuted callback. /// /// Param [onAnnouncementChangedFromGroup] The announcement is updated callback. /// @@ -893,8 +1441,60 @@ class EMGroupEventHandler { /// /// Param [onSpecificationDidUpdate] Occurs when the group detail information is updated. /// - /// Param [onDisableChanged] /// Occurs when the group is enabled or disabled. + /// Param [onDisableChanged] Occurs when the group is enabled or disabled. + /// ~end + /// + /// ~chinese + /// 群组时间监听 + /// + /// Param [onAdminAddedFromGroup] 成员设置为管理员的回调。 + /// + /// Param [onAdminRemovedFromGroup] 取消成员的管理员权限的回调。 + /// + /// Param [onAllGroupMemberMuteStateChanged] 全员禁言状态变化回调。 + /// + /// Param [onAllowListAddedFromGroup] 成员加入群组白名单回调。 + /// + /// Param [onAllowListRemovedFromGroup] 成员移出群组白名单回调。 + /// + /// Param [onAnnouncementChangedFromGroup] 群公告更新回调。 /// + /// Param [onAutoAcceptInvitationFromGroup] 当前用户自动同意入群邀请的回调, 设置请见 [EMOptions.autoAcceptGroupInvitation]。 + /// + /// Param [onGroupDestroyed] 当前用户收到群组被解散的回调。 + /// + /// Param [onInvitationAcceptedFromGroup] 当前用户收到对端用户同意入群邀请触发的回调。 + /// + /// Param [onInvitationDeclinedFromGroup] 当前用户收到群组邀请被拒绝的回调。 + /// + /// Param [onInvitationReceivedFromGroup] 当前用户收到入群邀请的回调。 + /// + /// Param [onMemberExitedFromGroup] 群组成员主动退出回调。 + /// + /// Param [onMemberJoinedFromGroup] 新成员加入群组的回调。 + /// + /// Param [onMuteListAddedFromGroup] 有成员被禁言回调, 用户禁言后,将无法在群中发送消息,但可查看群组中的消息,而黑名单中的用户无法查看和发送群组消息。 + /// + /// Param [onMuteListRemovedFromGroup] 有成员被解除禁言的回调。 + /// + /// Param [onOwnerChangedFromGroup] 转移群主权限的回调。 + /// + /// Param [onRequestToJoinAcceptedFromGroup] 对端用户接受当前用户发送的群组申请的回调。 + /// + /// Param [onRequestToJoinDeclinedFromGroup] 对端用户拒绝群组申请的回调。 + /// + /// Param [onRequestToJoinReceivedFromGroup] 对端用户接收群组申请的回调。 + /// + /// Param [onSharedFileAddedFromGroup] 群组添加共享文件回调。 + /// + /// Param [onSharedFileDeletedFromGroup] 群组删除共享文件回调。 + /// + /// Param [onUserRemovedFromGroup] 当前用户被移出群组时的回调。 + /// + /// Param [onSpecificationDidUpdate] 群详情变更回调。 + /// + /// Param [onDisableChanged] 群是禁用状态变更。 + /// ~end EMGroupEventHandler({ this.onAdminAddedFromGroup, this.onAdminRemovedFromGroup, @@ -923,7 +1523,7 @@ class EMGroupEventHandler { }); } -/// +/// ~english /// The presence event handler. /// /// Occurs when the following presence events happens: presence status changed. @@ -937,18 +1537,40 @@ class EMGroupEventHandler { /// ```dart /// EMClient.getInstance.presenceManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` +/// ~end +/// +/// ~chinese +/// 订阅用户状态变更监听 +/// +/// 添加监听: +/// ```dart +/// EMClient.getInstance.presenceManager.addEventHandler(UNIQUE_HANDLER_ID, EMPresenceEventHandler()); +/// ``` /// +/// 移除监听: +/// ```dart +/// EMClient.getInstance.presenceManager.removeEventHandler(UNIQUE_HANDLER_ID); +/// ``` +/// ~end class EMPresenceEventHandler { - /// + /// ~english /// Occurs when the presence state of a subscribed user changes. + /// ~end /// + /// ~chinese + /// 收到被订阅用户的在线状态发生变化。 + /// ~end final Function(List list)? onPresenceStatusChanged; - /// + /// ~english /// The presence manager listener callback. /// /// Param [onPresenceStatusChanged] The presence state of a subscribed user changes callback. + /// ~end /// + /// ~chinese + /// 订阅用户状态变更监听。 + /// ~end EMPresenceEventHandler({ this.onPresenceStatusChanged, }); diff --git a/lib/src/internal/em_push_config.dart b/lib/src/internal/em_push_config.dart index b4888a8c..14c17d12 100644 --- a/lib/src/internal/em_push_config.dart +++ b/lib/src/internal/em_push_config.dart @@ -1,7 +1,9 @@ /// @nodoc import 'inner_headers.dart'; +/// ~english /// The push configuration class, which contains the push configuration information, such as the push style. +/// ~end class EMPushConfig { String? mzAppId = ''; String? mzAppKey = ''; diff --git a/lib/src/internal/inner_headers.dart b/lib/src/internal/inner_headers.dart index 3493c392..0f0b0c37 100644 --- a/lib/src/internal/inner_headers.dart +++ b/lib/src/internal/inner_headers.dart @@ -1,5 +1,4 @@ /// @nodoc -export '../em_listeners.dart'; export 'chat_method_keys.dart'; export 'em_channel_manager.dart'; @@ -39,7 +38,7 @@ export '../em_chat_thread_manager.dart'; export '../em_client.dart'; export '../em_contact_manager.dart'; export '../em_group_manager.dart'; -export '../em_message_status_callback.dart'; + export '../em_presence_manager.dart'; export '../em_push_manager.dart'; export '../em_userInfo_manager.dart'; diff --git a/lib/src/models/chat_silent_mode.dart b/lib/src/models/chat_silent_mode.dart index 82808410..0cd84f34 100644 --- a/lib/src/models/chat_silent_mode.dart +++ b/lib/src/models/chat_silent_mode.dart @@ -1,28 +1,62 @@ import '../internal/inner_headers.dart'; +/// ~english +/// Offline push Settings parameter entity class. +/// ~end /// -/// Offline push Settings parameter entity class -/// +/// ~chinese +/// 离线推送设置参数类。 +/// ~end class ChatSilentModeParam { final ChatSilentModeParamType _paramType; + /// ~english /// The offline push notification type. + /// ~end + /// + /// ~chinese + /// 离线推送通知类型。 + /// ~end final ChatPushRemindType? remindType; + /// ~english /// The start time of offline push DND. + /// ~end + /// + /// ~chinese + /// 离线推送免打扰的开始时间。 + /// ~end final ChatSilentModeTime? startTime; + /// ~english /// The end time of offline push DND. + /// ~end + /// + /// ~chinese + /// 离线推送免打扰结束时间。 + /// ~end final ChatSilentModeTime? endTime; + /// ~english /// The offline push DND duration. + /// ~end + /// + /// ~chinese + /// 离线push免打扰时长。 + /// ~end final int? silentDuration; - /// + /// ~english /// Set the offline push notification type. /// /// Param [remindType] Offline push notification type. + /// ~end + /// + /// ~chinese + /// 设置离线推送通知类型。 /// + /// Param [remindType] 离线推送通知类型。 + /// ~end ChatSilentModeParam.remindType( this.remindType, ) : this.silentDuration = null, @@ -30,24 +64,37 @@ class ChatSilentModeParam { this.endTime = null, this._paramType = ChatSilentModeParamType.REMIND_TYPE; - /// + /// ~english /// Set the offline push DND duration. /// /// Param [silentDuration] Offline push DND duration, units of minutes. + /// ~end /// + /// ~chinese + /// 设置离线推免打扰时长。 + /// Param [silentDuration] 离线推送免打扰时长,单位为分钟。 + /// ~end ChatSilentModeParam.silentDuration(this.silentDuration) : this.startTime = null, this.endTime = null, this.remindType = null, this._paramType = ChatSilentModeParamType.SILENT_MODE_DURATION; - /// + /// ~english /// Set the start time of offline push DND, you need to create the start time and end time together. /// /// Param [startTime] Do not disturb start time. /// /// Param [endTime] Do not disturb end time. + /// ~end + /// + /// ~chinese + /// 设置离线推送免打扰的开始时间,需要同时创建开始时间和结束时间。 /// + /// Param [startTime] 免扰乱开始时间。 + /// + /// Param [endTime] 免扰乱结束时间。 + /// ~end ChatSilentModeParam.silentModeInterval({ required this.startTime, required this.endTime, @@ -66,23 +113,47 @@ class ChatSilentModeParam { } } -/// +/// ~english /// For offline push DND time class. +/// ~end /// +/// ~chinese +/// 用于离线推送免打扰时间类。 +/// ~end class ChatSilentModeTime { + /// ~english /// Number of hours. + /// ~end + /// + /// ~chinese + /// 小时数。 + /// ~end final int hour; + /// ~english /// Minutes. + /// ~end + /// + /// ~chinese + /// 分钟 + /// ~end final int minute; - /// + /// ~english /// For offline push DND time. /// /// Param [hour] Set the number of hours to 24 hours. /// /// Param [minute] Set minutes. + /// ~end + /// + /// ~chinese + /// 用于离线推送免打扰时间。 /// + /// Param [hour] 设置小时数,为24小时制。 + /// + /// Param [minute] 设置分钟数。 + /// ~end ChatSilentModeTime({ this.minute = 0, this.hour = 0, @@ -103,29 +174,75 @@ class ChatSilentModeTime { } } -/// +/// ~english /// Offline push DND result class. +/// ~end /// +/// ~chinese +/// 离线推送免打扰结果。 +/// ~end class ChatSilentModeResult { + /// ~english /// Obtain the offline push DND expiration timestamp. + /// ~end + /// + /// ~chinese + /// 获取离线推送免打扰到期时间戳。 + /// ~end final int? expireTimestamp; + /// ~english /// The Conversation Type. + /// ~end + /// + /// ~chinese + /// 会话类型 + /// ~end final EMConversationType conversationType; + /// ~english /// The Conversation ID. + /// ~end + /// + /// ~chinese + /// 会话ID + /// ~end final String conversationId; + /// ~english /// The offline push notification type. + /// ~end + /// + /// ~chinese + /// 离线推送通知类型。 + /// ~end final ChatPushRemindType? remindType; + /// ~english /// The start time of offline push DND. + /// ~end + /// + /// ~chinese + /// 离线推送免打扰的开始时间。 + /// ~end final ChatSilentModeTime? startTime; + /// ~english /// The end time of offline push DND. + /// ~end + /// + /// ~chinese + /// 离线推送免打扰结束时间。 + /// ~end final ChatSilentModeTime? endTime; - /// @nodoc + /// ~english + /// Offline push DND result class. + /// ~end + /// + /// ~chinese + /// 离线推送免打扰结果类。 + /// ~end ChatSilentModeResult( this.expireTimestamp, this.conversationType, diff --git a/lib/src/models/em_chat_enums.dart b/lib/src/models/em_chat_enums.dart index 4fa93b10..8bceb79c 100644 --- a/lib/src/models/em_chat_enums.dart +++ b/lib/src/models/em_chat_enums.dart @@ -1,353 +1,972 @@ -/// +/// ~english /// The enumeration of group types. +/// ~end /// +/// ~chinese +/// 群组类型枚举。 +/// ~end enum EMGroupStyle { + /// ~english /// Private groups where only the the group owner can invite users to join. + /// ~end + /// + /// ~chinese + /// 私有群组,创建完成后,只允许群主邀请用户加入。 + /// ~end PrivateOnlyOwnerInvite, + /// ~english /// Private groups where all group members can invite users to join. + /// ~end + /// + /// ~chinese + /// 私有群组,创建完成后,只允许群主和群成员邀请用户加入。 + /// ~end PrivateMemberCanInvite, + /// ~english /// Public groups where users can join only after receiving an invitation from the group owner(admin) or the joining request being approved by the group owner(admin). + /// ~end + /// + /// ~chinese + /// 公开群组,创建完成后,只允许群主邀请用户加入;非群成员用户需发送入群申请,群主同意后才能入群。 + /// ~end PublicJoinNeedApproval, + /// ~english /// Public groups where users can join freely. + /// ~end + /// + /// ~chinese + /// 公开群组,创建完成后,允许非群组成员加入,无需群主同意。 + /// ~end PublicOpenJoin, } +/// ~english /// The conversation types. +/// ~end +/// +/// ~chinese +/// 会话类型枚举。 +/// ~end enum EMConversationType { + /// ~english /// One-to-one chat. + /// ~end + /// + /// ~chinese + /// 单聊。 + /// ~end Chat, + /// ~english /// Group chat. + /// ~end + /// + /// ~chinese + /// 群聊。 + /// ~end GroupChat, + /// ~english /// Chat room. + /// ~end + /// + /// ~chinese + /// 聊天室。 + /// ~end ChatRoom, } -/// +/// ~english /// The enumeration of chat types. /// /// There are three chat types: one-to-one chat, group chat, and chat room. +/// ~end /// +/// ~chinese +/// 会话类型枚举。 +/// ~end enum ChatType { + /// ~english /// One-to-one chat. + /// ~end + /// + /// ~chinese + /// 单聊。 + /// ~end Chat, + /// ~english /// Group chat. + /// ~end + /// + /// ~chinese + /// 群聊。 + /// ~end GroupChat, + /// ~english /// Chat room. + /// ~end + /// + /// ~chinese + /// 聊天室。 + /// ~end ChatRoom, } -/// +/// ~english /// The enumeration of the message directions. /// /// Whether the message is sent or received. +/// ~end +/// +/// ~chinese +/// 消息的方向类型枚举类。 /// +/// 区分是发送消息还是接收到的消息。 +/// ~end enum MessageDirection { + /// ~english /// This message is sent from the local user. + /// ~end + /// + /// ~chinese + /// 该消息是当前用户发送出去的。 + /// ~end SEND, + /// ~english /// The message is received by the local user. + /// ~end + /// + /// ~chinese + /// 该消息是当前用户接收到的。 + /// ~end RECEIVE, } -/// +/// ~english /// The enumeration of the message sending/reception status. +/// ~end /// +/// ~chinese +/// 消息的发送/接收状态枚举类。 +/// ~end enum MessageStatus { + /// ~english /// The message is created. + /// ~end + /// + /// ~chinese + /// 消息已创建待发送。 + /// ~end CREATE, + /// ~english /// The message is being delivered/received. + /// ~end + /// + /// ~chinese + /// 正在发送/接收。 + /// ~end PROGRESS, + /// ~english /// The message is successfully delivered/received. + /// ~end + /// + /// ~chinese + /// 发送/接收成功。 + /// ~end SUCCESS, + /// ~english /// The message fails to be delivered/received. + /// ~end + /// + /// ~chinese + /// 发送/接收失败。 + /// ~end FAIL, } -/// +/// ~english /// The download status of the attachment file. +/// ~end /// +/// ~chinese +/// 消息附件的下载状态。 +/// ~end enum DownloadStatus { + /// ~english /// The file message download is pending. + /// ~end + /// + /// ~chinese + /// 等待下载。 + /// ~end PENDING, + /// ~english /// The file message is being downloaded. + /// ~end + /// + /// ~chinese + /// 正在下载。 + /// ~end DOWNLOADING, + /// ~english /// The file message download succeeds. + /// ~end + /// + /// ~chinese + /// 下载成功。 + /// ~end SUCCESS, + /// ~english /// The file message download fails. + /// ~end + /// + /// ~chinese + /// 下载失败。 + /// ~end FAILED, } -/// +/// ~english /// The enumeration of message types. +/// ~end /// +/// ~chinese +/// 消息类型枚举。 +/// ~end enum MessageType { + /// ~english /// The text message. + /// ~end + /// + /// ~chinese + /// 文本消息。 + /// ~end TXT, + /// ~english /// The image message. + /// ~end + /// + /// ~chinese + /// 图片消息。 + /// ~end IMAGE, + /// ~english /// The video message. + /// ~end + /// + /// ~chinese + /// 视频消息。 + /// ~end VIDEO, + /// ~english /// The location message. + /// ~end + /// + /// ~chinese + /// 位置消息。 + /// ~end LOCATION, + /// ~english /// The voice message. + /// ~end + /// + /// ~chinese + /// 语音消息。 + /// ~end VOICE, + /// ~english /// The file message. + /// ~end + /// + /// ~chinese + /// 文件消息。 + /// ~end FILE, + /// ~english /// The command message. + /// ~end + /// + /// ~chinese + /// 命令消息。 + /// ~end CMD, + /// ~english /// The custom message. + /// ~end + /// + /// ~chinese + /// 自定义消息。 + /// ~end CUSTOM, } -/// +/// ~english /// The enumeration of group permission types. +/// ~end /// +/// ~chinese +/// 群组角色类型枚举。 +/// ~end enum EMGroupPermissionType { + /// ~english /// Unknown. + /// ~end + /// + /// ~chinese + /// 未知类型。 + /// ~end None, + /// ~english /// The group member. + /// ~end + /// + /// ~chinese + /// 群组成员。 + /// ~end Member, + /// ~english /// The group admin. + /// ~end + /// + /// ~chinese + /// 群管理员。 + /// ~end Admin, + /// ~english /// The group owner. + /// ~end + /// + /// ~chinese + /// 群主。 + /// ~end Owner, } -/// +/// ~english /// The enumeration of chat room role types. +/// ~end /// +/// ~chinese +/// 聊天室角色类型枚举。 +/// ~end enum EMChatRoomPermissionType { + /// ~english /// Unknown. + /// ~end + /// + /// ~chinese + /// 未知类型。 + /// ~end None, + /// ~english /// The chat room member. + /// ~end + /// + /// ~chinese + /// 普通成员。 + /// ~end Member, + /// ~english /// The chat room admin. + /// ~end + /// + /// ~chinese + /// 聊天室管理员。 + /// ~end Admin, + /// ~english /// The chat room owner. + /// ~end + /// + /// ~chinese + /// 聊天室所有者。 + /// ~end Owner, } -/// +/// ~english /// The enumeration of message search directions. +/// ~end /// +/// ~chinese +/// 消息检索方向类型枚举。 +/// ~end enum EMSearchDirection { + /// ~english /// Messages are retrieved in the reverse chronological order of when the server receives the message. + /// ~end + /// + /// ~chinese + /// 按消息中的时间戳的倒序搜索。 + /// ~end Up, + /// ~english /// Messages are retrieved in the chronological order of when the server receives the message. + /// ~end + /// + /// ~chinese + /// 按消息中的时间戳的顺序搜索。 + /// ~end Down, } -/// +/// ~english /// Multi-device event types. /// /// This enumeration takes user A logged into both DeviceA1 and DeviceA2 as an example to illustrate the various multi-device event types and when these events are triggered. +/// ~end +/// +/// ~chinese +/// 多设备登录事件类型。 /// +/// 本枚举类以用户 A 同时登录设备 A1 和 设备 A2 为例,描述多设备登录各事件的触发时机。 +/// ~end enum EMMultiDevicesEvent { + /// ~english /// The current user removed a contact on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上删除了好友,则设备 A2 上会收到该事件。 + /// ~end CONTACT_REMOVE, + /// ~english /// The current user accepted a friend request on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上同意了好友请求,则设备 A2 上会收到该事件。 + /// ~end CONTACT_ACCEPT, + /// ~english /// The current user declined a friend request on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上拒绝了好友请求,则设备 A2 上会收到该事件。 + /// ~end CONTACT_DECLINE, + /// ~english /// The current user added a contact to the block list on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上将其他用户加入了黑名单,则设备 A2 上会收到该事件。 + /// ~end CONTACT_BAN, + /// ~english /// The current user removed a contact from the block list on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上将其他用户移出了黑名单,则设备 A2 上会收到该事件。 + /// ~end CONTACT_ALLOW, + /// ~english /// The current user created a group on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上创建了群组,则设备 A2 上会收到该事件。 + /// ~end GROUP_CREATE, + /// ~english /// The current user destroyed a group on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上销毁了群组,则设备 A2 上会收到该事件。 + /// ~end GROUP_DESTROY, + /// ~english /// The current user joined a group on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上加入了群组,则设备 A2 会收到该事件。 + /// ~end GROUP_JOIN, + /// ~english /// The current user left a group on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上退出群组,则设备 A2 会收到该事件。 + /// ~end GROUP_LEAVE, + /// ~english /// The current user requested to join a group on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上申请加入群组,则设备 A2 会收到该事件。 + /// ~end GROUP_APPLY, + /// ~english /// The current user accepted a group request on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上收到了入群申请,则设备 A2 会收到该事件。 + /// ~end GROUP_APPLY_ACCEPT, + /// ~english /// The current user declined a group request on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上拒绝了入群申请,设备 A2 上会收到该事件。 + /// ~end GROUP_APPLY_DECLINE, + /// ~english /// The current user invited a user to join the group on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上邀请了其他用户进入群组,则设备 A2 上会收到该事件。 + /// ~end GROUP_INVITE, + /// ~english /// The current user accepted a group invitation on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上同意了其他用户的群组邀请,则设备 A2 上会收到该事件。 + /// ~end GROUP_INVITE_ACCEPT, + /// ~english /// The current user declined a group invitation on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上拒绝了其他用户的群组邀请,则设备 A2 上会收到该事件。 + /// ~end GROUP_INVITE_DECLINE, + /// ~english /// The current user kicked a member out of a group on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上将其他用户踢出群组,则设备 A2 上会收到该事件。 + /// ~end GROUP_KICK, + /// ~english /// The current user added a member to a group block list on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上被加入黑名单,则设备 A2 上会收到该事件。 + /// ~end GROUP_BAN, + /// ~english /// The current user removed a member from a group block list on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上将其他用户移出群组,则设备 A2 上会收到该事件。 + /// ~end GROUP_ALLOW, + /// ~english /// The current user blocked a group on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上屏蔽了某个群组的消息,设备 A2 上会收到该事件。 + /// ~end GROUP_BLOCK, + /// ~english /// The current user unblocked a group on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上取消屏蔽了某个群组的消息,设备 A2 上会收到该事件。 + /// ~end GROUP_UNBLOCK, + /// ~english /// The current user transferred the group ownership on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上更新了群主,则设备 A2 上会收到该事件。 + /// ~end GROUP_ASSIGN_OWNER, + /// ~english /// The current user added an admin on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上添加了群组管理员,则设备 A2 上会收到该事件。 + /// ~end GROUP_ADD_ADMIN, + /// ~english /// The current user removed an admin on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上移除了群组管理员,则设备 A2 上会收到该事件。 + /// ~end GROUP_REMOVE_ADMIN, + /// ~english /// The current user muted a member on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上禁言了群成员,则设备 A2 上会收到该事件。 + /// ~end GROUP_ADD_MUTE, + /// ~english /// The current user unmuted a member on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上取消禁言了群成员,则设备 A2 上会收到该事件。 + /// ~end GROUP_REMOVE_MUTE, + /// ~english /// The current user added on allow list on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上将其他成员添加到群组白名单中,则设备 A2 上会收到该事件。 + /// ~end GROUP_ADD_USER_ALLOW_LIST, + /// ~english /// The current user removed on allow list on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上将其他成员移除群组白名单,则设备 A2 上会收到该事件。 + /// ~end GROUP_REMOVE_USER_ALLOW_LIST, + /// ~english /// The current user are group ban on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上将所有其他群组成员添加到群组禁言列表,则设备 A2 上会收到该事件。 + /// ~end GROUP_ALL_BAN, + /// ~english /// The current user are remove group ban on another device. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上将所有其他群组成员移除群组禁言列表,则设备 A2 上会收到该事件。 + /// ~end GROUP_REMOVE_ALL_BAN, + /// ~english /// The current user are group disable on another device. + /// ~end + /// + /// ~chinese + /// 用户的群组功能被关闭事件。 + /// ~end GROUP_DISABLED, + /// ~english /// The current user are group able on another device. + /// ~end + /// + /// ~chinese + /// 当前用户的群组功能开启事件。 + /// ~end GROUP_ABLE, + /// ~english /// User A creates an event in the sub-area of device A1, and other devices logged in to this account will receive this event + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上创建了子区,则设备 A2 上会收到该事件。 + /// ~end CHAT_THREAD_CREATE, + /// ~english /// User A destroys the event in the sub-area of device A1, and all other devices logged in to this account will receive this event + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上移除了子区,则设备 A2 上会收到该事件。 + /// ~end CHAT_THREAD_DESTROY, + /// ~english /// User A joins the event in the sub-area of device A1, and other devices logged in to this account will receive this event + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上加入了子区,则设备 A2 上会收到该事件。 + /// ~end CHAT_THREAD_JOIN, + /// ~english /// User A leaves the event in the sub-area of device A1, and other devices logged in to this account will receive this event + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上离开了子区,则设备 A2 上会收到该事件。 + /// ~end CHAT_THREAD_LEAVE, + /// ~english /// User A updates the event in the sub-area of device A1, and other devices logged in to this account will receive this event + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上更新了子区信息,则设备 A2 上会收到该事件。 + /// ~end CHAT_THREAD_UPDATE, + /// ~english /// User A is kicked in the sub-area of device A1, and all other devices that log in to this account will receive this event + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 上将其他用户踢出子区,则设备 A2 上会收到该事件。 + /// ~end CHAT_THREAD_KICK, } -/// +/// ~english /// The message thread event types. +/// ~end /// +/// ~chinese +/// 子区事件类型枚举。 +/// ~end enum EMChatThreadOperation { + /// ~english /// The unknown type of message thread event. + /// ~end + /// + /// ~chinese + /// 未知类型。 + /// ~end UnKnown, + /// ~english /// The message thread is created. + /// ~end + /// + /// ~chinese + /// 子区创建。 + /// ~end Create, + /// ~english /// The message thread is updated. + /// ~end + /// + /// ~chinese + /// 子区更新。 + /// ~end Update, + /// ~english /// The message thread is destroyed. + /// ~end + /// + /// ~chinese + /// 子区删除。 + /// ~end Delete, + /// ~english /// The last reply in the message thread is updated. + /// ~end + /// + /// ~chinese + /// 更新子区最新一条消息。 + /// ~end Update_Msg, } -/// +/// ~english /// The push styles. +/// ~end /// -/// +/// ~chinese +/// 推送通知展示方式。 +/// ~end enum DisplayStyle { + /// ~english /// The push message presentation style: SimpleBanner represents the presentation of a simple message. + /// ~end + /// + /// ~chinese + /// 显示通用标题,如 “您有一条新消息”。 + /// ~end Simple, + /// ~english /// The push message presentation style: MessageSummary represents the presentation of message content. + /// ~end + /// + /// ~chinese + /// 显示离线消息的内容。 + /// ~end Summary, } -/// +/// ~english /// Offline push DND parameter type Enumeration class. +/// ~end /// +/// ~chinese +/// 离线推送免打扰参数类型枚举类。 +/// ~end enum ChatSilentModeParamType { + /// ~english /// Offline push notification type. + /// ~end + /// + /// ~chinese + /// 离线推送通知类型。 + /// ~end REMIND_TYPE, + /// ~english /// Offline push DND duration. + /// ~end + /// + /// ~chinese + /// 离线推送免打扰时长。 + /// ~end SILENT_MODE_DURATION, + /// ~english /// Offline push DND period. + /// ~end + /// + /// ~chinese + /// 离线推送免打扰时间段。 + /// ~end SILENT_MODE_INTERVAL, } +/// ~english /// Offline push notification type enumeration class. +/// ~end +/// +/// ~chinese +/// 离线推送通知类型枚举类。 +/// ~end enum ChatPushRemindType { + /// ~english /// Collect all offline push. + /// ~end + /// + /// ~chinese + /// 所有离线推送。 + /// ~end ALL, + /// ~english /// Only receive @me offline push. + /// ~end + /// + /// ~chinese + /// 只有@我的离线推送 + /// ~end MENTION_ONLY, + /// ~english /// Offline push is not collected. + /// ~end + /// + /// ~chinese + /// 不接收离线推送。 + /// ~end NONE, } +/// ~english /// Chat room message priorities. +/// ~end +/// +/// ~chinese +/// 聊天室消息优先级。 +/// ~end enum ChatRoomMessagePriority { + /// ~english /// High + /// ~end + /// + /// ~chinese + /// 高 + /// ~end High, + /// ~english /// Normal + /// ~end + /// + /// ~chinese + /// 中 + /// ~end Normal, + /// ~english /// Low + /// ~end + /// + /// ~chinese + /// 低 + /// ~end Low, } diff --git a/lib/src/models/em_chat_room.dart b/lib/src/models/em_chat_room.dart index ca9e6b18..ee8a0f3b 100644 --- a/lib/src/models/em_chat_room.dart +++ b/lib/src/models/em_chat_room.dart @@ -1,11 +1,18 @@ import '../internal/inner_headers.dart'; -/// +/// ~english /// The chat room instance class. /// /// **Note** /// To get the correct value, ensure that you call [EMChatRoomManager.fetchChatRoomInfoFromServer] before calling this method. +/// ~end +/// +/// ~chinese +/// 聊天室信息类,包含内存中的聊天室信息。 /// +/// **Note** +/// 如需最新数据,需从服务器获取:[EMChatRoomManager.fetchChatRoomInfoFromServer]。 +/// ~end class EMChatRoom { EMChatRoom._private({ required this.roomId, @@ -63,107 +70,200 @@ class EMChatRoom { return data; } - /// + /// ~english /// Gets the chat room ID. /// /// **Note** /// To get the correct value, ensure that you call [EMChatRoomManager.fetchChatRoomInfoFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取聊天室 ID。 /// + /// **Note** + /// 如需最新数据,需从服务器获取:[EMChatRoomManager.fetchChatRoomInfoFromServer]。 + /// ~end final String roomId; - /// + /// ~english /// Gets the chat room name from the memory. /// /// **Note** /// To get the correct value, ensure that you call [EMChatRoomManager.fetchChatRoomInfoFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取聊天室名称。 /// + /// **Note** + /// 如需最新数据,需从服务器获取:[EMChatRoomManager.fetchChatRoomInfoFromServer]。 + /// ~end final String? name; - /// + /// ~english /// Gets the chat room description from the memory. /// /// **Note** /// To get the correct value, ensure that you call [EMChatRoomManager.fetchChatRoomInfoFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取聊天室描述。 /// + /// **Note** + /// 如需最新数据,需从服务器获取:[EMChatRoomManager.fetchChatRoomInfoFromServer]。 + /// ~end final String? description; - /// + /// ~english /// Gets the chat room owner ID. If this method returns an empty string, the SDK fails to get chat room details. /// /// **Note** /// To get the correct value, ensure that you call [EMChatRoomManager.fetchChatRoomInfoFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取聊天室所有者 ID。 /// + /// **Note** + /// 如需最新数据,需从服务器获取:[EMChatRoomManager.fetchChatRoomInfoFromServer]。 + /// ~end final String? owner; - /// + /// ~english /// Gets the chat room announcement in the chat room from the memory. /// /// **Note** /// To get the correct value, ensure that you call [EMChatRoomManager.fetchChatRoomAnnouncement] before calling this method. Otherwise, the return value may not be correct. + /// ~end /// + /// ~chinese + /// 从内存中获取聊天室公告。 + /// + /// **Note** + /// 如需最新数据,需从服务器获取:[EMChatRoomManager.fetchChatRoomInfoFromServer]。 + /// ~end final String? announcement; - /// + /// ~english /// Gets the number of online members from the memory. /// /// **Note** /// To get the correct value, ensure that you call [EMChatRoomManager.fetchChatRoomInfoFromServer] before calling this method. + /// ~end /// + /// ~chinese + /// 从内存中获取聊天室在线用户数量。 + /// + /// **Note** + /// 如需最新数据,需从服务器获取:[EMChatRoomManager.fetchChatRoomInfoFromServer]。 + /// ~end final int? memberCount; - /// + /// ~english /// Gets the maximum number of members in the chat room from the memory, which is set/specified when the chat room is created. /// /// **Note** /// To get the correct value, ensure that you call [EMChatRoomManager.fetchChatRoomInfoFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取聊天室最大人数限制,在创建聊天室时设置。 /// + /// **Note** + /// 如需最新数据,需从服务器获取:{[EMChatRoomManager.fetchChatRoomInfoFromServer]。 + /// ~end final int? maxUsers; - /// + /// ~english /// Gets the chat room admin list. /// /// **Note** /// To get the correct value, ensure that you call [EMChatRoomManager.fetchChatRoomInfoFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取聊天室管理员列表。 /// + /// **Note** + /// 如需最新数据,需从服务器获取:[EMChatRoomManager.fetchChatRoomInfoFromServer]。 + /// ~end final List? adminList; - /// + /// ~english /// Gets the member list. /// /// **Note** /// To get the correct value, ensure that you call [EMChatRoomManager.fetchChatRoomMembers]. + /// ~end + /// + /// ~chinese + /// 从内存中获取聊天室成员列表。 /// + /// **Note** + /// 如需最新数据,需从服务器获取:[EMChatRoomManager.fetchChatRoomMembers]。 + /// ~end final List? memberList; - /// + /// ~english /// Gets the chat room block list. /// /// **Note** /// To get the block list, you can call [EMChatRoomManager.fetchChatRoomBlockList]. + /// ~end + /// + /// ~chinese + /// 从内存中获取聊天室黑名单列表。 /// + /// **Note** + /// 如果需要获取最新值,请调用:[EMChatRoomManager.fetchChatRoomBlockList]。 + /// ~end final List? blockList; - /// + /// ~english /// Gets the mute list of the chat room. /// /// **Note** /// To get the mute list, you can call [EMChatRoomManager.fetchChatRoomMuteList]. + /// ~end + /// + /// ~chinese + /// 从内存中获取禁言列表。 /// + /// **Note** + /// 如果需要获取最新值,请调用 [EMChatRoomManager.fetchChatRoomMuteList]。 + /// ~end final List? muteList; - /// + /// ~english /// Checks whether all members are muted in the chat room from the memory. /// /// **Note** /// To get the correct value, ensure that you call [EMChatRoomManager.fetchChatRoomInfoFromServer] before calling this method. + /// ~end /// + /// ~chinese + /// 从内存中查看是否在全员禁言状态。 + /// - `true`:开启全员禁言。 + /// - `false`:关闭全员禁言。 + /// + /// **Note** + /// 如果需要获取最新值,请调用 [EMChatRoomManager.fetchChatRoomInfoFromServer]。 + /// ~end final bool? isAllMemberMuted; - /// + /// ~english /// Gets the current user's role in the chat room. The role types: [EMChatRoomPermissionType]. /// /// **Note** /// To get the correct value, ensure that you call [EMChatRoomManager.fetchChatRoomInfoFromServer] before calling this method. + /// ~end /// + /// ~chinese + /// 从内存中获取当前用户在聊天室角色,详见 [EMChatRoomPermissionType]。 + /// + /// **Note** + /// 如果需要获取最新值,请调用 [EMChatRoomManager.fetchChatRoomInfoFromServer]。 + /// ~end final EMChatRoomPermissionType permissionType; } diff --git a/lib/src/models/em_chat_thread.dart b/lib/src/models/em_chat_thread.dart index 69bca5b7..69675dfc 100644 --- a/lib/src/models/em_chat_thread.dart +++ b/lib/src/models/em_chat_thread.dart @@ -1,34 +1,92 @@ import '../internal/inner_headers.dart'; -/// +/// ~english /// The message thread class. +/// ~end /// +/// ~chinese +/// 子区详情类。 +/// ~end class EMChatThread { + /// ~english /// The message thread ID. + /// ~end + /// + /// ~chinese + /// 子区 ID。 + /// ~end final String threadId; + /// ~english /// The name of the message thread. + /// ~end + /// + /// ~chinese + /// 子区名称。 + /// ~end final String? threadName; + /// ~english /// The creator of the message thread. + /// ~end + /// + /// ~chinese + /// 子区创建者的用户 ID。 + /// ~end final String owner; + /// ~english /// The ID of the parent message of the message thread. + /// ~end + /// + /// ~chinese + /// 子区父消息 ID。 + /// ~end final String messageId; + /// ~english /// The group ID where the message thread belongs. + /// ~end + /// + /// ~chinese + /// 子区所属的群组 ID。 + /// ~end final String parentId; + /// ~english /// The count of members in the message thread. + /// ~end + /// + /// ~chinese + /// 子区成员数量。 + /// ~end final int membersCount; + /// ~english /// The count of messages in the message thread. + /// ~end + /// + /// ~chinese + /// 子区消息数量。 + /// ~end final int messageCount; + /// ~english /// The Unix timestamp when the message thread is created. The unit is millisecond. + /// ~end + /// + /// ~chinese + /// 子区创建的 Unix 时间戳。单位为毫秒。 + /// ~end final int createAt; + /// ~english /// The last reply in the message thread. If it is empty, the last message is withdrawn. + /// ~end + /// + /// ~chinese + /// 子区最新一条消息。如果为空,表明最新一条消息被撤回。 + /// ~end final EMMessage? lastMessage; /// @nodoc @@ -75,17 +133,39 @@ class EMChatThread { } } -/// +/// ~english /// The message thread event class. +/// ~end /// +/// ~chinese +/// 子区通知类。 +/// ~end class EMChatThreadEvent { + /// ~english /// Received the operation type of the sub-area from others + /// ~end + /// + /// ~chinese + /// 子区事件类型。 + /// ~end final EMChatThreadOperation type; + /// ~english /// User id of the operation sub-area + /// ~end + /// + /// ~chinese + /// 子区操作者。 + /// ~end final String from; + /// ~english /// sub-area + /// ~end + /// + /// ~chinese + /// 子区实例。 + /// ~end final EMChatThread? chatThread; EMChatThreadEvent._private({ diff --git a/lib/src/models/em_conversation.dart b/lib/src/models/em_conversation.dart index 02aefdef..d94abb28 100644 --- a/lib/src/models/em_conversation.dart +++ b/lib/src/models/em_conversation.dart @@ -3,7 +3,7 @@ import 'package:flutter/services.dart'; import '../internal/inner_headers.dart'; -/// +/// ~english /// The conversation class, indicating a one-to-one chat, a group chat, or a conversation chat. It contains the messages that are sent and received within the conversation. /// /// The following code shows how to get the number of the unread messages from the conversation. @@ -12,7 +12,18 @@ import '../internal/inner_headers.dart'; /// EMConversation? con = await EMClient.getInstance.chatManager.getConversation(conversationId); /// int? unreadCount = con?.unreadCount; /// ``` +/// ~end +/// +/// ~chinese +/// 会话类,用于定义单聊会话、群聊会话和聊天室会话。每类会话中包含发送和接收的消息。 /// +/// 以下示例代码展示如何从会话中获取未读消息数: +/// ```dart +/// // The `ConversationId` can be the other party ID, the group ID, or the chat room ID. +/// EMConversation? con = await EMClient.getInstance.chatManager.getConversation(conversationId); +/// int? unreadCount = con?.unreadCount; +/// ``` +/// ~end class EMConversation { EMConversation._private(this.id, this.type, this._ext, this.isChatThread); @@ -38,23 +49,45 @@ class EMConversation { return data; } - /// + /// ~english /// The conversation ID. /// /// For one-to-one chat,the conversation ID is the username of the other party. /// For group chat, the conversation ID is the group ID, not the group name. /// For chat room, the conversation ID is the chat room ID, not the chat room name. /// For help desk, the conversation ID is the username of the other party. + /// ~end + /// + /// ~chinese + /// 获取会话 ID。 /// + /// 对于单聊类型,会话 ID 同时也是对方用户的名称。 + /// 对于群聊类型,会话 ID 同时也是对方群组的 ID,并不同于群组的名称。 + /// 对于聊天室类型,会话 ID 同时也是聊天室的 ID,并不同于聊天室的名称。 + /// 对于 HelpDesk 类型,会话 ID 与单聊类型相同,是对方用户的名称。 + /// + /// **Return** 会话 ID。 + /// ~end final String id; - /// + /// ~english /// The conversation type. + /// ~end /// + /// ~chinese + /// 会话类型。 + /// ~end final EMConversationType type; - /// + /// ~english /// Is chat thread conversation. + /// ~end + /// + /// ~chinese + /// 是否为子区会话。 + /// - `true`:是; + /// - `false`:否。 + /// ~end final bool isChatThread; Map? _ext; @@ -77,7 +110,7 @@ class EMConversation { } } - /// + /// ~english /// Gets the last message from the conversation. /// /// The operation does not change the unread message count. @@ -85,7 +118,17 @@ class EMConversation { /// The SDK gets the latest message from the local memory first. If no message is found, the SDK loads the message from the local database and then puts it in the memory. /// /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 获取会话的最新一条消息。 + /// + /// 不影响未读数统计。 /// + /// 会先从缓存中获取,如果没有则从本地数据库获取后存入缓存。 + /// + /// **Return** 消息体实例。 + /// ~end Future latestMessage() async { Map req = this._toJson(); Map result = await _emConversationChannel.invokeMethod( @@ -102,11 +145,17 @@ class EMConversation { } } - /// + /// ~english /// Gets the latest message from the conversation. /// /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 获取最近收到的一条消息。 /// + /// **Return** 消息体实例。 + /// ~end Future lastReceivedMessage() async { Map req = this._toJson(); Map result = await _emConversationChannel.invokeMethod( @@ -124,13 +173,21 @@ class EMConversation { } } - /// + /// ~english /// Gets the unread message count of the conversation. /// /// **Return** The unread message count of the conversation. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 获取会话的消息未读数。 /// + /// **Return** 会话的消息未读数量。 + /// + /// **Throws** 如果有异常会在此抛出,包含错误码和原因,详见 [EMError]。 + /// ~end Future unreadCount() async { Map req = this._toJson(); Map result = await _emConversationChannel.invokeMethod( @@ -147,13 +204,21 @@ class EMConversation { } } - /// + /// ~english /// Marks a message as read. /// /// Param [messageId] The message ID. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 将消息标为已读。 /// + /// Param [messageId] 消息 ID。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future markMessageAsRead(String messageId) async { Map req = this._toJson(); req['msg_id'] = messageId; @@ -166,9 +231,13 @@ class EMConversation { } } - /// + /// ~english /// Marks all messages as read. + /// ~end /// + /// ~chinese + /// 将所有消息标为已读。 + /// ~end Future markAllMessagesAsRead() async { Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.markAllMessagesAsRead, this._toJson()); @@ -179,7 +248,7 @@ class EMConversation { } } - /// + /// ~english /// Inserts a message to a conversation in the local database and the SDK will automatically update the last message. /// /// Make sure you set the conversation ID as that of the conversation where you want to insert the message. @@ -187,7 +256,15 @@ class EMConversation { /// Param [message] The message instance. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 插入一条消息在 SDK 本地数据库,消息的 conversation ID 应该和会话的 conversation ID 一致,消息会根据消息里的时间戳被插入 SDK 本地数据库,并且更新会话的 `latestMessage` 等属性。 + /// + /// Param [message] 消息体实例。 /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future insertMessage(EMMessage message) async { Map req = this._toJson(); req['msg'] = message.toJson(); @@ -200,7 +277,7 @@ class EMConversation { } } - /// + /// ~english /// Inserts a message to the end of a conversation in the local database. /// /// Make sure you set the conversation ID as that of the conversation where you want to insert the message. @@ -208,7 +285,17 @@ class EMConversation { /// Param [message] The message instance. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 插入一条消息到会话尾部。 /// + /// @note + /// 请确保消息的 conversation ID 与要插入的会话的 conversationId 一致,消息会被插入 SDK 本地数据库,并且更新会话的 `latestMessage` 等属性。 + /// Param [message] 消息体实例。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future appendMessage(EMMessage message) async { Map req = this._toJson(); req['msg'] = message.toJson(); @@ -221,7 +308,7 @@ class EMConversation { } } - /// + /// ~english /// Updates a message in the local database. /// /// The latestMessage of the conversation and other properties will be updated accordingly. The message ID of the message, however, remains the same. @@ -229,7 +316,17 @@ class EMConversation { /// Param [message] The message to be updated. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 更新 SDK 本地数据库的消息。 /// + /// @note + /// 不能更新消息 ID,消息更新后,会话的 `latestMessage` 等属性进行相应更新。 + /// Param [message] 要更新的消息。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future updateMessage(EMMessage message) async { Map req = this._toJson(); req['msg'] = message.toJson(); @@ -243,7 +340,7 @@ class EMConversation { } } - /// + /// ~english /// Deletes a message in the local database. /// /// **Note** @@ -252,7 +349,15 @@ class EMConversation { /// Param [messageId] The ID of message to be deleted. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end /// + /// ~chinese + /// 删除会话中的一条消息,同时清除内存和数据库中的消息。 + /// + /// Param [messageId] 要删除的消息。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future deleteMessage(String messageId) async { Map req = this._toJson(); req['msg_id'] = messageId; @@ -265,11 +370,17 @@ class EMConversation { } } - /// + /// ~english /// Deletes all the messages of the conversation from both the memory and local database. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 同时从内存和本地数据库中删除会话中的所有消息。 /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future deleteAllMessages() async { Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.clearAllMessages, this._toJson()); @@ -280,7 +391,7 @@ class EMConversation { } } - /// + /// ~english /// Gets the message with a specific message ID. /// /// If the message is already loaded into the memory cache, the message will be directly returned; otherwise, the message will be loaded from the local database and loaded in the memory. @@ -290,7 +401,19 @@ class EMConversation { /// **Return** The message instance. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 获取指定 ID 的消息。 + /// + /// 优先从内存中加载,如果内存中没有则从数据库中加载,并将其插入到内存中。 + /// + /// Param [messageId] 消息 ID。 + /// + /// **Return** 消息实例。 /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future loadMessage(String messageId) async { Map req = this._toJson(); req['msg_id'] = messageId; @@ -308,7 +431,7 @@ class EMConversation { } } - /// + /// ~english /// Retrieves messages from the database according to the following parameters: the message type, the Unix timestamp, max count, sender. /// /// **Note** @@ -329,7 +452,27 @@ class EMConversation { /// **Return** The message list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 根据消息类型、搜索消息的时间点、搜索结果的最大条数、搜索来源和搜索方向从 SDK 本地数据库中搜索指定数量的消息。 + /// + /// **Note** 当 maxCount 非常大时,需要考虑内存消耗。 + /// + /// Param [type] 消息类型,文本、图片、语音等等。 + /// + /// Param [timestamp] 搜索时间。 /// + /// Param [count] 搜索结果的最大条数。 + /// + /// Param [sender] 搜索来自某人的消息,也可用于搜索群组或聊天室里的消息。 + /// + /// Param [direction] 消息加载的方向。 + /// + /// **Return** 消息列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> loadMessagesWithMsgType({ required MessageType type, int timestamp = -1, @@ -357,7 +500,7 @@ class EMConversation { } } - /// + /// ~english /// Loads multiple messages from the local database. /// /// Loads messages from the local database before the specified message. @@ -375,7 +518,25 @@ class EMConversation { /// **Return** The message list. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 从本地数据库加载消息。 + /// + /// 根据传入的参数从本地数据库加载 startMsgId 之前(存储顺序)指定数量的消息。 + /// + /// 加载到的 messages 也会加入到当前会话的缓存中,通过 {@link #getAllMessages()} 将会返回所有加载的消息。 + /// + /// Param [startMsgId] 加载这个 ID 之前的 message,如果传入 "" 或者 null,将从最近的消息开始加载。 + /// + /// Param [loadCount] 加载的条数。 /// + /// Param [direction] 消息的加载方向。 + /// + /// **Return** 消息列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> loadMessages({ String startMsgId = '', int loadCount = 20, @@ -401,7 +562,7 @@ class EMConversation { } } - /// + /// ~english /// Loads messages from the local database by the following parameters: keywords, timestamp, max count, sender, search direction. /// /// **Note** Pay attention to the memory usage when the maxCount is large. @@ -421,7 +582,27 @@ class EMConversation { /// **Returns** The list of retrieved messages. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 根据消息中的关键词、搜索消息的时间点、搜索结果的最大条数、搜索来源和搜索方向从 SDK 本地数据库中搜索指定数量的消息。 + /// + /// 注意:当 maxCount 非常大时,需要考虑内存消耗。 + /// + /// Param [keywords] 搜索消息中的关键词。 + /// + /// Param [sender] 消息发送方(用户、群组或聊天室)。 + /// + /// Param [timestamp] 搜索消息的时间点。 + /// + /// Param [count] 搜索结果的最大条数。 + /// + /// Param [direction] 消息搜索方向。 /// + /// **Return** 消息列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> loadMessagesWithKeyword( String keywords, { String? sender, @@ -451,7 +632,7 @@ class EMConversation { } } - /// + /// ~english /// Loads messages from the local database according the following parameters: start timestamp, end timestamp, count. /// /// **Note** Pay attention to the memory usage when the maxCount is large. @@ -465,7 +646,23 @@ class EMConversation { /// **Returns** The list of searched messages. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 加载一个时间段内的消息,不超过最大数量。 + /// + /// 注意:当 maxCount 非常大时,需要考虑内存消耗。 + /// + /// Param [startTime] 搜索的起始时间。 /// + /// Param [endTime] 搜索的结束时间。 + /// + /// Param [count] 搜索结果的最大条数。 + /// + /// **Return** 消息列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end Future> loadMessagesFromTime({ required int startTime, required int endTime, @@ -491,9 +688,13 @@ class EMConversation { } } - /// + /// ~english /// Message count + /// ~end /// + /// ~chinese + /// 会话中的消息数 + /// ~end Future messagesCount() async { Map req = this._toJson(); Map result = await _emConversationChannel.invokeMethod( diff --git a/lib/src/models/em_cursor_result.dart b/lib/src/models/em_cursor_result.dart index d8a0ca13..99733147 100644 --- a/lib/src/models/em_cursor_result.dart +++ b/lib/src/models/em_cursor_result.dart @@ -1,6 +1,6 @@ typedef CursorResultCallback = Object Function(dynamic obj); -/// +/// ~english /// The EMCursorResult class, which specifies the cursor from which to query results. /// When querying using this class, the SDK returns the queried instance and the cursor. /// @@ -10,7 +10,20 @@ typedef CursorResultCallback = Object Function(dynamic obj); /// List? group = result.data; /// cursor = result.cursor; /// ``` +/// ~end +/// +/// ~chinese +/// 带游标及分页获取结果的泛型类。 +/// 做为分页获取且含有游标的返回对象。 /// +/// 示例代码如下: +/// ```dart +/// String? cursor; +/// EMCursorResult result = await EMClient.getInstance.groupManager.getPublicGroupsFromServer(pageSize: 10, cursor: cursor); +/// List? group = result.data; +/// cursor = result.cursor; +/// ``` +/// ~end class EMCursorResult { EMCursorResult._private( this.cursor, @@ -28,9 +41,21 @@ class EMCursorResult { return result; } + /// ~english /// Gets the cursor. + /// ~end + /// + /// ~chinese + /// 获取游标。 + /// ~end final String? cursor; + /// ~english /// Gets the data list. + /// ~end + /// + /// ~chinese + /// 获取一页数据列表。 + /// ~end final List data; } diff --git a/lib/src/models/em_deviceInfo.dart b/lib/src/models/em_deviceInfo.dart index 19025b2d..7374c1f9 100644 --- a/lib/src/models/em_deviceInfo.dart +++ b/lib/src/models/em_deviceInfo.dart @@ -1,8 +1,12 @@ import '../internal/inner_headers.dart'; -/// +/// ~english /// The EMDeviceInfo class, which contains the multi-device information. +/// ~end /// +/// ~chinese +/// 多设备登录信息类。 +/// ~end class EMDeviceInfo { EMDeviceInfo._private( this.resource, @@ -29,12 +33,30 @@ class EMDeviceInfo { ); } + /// ~english /// The information of other login devices. + /// ~end + /// + /// ~chinese + /// 登录的其他设备的信息。 + /// ~end final String? resource; + /// ~english /// The UUID of the device. + /// ~end + /// + /// ~chinese + /// 设备的 UUID(唯一标识码)。 + /// ~end final String? deviceUUID; + /// ~english /// The device type. For example: "Pixel 6 Pro". + /// ~end + /// + /// ~chinese + /// 设备型号,如 "Pixel 6 Pro"。 + /// ~end final String? deviceName; } diff --git a/lib/src/models/em_download_callback.dart b/lib/src/models/em_download_callback.dart index 13a64771..321e8540 100644 --- a/lib/src/models/em_download_callback.dart +++ b/lib/src/models/em_download_callback.dart @@ -1,27 +1,47 @@ import '../internal/inner_headers.dart'; -/// +/// ~english /// The group shared download callback. +/// ~end /// +/// ~chinese +/// 群文件下载回调。 +/// ~end class EMDownloadCallback { - /// + /// ~english /// Download success callback. + /// ~end /// + /// ~chinese + /// 群文件下载成功回调。 + /// ~end final void Function(String fileId, String path)? onSuccess; - /// + /// ~english /// Download error callback. + /// ~end /// + /// ~chinese + /// 群文件下载失败回调。 + /// ~end final void Function(String fileId, EMError error)? onError; - /// + /// ~english /// Download progress callback. + /// ~end /// + /// ~chinese + /// 群文件下载进度。取值范围 [0,100]。 + /// ~end final void Function(String fileId, int progress)? onProgress; - /// + /// ~english /// Create a group shared file download callback. + /// ~end /// + /// ~chinese + /// 创建文件下载对象。 + /// ~end EMDownloadCallback({ this.onSuccess, this.onError, diff --git a/lib/src/models/em_error.dart b/lib/src/models/em_error.dart index 8947b402..37882181 100644 --- a/lib/src/models/em_error.dart +++ b/lib/src/models/em_error.dart @@ -1,17 +1,29 @@ -/// +/// ~english /// The error class defined by the SDK. +/// ~end /// +/// ~chinese +/// SDK 定义的错误类。 +/// ~end class EMError { EMError._private(this.code, this.description); - /// + /// ~english /// The error code. + /// ~end /// + /// ~chinese + /// 错误码。 + /// ~end final int code; - /// + /// ~english /// The error description. + /// ~end /// + /// ~chinese + /// 错误描述。 + /// ~end final String description; /// @nodoc diff --git a/lib/src/models/em_group.dart b/lib/src/models/em_group.dart index 5a5370bb..fdef7e45 100644 --- a/lib/src/models/em_group.dart +++ b/lib/src/models/em_group.dart @@ -1,8 +1,15 @@ import '../internal/inner_headers.dart'; -/// +/// ~english /// The EMGroup class, which contains the information of the chat group. +/// ~end +/// +/// ~chinese +/// 群组信息类,包含内存中的群组相关信息。 /// +/// **Note** +/// 如需最新数据,需先从服务器获取:[EMGroupManager.fetchGroupInfoFromServer]。 +/// ~end class EMGroup { EMGroup._private({ required this.groupId, @@ -25,122 +32,247 @@ class EMGroup { this.isDisabled = false, }); - /// + /// ~english /// Gets the group ID. + /// ~end /// + /// ~chinese + /// 群组 ID。 + /// ~end final String groupId; - /// + /// ~english /// Gets the group name. /// /// **Note** /// To get the correct value, ensure that you call [EMGroupManager.fetchGroupInfoFromServer] before calling this method. + /// ~end /// - + /// ~chinese + /// 从内存中获取群组名称。 + /// + /// **Note** + /// 如需最新数据,需先从服务器获取:[EMGroupManager.fetchGroupInfoFromServer]。 + /// + /// **Return** 群组名称。 + /// ~end final String? name; - /// + /// ~english /// Gets the group description. /// /// **Note** /// To get the correct value, ensure that you call [EMGroupManager.fetchGroupInfoFromServer] before calling this method. + /// ~end /// - + /// ~chinese + /// 从内存中获取群组描述。 + /// + /// **Note** + /// 如需最新数据,需先从服务器获取:[EMGroupManager.fetchGroupInfoFromServer]。 + /// + /// **Return** 群组描述。 + /// ~end final String? description; - /// + /// ~english /// Gets the user ID of the group owner. /// /// **Note** /// To get the correct value, ensure that you call [EMGroupManager.fetchGroupInfoFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取群主用户 ID。 /// + /// **Note** + /// 如需最新数据,需先从服务器获取:[EMGroupManager.fetchGroupInfoFromServer]。 + /// + /// **Return** 群主用户 ID。 + /// ~end final String? owner; - /// + /// ~english /// The content of the group announcement. + /// ~end /// + /// ~chinese + /// 从内存中获取群公告内容。 + /// + /// **Note** + /// 如需最新数据,需先从服务器获取:[EMGroupManager.fetchGroupInfoFromServer]。 + /// ~end final String? announcement; - /// + /// ~english /// Gets the member count of the group. /// /// **Note** /// To get the correct value, ensure that you call [EMGroupManager.fetchGroupInfoFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取群组成员数量。 /// + /// **Note** + /// 如需最新数据,需先从服务器获取:[EMGroupManager.fetchGroupInfoFromServer]。 + /// + /// **Return** 群组成员数量。 + /// ~end final int? memberCount; - /// + /// ~english /// Gets the member list of the group. /// /// **Note** /// To get the correct value, ensure that you call [EMGroupManager.fetchMemberListFromServer] before calling this method. + /// ~end /// - + /// ~chinese + /// 从内存中获取群组成员列表。 + /// + /// **Note** + /// 如需最新数据,需先从服务器获取:{@link #fetchMemberListFromServer(String, int?, String?)}.。 + /// + /// **Return** 群组成员列表。 + /// ~end final List? memberList; - /// + /// ~english /// Gets the admin list of the group. /// /// **Note** /// To get the correct value, ensure that you call [EMGroupManager.fetchGroupInfoFromServer] before calling this method. + /// ~end /// - + /// ~chinese + /// 从内存中获取群组管理员列表。 + /// + /// **Note** + /// 如需最新数据,需先从服务器获取:[EMGroupManager.fetchGroupInfoFromServer]。 + /// + /// **Return** 群组管理员列表。 + /// ~end final List? adminList; - /// + /// ~english /// Gets the block list of the group. /// /// If no block list is found from the server, the return may be empty. /// /// **Note** /// To get the correct value, ensure that you call [EMGroupManager.fetchBlockListFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取群组黑名单。 + /// + /// 如果没有找到会返回空列表。 + /// + /// **Note** + /// 如需最新数据,需先从服务器获取:{@link EMGroupManager#fetchBlockListFromServer(String, int?, int?)}。 /// + /// 只有群主和管理员可以调用该方法。 + /// + /// **Return** 群组黑名单。 + /// ~end final List? blockList; - /// + /// ~english /// Gets the mute list of the group. /// /// **Note** /// To get the correct value, ensure that you call [EMGroupManager.fetchMuteListFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取群组禁言名单。 + /// + /// 只有群主和管理员可以调用该方法。 + /// + /// **Note** + /// 如需最新数据,需先从服务器获取:{@link EMGroupManager# fetchMuteListFromServer(String, int?, int?)}。 /// + /// **Return** 群组禁言名单。 + /// ~end final List? muteList; - /// + /// ~english /// Gets whether the group message is blocked. /// /// **Note** /// To get the correct value, ensure that you call [EMGroupManager.fetchGroupInfoFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取消息是否被屏蔽。 + /// + /// **Note** + /// 如需最新数据,需先从服务器获取: [EMGroupManager.fetchGroupInfoFromServer]。 /// + /// **Return** 消息是否被屏蔽。 + /// - `true`: 是; + /// - `false`: 否。 + /// ~end final bool? messageBlocked; - /// + /// ~english /// Gets Whether all members are muted. /// /// **Note** /// To get the correct value, ensure that you call [EMGroupManager.fetchGroupInfoFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取是否已经全员禁言。 /// + /// **Note** + /// 如需最新数据,需先从服务器获取: [EMGroupManager.fetchGroupInfoFromServer]。 + /// + /// **Return** 是否全员禁言。 + /// - `true`: 是; + /// - `false`: 否。 + /// ~end final bool? isAllMemberMuted; - /// + /// @nodoc EMGroupOptions? _options; - /// + /// ~english /// Gets the current user's role in group. /// /// **Note** /// To get the correct value, ensure that you call [EMGroupManager.fetchGroupInfoFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取当前用户在群组中的角色。 + /// + /// **Note** + /// 如需最新数据,需先从服务器获取: [EMGroupManager.fetchGroupInfoFromServer]。 /// + /// **Return** 当前用户在群组中的角色。 + /// ~end final EMGroupPermissionType? permissionType; - /// + /// ~english /// Gets the maximum number of group members allowed in a group. The parameter is set when the group is created. /// /// **Note** /// To get the correct value, ensure that you call [EMGroupManager.fetchGroupInfoFromServer] before calling this method. + /// ~end + /// + /// ~chinese + /// 从内存中获取群组最大人数限制,创建时确定。 + // + /// **Note** + /// 如需最新数据,需先从服务器获取: [EMGroupManager.fetchGroupInfoFromServer]。 /// + /// **Return** 群组最大人数限制。 + /// ~end final int? maxUserCount; - /// + /// ~english /// Checks whether users cannot join a chat group freely: /// - `true`: Yes. Needs the approval from the group owner(admin) or being invited by group members(PrivateOnlyOwnerInvite, PrivateMemberCanInvite, PublicJoinNeedApproval). /// - `false`: No. Users can join freely [EMGroupStyle.PublicOpenJoin]. @@ -152,10 +284,23 @@ class EMGroup { /// Whether users can join a chat group with only the approval of the group owner(admin): /// - `true`: Yes. Needs the approval from the group owner(admin) or being invited by group members. /// - `false`: No. + /// ~end + /// + /// ~chinese + /// 从内存中获取群组类型:成员是否能自由加入,还是需要申请或者被邀请。 /// + /// 群组有四个类型属性,`isMemberOnly`是除了 [EMGroupStyle.PublicOpenJoin] 之外的三种属性,表示该群不是自由加入的群组。 + /// + /// **Note** + /// 如需最新数据,需先从服务器获取: [EMGroupManager.fetchGroupInfoFromServer]。 + /// + /// **Return** + /// - `true`:进群需要群主邀请,群成员邀请,或者群主和管理员同意入群申请; + /// - `false`:意味着用户可以自由加入群,不需要申请和被邀请。 + /// ~end final bool? isMemberOnly; - /// + /// ~english /// Checks whether a group member is allowed to invite other users to join the group. /// /// **Note** @@ -164,17 +309,36 @@ class EMGroup { /// **Return** /// - `true`: Yes; /// - `false`: No. Only the group owner or admin can invite others to join the group. + /// ~end /// + /// ~chinese + /// 从内存中获取是否允许成员邀请他人进群。 + /// + /// **Note** + /// 如需最新数据,需先从服务器获取:[EMGroupManager.fetchGroupInfoFromServer]。 + /// + /// **Return** + /// - `true`: 允许; + /// - `false`: 不允许。 + /// ~end final bool? isMemberAllowToInvite; - /// + /// ~english /// Group detail extensions which can be in the JSON format to contain more group information. + /// ~end /// + /// ~chinese + /// 群组ext + /// ~end final String? extension; - /// + /// ~english /// Whether the group is disabled. The default value for reading or pulling roaming messages from the database is NO + /// ~end /// + /// ~chinese + /// 组是否被禁用。从数据库读取或提取漫游消息的默认值是false。 + /// ~end final bool isDisabled; @Deprecated( @@ -252,14 +416,27 @@ class EMGroup { } } -/// +/// ~english /// The class that defines basic information of chat groups. +/// ~end /// +/// ~chinese +/// ~end class EMGroupInfo { + /// ~english /// The group ID. + /// ~end + /// + /// ~chinese + /// ~end final String groupId; + /// ~english /// The group name. + /// ~end + /// + /// ~chinese + /// ~end final String? name; EMGroupInfo._private({ diff --git a/lib/src/models/em_group_message_ack.dart b/lib/src/models/em_group_message_ack.dart index a275fd46..7d60f777 100644 --- a/lib/src/models/em_group_message_ack.dart +++ b/lib/src/models/em_group_message_ack.dart @@ -1,6 +1,6 @@ import '../internal/inner_headers.dart'; -/// +/// ~english /// The class for group message read receipts. /// /// To get the chat group message receipts, call [EMChatManager.fetchGroupAcks]. @@ -8,49 +8,86 @@ import '../internal/inner_headers.dart'; /// ```dart /// EMCursorResult result = await EMClient.getInstance.chatManager.fetchGroupAcks("msgId"); /// ``` +/// ~end +/// +/// ~chinese +/// 群组消息回执类。 /// +/// 调用 [EMChatManager.fetchGroupAcks] 方法,示例代码如下: +/// +/// ```dart +/// EMCursorResult result = await EMClient.getInstance.chatManager.fetchGroupAcks("msgId"); +/// ``` +/// ~end class EMGroupMessageAck { - /// + /// ~english /// Gets the group message ID. /// /// **Return** The group message ID. + /// ~end /// + /// ~chinese + /// 群组消息 ID。 + /// ~end final String messageId; - /// + /// ~english /// Gets the ID of the group message read receipt. /// /// **Return** The read receipt ID. + /// ~end /// + /// ~chinese + /// 群组消息已读回执 ID。 + /// ~end final String? ackId; - /// + /// ~english /// Gets the username of the user who sends the read receipt. /// /// **Return** The username of the read receipt sender. + /// ~end /// + /// ~chinese + /// 发送已读回执的用户 ID。 + /// ~end final String from; - /// + /// ~english /// Gets the read receipt extension. /// /// For how to set the extension, see [EMChatManager.sendGroupMessageReadAck]. /// /// **Return** The read receipt extension. + /// ~end + /// + /// ~chinese + /// 已读回执扩展内容。 /// + /// 设定该扩展内容详见 [EMChatManager.sendGroupMessageReadAck].。 + /// ~end final String? content; - /// + /// ~english /// Gets the number read receipts of group messages. /// /// **Return** The count in which read receipts of group messages are sent. + /// ~end /// + /// ~chinese + /// 群组消息已读回执数量。 + /// ~end final int readCount; - /// + /// ~english /// Gets the timestamp of sending read receipts of group messages. /// /// **Return** The timestamp of sending read receipts of group messages. + /// ~end + /// + /// ~chinese + /// 发送已读回执的时间戳。 + /// ~end final int timestamp; /// @nodoc diff --git a/lib/src/models/em_group_options.dart b/lib/src/models/em_group_options.dart index 35787a1d..3c3caa82 100644 --- a/lib/src/models/em_group_options.dart +++ b/lib/src/models/em_group_options.dart @@ -1,10 +1,14 @@ import '../internal/inner_headers.dart'; -/// +/// ~english /// The group options to be configured when the chat group is created. +/// ~end /// +/// ~chinese +/// 创建群组时的属性配置类。 +/// ~end class EMGroupOptions { - /// + /// ~english /// Sets the group options. /// /// Param [style] The group style: {EMGroupStyle}. @@ -19,7 +23,26 @@ class EMGroupOptions { /// - If `autoAcceptGroupInvitation` is set to `false`, the invitee does not join the chat group until this invitee approves the group invitation. /// /// Param [ext] Group detail extensions which can be in the JSON format to contain more group information. + /// ~end + /// + /// ~chinese + /// 设置群组属性。 + /// + /// Param [style] 群组的类型。详见 {EMGroupStyle}。 + /// + /// Param [maxCount] 群组的最大成员数,默认为 200。 + /// + /// Param [inviteNeedConfirm] 邀请用户进群是否需要对方同意。收到邀请是否自动入群取决于两个设置:创建群组时设置 inviteNeedConfirm 以及通过 {@link EMOptions#setAutoAcceptGroupInvitation(boolean)} 确定是否自动接受加群邀请。 + /// 具体使用如下: + ///(1)如果 inviteNeedConfirm 设置为 'false',在服务端直接加受邀人进群, + /// 与受邀人对 {@link EMOptions#setAutoAcceptGroupInvitation(boolean)} 的设置无关。 + /// (2) 如果 inviteNeedConfirm 设置为 'true',是否自动入群取决于被邀请人对 {@link EMOptions#setAutoAcceptGroupInvitation(boolean)} 的设置。 + /// {@link EMOptions#setAutoAcceptGroupInvitation(boolean)} 为 SDK 级别操作,设置为 'true' 时,受邀人收到入群邀请后,SDK 在内部调用同意入群的 API, + /// 自动接受邀请入群; + /// 若设置为 'false',即非自动同意其邀请,用户可以选择接受邀请进群,也可选择拒绝邀请。 /// + /// Param [ext] 群组详情扩展,可以采用 JSON 格式,以包含更多群信息。 + /// ~end EMGroupOptions({ this.style = EMGroupStyle.PrivateOnlyOwnerInvite, this.maxCount = 200, @@ -27,21 +50,29 @@ class EMGroupOptions { this.ext, }); - /// + /// ~english /// Gets the group style. /// /// **Return** The group style. See {EMGroupStyle}. + /// ~end /// + /// ~chinese + /// 群组类型。 + /// ~end final EMGroupStyle style; - /// + /// ~english /// Gets the maximum number of members in a group. /// /// **Return** The maximum number of members in a group. + /// ~end /// + /// ~chinese + /// 群组的最大人数上限。 + /// ~end final int maxCount; - /// + /// ~english /// Whether you need the approval from the user when adding this user to the chat group. /// /// Whether you can automatically add a user to the chat group depends on the settings of [inviteNeedConfirm] and [EMOptions.autoAcceptGroupInvitation]. @@ -52,14 +83,30 @@ class EMGroupOptions { /// - If `autoAcceptGroupInvitation` is set to `false`, the invitee does not join the chat group until this invitee approves the group invitation. /// /// **Return** Whether you need the approval from the user when adding this user to the chat group. - /// + /// ~end + /// + /// ~chinese + /// 邀请用户进群是否需要对方同意。收到邀请是否自动入群取决于两个设置:创建群组时设置 inviteNeedConfirm 以及通过 {@link EMOptions#setAutoAcceptGroupInvitation(boolean)} 确定是否自动接受加群邀请。 + /// 具体使用如下: + ///(1)如果 inviteNeedConfirm 设置为 'false',在服务端直接加受邀人进群, + /// 与受邀人对 {@link EMOptions#setAutoAcceptGroupInvitation(boolean)} 的设置无关。 + /// (2) 如果 inviteNeedConfirm 设置为 'true',是否自动入群取决于被邀请人对 {@link EMOptions#setAutoAcceptGroupInvitation(boolean)} 的设置。 + /// {@link EMOptions#setAutoAcceptGroupInvitation(boolean)} 为 SDK 级别操作,设置为 'true' 时,受邀人收到入群邀请后,SDK 在内部调用同意入群的 API,自动接受邀请入群; + /// 若设置为 'false',即非自动同意其邀请,用户可以选择接受邀请进群,也可选择拒绝邀请。 + /// + /// **Return** 邀请用户进群是否需要对方同意。 + /// ~end final bool inviteNeedConfirm; - /// + /// ~english /// Gets the extension in a group. /// /// **Return** The extension in a group. + /// ~end /// + /// ~chinese + /// 群组扩展属性。 + /// ~end final String? ext; /// @nodoc diff --git a/lib/src/models/em_group_shared_file.dart b/lib/src/models/em_group_shared_file.dart index 76739a6e..aeb30f4a 100644 --- a/lib/src/models/em_group_shared_file.dart +++ b/lib/src/models/em_group_shared_file.dart @@ -1,6 +1,6 @@ import '../internal/inner_headers.dart'; -/// +/// ~english /// The EMGroupSharedFile class, which manages the chat group shared files. /// /// To get the information of the chat group shared file, call [EMGroupManager.fetchGroupFileListFromServer]. @@ -8,6 +8,17 @@ import '../internal/inner_headers.dart'; /// ```dart /// List? list = await EMClient.getInstance.groupManager.fetchGroupFileListFromServer(groupId); /// ``` +/// ~end +/// +/// ~chinese +/// 群组共享文件类。 +/// +/// 可以通过 [EMGroupManager.fetchGroupFileListFromServer] 方法获取共享文件信息,示例如下: +/// +/// ```dart +/// List list = await EMClient.getInstance.groupManager.fetchGroupFileListFromServer(groupId); +/// ``` +/// ~end class EMGroupSharedFile { EMGroupSharedFile._private(); @@ -17,39 +28,59 @@ class EMGroupSharedFile { int? _createTime; int? _fileSize; - /// + /// ~english /// Gets the shared file ID. /// /// **Return** The shared file ID. + /// ~end /// + /// ~chinese + /// 共享文件 ID。 + /// ~end String? get fileId => _fileId; - /// + /// ~english /// Gets the shared file name. /// /// **Return** The shared file name. + /// ~end /// + /// ~chinese + /// 共享文件名称。 + /// ~end String? get fileName => _fileName; - /// + /// ~english /// Gets the username that uploads the shared file. /// /// **Return** The username that uploads the shared file. + /// ~end /// + /// ~chinese + /// 上传共享文件的成员用户 ID。 + /// ~end String? get fileOwner => _fileOwner; - /// + /// ~english /// Gets the Unix timestamp for uploading the shared file, in milliseconds. /// /// **Return** The Unix timestamp for uploading the shared file, in milliseconds. + /// ~end /// + /// ~chinese + /// 共享文件的上传时间戳,单位为毫秒。 + /// ~end int? get createTime => _createTime; - /// + /// ~english /// Gets the data length of the shared file, in bytes. /// /// **Return** The data length of the shared file, in bytes. + /// ~end /// + /// ~chinese + /// 共享文件大小,单位为字节。 + /// ~end int? get fileSize => _fileSize; /// @nodoc diff --git a/lib/src/models/em_message.dart b/lib/src/models/em_message.dart index bd1ef8c1..4585c8c4 100644 --- a/lib/src/models/em_message.dart +++ b/lib/src/models/em_message.dart @@ -6,7 +6,7 @@ import 'package:flutter/services.dart'; import '../internal/inner_headers.dart'; -/// +/// ~english /// The message class. /// /// The sample code for constructing a text message to send is as follows. @@ -17,138 +17,256 @@ import '../internal/inner_headers.dart'; /// content: "hello", /// ); /// ``` +/// ~end +/// +/// ~chinese +/// 消息对象类。 +/// +/// 创建一条待发送的文本消息示例代码如下: /// +/// ```dart +/// EMMessage msg = EMMessage.createTxtSendMessage( +/// targetId: "user1", +/// content: "hello", +/// ); +/// ``` +/// ~end class EMMessage { /// 消息 ID。 String? _msgId; String _msgLocalId = DateTime.now().millisecondsSinceEpoch.toString() + Random().nextInt(99999).toString(); - /// + /// ~english /// Gets the message ID. /// /// **return** The message ID. + /// ~end + /// + /// ~chinese + /// 消息 ID。 + /// ~end String get msgId => _msgId ?? _msgLocalId; - /// + /// ~english /// The conversation ID. + /// ~end /// + /// ~chinese + /// 会话 ID。 + /// ~end String? conversationId; - /// + /// ~english /// The ID of the message sender. /// - For a one-to-one chat, it is the username of the peer user. /// - For a group chat, it is the group ID. /// - For a chat room, it is the chat room ID. - /// + /// ~end + /// + /// ~chinese + /// 消息发送方,可以是: + /// - 用户:用户 ID; + /// - 群组:群组 ID; + /// - 聊天室:聊天室 ID。 + /// ~end String? from = ''; - /// + /// ~english /// The ID of the message recipient. /// - For a one-to-one chat, it is the username of the peer user. /// - For a group chat, it is the group ID. /// - For a chat room, it is the chat room ID. - /// + /// ~end + /// + /// ~chinese + /// 消息接收方,可以是: + /// - 用户:用户 ID; + /// - 群组:群组 ID; + /// - 聊天室:聊天室 ID。 + /// ~end String? to = ''; - /// + /// ~english /// The local timestamp when the message is created on the local device, in milliseconds. + /// ~end /// + /// ~chinese + /// 消息的本地时间戳,单位为毫秒。 + /// ~end int localTime = DateTime.now().millisecondsSinceEpoch; - /// + /// ~english /// The timestamp when the message is received by the server. + /// ~end /// + /// ~chinese + /// 消息的服务器时间戳,单位为毫秒。 + /// ~end int serverTime = DateTime.now().millisecondsSinceEpoch; - /// + /// ~english /// The delivery receipt, which is to check whether the other party has received the message. /// /// Whether the recipient has received the message. /// - `true`: Yes. /// - `false`: No. + /// ~end + /// + /// ~chinese + /// 设置送达回执,即接收方是否已收到消息。 /// + /// - `true`:是; + /// - `false`:否。 + /// ~end bool hasDeliverAck = false; - /// + /// ~english /// Whether the recipient has read the message. /// - `true`: Yes. /// - `false`: No. + /// ~end /// + /// ~chinese + /// 设置已读回执,即接收方是否已阅读消息。 + /// - `true`:是; + /// - `false`:否。 + /// ~end bool hasReadAck = false; - /// + /// ~english /// Whether read receipts are required for group messages. /// /// - `true`: Yes. /// - `false`: No. /// + /// ~end + /// + /// ~chinese + /// 设置是否需要群组已读回执。 /// + /// - `true`:是; + /// - `false`:否。 + /// ~end bool needGroupAck = false; - /// + /// ~english /// Is it a message sent within a thread + /// ~end + /// + /// ~chinese + /// 是否为子区中的消息。 + /// ~end bool isChatThreadMessage = false; - /// + /// ~english /// Whether the message is read. /// - `true`: Yes. /// - `false`: No. + /// ~end /// + /// ~chinese + /// 查看消息是否已读。 /// + /// - `true`:是; + /// - `false`:否。 + /// ~end bool hasRead = false; - /// + /// ~english /// The enumeration of the chat type. /// /// There are three chat types: one-to-one chat, group chat, and chat room. + /// ~end + /// + /// ~chinese + /// 会话类型枚举。 /// + /// 三种会话类型:单聊,群聊,聊天室。 + /// ~end ChatType chatType = ChatType.Chat; + /// ~english + /// The message direction. see [MessageDirection]. + /// ~end /// - /// The message direction. see [MessageDirection] - /// + /// ~chinese + /// 消息方向,详见 [MessageDirection]。 + /// ~end MessageDirection direction = MessageDirection.SEND; + /// ~english + /// Gets the message sending/reception status. see [MessageStatus]. + /// ~end /// - /// Gets the message sending/reception status. see [MessageStatus] - /// + /// ~chinese + /// 消息状态,详见 [MessageStatus]。 + /// ~end MessageStatus status = MessageStatus.CREATE; - /// + /// ~english /// Message's extension attribute. + /// ~end /// + /// ~chinese + /// 消息的扩展字段。 + /// ~end Map? attributes; - /// + /// ~english /// Message body. We recommend you use [EMMessageBody]. + /// ~end /// + /// ~chinese + /// 消息体。请参见 [EMMessageBody]。 + /// ~end late EMMessageBody body; - /// + /// ~english /// Message Online Status /// /// Local database does not store. The default value for reading or pulling roaming messages from the database is YES + /// ~end + /// + /// ~chinese + /// 消息在线状态 /// + /// 本地数据库不存储。从数据库读取或提取漫游消息的默认值是true。 + /// ~end late final bool onlineState; ChatRoomMessagePriority? _priority; + /// ~english /// Sets the priority of chat room messages. /// param [priority] The priority of chat room messages. The default value is `Normal`, indicating the normal priority. For details, see[ChatRoomMessagePriority]. + /// ~end + /// + /// ~chinese + /// 设置聊天室消息优先级。 + /// Param [priority] 消息优先级。默认值为 `Normal`,表示普通优先级。详见 [ChatRoomMessagePriority]。 + /// ~end set chatroomMessagePriority(ChatRoomMessagePriority priority) { _priority = priority; } EMMessage._private(); - /// + /// ~english /// Creates a received message instance. /// /// Param [body] The message body. /// /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 创建一条接收消息。 /// + /// Param [body] 消息体。 + /// + /// **Return** 消息实例。 + /// ~end EMMessage.createReceiveMessage({ required this.body, this.chatType = ChatType.Chat, @@ -157,7 +275,7 @@ class EMMessage { this.direction = MessageDirection.RECEIVE; } - /// + /// ~english /// Creates a message instance for sending. /// /// Param [body] The message body. @@ -168,12 +286,25 @@ class EMMessage { /// - For a chat room, it is the chat room ID. /// /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 创建一条待发送的消息。 /// + /// Param [body] 消息体。 + /// + /// Param [to] 接收方,可以是: + /// - 用户:用户 ID; + /// - 群组:群组 ID; + /// - 聊天室:聊天室 ID。 + /// + /// **Return** 消息对象。 + /// ~end EMMessage.createSendMessage({ required this.body, this.to, this.chatType = ChatType.Chat, - }) : this.from = EMClient.getInstance.currentUsername, + }) : this.from = EMClient.getInstance.currentUserId, this.conversationId = to { this.hasRead = true; this.direction = MessageDirection.SEND; @@ -182,7 +313,7 @@ class EMMessage { void dispose() {} - /// + /// ~english /// Creates a text message for sending. /// /// Param [targetId] The ID of the message recipient. @@ -195,7 +326,20 @@ class EMMessage { /// Param [targetLanguages] Target languages. /// /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 创建一条文本消息。 + /// + /// Param [targetId] 消息接收方,可以是: + /// - 用户:用户 ID; + /// - 群组:群组 ID; + /// - 聊天室:聊天室 ID。 /// + /// Param [content] 文本消息内容。 + /// + /// **Return** 消息体实例。 + /// ~end EMMessage.createTxtSendMessage({ required String targetId, required String content, @@ -210,7 +354,7 @@ class EMMessage { ), ); - /// + /// ~english /// Creates a file message for sending. /// /// Param [targetId] The ID of the message recipient. @@ -225,7 +369,24 @@ class EMMessage { /// Param [fileSize] The file size in bytes. /// /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 创建一条待发送的文件消息。 + /// + /// Param [targetId] 消息接收方,可以是: + /// - 用户:用户 ID; + /// - 群组:群组 ID; + /// - 聊天室:聊天室 ID。 + /// + /// Param [filePath] 文件路径。 + /// + /// Param [displayName] 文件名。 /// + /// Param [fileSize] 文件大小,单位为字节。 + /// + /// **Return** 消息体实例。 + /// ~end EMMessage.createFileSendMessage({ required String targetId, required String filePath, @@ -241,7 +402,7 @@ class EMMessage { displayName: displayName, )); - /// + /// ~english /// Creates an image message for sending. /// /// Param [targetId] The ID of the message recipient. @@ -266,7 +427,34 @@ class EMMessage { /// Param [height] The image height in pixels. /// /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 创建一条待发送的图片消息。 + /// + /// Param [targetId] 消息接收方,可以是: + /// - 用户:用户 ID; + /// - 群组:群组 ID; + /// - 聊天室:聊天室 ID。 + /// + /// Param [filePath] 文件路径。 + /// + /// Param [displayName] 图片名。 /// + /// Param [thumbnailLocalPath] 缩略图本地路径。 + /// + /// Param [sendOriginalImage] 是否发送原图。 + /// - `true`: 是。 + /// - `false`: (default) 否。默认大于 100 kb 的图片会自动压缩发送缩略图。 + /// + /// Param [fileSize] 图片文件大小,单位是字节。 + /// + /// Param [width] 图片的宽,单位是像素。 + /// + /// Param [height] 图片的高,单位是像素。 + /// + /// **Return** 图片实例。 + /// ~end EMMessage.createImageSendMessage({ required String targetId, required String filePath, @@ -289,8 +477,8 @@ class EMMessage { height: height, )); - /// - /// Creates a video message instance for sending. + /// ~english + /// Creates a video message instance for sending. /// /// Param [targetId] The ID of the message recipient. /// - For a one-to-one chat, it is the username of the peer user. @@ -312,7 +500,32 @@ class EMMessage { /// Param [height] The height of the video thumbnail, in pixels. /// /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 创建一条待发送的视频消息。 + /// + /// Param [targetId] 消息接收方,可以是: + /// - 用户:用户 ID; + /// - 群组:群组 ID; + /// - 聊天室:聊天室 ID。 + /// + /// Param [filePath] 视频文件路径。 + /// + /// Param [displayName] 文件名。 + /// + /// Param [duration] 视频时长,单位是秒。 /// + /// Param [fileSize] 视频文件大小。 + /// + /// Param [thumbnailLocalPath] 缩略图的本地路径,一般取视频第一帧作为缩略图。 + /// + /// Param [width] 缩略图宽度,单位是像素。 + /// + /// Param [height] 缩略图高度,单位是像素。 + /// + /// **Return** 消息体实例。 + /// ~end EMMessage.createVideoSendMessage({ required String targetId, required String filePath, @@ -336,7 +549,7 @@ class EMMessage { height: height, )); - /// + /// ~english /// Creates a voice message for sending. /// /// Param [targetId] The ID of the message recipient. @@ -353,7 +566,26 @@ class EMMessage { /// Param [displayName] The name of the voice file which ends with a suffix that indicates the format of the file. For example "voice.mp3". /// /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 创建一条待发送的语音消息。 + /// + /// Param [targetId] 消息接收方,可以是: + /// - 用户:用户 ID; + /// - 群组:群组 ID; + /// - 聊天室:聊天室 ID。 + /// + /// Param [filePath] 文件路径。 + /// + /// Param [duration] 语音时长,单位为秒。 + /// + /// Param [fileSize] 语音文件大小,单位是字节。 + /// + /// Param [displayName] 文件名。 /// + /// **Return** 消息体实例。 + /// ~end EMMessage.createVoiceSendMessage({ required String targetId, required String filePath, @@ -370,7 +602,7 @@ class EMMessage { fileSize: fileSize, displayName: displayName)); - /// + /// ~english /// Creates a location message for sending. /// /// Param [targetId] The ID of the message recipient. @@ -387,7 +619,26 @@ class EMMessage { /// Param [buildingName] The building name. /// /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 创建一条待发送的位置信息。 + /// + /// Param [targetId] 消息接收方,可以是: + /// - 用户:用户 ID; + /// - 群组:群组 ID; + /// - 聊天室:聊天室 ID。 + /// + /// Param [latitude] 纬度。 + /// + /// Param [longitude] 经度。 + /// + /// Param [address] 地址。 /// + /// Param [buildingName] 建筑物名称。 + /// + /// **Return** 消息体实例。 + /// ~end EMMessage.createLocationSendMessage({ required String targetId, required double latitude, @@ -405,6 +656,7 @@ class EMMessage { buildingName: buildingName, )); + /// ~english /// Creates a command message for sending. /// /// Param [targetId] The ID of the message recipient. @@ -415,7 +667,20 @@ class EMMessage { /// Param [action] The command action. /// /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 创建一条待发送的命令消息。 + /// + /// Param [targetId] 消息接收方,可以是: + /// - 用户:用户 ID; + /// - 群组:群组 ID; + /// - 聊天室:聊天室 ID。 /// + /// Param [action] 命令内容。 + /// + /// **Return** 消息体实例。 + /// ~end EMMessage.createCmdSendMessage({ required String targetId, required action, @@ -427,6 +692,7 @@ class EMMessage { body: EMCmdMessageBody( action: action, deliverOnlineOnly: deliverOnlineOnly)); + /// ~english /// Creates a custom message for sending. /// /// Param [targetId] The ID of the message recipient. @@ -439,7 +705,22 @@ class EMMessage { /// Param [params] The params map. /// /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 创建一条待发送的自定义消息。 /// + /// Param [targetId] 消息接收方,可以是: + /// - 用户:用户 ID; + /// - 群组:群组 ID; + /// - 聊天室:聊天室 ID。 + /// + /// Param [event] 事件内容。 + /// + /// Param [params] 自定义消息的键值对 Map 列表。 + /// + /// **Return** 消息体实例。 + /// ~end EMMessage.createCustomSendMessage({ required String targetId, required event, @@ -542,13 +823,21 @@ class EMMessage { static const MethodChannel _emMessageChannel = const MethodChannel('com.chat.im/chat_message', JSONMethodCodec()); - /// + /// ~english /// Gets the Reaction list. /// /// **Return** The Reaction list /// /// **Throws** A description of the exception. See [EMError] + /// ~end + /// + /// ~chinese + /// 获取 Reaction 列表。 + /// + /// **Return** Reaction 列表。 /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 [EMError]。 + /// ~end Future> reactionList() async { Map req = {"msgId": msgId}; Map result = await _emMessageChannel.invokeMethod( @@ -569,13 +858,21 @@ class EMMessage { } } - /// + /// ~english /// Gets the number of members that have read the group message. /// /// **Return** group ack count /// /// **Throws** A description of the exception. See [EMError] + /// ~end + /// + /// ~chinese + /// 获取群消息已读人数。 + /// + /// **Return** 群消息已读人数。 /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 [EMError]。 + /// ~end Future groupAckCount() async { Map req = {"msgId": msgId}; Map result = @@ -592,13 +889,24 @@ class EMMessage { } } - /// + /// ~english /// Get an overview of the thread in the message (currently only supported by group messages) /// /// **Return** overview of the thread /// /// **Throws** A description of the exception. See [EMError] + /// ~end + /// + /// ~chinese + /// 获得消息中的子区概述。 + /// + /// @note + /// 目前,该方法只适用于群组消息。 /// + /// **Return** 子区概述内容。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 [EMError]。 + /// ~end Future chatThread() async { Map req = {"msg": msgId}; Map result = @@ -639,17 +947,31 @@ abstract class EMMessageBody { return toJson().toString(); } + /// ~english /// Gets the chat message type. + /// ~end + /// + /// ~chinese + /// 获取消息类型。 + /// ~end MessageType type; } -/// +/// ~english /// The command message body. +/// ~end /// +/// ~chinese +/// 命令消息体类。 +/// ~end class EMCmdMessageBody extends EMMessageBody { - /// + /// ~english /// Creates a command message. + /// ~end /// + /// ~chinese + /// 创建一个命令消息。 + /// ~end EMCmdMessageBody({required this.action, this.deliverOnlineOnly = false}) : super(type: MessageType.CMD); @@ -670,23 +992,40 @@ class EMCmdMessageBody extends EMMessageBody { return data; } + /// ~english /// The command action content. + /// ~end + /// + /// ~chinese + /// 命令内容。 + /// ~end late final String action; - /// + /// ~english /// Checks whether this command message is only delivered to online users. /// /// - `true`: Yes. /// - `false`: No. + /// ~end /// + /// ~chinese + /// 判断当前 CMD 类型消息是否只投递在线用户。 + /// + /// - `true`:是; + /// - `false`:否。 + /// ~end bool deliverOnlineOnly = false; } -/// +/// ~english /// The location message class. +/// ~end /// +/// ~chinese +/// 位置消息类。 +/// ~end class EMLocationMessageBody extends EMMessageBody { - /// + /// ~english /// Creates a location message body instance. /// /// Param [latitude] The latitude. @@ -696,7 +1035,19 @@ class EMLocationMessageBody extends EMMessageBody { /// Param [address] The address. /// /// Param [buildingName] The building name. + /// ~end + /// + /// ~chinese + /// 创建一个位置消息体实例。 + /// + /// Param [latitude] 纬度。 /// + /// Param [longitude] 经度。 + /// + /// Param [address] 地址。 + /// + /// Param [buildingName] 建筑物名称。 + /// ~end EMLocationMessageBody({ required this.latitude, required this.longitude, @@ -730,23 +1081,52 @@ class EMLocationMessageBody extends EMMessageBody { String? _address; String? _buildingName; + /// ~english /// The address. + /// ~end + /// + /// ~chinese + /// 地址。 + /// ~end String? get address => _address; + /// ~english /// The building name. + /// ~end + /// + /// ~chinese + /// 建筑物名称。 + /// ~end String? get buildingName => _buildingName; + /// ~english /// The latitude. + /// ~end + /// + /// ~chinese + /// 纬度。 + /// ~end late final double latitude; + /// ~english /// The longitude. + /// ~end + /// + /// ~chinese + /// 经度。 + /// ~end late final double longitude; } -/// +/// ~english /// The base class of file messages. +/// ~end /// +/// ~chinese +/// 文件类消息的基类。 +/// ~end class EMFileMessageBody extends EMMessageBody { + /// ~english /// Creates a message with an attachment. /// /// Param [localPath] The path of the image file. @@ -756,7 +1136,19 @@ class EMFileMessageBody extends EMMessageBody { /// Param [fileSize] The size of the file in bytes. /// /// Param [type] The file type. + /// ~end + /// + /// ~chinese + /// 创建一条带文件附件的消息。 + /// + /// Param [localPath] 图片文件路径。 + /// + /// Param [displayName] 文件显示名称。 + /// + /// Param [fileSize] 文件大小,单位是字节。 /// + /// Param [type] 文件类型。 + /// ~end EMFileMessageBody({ required this.localPath, this.displayName, @@ -791,22 +1183,58 @@ class EMFileMessageBody extends EMMessageBody { return data; } + /// ~english /// The local path of the attachment. + /// ~end + /// + /// ~chinese + /// 附件的本地路径。 + /// ~end late final String localPath; + /// ~english /// The token used to get the attachment. + /// ~end + /// + /// ~chinese + /// 获取附件的密钥。 + /// ~end String? secret; + /// ~english /// The attachment path in the server. + /// ~end + /// + /// ~chinese + /// 附件的服务器路径。 + /// ~end String? remotePath; + /// ~english /// The download status of the attachment. + /// ~end + /// + /// ~chinese + /// 附件的下载状态。 + /// ~end DownloadStatus fileStatus = DownloadStatus.PENDING; - /// The size of the attachment in bytes. + /// ~english + /// The size of the attachment in bytes. + /// ~end + /// + /// ~chinese + /// 附件的大小,以字节为单位。 + /// ~end int? fileSize; + /// ~english /// The attachment name. + /// ~end + /// + /// ~chinese + /// 附件的名称。 + /// ~end String? displayName; static DownloadStatus downloadStatusFromInt(int? status) { @@ -822,11 +1250,15 @@ class EMFileMessageBody extends EMMessageBody { } } -/// +/// ~english /// The image message body class. +/// ~end /// +/// ~chinese +/// 图片消息体类。 +/// ~end class EMImageMessageBody extends EMFileMessageBody { - /// + /// ~english /// Creates an image message body with an image file. /// /// Param [localPath] The local path of the image file. @@ -842,7 +1274,25 @@ class EMImageMessageBody extends EMFileMessageBody { /// Param [width] The image width in pixels. /// /// Param [height] The image height in pixels. + /// ~end + /// + /// ~chinese + /// 用图片文件创建一个图片消息体。 + /// + /// Param [localPath] 图片文件本地路径。 + /// + /// Param [displayName] 文件名。 /// + /// Param [thumbnailLocalPath] 图片缩略图本地路径。 + /// + /// Param [sendOriginalImage] 发送图片消息时的原始图片文件。 + /// + /// Param [fileSize] 图片文件大小,单位是字节。 + /// + /// Param [width] 图片宽度,单位为像素。 + /// + /// Param [height] 图片高度,单位为像素。 + /// ~end EMImageMessageBody({ required String localPath, String? displayName, @@ -885,42 +1335,94 @@ class EMImageMessageBody extends EMFileMessageBody { return data; } - /// + /// ~english /// Whether to send the original image. /// /// - `false`: (default) No. The original image will be compressed if it exceeds 100 KB and the thumbnail will be sent. /// - `true`: Yes. + /// ~end /// + /// ~chinese + /// 设置发送图片时,是否发送原图。 + /// - (默认)`false`:图片小于 100 KB 时,发送原图和缩略图;图片大于 100 KB 时,发送压缩后的图片和压缩后图片的缩略图。 + /// - `true`:发送原图和缩略图。 + /// ~end bool sendOriginalImage = false; + /// ~english /// The local path or the URI (a string) of the thumbnail. + /// ~end + /// + /// ~chinese + /// 缩略图的本地路径或者字符串形式的资源标识符。 + /// ~end String? thumbnailLocalPath; + /// ~english /// The URL of the thumbnail on the server. + /// ~end + /// + /// ~chinese + /// 缩略图的服务器路径。 + /// ~end String? thumbnailRemotePath; + /// ~english /// The secret to access the thumbnail. A secret is required for verification for thumbnail download. + /// ~end + /// + /// ~chinese + /// 设置访问缩略图的密钥。下载缩略图时用户需要提供密钥进行校验。 + /// ~end String? thumbnailSecret; + /// ~english /// The download status of the thumbnail. + /// ~end + /// + /// ~chinese + /// 缩略图的下载状态。 + /// ~end DownloadStatus thumbnailStatus = DownloadStatus.PENDING; + /// ~english /// The image width in pixels. + /// ~end + /// + /// ~chinese + /// 图片宽度,单位为像素。 + /// ~end double? width; + /// ~english /// The image height in pixels. + /// ~end + /// + /// ~chinese + /// 图片高度,单位为像素。 + /// ~end double? height; } -/// +/// ~english /// The text message class. +/// ~end /// +/// ~chinese +/// 文本消息类。 +/// ~end class EMTextMessageBody extends EMMessageBody { - /// + /// ~english /// Creates a text message. /// /// Param [content] The text content. + /// ~end + /// + /// ~chinese + /// 创建一条文本消息。 /// + /// Param [content] 文本消息内容。 + /// ~end EMTextMessageBody({ required this.content, this.targetLanguages, @@ -950,21 +1452,43 @@ class EMTextMessageBody extends EMMessageBody { return data; } + /// ~english /// The text content. + /// ~end + /// + /// ~chinese + /// 文本消息内容。 + /// ~end late final String content; + /// ~english /// The target languages to translate + /// ~end + /// + /// ~chinese + /// 翻译的目标语言。 + /// ~end List? targetLanguages; + /// ~english /// It is Map, key is target language, value is translated content + /// ~end + /// + /// ~chinese + /// 译文。 + /// ~end Map? translations; } -/// +/// ~english /// The video message body class. +/// ~end /// +/// ~chinese +/// 视频消息体类。 +/// ~end class EMVideoMessageBody extends EMFileMessageBody { - /// + /// ~english /// Creates a video message. /// /// Param [localPath] The local path of the video file. @@ -980,7 +1504,25 @@ class EMVideoMessageBody extends EMFileMessageBody { /// Param [height] The video height in pixels. /// /// Param [width] The video width in pixels. + /// ~end + /// + /// ~chinese + /// 创建一条视频消息。 + /// + /// Param [localPath] 视频文件本地路径。 + /// + /// Param [displayName] 视频名称。 /// + /// Param [duration] 视频时长,单位为秒。 + /// + /// Param [fileSize] 视频文件大小,单位是字节。 + /// + /// Param [thumbnailLocalPath] 视频缩略图本地路径。 + /// + /// Param [height] 视频高度,单位是像素。 + /// + /// Param [width] 视频宽度,单位是像素。 + /// ~end EMVideoMessageBody({ required String localPath, String? displayName, @@ -1024,33 +1566,79 @@ class EMVideoMessageBody extends EMFileMessageBody { return data; } + /// ~english /// The video duration in seconds. + /// ~end + /// + /// ~chinese + /// 视频时长,单位是秒。 + /// ~end int? duration; - /// The local path of the video thumbnail. + /// ~english + /// The local path of the video thumbnail. + /// ~end + /// + /// ~chinese + /// 视频缩略图的本地路径。 + /// ~end String? thumbnailLocalPath; + /// ~english /// The URL of the thumbnail on the server. + /// ~end + /// + /// ~chinese + /// 视频缩略图的在服务器上的存储路径。 + /// ~end String? thumbnailRemotePath; + /// ~english /// The secret key of the video thumbnail. + /// ~end + /// + /// ~chinese + /// 视频缩略图的密钥。 + /// ~end String? thumbnailSecret; + /// ~english /// The download status of the video thumbnail. + /// ~end + /// + /// ~chinese + /// 视频缩略图的下载状态。 + /// ~end DownloadStatus thumbnailStatus = DownloadStatus.PENDING; + /// ~english /// The video width in pixels. + /// ~end + /// + /// ~chinese + /// 视频宽度,单位是像素。 + /// ~end double? width; + /// ~english /// The video height in pixels. + /// ~end + /// + /// ~chinese + /// 视频高度,单位是像素。 + /// ~end double? height; } -/// +/// ~english /// The voice message body class. +/// ~end /// +/// ~chinese +/// 语音消息体类。 +/// ~end class EMVoiceMessageBody extends EMFileMessageBody { - /// + /// ~english /// Creates a voice message. /// /// Param [localPath] The local path of the voice file. @@ -1060,7 +1648,19 @@ class EMVoiceMessageBody extends EMFileMessageBody { /// Param [fileSize] The size of the voice file in bytes. /// /// Param [duration] The voice duration in seconds. + /// ~end + /// + /// ~chinese + /// 创建一条语音消息。 + /// + /// Param [localPath] 语言消息本地路径。 + /// + /// Param [displayName] 语音文件名。 + /// + /// Param [duration] 语音时长,单位是秒。 /// + /// Param [fileSize] 语音文件大小,单位是字节。 + /// ~end EMVoiceMessageBody({ localPath, this.duration = 0, @@ -1087,17 +1687,31 @@ class EMVoiceMessageBody extends EMFileMessageBody { return data; } + /// ~english /// The voice duration in seconds. + /// ~end + /// + /// ~chinese + /// 语音时长,单位是秒。 + /// ~end late final int duration; } -/// +/// ~english /// The custom message body. +/// ~end /// +/// ~chinese +/// 自定义消息体类。 +/// ~end class EMCustomMessageBody extends EMMessageBody { - /// + /// ~english /// Creates a custom message. + /// ~end /// + /// ~chinese + /// 自定义消息体类。 + /// ~end EMCustomMessageBody({ required this.event, this.params, @@ -1118,9 +1732,21 @@ class EMCustomMessageBody extends EMMessageBody { return data; } + /// ~english /// The event. + /// ~end + /// + /// ~chinese + /// 自定义事件内容。 + /// ~end late final String event; + /// ~english /// The custom params map. + /// ~end + /// + /// ~chinese + /// 自定义消息的键值对 Map 列表。 + /// ~end Map? params; } diff --git a/lib/src/models/em_message_reaction.dart b/lib/src/models/em_message_reaction.dart index d03fcabe..0ff7a0d4 100644 --- a/lib/src/models/em_message_reaction.dart +++ b/lib/src/models/em_message_reaction.dart @@ -1,33 +1,61 @@ import '../internal/inner_headers.dart'; -/// +/// ~english /// The message Reaction instance class, which has the following attributes: /// Reaction: The message Reaction. /// UserCount: The count of users that added the Reaction. /// UserList: The list of users that added the Reaction. /// isAddedBySelf: Whether the current user added this Reaction. +/// ~end /// +/// ~chinese +/// 消息 Reaction 实体类,用于指定 Reaction 属性。 +/// ~end class EMMessageReaction { + /// ~english /// The Reaction content + /// ~end + /// + /// ~chinese + /// Reaction 内容。 + /// ~end final String reaction; - /// The count of the users who added this Reaction + /// ~english + /// The count of the users who added this Reaction. + /// ~end + /// + /// ~chinese + /// 添加了指定 Reaction 的用户数量。 + /// ~end final int userCount; - /// Whether the current user added this Reaction + /// ~english + /// Whether the current user added this Reaction. /// /// `Yes`: is added by self /// `No`: is not added by self. + /// ~end /// + /// ~chinese + /// 当前用户是否添加了该 Reaction。 + /// + /// - `true`:是; + /// - `false`:否。 + /// ~end final bool isAddedBySelf; - /// + /// ~english /// The list of users that added this Reaction /// /// **Note** /// To get the entire list of users adding this Reaction, you can call [EMChatManager.fetchReactionDetail] which returns the user list with pagination. /// Other methods like [EMMessage.reactionList], [EMChatManager.fetchReactionList] or [EMChatEventHandler.onMessageReactionDidChange] can get the first three users. + /// ~end /// + /// ~chinese + /// 添加了指定 Reaction 的用户列表。 + /// ~end final List userList; EMMessageReaction._private({ @@ -57,17 +85,39 @@ class EMMessageReaction { } } -/// +/// ~english /// The message reaction change event class. +/// ~end /// +/// ~chinese +/// 消息 Reaction 事件类。 +/// ~end class EMMessageReactionEvent { - /// The conversation ID + /// ~english + /// The conversation ID. + /// ~end + /// + /// ~chinese + /// 会话 ID。 + /// ~end final String conversationId; - /// The message ID + /// ~english + /// The message ID. + /// ~end + /// + /// ~chinese + /// 消息 ID。 + /// ~end final String messageId; - /// The Reaction which is changed + /// ~english + /// The Reaction which is changed. + /// ~end + /// + /// ~chinese + /// Reaction 列表。 + /// ~end final List reactions; EMMessageReactionEvent._private({ diff --git a/lib/src/models/em_options.dart b/lib/src/models/em_options.dart index d3c8d763..42ad625c 100644 --- a/lib/src/models/em_options.dart +++ b/lib/src/models/em_options.dart @@ -1,301 +1,529 @@ import '../internal/inner_headers.dart'; -/// +/// ~english /// The EMOptions class, which contains the settings of the Chat SDK. /// /// For example, whether to encrypt the messages before sending and whether to automatically accept the friend invitations. +/// ~end /// +/// ~chinese +/// 提供 SDK 聊天相关的设置。 +/// 用户可以用来配置 SDK 的各种参数、选项, +/// 比如,发送消息加密,是否自动接受加好友邀请。 +/// ~end class EMOptions { + /// ~english /// The app key that you get from the console when creating the app. + /// ~end + /// + /// ~chinese + /// 创建 app 时在 console 后台上注册的 app 唯一识别符。 + /// ~end late final String appKey; - /// + /// ~english /// Whether to enable automatic login. /// /// - `true`: (Default) Yes; /// - `false`: No. + /// ~end + /// + /// ~chinese + /// 是否允许自动登录。 /// + /// - (默认) `true`:允许; + /// - `false`:不允许. + /// ~end final bool autoLogin; - /// + /// ~english /// Whether to output the debug information. Make sure to call the method after initializing the EMClient using [EMClient.init]. /// /// - `true`: Yes. /// - `false`: (Default)No. + /// ~end /// + /// ~chinese + /// 是否输出调试信息,在 EMClient 初始化完成后调用,详见 {@link #init(Context, EMOptions)}。 + /// - `true`:SDK 会在 log 里输出调试信息; + /// - (默认)`false`:不会输出调试信息。 + /// ~end final bool debugModel; - /// + /// ~english /// Whether to accept friend invitations from other users automatically. /// /// - `true`: (Default) Yes; /// - `false`: No. + /// ~end + /// + /// ~chinese + /// 是否自动接受加好友邀请。 + /// - `true`:是。 + /// - (默认)`false`:否。 + /// ~end final bool acceptInvitationAlways; - /// + /// ~english /// Whether to accept group invitations automatically. /// /// - `true`: (Default) Yes; /// - `false`: No. + /// ~end /// + /// ~chinese + /// 是否自动接受群组邀请。 + /// - `true`:是; + /// - (默认)`false`:否。 + /// ~end final bool autoAcceptGroupInvitation; - /// + /// ~english /// Whether to require read receipt after sending a message. /// /// - `true`: (Default) Yes; /// - `false`: No. + /// ~end /// + /// ~chinese + /// 是否发送消息已读回执. + /// - (默认)`true`:是; + /// - `false`:否。 + /// ~end final bool requireAck; - /// + /// ~english /// Whether to require the delivery receipt after sending a message. /// /// - `true`: Yes; /// - `false`: (Default) No. + /// ~end /// + /// ~chinese + /// /// 是否发送消息已送达回执。 + /// - `true`:是。 + /// - (默认)`false`:否。 + /// ~end final bool requireDeliveryAck; - /// + /// ~english /// Whether to delete the group messages when leaving a group. /// /// - `true`: (Default) Yes; /// - `false`: No. + /// ~end /// + /// ~chinese + /// 离开群组时是否删除消息。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// ~end final bool deleteMessagesAsExitGroup; - /// + /// ~english /// Whether to delete the chat room messages when leaving the chat room. /// /// - `true`: (Default) Yes; /// - `false`: No. + /// ~end + /// + /// ~chinese + /// 离开聊天室时是否删除消息。 /// + /// - (默认)`true`:是; + /// - `false`:否。 + /// ~end final bool deleteMessagesAsExitChatRoom; - /// + /// ~english /// Whether to allow the chat room owner to leave the chat room. /// /// - `true`: (Default) Yes; /// - `false`: No. + /// ~end + /// + /// ~chinese + /// 是否允许聊天室所有者离开聊天室。 /// + /// - (默认)`true`:是; + /// - `false`:否。 + /// ~end final bool isChatRoomOwnerLeaveAllowed; - /// + /// ~english /// Whether to sort the messages by the time when the messages are received by the server. /// /// - `true`: (Default) Yes; /// - `false`: No. + /// ~end + /// + /// ~chinese + /// 是否根据服务器收到消息的时间对消息进行排序。 /// + /// - (默认)`true`:是; + /// - `false`:否。 + /// ~end final bool sortMessageByServerTime; - /// + /// ~english /// Whether only HTTPS is used for REST operations. /// /// - `true`: (Default) Only HTTPS is used. /// - `false`: Both HTTP and HTTPS are allowed. + /// ~end + /// + /// ~chinese + /// 是否只用 HTTPS。 /// + /// - (默认)`true`:是; + /// - `false`:否。可以同时用 HTTP 和 HTTPS。 + /// ~end final bool usingHttpsOnly; - /// + /// ~english /// Whether to upload the message attachments automatically to the chat server. /// /// - `true`: (Default) Yes; /// - `false`: No. Message attachments are uploaded to a custom path. + /// ~end /// + /// ~chinese + /// 是否自动将消息附件上传到聊天服务器。 + /// + /// - (默认)`true`:是; + /// - `false`:否。使用自定义路径。 + /// ~end final bool serverTransfer; - /// + /// ~english /// Whether to automatically download the thumbnail. /// /// - `true`: (Default) Yes; /// - `false`: No. + /// ~end + /// + /// ~chinese + /// 是否自动下载缩略图。 /// + /// - (默认)`true`:是; + /// - `false`:否。 + /// ~end final bool isAutoDownloadThumbnail; - /// + /// ~english /// Whether to enable DNS. /// /// - `true`: (Default) Yes; /// - `false`: No. + /// ~end + /// + /// ~chinese + /// 是否开启 DNS。 /// + /// - (默认)`true`:是; + /// - `false`:否。 + /// ~end final bool enableDNSConfig; + /// ~english /// The DNS URL. + /// ~end + /// + /// ~chinese + /// DNS 地址。 + /// ~end final String? dnsUrl; + /// ~english /// The custom REST server. + /// ~end + /// + /// ~chinese + /// REST 服务器。 + /// ~end final String? restServer; + /// ~english /// The custom IM message server url. + /// ~end + /// + /// ~chinese + /// 消息服务器。 + /// ~end final String? imServer; + /// ~english /// The custom IM server port. + /// ~end + /// + /// ~chinese + /// 是否使用自定义 IM 服务的端口。用于私有化部署。 + /// ~end final int? imPort; + /// ~english /// The area code. /// This attribute is used to restrict the scope of accessible edge nodes. The default value is `AreaCodeGLOB`. /// This attribute can be set only when you call [EMClient.init]. The attribute setting cannot be changed during the app runtime. - final int areaCode; + /// ~end + /// + /// ~chinese + /// 区号 + /// 此属性用于限制可访问边缘节点的范围。缺省值为AreaCodeGLOB。 + /// 此属性只能在调用[EMClient.init]时设置。在应用程序运行期间不能更改属性设置。 + /// ~end + final int serverAreaCode; EMPushConfig _pushConfig = EMPushConfig(); + /// ~english /// Enable OPPO PUSH on OPPO devices. /// /// Param [appKey] The app id for OPPO PUSH. /// /// Param [secret] The app secret for OPPO PUSH. + /// ~end /// + /// ~chinese + /// 开启 Oppo 推送。 + /// + /// Param [appId] Oppo 推送的 App ID。 + /// + /// Param [appKey] Oppo 推送的 app key。 + /// ~end void enableOppoPush(String appKey, String secret) { _pushConfig.enableOppoPush = true; _pushConfig.oppoAppKey = appKey; _pushConfig.oppoAppSecret = secret; } - /// + /// ~english /// Enable Mi Push on Mi devices. /// /// Param [appId] The app ID for Mi Push. /// /// Param [appKey] The app key for Mi Push. + /// ~end /// + /// ~chinese + /// 开启小米推送。 + /// + /// Param [appId] 小米推送的 App ID。 + /// + /// Param [appKey] 小米推送的 app key。 + /// ~end void enableMiPush(String appId, String appKey) { _pushConfig.enableMiPush = true; _pushConfig.miAppId = appId; _pushConfig.miAppKey = appKey; } + /// ~english /// Enable MeiZu Push on MeiZu devices. /// Param [appId] The app ID for MeiZu Push. /// Param [appKey] The app key for MeiZu Push. + /// ~end + /// + /// ~chinese + /// 开启魅族推送. + /// Param [appId] 魅族AppId. + /// Param [appKey] 魅族Appkey. + /// ~end void enableMeiZuPush(String appId, String appKey) { _pushConfig.mzAppId = appId; _pushConfig.mzAppKey = appKey; } - /// + /// ~english /// Enable Firebase Cloud Messaging (FCM) push on devices that support Google Play. /// /// Param [appId] The app ID for FCM push. + /// ~end + /// + /// ~chinese + /// 开启 FCM(GCM 的升级版)推送。 /// + /// Param [appId] FCM 推送的 App ID。 + /// ~end void enableFCM(String appId) { _pushConfig.enableFCM = true; _pushConfig.fcmId = appId; } - /// + /// ~english /// Enable vivo Push on vivo devices. + /// ~end /// + /// ~chinese + /// 开启 vivo 推送。 + /// ~end void enableVivoPush() { _pushConfig.enableVivoPush = true; } + /// ~english /// Enable Huawei Push on Huawei devices. + /// ~end /// + /// ~chinese + /// 开启华为推送。 + /// ~end void enableHWPush() { _pushConfig.enableHWPush = true; } - /// + /// ~english /// Enables Apple Push Notification service (APNs) on iOS devices. /// /// Param [certName] The APNs certificate name. + /// ~end + /// + /// ~chinese + /// 开启 Apple 推送通知服务(APNs)推送。 /// + /// Param [certName] APNs 推送证书的名称。 + /// ~end void enableAPNs(String certName) { _pushConfig.enableAPNS = true; _pushConfig.apnsCertName = certName; } - /// + /// ~english /// Sets the app options. /// + /// Param [appKey] The app key that you get from the console when creating an app. + /// + /// Param [autoLogin] Whether to enable automatic login. + /// + /// Param [debugModel] Whether to output the debug information. Make sure to call the method after the EMClient is initialized. See [EMClient.init]. + /// + /// Param [acceptInvitationAlways] Whether to accept friend invitations from other users automatically. + /// + /// Param [autoAcceptGroupInvitation] Whether to accept group invitations automatically. + /// + /// Param [requireAck] Whether the read receipt is required. + /// + /// Param [requireDeliveryAck] Whether the delivery receipt is required. + /// + /// Param [deleteMessagesAsExitGroup] Whether to delete the related group messages when leaving a group. + /// + /// Param [deleteMessagesAsExitChatRoom] Whether to delete the related chat room messages when leaving the chat room. + /// + /// Param [isChatRoomOwnerLeaveAllowed] Whether to allow the chat room owner to leave the chat room. + /// + /// Param [sortMessageByServerTime] Whether to sort the messages by the time the server receives messages. + /// + /// Param [usingHttpsOnly] Whether only HTTPS is used for REST operations. + /// + /// Param [serverTransfer] Whether to upload the message attachments automatically to the chat server. + /// + /// Param [isAutoDownloadThumbnail] Whether to automatically download the thumbnail. + /// + /// Param [enableDNSConfig] Whether to enable DNS. + /// + /// Param [dnsUrl] The DNS url. + /// + /// Param [restServer] The REST server for private deployments. + /// + /// Param [imPort] The IM server port for private deployments. + /// + /// Param [imServer] The IM server URL for private deployment. + /// + /// Param [serverAreaCode] The area code. + /// + /// ~end + /// + /// ~chinese + /// 设置 SDK + /// Param [appKey] 创建 app 时在 console 后台上注册的 app 唯一识别符。 + /// + /// Param [autoLogin] 是否开启自动登录。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// Param [debugModel] 是否输出调试信息,在 EMClient 初始化完成后调用,详见 {@link #init(Context, EMOptions)}。 + /// - `true`:SDK 会在 log 里输出调试信息; + /// - (默认)`false`:不会输出调试信息。 + /// + /// Param [acceptInvitationAlways] 是否自动接受加好友邀请。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// Param [autoAcceptGroupInvitation] 是否自动接受群组邀请。 + /// - `true`:是; + /// - (默认)`false`:否。 + /// + /// Param [requireAck] 是否发送已读回执。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// Param [requireDeliveryAck] 是否发送已送达回执。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// Param [deleteMessagesAsExitGroup] 是否在离开群组时删除群组历史消息。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// Param [deleteMessagesAsExitChatRoom] 是否在离开聊天室时删除聊天历史消息。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// Param [isChatRoomOwnerLeaveAllowed] 是否允许聊天室所有者离开聊天室。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// Param [sortMessageByServerTime] 是否根据服务器收到消息的时间对消息进行排序。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// Param [usingHttpsOnly] 是否只使用 HTTPS。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// Param [serverTransfer] 是否自动将消息附件上传到聊天服务器。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// Param [isAutoDownloadThumbnail] 是否自动下载缩略图。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// Param [enableDNSConfig] 设置是否开启 DNS。 + /// - (默认)`true`:是; + /// - `false`:否。 + /// + /// Param [dnsUrl] DNS 地址。 + /// + /// Param [restServer] 私有部署时的 REST 服务器地址。 + /// + /// Param [imPort] 私有部署时的 IM 服务器端口。 + /// + /// Param [imServer] 私有部署时的 IM 服务器地址。 + /// + /// Param [serverAreaCode] server 区域码. + /// ~end EMOptions({ - /// Param [appKey] The app key that you get from the console when creating an app. required this.appKey, - - /// Param [autoLogin] Whether to enable automatic login. - /// - `true`: (Default) Yes; - /// - `false`: No. this.autoLogin = true, - - /// Param [debugModel] Whether to output the debug information. Make sure to call the method after the EMClient is initialized. See [EMClient.init]. - /// - `true`: Yes. - /// - `false`: (Default) No. this.debugModel = false, - - /// Param [acceptInvitationAlways] Whether to accept friend invitations from other users automatically. - /// - `true`: Yes; - /// - `false`: (Default) No. this.acceptInvitationAlways = false, - - /// Param [autoAcceptGroupInvitation] Whether to accept group invitations automatically. - /// - `true`: Yes; - /// - `false`: (Default) No. this.autoAcceptGroupInvitation = false, - - /// Param [requireAck] Whether the read receipt is required. - /// - `true`: (Default) Yes; - /// - `false`: No. this.requireAck = true, - - /// Param [requireDeliveryAck] Whether the delivery receipt is required. - /// - `true`: Yes; - /// - `false`: (Default) No. this.requireDeliveryAck = false, - - /// Param [deleteMessagesAsExitGroup] Whether to delete the related group messages when leaving a group. - /// - `true`: (Default) Yes; - /// - `false`: No. this.deleteMessagesAsExitGroup = true, - - /// Param [deleteMessagesAsExitChatRoom] Whether to delete the related chat room messages when leaving the chat room. - /// - `true`: (Default) Yes; - /// - `false`: No. this.deleteMessagesAsExitChatRoom = true, - - /// Param [isChatRoomOwnerLeaveAllowed] Whether to allow the chat room owner to leave the chat room. - /// - `true`: (Default) Yes; - /// - `false`: No. this.isChatRoomOwnerLeaveAllowed = true, - - /// Param [sortMessageByServerTime] Whether to sort the messages by the time the server receives messages. - /// - `true`: (Default) Yes; - /// - `false`: No. this.sortMessageByServerTime = true, - - /// Param [usingHttpsOnly] Whether only HTTPS is used for REST operations. - /// - `true`: (Default) Yes; - /// - `false`: No. this.usingHttpsOnly = true, - - /// Param [serverTransfer] Whether to upload the message attachments automatically to the chat server. - /// - `true`: (Default) Yes; - /// - `false`: No. this.serverTransfer = true, - - /// Param [isAutoDownloadThumbnail] Whether to automatically download the thumbnail. - /// - `true`: (Default) Yes; - /// - `false`: No. this.isAutoDownloadThumbnail = true, - - /// Param [enableDNSConfig] Whether to enable DNS. - /// - `true`: (Default) Yes; - /// - `false`: No. this.enableDNSConfig = true, - - /// Param [dnsUrl] The DNS url. this.dnsUrl, - - /// Param [restServer] The REST server for private deployments. this.restServer, - - /// Param [imPort] The IM server port for private deployments. this.imPort, - - /// Param [imServer] The IM server URL for private deployment. this.imServer, - - /// Param [areaCode] The area code. - this.areaCode = AreaCode.GLOB, + this.serverAreaCode = AreaCode.GLOB, }); /// @nodoc @@ -322,7 +550,7 @@ class EMOptions { imServer: json["imServer"], restServer: json["restServer"], dnsUrl: json["dnsUrl"], - areaCode: json["areaCode"] ?? AreaCode.GLOB, + serverAreaCode: json["areaCode"] ?? AreaCode.GLOB, ); ret._pushConfig = EMPushConfig(); @@ -361,7 +589,7 @@ class EMOptions { data["usingHttpsOnly"] = this.usingHttpsOnly; data["pushConfig"] = this._pushConfig.toJson(); - data["areaCode"] = this.areaCode; + data["areaCode"] = this.serverAreaCode; return data; } diff --git a/lib/src/models/em_page_result.dart b/lib/src/models/em_page_result.dart index 0a6a8ce4..07b0c68a 100644 --- a/lib/src/models/em_page_result.dart +++ b/lib/src/models/em_page_result.dart @@ -1,11 +1,19 @@ typedef PageResultCallback = Object Function(dynamic obj); -/// +/// ~english /// The EMPageResult class, which is returned when calling the methods that fetch data by pagination. /// The SDK also returns the number of remaining pages and the data count of the next page. If the dada count is less than the count you set, there is no more data on server. /// /// Param [T] Generics. +/// ~end +/// +/// ~chinese +/// 分页类。 +/// 该类包含下次查询的页码以及相应页面上的数据条数。 +/// 该对象在分页获取数据时返回。 /// +/// Param [T] 泛型类型 T。 +/// ~end class EMPageResult { EMPageResult._private(); @@ -28,9 +36,21 @@ class EMPageResult { int? _pageCount; List _data = []; + /// ~english /// The page count. + /// ~end + /// + /// ~chinese + /// 当前页面上的数据条数。若 `PageCount` 小于传入的每页要获取的数量,表示当前是最后一页。 + /// ~end get pageCount => _pageCount; + /// ~english /// The result data. + /// ~end + /// + /// ~chinese + /// 获取 泛型数据。 + /// ~end List? get data => _data; } diff --git a/lib/src/models/em_presence.dart b/lib/src/models/em_presence.dart index 405020e1..40d8a0dc 100644 --- a/lib/src/models/em_presence.dart +++ b/lib/src/models/em_presence.dart @@ -1,20 +1,54 @@ -/// +/// ~english /// The presence property class that contains presence properties, including the publisher's user ID and current presence state, and the platform used by the online device, as well as the presence's extension information, update time, and subscription expiration time. +/// ~end /// +/// ~chinese +/// 在线状态属性类,包含发布者的用户名、在线设备使用的平台、当前在线状态以及在线状态的扩展信息、更新时间和到期时间。 +/// ~end class EMPresence { + /// ~english /// The user ID of the presence publisher. + /// ~end + /// + /// ~chinese + /// 在线状态发布者的用户 ID。 + /// ~end final String publisher; + /// ~english /// The presence description information. + /// ~end + /// + /// ~chinese + /// 自定义在线状态,例如忙碌、离开和隐身等。 + /// ~end final String statusDescription; + /// ~english /// The presence update time, which is generated by the server. + /// ~end + /// + /// ~chinese + /// 在线状态更新 Unix 时间戳,单位为秒。 + /// ~end final int lastTime; + /// ~english /// The expiration time of the presence subscription. + /// ~end + /// + /// ~chinese + /// 在线状态订阅到期 Unix 时间戳,单位为秒。 + /// ~end final int expiryTime; + /// ~english /// The details of the current presence state. + /// ~end + /// + /// ~chinese + /// 该用户的当前在线状态详情。 + /// ~end Map? statusDetails; /// @nodoc @@ -38,18 +72,30 @@ class EMPresence { } } -/// +/// ~english /// The presence details, including the platform used by the publisher's current online device and the current presence state. +/// ~end /// +/// ~chinese +/// 用户在线状态详情。 +/// ~end class EMPresenceStatusDetail { - /// + /// ~english /// The platform used by the current online device of the publisher, which can be "ios", "android", "linux", "windows", or "webim". + /// ~end /// + /// ~chinese + /// 发布在线设备,可能是 "ios", "android", "linux", "windows", "webim"。 + /// ~end final String device; - /// + /// ~english /// The current presence state of the publisher. + /// ~end /// + /// ~chinese + /// 发布的在线状态。 + /// ~end final int status; /// @nodoc diff --git a/lib/src/models/em_push_configs.dart b/lib/src/models/em_push_configs.dart index 495e2d3c..6680a65f 100644 --- a/lib/src/models/em_push_configs.dart +++ b/lib/src/models/em_push_configs.dart @@ -1,55 +1,41 @@ import '../internal/inner_headers.dart'; +/// ~english /// The push configuration class. +/// ~end +/// +/// ~chinese +/// 推送设置类。 +/// ~end class EMPushConfigs { EMPushConfigs._private({ this.displayStyle = DisplayStyle.Simple, this.displayName, - this.noDisturb = false, - this.noDisturbStartHour = -1, - this.noDisturbEndHour = -1, }); - /// + /// ~english /// The display type of push notifications. + /// ~end /// + /// ~chinese + /// 获取推送显示类型。 + /// ~end final DisplayStyle displayStyle; - /// + /// ~english /// The user's nickname to be displayed in the notification. + /// ~end /// + /// ~chinese + /// 通知中显示的用户昵称。 + /// ~end final String? displayName; - /// - /// Whether to enable the do-not-disturb mode for push notifications. - /// - `true`: Yes. - /// - `false`: No. - /// Sets it by [EMPushManager.disableOfflinePush]. - /// - @Deprecated( - "Use ChatSilentModeResult property remindType, expireTimestamp and silentModeTime determine whether to enable") - final bool noDisturb; - - /// - /// The start hour of the do-not-disturb mode for push notifications. - /// - @Deprecated("Use ChatSilentModeResult property startTime instead") - final int noDisturbStartHour; - - /// - /// The end hour of the do-not-disturb mode for push notifications. - /// - @Deprecated("Use ChatSilentModeResult property endTime instead") - final int noDisturbEndHour; - /// @nodoc factory EMPushConfigs.fromJson(Map map) { return EMPushConfigs._private( displayStyle: map['pushStyle'] == 0 ? DisplayStyle.Simple : DisplayStyle.Summary, - noDisturb: map.boolValue('noDisturb'), - noDisturbStartHour: map['noDisturbStartHour'], - noDisturbEndHour: map['noDisturbEndHour'], displayName: map["displayName"], ); } diff --git a/lib/src/models/em_translate_language.dart b/lib/src/models/em_translate_language.dart index d22bf973..d669feb9 100644 --- a/lib/src/models/em_translate_language.dart +++ b/lib/src/models/em_translate_language.dart @@ -1,14 +1,36 @@ +/// ~english +/// The translation language class, which contains the information of the translation languages. +/// ~end /// -/// The translation language class, which contains the information of the translation languages. -/// +/// ~chinese +/// 翻译语言类,包含翻译语言相关信息。 +/// ~end class EMTranslateLanguage { + /// ~english /// The code of a target language. For example, the code for simplified Chinese is "zh-Hans". + /// ~end + /// + /// ~chinese + /// 目标语言代码,如中文简体为 "zh-Hans"。 + /// ~end final String languageCode; + /// ~english /// The language name. For example, the code for simplified Chinese is "Chinese Simplified". + /// ~end + /// + /// ~chinese + /// 语言名称,如中文简体为 "Chinese Simplified"。 + /// ~end final String languageName; + /// ~english /// The native name of the language. For example, the native name of simplified Chinese is "Chinese (Simplified)". + /// ~end + /// + /// ~chinese + /// 语言的原生名称,如中文简体为 "中文 (简体)"。 + /// ~end final String languageNativeName; EMTranslateLanguage._private({ diff --git a/lib/src/models/em_userInfo.dart b/lib/src/models/em_userInfo.dart index 80b02d5d..a0cbbcb5 100644 --- a/lib/src/models/em_userInfo.dart +++ b/lib/src/models/em_userInfo.dart @@ -1,12 +1,18 @@ -/// +/// ~english /// The EMUserInfo class, which contains the user attributes, such as the nickname, description, and avatar. +/// ~end /// +/// ~chinese +/// 用户属性类。 +/// ~end class EMUserInfo { - /// + /// ~english /// Creates a user attribute. + /// ~end /// - /// Param [userId] The username. - /// + /// ~chinese + /// 创建用户属性。 + /// ~end EMUserInfo._private( this.userId, { this.nickName, @@ -65,77 +71,106 @@ class EMUserInfo { return data; } - /// Gets the username. - /// - /// **Return** - /// The user's username. + /// ~english + /// Gets the userId. + /// ~end /// + /// ~chinese + /// 用户 ID。 + /// ~end final String userId; + /// ~english /// Gets the user's nickname. + /// ~end /// - /// **Return** - /// The user's nickname. - /// + /// ~chinese + /// 用户昵称。 + /// ~end final String? nickName; + /// ~english /// Gets the avatar URL of the user. + /// ~end /// - /// **Return** - /// The avatar URL of the user. - /// + /// ~chinese + /// 用户头像。 + /// ~end final String? avatarUrl; + /// ~english /// Gets the email address of the user. + /// ~end /// - /// **Return** - /// The email address of the user. - /// + /// ~chinese + /// 用户邮箱。 + /// ~end final String? mail; + /// ~english /// Gets the mobile numbers of the user. + /// ~end /// - /// **Return** - /// The mobile numbers of the user. - /// + /// ~chinese + /// 用户手机号。 + /// ~end final String? phone; + /// ~english /// Gets the user's gender. /// - /// **Return** /// The user's gender: /// - `0`: (Default) UnKnow; /// - `1`: Male; /// - `2`: Female. - /// + /// ~end + /// + /// ~chinese + /// 用户性别。 + /// - (默认) `0`:未知; + /// - `1`: 男; + /// - `2`: 女。 + /// ~end final int gender; + /// ~english /// Gets the user's signature. + /// ~end /// - /// **Return** - /// The user's signature. - /// + /// ~chinese + /// 用户签名。 + /// ~end final String? sign; + /// ~english /// Gets the user's data of birth. + /// ~end /// - /// **Return** - /// The user's data of birth. - /// + /// ~chinese + /// 用户生日。 + /// ~end final String? birth; + /// ~english /// Gets the user's extension information. + /// ~end /// - /// **Return** - /// The user's extension information. - /// + /// ~chinese + /// 用户自定义属性字段。 + /// ~end final String? ext; + /// ~english /// Gets the time period(seconds) when the user attributes in the cache expire. - /// If the interval between two callers is less than or equal to the value you set in the parameter, user attributes are obtained directly from the local cache; otherwise, they are obtained from the server. For example, if you set this parameter to 120(2 minutes), once this method is called again within 2 minutes, the SDK returns the attributes obtained last time. - /// - /// **Return** - /// The time period(seconds) when the user attributes in the cache expire. - /// + /// If the interval between two callers is less than or equal to the value you set in the parameter, + /// user attributes are obtained directly from the local cache; otherwise, they are obtained from the server. + /// For example, if you set this parameter to 120(2 minutes), once this method is called again within 2 minutes, + /// the SDK returns the attributes obtained last time. + /// ~end + /// + /// ~chinese + /// 获取缓存中的用户属性到期时的时间段(秒)。如果两个调用者之间的间隔小于或等于参数中设置的值,则直接从本地缓存获取用户属性; + /// 否则,从服务器获取。例如,如果将该参数设置为120(2分钟),则在2分钟内再次调用该方法,SDK将返回上次获取的属性。 + /// ~end final int expireTime = DateTime.now().millisecondsSinceEpoch; } From 20793a4a7d1959bb4f28f41dfc6fe2d03bad6b38 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Wed, 10 May 2023 15:53:29 +0800 Subject: [PATCH 03/49] change ios to support multiple_engine. --- ios/Classes/EMChatManagerWrapper.h | 1 + ios/Classes/EMChatMessageWrapper.m | 1 + ios/Classes/EMChatroomManagerWrapper.m | 1 + ios/Classes/EMClientWrapper.h | 7 ------- ios/Classes/EMClientWrapper.m | 23 +++++------------------ ios/Classes/EMGroupManagerWrapper.h | 3 ++- ios/Classes/EMGroupManagerWrapper.m | 6 +++--- ios/Classes/EMProgressManager.m | 11 ++++++++--- ios/Classes/EMUserInfoManagerWrapper.m | 4 ++-- ios/Classes/EMWrapper.h | 4 +++- ios/Classes/EMWrapper.m | 14 +++++++++++++- ios/Classes/ImFlutterSdkPlugin.h | 2 +- ios/Classes/ImFlutterSdkPlugin.m | 7 +++---- 13 files changed, 43 insertions(+), 41 deletions(-) diff --git a/ios/Classes/EMChatManagerWrapper.h b/ios/Classes/EMChatManagerWrapper.h index 744cfbc5..74a29f8a 100644 --- a/ios/Classes/EMChatManagerWrapper.h +++ b/ios/Classes/EMChatManagerWrapper.h @@ -10,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN @interface EMChatManagerWrapper : EMWrapper + @end NS_ASSUME_NONNULL_END diff --git a/ios/Classes/EMChatMessageWrapper.m b/ios/Classes/EMChatMessageWrapper.m index a59255ef..12412519 100644 --- a/ios/Classes/EMChatMessageWrapper.m +++ b/ios/Classes/EMChatMessageWrapper.m @@ -96,4 +96,5 @@ - (void)getChatThread:(NSDictionary *)param - (EMChatMessage *)getMessageWithId:(NSString *)aMessageId { return [EMClient.sharedClient.chatManager getMessageWithMessageId:aMessageId]; } + @end diff --git a/ios/Classes/EMChatroomManagerWrapper.m b/ios/Classes/EMChatroomManagerWrapper.m index c4bdcc9c..72b687b3 100644 --- a/ios/Classes/EMChatroomManagerWrapper.m +++ b/ios/Classes/EMChatroomManagerWrapper.m @@ -987,4 +987,5 @@ - (NSDictionary *)dictionaryWithCursorResult:(EMCursorResult *)cursorResult return resultDict; } + @end diff --git a/ios/Classes/EMClientWrapper.h b/ios/Classes/EMClientWrapper.h index dc5eee38..a2bac9e2 100644 --- a/ios/Classes/EMClientWrapper.h +++ b/ios/Classes/EMClientWrapper.h @@ -7,17 +7,10 @@ #import "EMWrapper.h" #import "EMProgressManager.h" - NS_ASSUME_NONNULL_BEGIN @interface EMClientWrapper : EMWrapper - - -+ (EMClientWrapper *)channelName:(NSString *)aChannelName - registrar:(NSObject*)registrar; - -+ (EMClientWrapper *)sharedWrapper; - (void)sendDataToFlutter:(NSDictionary *)aData; - (EMProgressManager *)progressManager; @end diff --git a/ios/Classes/EMClientWrapper.m b/ios/Classes/EMClientWrapper.m index 02d5136d..e3c42400 100644 --- a/ios/Classes/EMClientWrapper.m +++ b/ios/Classes/EMClientWrapper.m @@ -33,20 +33,15 @@ @interface EMClientWrapper () *)registrar -{ - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - wrapper = [[EMClientWrapper alloc] initWithChannelName:aChannelName registrar:registrar]; - }); - return wrapper; -} - (instancetype)initWithChannelName:(NSString *)aChannelName registrar:(NSObject*)registrar { @@ -183,7 +169,6 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { #pragma mark - Actions - (void)initSDKWithDict:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { - __weak typeof(self) weakSelf = self; EMOptions *options = [EMOptions fromJson:param]; @@ -206,12 +191,13 @@ - (void)registerManagers { _contactManager = [[EMContactManagerWrapper alloc] initWithChannelName:EMChannelName(@"chat_contact_manager") registrar:self.flutterPluginRegister]; _conversationManager = [[EMConversationWrapper alloc] initWithChannelName:EMChannelName(@"chat_conversation") registrar:self.flutterPluginRegister]; _groupManager = [[EMGroupManagerWrapper alloc] initWithChannelName:EMChannelName(@"chat_group_manager") registrar:self.flutterPluginRegister]; + _groupManager.clientWrapper = self; _roomManager =[[EMChatroomManagerWrapper alloc] initWithChannelName:EMChannelName(@"chat_room_manager") registrar:self.flutterPluginRegister]; _pushManager =[[EMPushManagerWrapper alloc] initWithChannelName:EMChannelName(@"chat_push_manager") registrar:self.flutterPluginRegister]; _userInfoManager = [[EMUserInfoManagerWrapper alloc] initWithChannelName:EMChannelName(@"chat_userInfo_manager") registrar:self.flutterPluginRegister]; _presenceManager = [[EMPresenceManagerWrapper alloc] initWithChannelName:EMChannelName(@"chat_presence_manager") registrar:self.flutterPluginRegister]; _threadManager = [[EMChatThreadManagerWrapper alloc] initWithChannelName:EMChannelName(@"chat_thread_manager") registrar:self.flutterPluginRegister]; - _progressManager = [[EMProgressManager alloc] initWithChannelName:EMChannelName(@"file_progress_manager") registrar:self.flutterPluginRegister]; + _msgWrapper = [[EMChatMessageWrapper alloc] initWithChannelName:EMChannelName(@"chat_message") registrar:self.flutterPluginRegister]; } @@ -224,8 +210,8 @@ - (void)clearAllListener { [_userInfoManager unRegisterEaseListener]; [_presenceManager unRegisterEaseListener]; [_threadManager unRegisterEaseListener]; - [_progressManager unRegisterEaseListener]; [_msgWrapper unRegisterEaseListener]; + [super unRegisterEaseListener]; } - (void)unRegisterEaseListener { @@ -557,4 +543,5 @@ - (void)applicationWillEnterForeground:(UIApplication *)application [[EMClient sharedClient] applicationWillEnterForeground:application]; } + @end diff --git a/ios/Classes/EMGroupManagerWrapper.h b/ios/Classes/EMGroupManagerWrapper.h index 85f95d26..1d488bbd 100644 --- a/ios/Classes/EMGroupManagerWrapper.h +++ b/ios/Classes/EMGroupManagerWrapper.h @@ -7,11 +7,12 @@ // #import "EMWrapper.h" +#import "EMClientWrapper.h" NS_ASSUME_NONNULL_BEGIN @interface EMGroupManagerWrapper : EMWrapper - +@property (nonatomic, weak) EMClientWrapper *clientWrapper; @end NS_ASSUME_NONNULL_END diff --git a/ios/Classes/EMGroupManagerWrapper.m b/ios/Classes/EMGroupManagerWrapper.m index a8d5bfba..f5920656 100644 --- a/ios/Classes/EMGroupManagerWrapper.m +++ b/ios/Classes/EMGroupManagerWrapper.m @@ -786,13 +786,13 @@ - (void)downloadGroupSharedFile:(NSDictionary *)param channelName:(NSString *)aC sharedFileId:fileId progress:^(int progress) { - [EMClientWrapper.sharedWrapper.progressManager sendDownloadProgressToFlutter:fileId progress:progress]; + [self.clientWrapper.progressManager sendDownloadProgressToFlutter:fileId progress:progress]; } completion:^(EMGroup *aGroup, EMError *aError) { if (aError) { - [EMClientWrapper.sharedWrapper.progressManager sendDownloadErrorToFlutter:fileId error:aError]; + [self.clientWrapper.progressManager sendDownloadErrorToFlutter:fileId error:aError]; }else { - [EMClientWrapper.sharedWrapper.progressManager sendDownloadSuccessToFlutter:fileId path:savePath]; + [self.clientWrapper.progressManager sendDownloadSuccessToFlutter:fileId path:savePath]; } }]; [self wrapperCallBack:result diff --git a/ios/Classes/EMProgressManager.m b/ios/Classes/EMProgressManager.m index e4d6cb86..45353820 100644 --- a/ios/Classes/EMProgressManager.m +++ b/ios/Classes/EMProgressManager.m @@ -4,11 +4,12 @@ // // Created by 杜洁鹏 on 2022/5/23. // - +#import +#import #import "EMProgressManager.h" #import "EMError+Helper.h" -@interface EMProgressManager () +@interface EMProgressManager () @end @@ -20,7 +21,6 @@ - (instancetype)initWithChannelName:(NSString *)aChannelName if(self = [super initWithChannelName:aChannelName registrar:registrar]) { - } return self; } @@ -37,4 +37,9 @@ - (void)sendDownloadErrorToFlutter:(NSString *)fileId error:(EMError *)error { [self.channel invokeMethod:@"onError" arguments:@{@"fileId":fileId, @"error": [error toJson]}]; } + +- (void)unRegisterEaseListener { +} + + @end diff --git a/ios/Classes/EMUserInfoManagerWrapper.m b/ios/Classes/EMUserInfoManagerWrapper.m index 8bbb5f92..f6b4c938 100644 --- a/ios/Classes/EMUserInfoManagerWrapper.m +++ b/ios/Classes/EMUserInfoManagerWrapper.m @@ -82,9 +82,9 @@ - (void)updateOwnUserInfoWithType:(NSDictionary *)param channelName:(NSString *) [EMClient.sharedClient.userInfoManager updateOwnUserInfo:userInfoValue withType:userInfoType completion:^(EMUserInfo *aUserInfo, EMError *aError) { - + __strong typeof (self)strongSelf = weakSelf; NSDictionary *objDic = [aUserInfo toJson]; - [weakSelf wrapperCallBack:result + [strongSelf wrapperCallBack:result channelName:aChannelName error:aError object:objDic]; diff --git a/ios/Classes/EMWrapper.h b/ios/Classes/EMWrapper.h index 7c79c45b..7a15fd24 100644 --- a/ios/Classes/EMWrapper.h +++ b/ios/Classes/EMWrapper.h @@ -7,13 +7,13 @@ #import #import - NS_ASSUME_NONNULL_BEGIN #define EMChannelName(name) [NSString stringWithFormat:@"com.chat.im/%@", name] @interface EMWrapper : NSObject + @property(nonatomic, strong) FlutterMethodChannel *channel; @property(nonatomic, strong) NSObject *flutterPluginRegister; @@ -28,6 +28,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)unRegisterEaseListener; + + @end NS_ASSUME_NONNULL_END diff --git a/ios/Classes/EMWrapper.m b/ios/Classes/EMWrapper.m index 075ccb9a..df66bdfd 100644 --- a/ios/Classes/EMWrapper.m +++ b/ios/Classes/EMWrapper.m @@ -27,11 +27,13 @@ - (instancetype)initWithChannelName:(NSString *)aChannelName codec:codec]; self.channel = channel; [registrar addMethodCallDelegate:self channel:channel]; + } return self; } + - (void)wrapperCallBack:(FlutterResult)result channelName:(NSString *)aChannelName error:(EMError *)error @@ -50,7 +52,9 @@ - (void)wrapperCallBack:(FlutterResult)result } } -- (void)unRegisterEaseListener {} +- (void)unRegisterEaseListener { + +} - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { result(FlutterMethodNotImplemented); @@ -61,4 +65,12 @@ + (void)registerWithRegistrar:(nonnull NSObject *)regist } +- (void)detachFromEngineForRegistrar:(NSObject*)registrar { + +} + +-(void)dealloc{ + NSLog(@"wrapper dealloc"); +} + @end diff --git a/ios/Classes/ImFlutterSdkPlugin.h b/ios/Classes/ImFlutterSdkPlugin.h index 5130baa9..94047d8c 100644 --- a/ios/Classes/ImFlutterSdkPlugin.h +++ b/ios/Classes/ImFlutterSdkPlugin.h @@ -1,5 +1,5 @@ #import @interface ImFlutterSdkPlugin : NSObject - +- (void)sendDataToFlutter:(NSDictionary *)aData; @end diff --git a/ios/Classes/ImFlutterSdkPlugin.m b/ios/Classes/ImFlutterSdkPlugin.m index 3a13e270..9ee0bb18 100644 --- a/ios/Classes/ImFlutterSdkPlugin.m +++ b/ios/Classes/ImFlutterSdkPlugin.m @@ -9,16 +9,15 @@ #import #import + @implementation ImFlutterSdkPlugin + (void)registerWithRegistrar:(NSObject*)registrar { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-variable" - [EMClientWrapper channelName:EMChannelName(@"chat_client") registrar:registrar]; -#pragma clang diagnostic pop + [[EMClientWrapper alloc] initWithChannelName:EMChannelName(@"chat_client") registrar:registrar]; } + - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } From 97cb555d479dc9696ac3372c4acd5cc96545517a Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Wed, 10 May 2023 18:47:29 +0800 Subject: [PATCH 04/49] add chinese docs. --- example/ios/Runner.xcodeproj/project.pbxproj | 7 +- lib/src/em_contact_manager.dart | 125 ++++ lib/src/em_group_manager.dart | 588 +++++++++++++++++++ lib/src/em_presence_manager.dart | 100 +++- lib/src/em_push_manager.dart | 143 +++++ lib/src/em_userInfo_manager.dart | 57 ++ 6 files changed, 1006 insertions(+), 14 deletions(-) diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index a24e3bb1..41498a6b 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -68,7 +68,6 @@ 910082E8A50D4F0B2BEEBEBA /* Pods-Runner.release.xcconfig */, 640349243A4F6AECC9FD1C86 /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -358,7 +357,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 499WYUV8Q2; + DEVELOPMENT_TEAM = JC854K845H; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -487,7 +486,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 499WYUV8Q2; + DEVELOPMENT_TEAM = JC854K845H; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -510,7 +509,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 499WYUV8Q2; + DEVELOPMENT_TEAM = JC854K845H; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/lib/src/em_contact_manager.dart b/lib/src/em_contact_manager.dart index 39e1e60f..54fdb09b 100644 --- a/lib/src/em_contact_manager.dart +++ b/lib/src/em_contact_manager.dart @@ -8,6 +8,10 @@ import 'internal/inner_headers.dart'; /// ~english /// The contact manager class, which manages chat contacts such as adding, deleting, retrieving, and modifying contacts. /// ~end +/// +/// ~chinese +/// `EMContactManager` 是联系人管理类,用于记录、查询和修改用户的联系人列表。 +/// ~end class EMContactManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( @@ -60,6 +64,14 @@ class EMContactManager { /// /// Param [handler] The handle for contact event. See [EMContactEventHandler]. /// ~end + /// + /// ~chinese + /// 添加联系人事件处理程序。调用此方法后,您可以在新的联系人事件到达时处理它们。 + /// + /// Param [identifier] 自定义处理程序标识符,用于查找相应的处理程序。 + /// + /// Param [handler] 事件的句柄. See [EMContactEventHandler]. + /// ~end void addEventHandler( String identifier, EMContactEventHandler handler, @@ -72,6 +84,12 @@ class EMContactManager { /// /// Param [identifier] The custom handler identifier. /// ~end + /// + /// ~chinese + /// 删除联系人事件处理程序。 + /// + /// Param [identifier] 自定义处理程序标识符。 + /// ~end void removeEventHandler(String identifier) { _eventHandlesMap.remove(identifier); } @@ -83,13 +101,25 @@ class EMContactManager { /// /// **Return** The contact event handler. /// ~end + /// + /// ~chinese + /// 获取联系人事件处理程序。 + /// + /// Param [identifier] 自定义处理程序标识符。 + /// + /// **Return** 事件的句柄。 + /// ~end EMContactEventHandler? getEventHandler(String identifier) { return _eventHandlesMap[identifier]; } /// ~english /// Clear all contact event handlers. + /// ~end /// + /// ~chinese + /// 清除所有联系人事件处理程序。 + /// ~end void clearEventHandlers() { _eventHandlesMap.clear(); } @@ -103,6 +133,16 @@ class EMContactManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 添加联系人 + /// + /// Param [userId] 要添加的好友的用户 ID。 + /// + /// Param [reason] (可选)添加为好友的原因。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 {@link EMError}。 + /// ~end Future addContact( String userId, { String? reason, @@ -131,6 +171,18 @@ class EMContactManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 删除联系人及其相关的会话。 + /// + /// Param [username] 要删除的联系人用户 ID。 + /// + /// Param [keepConversation] 是否保留要删除的联系人的会话。 + /// - `true`:是; + /// - (默认)`false`:否。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 {@link EMError}。 + /// ~end Future deleteContact( String username, { bool keepConversation = false, @@ -151,6 +203,14 @@ class EMContactManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 从服务器获取联系人列表。 + /// + /// **Return** 联系人列表。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 {@link EMError}。 + /// ~end Future> getAllContactsFromServer() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getAllContactsFromServer); @@ -175,6 +235,14 @@ class EMContactManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 从数据库获取好友列表。 + /// + /// **Return** 调用成功会返回好友列表。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 {@link EMError}。 + /// ~end Future> getAllContactsFromDB() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getAllContactsFromDB); @@ -201,6 +269,15 @@ class EMContactManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 将指定用户加入黑名单。 + /// 你可以向黑名单中用户发消息,但是接收不到对方发送的消息。 + /// + /// Param [username] 要加入黑名单的用户的用户 ID。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 {@link EMError}。 + /// ~end Future addUserToBlockList( String username, ) async { @@ -223,6 +300,14 @@ class EMContactManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 将指定用户移除黑名单。 + /// + /// Param [username] 要在黑名单中移除的用户 ID。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 {@link EMError}。 + /// ~end Future removeUserFromBlockList(String username) async { Map req = {'username': username}; Map result = await _channel.invokeMethod( @@ -241,6 +326,14 @@ class EMContactManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 从服务器获取黑名单列表。 + /// + /// **Return** 该方法调用成功会返回黑名单列表。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 {@link EMError}。 + /// ~end Future> getBlockListFromServer() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getBlockListFromServer); @@ -265,6 +358,14 @@ class EMContactManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 从本地数据库获取黑名单列表。 + /// + /// **Return** 该方法调用成功会返回黑名单列表。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 {@link EMError}。 + /// ~end Future> getBlockListFromDB() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getBlockListFromDB); try { @@ -288,6 +389,14 @@ class EMContactManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 接受加好友的邀请。 + /// + /// Param [username] 发起好友邀请的用户 ID。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 {@link EMError}。 + /// ~end Future acceptInvitation(String username) async { Map req = {'username': username}; Map result = @@ -306,6 +415,14 @@ class EMContactManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 拒绝加好友的邀请。 + /// + /// Param [username] 发起好友邀请的用户 ID。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 {@link EMError}。 + /// ~end Future declineInvitation(String username) async { Map req = {'username': username}; Map result = @@ -324,6 +441,14 @@ class EMContactManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 获取登录用户在其他登录设备上唯一 ID,该 ID 由 username + "/" + resource 组成。 + /// + /// **Return** 该方法调用成功会返回 ID 列表。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 {@link EMError}。 + /// ~end Future> getSelfIdsOnOtherPlatform() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getSelfIdsOnOtherPlatform); diff --git a/lib/src/em_group_manager.dart b/lib/src/em_group_manager.dart index 2b665361..1c5ab922 100644 --- a/lib/src/em_group_manager.dart +++ b/lib/src/em_group_manager.dart @@ -8,6 +8,10 @@ import 'internal/inner_headers.dart'; /// ~english /// The group manager class, which manages group creation and deletion, user joining and exiting the group, etc. /// ~end +/// +/// ~chinese +/// 群组管理类,用于管理群组的创建,删除及成员管理等操作。 +/// ~end class EMGroupManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( @@ -18,6 +22,10 @@ class EMGroupManager { /// ~english /// group shared file download callback. /// ~end + /// + /// ~chinese + /// 群文件下载回调。 + /// ~end EMDownloadCallback? downloadCallback; /// @nodoc @@ -38,6 +46,14 @@ class EMGroupManager { /// /// Param [handler] The handle for group event. See [EMGroupEventHandler]. /// ~end + /// + /// ~chinese + /// 添加群组事件监听。 + /// + /// Param [identifier] 自定义监听对应 ID,可用于查找或删除监听。 + /// + /// Param [handler] 群组事件监听,请见 [EMGroupEventHandler]. + /// ~end void addEventHandler( String identifier, EMGroupEventHandler handler, @@ -50,6 +66,12 @@ class EMGroupManager { /// /// Param [identifier] The custom handler identifier. /// ~end + /// + /// ~chinese + /// 移出群组事件监听 + /// + /// Param [identifier] 需要移除监听对应的 ID。 + /// ~end void removeEventHandler(String identifier) { _eventHandlesMap.remove(identifier); } @@ -61,6 +83,14 @@ class EMGroupManager { /// /// **Return** The group event handler. /// ~end + /// + /// ~chinese + /// 获取群组事件监听 + /// + /// Param [identifier] 需要获取监听对应的 ID。 + /// + /// **Return** ID 对应的监听。 + /// ~end EMGroupEventHandler? getEventHandler(String identifier) { return _eventHandlesMap[identifier]; } @@ -68,6 +98,10 @@ class EMGroupManager { /// ~english /// Clear all group event handlers. /// ~end + /// + /// ~chinese + /// 清除所有事件监听。 + /// ~end void clearEventHandlers() { _eventHandlesMap.clear(); } @@ -81,6 +115,16 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 根据群组 ID,从本地缓存中获取指定群组。 + /// + /// Param [groupId] 群组 ID。 + /// + /// **Return** 返回群组对象。如果群组不存在,返回 null。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future getGroupWithId(String groupId) async { Map req = {'groupId': groupId}; Map result = @@ -104,6 +148,14 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 从本地缓存中获取当前用户加入的所有群组。 + /// + /// **Return** 群组列表。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 {@link EMError}。 + /// ~end Future> getJoinedGroups() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getJoinedGroups); try { @@ -134,6 +186,16 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 从服务器中获取当前用户加入的所有群组。 + /// + /// 此操作只返回群组列表,不包含所有成员的信息。如果要更新某个群组包括成员的全部信息,需要再调用 [EMGroupManager.fetchGroupInfoFromServer]。 + /// + /// **Return** 当前用户加入的群组的列表。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 {@link EMError}。 + /// ~end Future> fetchJoinedGroupsFromServer({ int pageSize = 20, int pageNum = 0, @@ -171,6 +233,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 以分页方式从服务器获取当前用户加入的所有公开群组。 + /// + /// Param [pageSize] 每页返回的群组数。 + /// + /// Param [cursor] 从这个游标位置开始取数据,首次获取数据时传 `null`,按照用户加入公开群组时间的顺序还是逆序获取数据。 + /// + /// **Return** 包含用于下次获取数据的 cursor 以及群组列表。返回的结果中,当 `EMCursorResult.getCursor()` 为空字符串 ("") 时,表示没有更多数据。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 {@link EMError}。 + /// ~end Future> fetchPublicGroupsFromServer({ int pageSize = 200, String? cursor, @@ -218,6 +292,32 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 创建群组。 + /// + /// 群组创建成功后,会更新内存及数据库中的数据,多端多设备会收到相应的通知事件,将群组更新到内存及数据库中。 + /// 可通过设置 [EMClient.addMultiDeviceEventHandler] 监听相关事件,事件回调函数为 [EMMultiDeviceEventHandler.onGroupEvent],第一个参数为事件,创建群组事件为 [EMMultiDevicesEvent.GROUP_CREATE]。 + /// + /// Param [groupName] 群组名称。 + /// + /// Param [desc] 群组描述。 + /// + /// Param [inviteMembers] 群成员数组。群主 ID 可选。 + /// + /// Param [inviteReason] 用户入群邀请信息。 + /// + /// Param [options] 群组的其他选项。请参见 {@link EMGroupOptions}。 + /// 群组的其他选项。 + /// - 群最大成员数,默认值为 200; + /// - 群组类型,详见 [EMGroupStyle],默认为 [EMGroupStyle.PrivateOnlyOwnerInvite]; + /// - 邀请进群是否需要对方同意,默认为 false,即邀请后直接进群; + /// - 群组详情扩展。 + /// + /// **Return** 创建成功的群对象。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 {@link EMError}。 + /// ~end Future createGroup({ String? groupName, String? desc, @@ -253,6 +353,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 从服务器获取群组的详细信息。 + /// + /// 该方法不获取成员。如需获取成员,使用 [fetchMemberListFromServer]。 + /// + /// Param [groupId] 群组 ID。 + /// + /// **Return** 群组描述。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future fetchGroupInfoFromServer( String groupId, { bool fetchMembers = false, @@ -289,6 +401,26 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 以分页方式获取群组成员列表。 + /// + /// 例如: + /// ```dart + /// EMCursorResult result = await EMClient.getInstance.groupManager.fetchMemberListFromServer(groupId); // search 1 + /// result = await EMClient.getInstance.groupManager.fetchMemberListFromServer(groupId, cursor: result.cursor); // search 2 + /// ``` + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [pageSize] 每页返回的群组成员数。 + /// + /// Param [cursor] 从这个游标位置开始取数据,首次获取数据时传 null 即可。 + /// + /// **Return** 分页获取结果 [EMCursorResult],包含用于下次获取数据的 cursor 以及群组成员列表。返回的结果中,当 [EMCursorResult.cursor] 为空字符串 ("") 时,表示没有更多数据。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 {@link EMError}。 + /// ~end Future> fetchMemberListFromServer( String groupId, { int pageSize = 200, @@ -328,6 +460,22 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 以分页方式获取群组的黑名单。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [pageSize] 每页返回的群组黑名单成员数量。 + /// + /// Param [pageNum] 当前页码,从 1 开始。 + /// + /// **Return** 返回的黑名单列表。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future> fetchBlockListFromServer( String groupId, { int pageSize = 200, @@ -361,6 +509,22 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 获取群组的禁言列表。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [pageSize] 每页返回的禁言成员数。 + /// + /// Param [pageNum] 当前页码,从 1 开始。 + /// + /// **Return** 群组的禁言列表。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future> fetchMuteListFromServer( String groupId, { int pageSize = 200, @@ -397,6 +561,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 获取群组白名单列表。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// **Return** 群组的白名单。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future> fetchAllowListFromServer(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod( @@ -424,6 +600,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 检查当前用户是否在群组白名单中。 + /// + /// Param [groupId] 群组 ID。 + /// + /// **Return** 是否在群组白名单。 + /// - `true`: 是; + /// - `false`: 否。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future isMemberInAllowListFromServer(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod( @@ -449,6 +637,20 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 从服务器获取群组的共享文件列表。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [pageSize] 每页返回的共享文件数量。 + /// + /// Param [pageNum] 当前页码,从 1 开始。 + /// + /// **Return** 返回共享文件列表。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future> fetchGroupFileListFromServer( String groupId, { int pageSize = 200, @@ -480,6 +682,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 从服务器获取群组公告。 + /// + /// 群成员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// **Return** 群组公告。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future fetchAnnouncementFromServer(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod( @@ -505,6 +719,20 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 向群组中添加新成员。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [members] 要添加的新成员数组。 + /// + /// Param [welcome] 欢迎消息。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future addMembers( String groupId, List members, { @@ -535,6 +763,24 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 邀请用户加入群组。 + /// + /// 群类型为 [EMGroupStyle.PrivateOnlyOwnerInvite]、[EMGroupStyle.PrivateMemberCanInvite] 和 [EMGroupStyle.PublicJoinNeedApproval] 的群组可以邀请用户加入。 + /// + /// - 对于 [EMGroupStyle.PrivateOnlyOwnerInvite] 属性的群组,仅群主可邀请用户入群。 + /// - 对于 [EMGroupStyle.PrivateMemberCanInvite] 属性的群组,群成员可邀请用户入群。 + /// - 对于 [EMGroupStyle.PublicJoinNeedApproval] 属性的群组,仅群主可邀请用户加入。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [members] 要邀请的新成员数组。 + /// + /// Param [reason] 邀请原因。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future inviterUser( String groupId, List members, { @@ -569,6 +815,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 将群成员移出群组。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID. + /// + /// Param [members] 要删除的成员的用户 ID。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future removeMembers( String groupId, List members, @@ -595,6 +853,20 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 将用户加入群组黑名单。 + /// + /// 先将用户移出群,再加入黑名单。加入黑名单的用户无法加入群。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [members] 要加入黑名单的用户 ID。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future blockMembers( String groupId, List members, @@ -619,6 +891,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 将用户从群组黑名单中移除。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [members] 要从黑名单中移除的用户。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future unblockMembers( String groupId, List members, @@ -644,6 +928,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 修改群组名称。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [name] 修改后的群组名称。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 详见 [EMError]。 + /// ~end Future changeGroupName( String groupId, String name, @@ -669,6 +965,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 修改群描述。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [desc] 修改后的群描述。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future changeGroupDescription( String groupId, String desc, @@ -690,6 +998,14 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 当前登录用户退出群组。 + /// + /// Param [groupId] 群组 ID。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future leaveGroup(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.leaveGroup, req); @@ -709,6 +1025,16 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 解散群组。 + /// + /// 仅群主可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future destroyGroup(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.destroyGroup, req); @@ -728,6 +1054,16 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 屏蔽群消息。 + /// + /// 屏蔽群消息的用户仍是群成员,但不会收到群消息。 + /// + /// Param [groupId] 群组 ID。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future blockGroup(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.blockGroup, req); @@ -745,6 +1081,14 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 取消屏蔽群消息。 + /// + /// Param [groupId] 群组 ID。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future unblockGroup(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.unblockGroup, req); @@ -766,6 +1110,20 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 转让群组所有权。 + /// + /// 仅群主可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [newOwner] 新的群主。 + /// + /// **Return** 返回新群主。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future changeOwner( String groupId, String newOwner, @@ -791,6 +1149,20 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 添加群组管理员。 + /// + /// 仅群主可调用此方法,管理员无权限。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [memberId] 要添加的管理员的用户 ID。 + /// + /// **Return** 返回更新后的群组对象。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future addAdmin( String groupId, String memberId, @@ -815,6 +1187,20 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 删除群组管理员。 + /// + /// 仅群主可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [adminId] 要移除的群组管理员的用户 ID。 + /// + /// **Return** 返回更新后的群组对象。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future removeAdmin( String groupId, String adminId, @@ -841,6 +1227,22 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 将指定群成员禁言。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [members] 要禁言的成员列表。 + /// + /// Param [duration] 禁言时长,单位为毫秒。 + /// + /// **Return** 返回更新后的群组对象。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future muteMembers( String groupId, List members, { @@ -866,6 +1268,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 取消禁言指定用户。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [members] 要解除禁言的成员列表。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future unMuteMembers( String groupId, List members, @@ -888,6 +1302,16 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 开启全员禁言。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future muteAllMembers(String groupId) async { Map req = {'groupId': groupId}; Map result = @@ -908,6 +1332,16 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 关闭全员禁言。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future unMuteAllMembers(String groupId) async { Map req = {'groupId': groupId}; Map result = @@ -930,6 +1364,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 将成员添加至群组白名单。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [members] 要添加至白名单的成员列表。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future addAllowList( String groupId, List members, @@ -954,6 +1400,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 将成员移除群组白名单。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [members] 要移除白名单的成员列表。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future removeAllowList( String groupId, List members, @@ -979,6 +1437,16 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 上传共享文件至群组。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [filePath] 共享文件的本地路径。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future uploadGroupSharedFile( String groupId, String filePath, @@ -1006,6 +1474,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 下载指定的群组共享文件。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [fileId] 共享文件的 ID。 + /// + /// Param [savePath] 共享文件的本地路径。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future downloadGroupSharedFile({ required String groupId, required String fileId, @@ -1032,6 +1512,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 删除指定的群组共享文件。 + /// + /// 群成员可删除自己上传的文件,群主或者管理员可删除所有共享文件。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [fileId] 共享文件的 ID。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future removeGroupSharedFile( String groupId, String fileId, @@ -1057,6 +1549,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 更新群公告。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [announcement] 群组公告。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future updateGroupAnnouncement( String groupId, String announcement, @@ -1082,6 +1586,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 更新群组扩展字段。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [extension] 群组扩展字段。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future updateGroupExtension( String groupId, String extension, @@ -1106,6 +1622,16 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 当前登录用户加入公开群。 + /// + /// 若是自由加入的公开群,直接进入群组;若公开群需验证,群主同意后才能入群。详见 [EMError]。 + /// + /// Param [groupId] 群组 ID。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future joinPublicGroup( String groupId, ) async { @@ -1130,6 +1656,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 申请加入群组。 + /// + /// 该方法仅适用于需要验证的公开群组,即类型为 [EMGroupStyle.PublicJoinNeedApproval] 的群组。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [reason] 申请入群的原因。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future requestToJoinPublicGroup( String groupId, { String? reason, @@ -1156,6 +1694,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 批准入群申请。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [username] 申请人的用户 ID。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future acceptJoinApplication( String groupId, String username, @@ -1183,6 +1733,20 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 拒绝入群申请。 + /// + /// 仅群主和管理员可调用此方法。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [userId] 申请人的用户 ID。 + /// + /// Param [reason] 拒绝理由。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future declineJoinApplication( String groupId, String username, { @@ -1211,6 +1775,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 接受入群邀请。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [inviter] 邀请者的用户 ID。 + /// + /// **Return** 用户已接受邀请的群组对象。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future acceptInvitation( String groupId, String inviter, @@ -1237,6 +1813,18 @@ class EMGroupManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 拒绝入群邀请。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [inviter] 邀请者的用户 ID。 + /// + /// Param [reason] 拒绝理由。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future declineInvitation({ required String groupId, required String inviter, diff --git a/lib/src/em_presence_manager.dart b/lib/src/em_presence_manager.dart index 250a78ab..e8b822d4 100644 --- a/lib/src/em_presence_manager.dart +++ b/lib/src/em_presence_manager.dart @@ -3,9 +3,13 @@ import 'package:flutter/services.dart'; import 'internal/inner_headers.dart'; -/// +/// ~english /// The Manager that defines how to manage presence states. +/// ~end /// +/// ~chinese +/// 用户在线状态管理类。 +/// ~end class EMPresenceManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( @@ -24,13 +28,21 @@ class EMPresenceManager { }); } - /// + /// ~english /// Adds the presence event handler. After calling this method, you can handle for new presence event when they arrive. /// /// Param [identifier] The custom handler identifier, is used to find the corresponding handler. /// /// Param [handler] The handle for presence event. See [EMPresenceEventHandler]. + /// ~end + /// + /// ~chinese + /// 添加用户状态变化监听器。 + /// + /// Param [identifier] 事件 ID。 /// + /// Param [handler] Presence 事件。 + /// ~end void addEventHandler( String identifier, EMPresenceEventHandler handler, @@ -38,40 +50,66 @@ class EMPresenceManager { _eventHandlesMap[identifier] = handler; } - /// + /// ~english /// Remove the presence event handler. /// /// Param [identifier] The custom handler identifier. + /// ~end + /// + /// ~chinese + /// 移除用户状态变化监听器。 /// + /// Param [identifier] 事件 ID。 + /// ~end void removeEventHandler(String identifier) { _eventHandlesMap.remove(identifier); } - /// + /// ~english /// Get the presence event handler. /// /// Param [identifier] The custom handler identifier. /// /// **Return** The presence event handler. + /// ~end + /// + /// ~chinese + /// 获取 Presence 事件句柄。 /// + /// Param [identifier] 事件对应 ID. + /// + /// **Return** Presence 事件。 + /// ~end EMPresenceEventHandler? getEventHandler(String identifier) { return _eventHandlesMap[identifier]; } - /// + /// ~english /// Clear all presence event handlers. + /// ~end /// + /// ~chinese + /// 清除所有 Presence 事件。 + /// ~end void clearEventHandlers() { _eventHandlesMap.clear(); } - /// + /// ~english /// Publishes a custom presence state. /// /// Param [description] The extension information of the presence state. It can be set as nil. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 发布自定义用户在线状态。 /// + /// Param [description] 用户在线状态的扩展信息。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。参见 {@link EMError}。 + /// ~end Future publishPresence( String description, ) async { @@ -85,7 +123,7 @@ class EMPresenceManager { } } - /// + /// ~english /// Subscribes to a user's presence states. If the subscription succeeds, the subscriber will receive the callback when the user's presence state changes. /// /// Param [members] The list of IDs of users whose presence states you want to subscribe to. @@ -95,7 +133,19 @@ class EMPresenceManager { /// **Return** Which contains IDs of users whose presence states you have subscribed to. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 订阅指定用户的在线状态。 /// + /// Param [members] 要订阅在线状态的用户 ID 数组。 + /// + /// Param [expiry] 订阅时长,单位为秒。最长不超过 2,592,000 (30×24×3600) 秒,即 30 天。 + /// + /// **Return** 返回被订阅用户的当前状态。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。参见 {@link EMError}。 + /// ~end Future> subscribe({ required List members, required int expiry, @@ -115,13 +165,21 @@ class EMPresenceManager { } } - /// + /// ~english /// Unsubscribes from a user's presence states. /// /// Param [members] The array of IDs of users whose presence states you want to unsubscribe from. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end /// + /// ~chinese + /// 取消订阅指定用户的在线状态。 + /// + /// Param [members] 要取消订阅在线状态的用户 ID 数组。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。参见 {@link EMError}。 + /// ~end Future unsubscribe({ required List members, }) async { @@ -135,7 +193,7 @@ class EMPresenceManager { } } - /// + /// ~english /// Uses pagination to get a list of users whose presence states you have subscribed to. /// /// Param [pageNum] The current page number, starting from 1. @@ -145,7 +203,19 @@ class EMPresenceManager { /// **Return** Which contains IDs of users whose presence states you have subscribed to. Returns null if you subscribe to no user's presence state. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 分页查询当前用户订阅了哪些用户的在线状态。 /// + /// Param [pageNum] 当前页码,从 1 开始。 + /// + /// Param [pageSize] 每页显示的被订阅用户数量。 + /// + /// **Return** 返回订阅的在线状态所属的用户 ID。若当前未订阅任何用户的在线状态,返回空列表。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。参见 {@link EMError}。 + /// ~end Future> fetchSubscribedMembers({ int pageNum = 1, int pageSize = 20, @@ -168,7 +238,7 @@ class EMPresenceManager { } } - /// + /// ~english /// Gets the current presence state of users. /// /// Param [members] The array of IDs of users whose current presence state you want to check. @@ -176,7 +246,17 @@ class EMPresenceManager { /// **Return** Which contains the users whose presence state you have subscribed to. /// /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 查询指定用户的当前在线状态。 + /// + /// Param [members] 用户 ID 数组,指定要查询哪些用户的在线状态。 + /// + /// **Return** 被订阅用户的当前状态。 /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。参见 {@link EMError}。 + /// ~end Future> fetchPresenceStatus({ required List members, }) async { diff --git a/lib/src/em_push_manager.dart b/lib/src/em_push_manager.dart index 90e3a8b8..4c144cb1 100644 --- a/lib/src/em_push_manager.dart +++ b/lib/src/em_push_manager.dart @@ -5,10 +5,18 @@ import 'internal/inner_headers.dart'; /// ~english /// The message push configuration options. /// ~end +/// +/// ~chinese +/// 推送设置管理类。 +/// ~end class EMPushManager { /// ~english /// Gets the push configurations from the server. /// ~end + /// + /// ~chinese + /// 从服务器获取推送设置信息。 + /// ~end Future fetchPushConfigsFromServer() async { Map result = await PushChannel.invokeMethod( ChatMethodKeys.getImPushConfigFromServer); @@ -32,6 +40,16 @@ class EMPushManager { /// /// **Throws** A description of the issue that caused this exception. See [EMError] /// ~end + /// + /// ~chinese + /// 更新推送通知收到时显示的昵称。 + /// + /// 该昵称与用户信息中的昵称设置不同,我们建议这两种昵称的设置保持一致。更新用户属性昵称详见 [EMUserInfoManager.updateUserInfo]。 + /// + /// Param [nickname] 推送通知收到时显示的昵称。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future updatePushNickname(String nickname) async { Map req = {'nickname': nickname}; Map result = @@ -50,6 +68,14 @@ class EMPushManager { /// /// **Throws** A description of the issue that caused this exception. See [EMError] /// ~end + /// + /// ~chinese + /// 更新推送通知的展示方式。 + /// + /// Param [displayStyle] 推送通知的展示方式。默认为 [DisplayStyle.Simple]。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future updatePushDisplayStyle(DisplayStyle displayStyle) async { Map req = {'pushStyle': displayStyle == DisplayStyle.Simple ? 0 : 1}; Map result = @@ -68,6 +94,14 @@ class EMPushManager { /// /// **Throws** A description of the issue that caused this exception. See [EMError] /// ~end + /// + /// ~chinese + /// 更新华为推送 token。 + /// + /// Param [token] 要更新的华为推送 token。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future updateHMSPushToken(String token) async { if (Platform.isAndroid) { Map req = {'token': token}; @@ -88,6 +122,14 @@ class EMPushManager { /// /// **Throws** A description of the issue that caused this exception. See [EMError] /// ~end + /// + /// ~chinese + /// 更新谷歌 FCM 推送 token。 + /// + /// Param [token] 要更新的谷歌 FCM 推送 token。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future updateFCMPushToken(String token) async { if (Platform.isAndroid) { Map req = {'token': token}; @@ -108,6 +150,14 @@ class EMPushManager { /// /// **Throws** A description of the issue that caused this exception. See [EMError] /// ~end + /// + /// ~chinese + /// 更新苹果推送(APNs)token。 + /// + /// Param [token] 要更新的苹果推送(APNs)token。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future updateAPNsDeviceToken(String token) async { if (Platform.isIOS) { Map req = {'token': token}; @@ -133,6 +183,18 @@ class EMPushManager { /// **Throws** A description of the exception. See [EMError]. /// /// ~end + /// + /// ~chinese + /// 设置特殊对话的离线推送通知类型。 + /// + /// Param [conversationId] 会话 ID. + /// + /// Param [type] 会话类型. + /// + /// Param [param] 推送免打扰参数. + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future setConversationSilentMode({ required String conversationId, required EMConversationType type, @@ -162,6 +224,17 @@ class EMPushManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 删除特殊会话的离线推送通知类型设置。 + /// 清除后,会话遵循当前登录用户的设置 [EMPushManager.setSilentModeForAll]。 + /// + /// Param [conversationId] 会话 ID。 + /// + /// Param [type] 会话类型。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future removeConversationSilentMode({ required String conversationId, required EMConversationType type, @@ -189,6 +262,18 @@ class EMPushManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 获取会话的免打扰设置。 + /// + /// Param [conversationId] 会话 ID。 + /// + /// Param [type] 会话类型。 + /// + /// **Return** 会话的免打扰设置。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future fetchConversationSilentMode({ required String conversationId, required EMConversationType type, @@ -214,6 +299,14 @@ class EMPushManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 设置当前登录用户的免打扰设置。 + /// + /// Param [param] 推送免打扰设置参数。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future setSilentModeForAll({ required ChatSilentModeParam param, }) async { @@ -237,6 +330,14 @@ class EMPushManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 获取当前登录用户的免打扰设置。 + /// + /// **Return** 免打扰设置。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future fetchSilentModeForAll() async { Map result = await PushChannel.invokeMethod(ChatMethodKeys.fetchSilentModeForAll); @@ -259,6 +360,16 @@ class EMPushManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 批量获取指定会话的免打扰设置。 + /// + /// Param [conversations] 会话列表。 + /// + /// **Return** 键为会话id,值为免打扰设置。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future> fetchSilentModeForConversations( List conversations, ) async { @@ -294,6 +405,14 @@ class EMPushManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 设置用户推送翻译语言。 + /// + /// Param [languageCode] 语言代码。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future setPreferredNotificationLanguage(String languageCode) async { Map req = {"code": languageCode}; Map result = await PushChannel.invokeMethod( @@ -314,6 +433,14 @@ class EMPushManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 获取用户设置的推送翻译语言。 + /// + /// **Return** 设置的语言代码。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future fetchPreferredNotificationLanguage() async { Map result = await PushChannel.invokeMethod( ChatMethodKeys.fetchPreferredNotificationLanguage, @@ -334,6 +461,14 @@ class EMPushManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 设置离线推送模板。 + /// + /// Param [pushTemplateName] 推送模版名称。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future setPushTemplate(String pushTemplateName) async { Map result = await PushChannel.invokeMethod(ChatMethodKeys.setPushTemplate, { @@ -353,6 +488,14 @@ class EMPushManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 获取推送模版名称。 + /// + /// **Return** 推送模板名称。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future getPushTemplate() async { Map result = await PushChannel.invokeMethod(ChatMethodKeys.getPushTemplate); try { diff --git a/lib/src/em_userInfo_manager.dart b/lib/src/em_userInfo_manager.dart index b7a14940..8846e262 100644 --- a/lib/src/em_userInfo_manager.dart +++ b/lib/src/em_userInfo_manager.dart @@ -8,6 +8,10 @@ import 'internal/inner_headers.dart'; /// ~english /// The user attribute manager class, which gets and sets the user attributes. /// ~end +/// +/// ~chinese +/// 用户属性类,用于获取和更新用户属性。 +/// ~end class EMUserInfoManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( @@ -41,6 +45,33 @@ class EMUserInfoManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 修改当前用户的属性信息。 + /// + /// Param [nickname] 用户昵称。该昵称与推送设置中的昵称设置不同,我们建议这两种昵称的设置保持一致。设置推送昵称详见 {@link EMPushManager#updatePushNickname()}。 + /// + /// Param [avatarUrl] 用户头像。 + /// + /// Param [mail] 用户邮箱。 + /// + /// Param [phone] 用户手机号。 + /// + /// Param [gender] 用户性别。 + /// - `0`: (默认) 未知; + /// - `1`: 男; + /// - `2`: 女. + /// + /// Param [sign] 用户签名。 + /// + /// Param [birth] 用户的生日。 + /// + /// Param [ext] 用户的自定义属性字段。该字段可为空,或设置为自定义扩展信息,封装为 JSON 字符串。 + /// + /// **Return** 用户属性信息。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 [EMError]。 + /// ~end Future updateUserInfo({ String? nickname, String? avatarUrl, @@ -83,6 +114,16 @@ class EMUserInfoManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 获取当前用户的属性信息。 + /// + /// Param [expireTime] 获取的用户属性到期时间。如果在到期时间内再次调用该方法,则 SDK 直接返回上次获取到的缓存数据。例如,将该参数设为 120,即 2 分钟,则如果你在 2 分钟内再次调用该方法获取用户属性,SDK 仍将返回上次获取到的属性。否则需从服务器获取。 + /// + /// **Return** 用户属性。请参见 {@link EMUserInfo}。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 [EMError]。 + /// ~end Future fetchOwnInfo({int expireTime = 0}) async { String? currentUser = await EMClient.getInstance.getCurrentUserId(); if (currentUser != null) { @@ -111,6 +152,18 @@ class EMUserInfoManager { /// /// **Throws** A description of the exception. See [EMError]. /// ~end + /// + /// ~chinese + /// 根据用户 ID,获取指定用户的用户属性。 + /// + /// Param [userIds] 用户 ID 数组。 + /// + /// Param [expireTime] 获取的用户属性到期时间。如果在到期时间内再次调用该方法,则 SDK 直接返回上次获取到的缓存数据。例如,将该参数设为 120,即 2 分钟,则如果你在 2 分钟内再次调用该方法获取用户属性,SDK 仍将返回上次获取到的属性。否则需从服务器获取。 + /// + /// **Return** 返回 key-value 格式的 Map 类型数据,key 为用户 ID,value 为用户属性。 + /// + /// **Throws** 如果有方法调用的异常会在这里抛出,可以看到具体错误原因。请参见 [EMError]。 + /// ~end Future> fetchUserInfoById( List userIds, { int expireTime = 0, @@ -154,6 +207,10 @@ class EMUserInfoManager { /// ~english /// clear all userInfo cache. /// ~end + /// + /// ~chinese + /// 清理内存中的用户属性。 + /// ~end void clearUserInfoCache() { _effectiveUserInfoMap.clear(); } From 23815759d5f45a09c11c092a5e10ecd37693c81d Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Thu, 11 May 2023 18:16:50 +0800 Subject: [PATCH 05/49] add android support multiple_engine. --- .../im_flutter_sdk/EMClientWrapper.java | 7 +------ .../im_flutter_sdk/EMGroupManagerWrapper.java | 20 ++++++++++++++++++- .../im_flutter_sdk/ImFlutterSdkPlugin.java | 18 ++++++++++++----- example/android/build.gradle | 2 +- example/ios/Runner.xcodeproj/project.pbxproj | 1 + ios/Classes/EMClientWrapper.m | 2 ++ ios/Classes/ImFlutterSdkPlugin.h | 2 +- ios/Classes/ImFlutterSdkPlugin.m | 12 ++++++++++- lib/src/em_chat_room_manager.dart | 2 +- lib/src/em_contact_manager.dart | 2 +- 10 files changed, 51 insertions(+), 17 deletions(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java index 2ea04afe..1aff9131 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java @@ -30,7 +30,6 @@ public class EMClientWrapper extends EMWrapper implements MethodCallHandler { - static EMClientWrapper wrapper; private EMChatManagerWrapper chatManagerWrapper; private EMGroupManagerWrapper groupManagerWrapper; private EMChatRoomManagerWrapper chatRoomManagerWrapper; @@ -48,11 +47,7 @@ public class EMClientWrapper extends EMWrapper implements MethodCallHandler { EMClientWrapper(FlutterPlugin.FlutterPluginBinding flutterPluginBinding, String channelName) { super(flutterPluginBinding, channelName); - wrapper = this; - } - public static EMClientWrapper getInstance() { - return wrapper; } public void sendDataToFlutter(final Map data) { @@ -62,7 +57,6 @@ public void sendDataToFlutter(final Map data) { post(()-> channel.invokeMethod(EMSDKMethod.onSendDataToFlutter, data)); } - @Override public void onMethodCall(MethodCall call, @NonNull Result result) { @@ -321,6 +315,7 @@ private void bindingManagers() { contactManagerWrapper = new EMContactManagerWrapper(binging, "chat_contact_manager"); chatRoomManagerWrapper = new EMChatRoomManagerWrapper(binging, "chat_room_manager"); groupManagerWrapper = new EMGroupManagerWrapper(binging, "chat_group_manager"); + groupManagerWrapper.clientWrapper = this; conversationWrapper = new EMConversationWrapper(binging, "chat_conversation"); pushManagerWrapper = new EMPushManagerWrapper(binging, "chat_push_manager"); userInfoManagerWrapper = new EMUserInfoManagerWrapper(binging, "chat_userInfo_manager"); diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java index b3657a47..67ea07a5 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java @@ -31,6 +31,8 @@ public class EMGroupManagerWrapper extends EMWrapper implements MethodCallHandle private EMGroupChangeListener groupChangeListener; + public EMClientWrapper clientWrapper; + EMGroupManagerWrapper(FlutterPlugin.FlutterPluginBinding flutterPluginBinding, String channelName) { super(flutterPluginBinding, channelName); registerEaseListener(); @@ -673,7 +675,23 @@ private void downloadGroupSharedFile(JSONObject param, String channelName, Resul } EMClient.getInstance().groupManager().asyncDownloadGroupSharedFile(groupId, fileId, savePath, - new EMDownloadCallback(fileId, savePath)); + new EMDownloadCallback(fileId, savePath){ + @Override + public void onSuccess() { + clientWrapper.progressManager.sendDownloadSuccessToFlutter(fileId, savePath); + } + + @Override + public void onProgress(int progress, String status) { + clientWrapper.progressManager.sendDownloadProgressToFlutter(fileId, progress); + } + + @Override + public void onError(int code, String error) { + HyphenateException e = new HyphenateException(code, error); + clientWrapper.progressManager.sendDownloadErrorToFlutter(fileId, e); + } + }); post(()->{ onSuccess(result, channelName, true); diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/ImFlutterSdkPlugin.java b/android/src/main/java/com/easemob/im_flutter_sdk/ImFlutterSdkPlugin.java index b42e3df9..efcd45f0 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/ImFlutterSdkPlugin.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/ImFlutterSdkPlugin.java @@ -25,11 +25,19 @@ public class ImFlutterSdkPlugin implements FlutterPlugin, MethodChannel.MethodCa static final Handler handler = new Handler(Looper.getMainLooper()); - private EMClientWrapper clientWrapper; + static EMClientWrapper clientWrapper; public ImFlutterSdkPlugin() { } + static public void clearWrapper(){ + clientWrapper = null; + } + static public void sendDataToFlutter(final Map data) { + if (clientWrapper != null) { + clientWrapper.sendDataToFlutter(data); + } + } @Override public void onAttachedToEngine(FlutterPlugin.FlutterPluginBinding flutterPluginBinding) { @@ -108,18 +116,18 @@ class EMDownloadCallback implements EMCallBack { @Override public void onSuccess() { - EMClientWrapper.getInstance().progressManager.sendDownloadSuccessToFlutter(fileId, savePath); +// EMClientWrapper.getInstance().progressManager.sendDownloadSuccessToFlutter(fileId, savePath); } @Override public void onError(int code, String error) { - HyphenateException e = new HyphenateException(code, error); - EMClientWrapper.getInstance().progressManager.sendDownloadErrorToFlutter(fileId, e); +// HyphenateException e = new HyphenateException(code, error); +// EMClientWrapper.getInstance().progressManager.sendDownloadErrorToFlutter(fileId, e); } @Override public void onProgress(int progress, String status) { - EMClientWrapper.getInstance().progressManager.sendDownloadProgressToFlutter(fileId, progress); +// EMClientWrapper.getInstance().progressManager.sendDownloadProgressToFlutter(fileId, progress); } } diff --git a/example/android/build.gradle b/example/android/build.gradle index 49c115da..6dce8083 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -26,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 41498a6b..ffae9f0c 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -204,6 +204,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( diff --git a/ios/Classes/EMClientWrapper.m b/ios/Classes/EMClientWrapper.m index e3c42400..9b257733 100644 --- a/ios/Classes/EMClientWrapper.m +++ b/ios/Classes/EMClientWrapper.m @@ -199,6 +199,8 @@ - (void)registerManagers { _threadManager = [[EMChatThreadManagerWrapper alloc] initWithChannelName:EMChannelName(@"chat_thread_manager") registrar:self.flutterPluginRegister]; _msgWrapper = [[EMChatMessageWrapper alloc] initWithChannelName:EMChannelName(@"chat_message") registrar:self.flutterPluginRegister]; + + _progressManager = [[EMProgressManager alloc] initWithChannelName:EMChannelName(@"file_progress_manager") registrar:self.flutterPluginRegister]; } - (void)clearAllListener { diff --git a/ios/Classes/ImFlutterSdkPlugin.h b/ios/Classes/ImFlutterSdkPlugin.h index 94047d8c..07c83656 100644 --- a/ios/Classes/ImFlutterSdkPlugin.h +++ b/ios/Classes/ImFlutterSdkPlugin.h @@ -1,5 +1,5 @@ #import @interface ImFlutterSdkPlugin : NSObject -- (void)sendDataToFlutter:(NSDictionary *)aData; ++ (void)sendDataToFlutter:(NSDictionary *)aData; @end diff --git a/ios/Classes/ImFlutterSdkPlugin.m b/ios/Classes/ImFlutterSdkPlugin.m index 9ee0bb18..df4c586d 100644 --- a/ios/Classes/ImFlutterSdkPlugin.m +++ b/ios/Classes/ImFlutterSdkPlugin.m @@ -12,11 +12,21 @@ @implementation ImFlutterSdkPlugin +static EMClientWrapper *wrapper; + (void)registerWithRegistrar:(NSObject*)registrar { - [[EMClientWrapper alloc] initWithChannelName:EMChannelName(@"chat_client") registrar:registrar]; + wrapper = [[EMClientWrapper alloc] initWithChannelName:EMChannelName(@"chat_client") registrar:registrar]; } ++ (void)clearWrapper{ + wrapper = nil; +} + ++ (void)sendDataToFlutter:(NSDictionary *)aData { + if (wrapper) { + [wrapper sendDataToFlutter:aData]; + } +} - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } diff --git a/lib/src/em_chat_room_manager.dart b/lib/src/em_chat_room_manager.dart index e06cec7b..12ae4260 100644 --- a/lib/src/em_chat_room_manager.dart +++ b/lib/src/em_chat_room_manager.dart @@ -13,7 +13,7 @@ import 'internal/inner_headers.dart'; /// await EMClient.getInstance.chatRoomManager.joinChatRoom(chatRoomId); /// } on EMError catch (e) { /// debugPrint(e.toString()); -// } +/// } /// ``` /// ~end /// diff --git a/lib/src/em_contact_manager.dart b/lib/src/em_contact_manager.dart index 54fdb09b..b42cb76b 100644 --- a/lib/src/em_contact_manager.dart +++ b/lib/src/em_contact_manager.dart @@ -10,7 +10,7 @@ import 'internal/inner_headers.dart'; /// ~end /// /// ~chinese -/// `EMContactManager` 是联系人管理类,用于记录、查询和修改用户的联系人列表。 +/// 联系人管理类,用于记录、查询和修改用户的联系人列表。 /// ~end class EMContactManager { static const _channelPrefix = 'com.chat.im'; From 6247c2d0462a0307313e189c290febf7d8dbfeaf Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Mon, 15 May 2023 16:34:14 +0800 Subject: [PATCH 06/49] add fetch message options --- .../im_flutter_sdk/EMChatManagerWrapper.java | 12 +- .../com/easemob/im_flutter_sdk/EMHelper.java | 12 ++ example/lib/main.dart | 32 ++-- ios/Classes/EMChatManagerWrapper.m | 12 +- ios/Classes/EMChatMessage+Helper.m | 2 + lib/im_flutter_sdk.dart | 31 ++-- lib/src/em_chat_manager.dart | 58 ++++++- lib/src/em_chat_thread_manager.dart | 16 +- lib/src/internal/chat_method_keys.dart | 2 + lib/src/models/em_conversation.dart | 22 +++ lib/src/models/em_error.dart | 1 + lib/src/models/em_message.dart | 19 ++- lib/src/models/fetch_message_options.dart | 153 ++++++++++++++++++ 13 files changed, 318 insertions(+), 54 deletions(-) create mode 100644 lib/src/models/fetch_message_options.dart diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java index 237a2d55..8457ee67 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java @@ -444,7 +444,7 @@ public void onSuccess() { post(() -> { Map map = new HashMap<>(); map.put("message", EMMessageHelper.toJson(msg)); - map.put("localTime", msg.localTime()); + map.put("localId", msg.getMsgId()); messageChannel.invokeMethod(EMSDKMethod.onMessageSuccess, map); }); } @@ -454,7 +454,7 @@ public void onProgress(int progress, String status) { post(() -> { Map map = new HashMap<>(); map.put("progress", progress); - map.put("localTime", msg.localTime()); + map.put("localId", msg.getMsgId()); messageChannel.invokeMethod(EMSDKMethod.onMessageProgressUpdate, map); }); } @@ -467,7 +467,7 @@ public void onError(int code, String desc) { post(() -> { Map map = new HashMap<>(); map.put("message", EMMessageHelper.toJson(msg)); - map.put("localTime", msg.localTime()); + map.put("localId", msg.getMsgId()); map.put("error", data); messageChannel.invokeMethod(EMSDKMethod.onMessageError, map); }); @@ -488,7 +488,7 @@ public void onSuccess() { post(() -> { Map map = new HashMap<>(); map.put("message", EMMessageHelper.toJson(msg)); - map.put("localTime", msg.localTime()); + map.put("localId", msg.getMsgId()); messageChannel.invokeMethod(EMSDKMethod.onMessageSuccess, map); }); } @@ -498,7 +498,7 @@ public void onProgress(int progress, String status) { post(() -> { Map map = new HashMap<>(); map.put("progress", progress); - map.put("localTime", msg.localTime()); + map.put("localId", msg.getMsgId()); messageChannel.invokeMethod(EMSDKMethod.onMessageProgressUpdate, map); }); } @@ -511,7 +511,7 @@ public void onError(int code, String desc) { post(() -> { Map map = new HashMap<>(); map.put("message", EMMessageHelper.toJson(msg)); - map.put("localTime", msg.localTime()); + map.put("localId", msg.getMsgId()); map.put("error", data); messageChannel.invokeMethod(EMSDKMethod.onMessageError, map); }); diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java index cb423ae6..230e06f9 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java @@ -12,6 +12,7 @@ import com.hyphenate.chat.EMCursorResult; import com.hyphenate.chat.EMCustomMessageBody; import com.hyphenate.chat.EMDeviceInfo; +import com.hyphenate.chat.EMFetchMessageOption; import com.hyphenate.chat.EMFileMessageBody; import com.hyphenate.chat.EMGroup; import com.hyphenate.chat.EMGroupInfo; @@ -441,6 +442,8 @@ static EMMessage fromJson(JSONObject json) throws JSONException { message.setIsChatThreadMessage(json.getBoolean("isThread")); + message.deliverOnlineOnly(json.getBoolean("deliverOnlineOnly")); + message.setLocalTime(json.getLong("localTime")); if (json.has("serverTime")){ message.setMsgTime(json.getLong("serverTime")); @@ -540,6 +543,7 @@ static Map toJson(EMMessage message) { data.put("hasRead", !message.isUnread()); data.put("needGroupAck", message.isNeedGroupAck()); data.put("onlineState", message.isOnlineState()); + // 通过EMMessageWrapper获取 // data.put("groupAckCount", message.groupAckCount()); data.put("isThread", message.isChatThreadMessage()); @@ -1391,4 +1395,12 @@ static Map toJson(EMSilentModeResult modeResult) { return data; } +} + +class FetchHistoryOptionsHelper { +// static EMFetchMessageOption fromJson(JSONObject obj) throws JSONException { +// EMFetchMessageOption options = new EMFetchMessageOption(); +// obj.has('') +// +// } } \ No newline at end of file diff --git a/example/lib/main.dart b/example/lib/main.dart index bb41c847..125e7e2b 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -155,20 +155,21 @@ class _MyHomePageState extends State { void _addChatListener() { EMClient.getInstance.chatManager.addMessageEvent( - "UNIQUE_HANDLER_ID", - ChatMessageEvent( - onSuccess: (msgId, msg) { - _addLogToConsole("send message succeed"); - }, - onProgress: (msgId, progress) { - _addLogToConsole("send message succeed"); - }, - onError: (msgId, msg, error) { - _addLogToConsole( - "send message failed, code: ${error.code}, desc: ${error.description}", - ); - }, - )); + "UNIQUE_HANDLER_ID", + ChatMessageEvent( + onSuccess: (msgId, msg) { + _addLogToConsole("on message succeed"); + }, + onProgress: (msgId, progress) { + _addLogToConsole("on message Progress"); + }, + onError: (msgId, msg, error) { + _addLogToConsole( + "on message failed, code: ${error.code}, desc: ${error.description}", + ); + }, + ), + ); EMClient.getInstance.chatManager.addEventHandler( "UNIQUE_HANDLER_ID", @@ -214,8 +215,9 @@ class _MyHomePageState extends State { break; case MessageType.FILE: { + EMClient.getInstance.chatManager.downloadAttachment(msg); _addLogToConsole( - "receive image message, from: ${msg.from}", + "receive file message, from: ${msg.from}", ); } break; diff --git a/ios/Classes/EMChatManagerWrapper.m b/ios/Classes/EMChatManagerWrapper.m index 7cba5e78..274001c9 100644 --- a/ios/Classes/EMChatManagerWrapper.m +++ b/ios/Classes/EMChatManagerWrapper.m @@ -472,7 +472,7 @@ - (void)downloadAttachment:(NSDictionary *)param [weakSelf.messageChannel invokeMethod:ChatOnMessageProgressUpdate arguments:@{ @"progress":@(progress), - @"localTime":@(msg.localTime) + @"localId": msg.messageId }]; } completion:^(EMChatMessage *message, EMError *error) { @@ -480,14 +480,14 @@ - (void)downloadAttachment:(NSDictionary *)param [weakSelf.messageChannel invokeMethod:ChatOnMessageError arguments:@{ @"error":[error toJson], - @"localTime":@(msg.localTime), + @"localId": msg.messageId, @"message":[message toJson] }]; }else { [weakSelf.messageChannel invokeMethod:ChatOnMessageSuccess arguments:@{ @"message":[message toJson], - @"localTime":@(msg.localTime) + @"localId": msg.messageId }]; } }]; @@ -510,7 +510,7 @@ - (void)downloadThumbnail:(NSDictionary *)param [weakSelf.messageChannel invokeMethod:ChatOnMessageProgressUpdate arguments:@{ @"progress":@(progress), - @"localTime":@(msg.localTime) + @"localId":msg.messageId }]; } completion:^(EMChatMessage *message, EMError *error) { @@ -518,14 +518,14 @@ - (void)downloadThumbnail:(NSDictionary *)param [weakSelf.messageChannel invokeMethod:ChatOnMessageError arguments:@{ @"error":[error toJson], - @"localTime":@(msg.localTime), + @"localId":msg.messageId, @"message":[message toJson] }]; }else { [weakSelf.messageChannel invokeMethod:ChatOnMessageSuccess arguments:@{ @"message":[message toJson], - @"localTime":@(msg.localTime) + @"localId":msg.messageId }]; } }]; diff --git a/ios/Classes/EMChatMessage+Helper.m b/ios/Classes/EMChatMessage+Helper.m index 5cef7b35..006b3e4d 100644 --- a/ios/Classes/EMChatMessage+Helper.m +++ b/ios/Classes/EMChatMessage+Helper.m @@ -50,6 +50,7 @@ + (EMChatMessage *)fromJson:(NSDictionary *)aJson msg.isDeliverAcked = [aJson[@"hasDeliverAck"] boolValue]; msg.isRead = [aJson[@"hasRead"] boolValue]; msg.isNeedGroupAck = [aJson[@"needGroupAck"] boolValue]; + msg.deliverOnlineOnly = [aJson[@"deliverOnlineOnly"] boolValue]; // read only // msg.groupAckCount = [aJson[@"groupAckCount"] intValue] // msg.chatThread = [EMChatThread forJson:aJson[@"thread"]]; @@ -83,6 +84,7 @@ - (NSDictionary *)toJson ret[@"direction"] = self.direction == EMMessageDirectionSend ? @"send" : @"rec"; ret[@"body"] = [self.body toJson]; ret[@"onlineState"] = @(self.onlineState); + ret[@"deliverOnlineOnly"] = @(self.deliverOnlineOnly); return ret; } diff --git a/lib/im_flutter_sdk.dart b/lib/im_flutter_sdk.dart index 95dab0cc..7ed7f3fe 100644 --- a/lib/im_flutter_sdk.dart +++ b/lib/im_flutter_sdk.dart @@ -13,26 +13,27 @@ export 'src/em_push_manager.dart'; export 'src/em_userInfo_manager.dart'; export 'src/em_presence_manager.dart'; -export 'src/models/em_group_message_ack.dart' show EMGroupMessageAck; -export 'src/models/em_chat_room.dart' show EMChatRoom; -export 'src/models/em_conversation.dart' show EMConversation; -export 'src/models/em_cursor_result.dart' show EMCursorResult; -export 'src/models/em_deviceInfo.dart' show EMDeviceInfo; -export 'src/models/em_error.dart' show EMError; +export 'src/models/em_group_message_ack.dart'; +export 'src/models/em_chat_room.dart'; +export 'src/models/em_conversation.dart'; +export 'src/models/em_cursor_result.dart'; +export 'src/models/em_deviceInfo.dart'; +export 'src/models/em_error.dart'; export 'src/models/em_group.dart'; -export 'src/models/em_translate_language.dart' show EMTranslateLanguage; -export 'src/models/em_presence.dart' show EMPresence; +export 'src/models/em_translate_language.dart'; +export 'src/models/em_presence.dart'; -export 'src/models/em_options.dart' show EMOptions; -export 'src/models/em_push_configs.dart' show EMPushConfigs; -export 'src/models/em_page_result.dart' show EMPageResult; -export 'src/models/em_userInfo.dart' show EMUserInfo; -export 'src/models/em_group_shared_file.dart' show EMGroupSharedFile; -export 'src/models/em_group_options.dart' show EMGroupOptions; +export 'src/models/em_options.dart'; +export 'src/models/em_push_configs.dart'; +export 'src/models/em_page_result.dart'; +export 'src/models/em_userInfo.dart'; +export 'src/models/em_group_shared_file.dart'; +export 'src/models/em_group_options.dart'; +export 'src/models/fetch_message_options.dart'; export 'src/models/em_chat_enums.dart'; export 'src/models/em_message.dart'; -export 'src/models/em_download_callback.dart' show EMDownloadCallback; +export 'src/models/em_download_callback.dart'; export 'src/models/em_message_reaction.dart'; export 'src/models/em_chat_thread.dart'; export 'src/models/chat_silent_mode.dart'; diff --git a/lib/src/em_chat_manager.dart b/lib/src/em_chat_manager.dart index 1d5e93d8..d1e4c9c5 100644 --- a/lib/src/em_chat_manager.dart +++ b/lib/src/em_chat_manager.dart @@ -3,6 +3,7 @@ import "dart:async"; import 'package:flutter/services.dart'; +import 'package:im_flutter_sdk/im_flutter_sdk.dart'; import 'internal/inner_headers.dart'; /// ~english @@ -160,8 +161,7 @@ class EMChatManager { void Function(EMMessage)? onSuccess, void Function(EMMessage)? onError, void Function(int)? onProgress, - )? - callback, + )? callback, }) async { message.status = MessageStatus.PROGRESS; Map result = await ChatChannel.invokeMethod( @@ -966,6 +966,58 @@ class EMChatManager { } } + /// ~english + /// [FetchMessageOptions] paging from the server to retrieve the history message for the specified session. + /// + /// Param [conversationId] The conversation ID, which is the user ID of the peer user for one-to-one chat, but the group ID for group chat. + /// + /// Param [type] The conversation type. You can set this parameter only to [EMConversationType.Chat] or [EMConversationType.GroupChat]. + /// + /// Param [options] The parameter configuration class for pulling historical messages from the server. See [FetchMessageOptions]. + /// + /// Param [cursor] The cursor position from which to start querying data. + /// + /// Param [pageSize] The number of messages that you expect to get on each page. The value range is [1,50]. + /// ~end + /// + /// ~chinese + /// 根据 [FetchMessageOptions] 从服务器分页获取指定会话的历史消息。 + /// + /// Param [conversationId] 会话 ID。 + /// + /// Param [type] 会话类型,只支持 [EMConversationType.Chat] 和群组 [EMConversationType.GroupChat] 。 + /// + /// Param [options] 查询历史消息的参数配置接口,详见 [FetchMessageOptions]。 + /// + /// Param [cursor] 查询的起始游标位置。 + /// + /// Param [pageSize] 每页期望获取的消息条数。取值范围为 [1,50]。 + /// ~end + Future> fetchHistoryMessagesByOption( + String conversationId, + EMConversationType type, { + FetchMessageOptions? options, + String? cursor, + int pageSize = 50, + }) async { + Map req = Map(); + req.add('pageSize', pageSize); + req.add('cursor', cursor); + req.add('options', options?.toJson()); + Map result = await ChatChannel.invokeMethod( + ChatMethodKeys.fetchHistoryMessagesByOptions, req); + try { + EMError.hasErrorFromResult(result); + return EMCursorResult.fromJson( + result[ChatMethodKeys.fetchHistoryMessagesByOptions], + dataItemCallback: (value) { + return EMMessage.fromJson(value); + }); + } on EMError catch (e) { + throw e; + } + } + /// ~english /// Retrieves messages from the database according to the parameters. /// @@ -1381,7 +1433,7 @@ class EMChatManager { /// /// Param [chatType] The chat type. Only one-to-one chat [ChatType.Chat] and group chat [ChatType.GroupChat] are allowed. /// - /// Param [groupId] which is invalid only when the chat type is group chat. + /// Param [groupId] which is valid only when the chat type is group chat. /// /// **Return** The Reaction list under the specified message ID([EMMessageReaction.userList] is the summary data, which only contains the information of the first three users). /// diff --git a/lib/src/em_chat_thread_manager.dart b/lib/src/em_chat_thread_manager.dart index 04e6ea98..7ed9418e 100644 --- a/lib/src/em_chat_thread_manager.dart +++ b/lib/src/em_chat_thread_manager.dart @@ -141,7 +141,7 @@ class EMChatThreadManager { /// /// Param [cursor] The initial value can be empty or empty string. /// - /// Param [limit] The number of fetches at one time. Value range (0, 50]. + /// Param [limit] The number of fetches at one time. Value range [1, 50]. /// /// **Return** Returns the result of [EMCursorResult], including the cursor for getting data next time and the chat thread object list. /// @@ -153,7 +153,7 @@ class EMChatThreadManager { /// /// Param [cursor] 开始获取数据的游标位置。首次调用方法时可以不传,按用户加入子区时间的倒序获取数据。 /// - /// Param [limit] 每页期望返回的子区数。取值范围为 (1,50]。 + /// Param [limit] 每页期望返回的子区数。取值范围为 [1,50]。 /// /// **Return** 若调用成功,返回子区列表;失败则抛出异常。 /// @@ -186,7 +186,7 @@ class EMChatThreadManager { /// /// Param [cursor] The initial value can be empty or empty string. /// - /// Param [limit] The number of fetches at one time. Value range (0, 50]. + /// Param [limit] The number of fetches at one time. Value range [1, 50]. /// /// **Return** result of [EMCursorResult], including the cursor for getting data next time and the chat thread object list. /// @@ -200,7 +200,7 @@ class EMChatThreadManager { /// /// Param [cursor] 开始取数据的游标位置。首次获取数据时可以不传,按子区创建时间的倒序获取数据。 /// - /// Param [limit] 每页期望返回的子区数。取值范围为 (1,50]。 + /// Param [limit] 每页期望返回的子区数。取值范围为 [1,50]。 /// /// **Return** 若调用成功,返回子区列表;失败则抛出异常。 /// @@ -237,7 +237,7 @@ class EMChatThreadManager { /// /// Param [cursor] The initial value can be empty or empty string. /// - /// Param [limit] The number of fetches at one time. Value range (0, 50]. + /// Param [limit] The number of fetches at one time. Value range [1, 50]. /// /// **Return** The result of [EMCursorResult], including the cursor for getting data next time and the chat thread object list. /// @@ -251,7 +251,7 @@ class EMChatThreadManager { /// /// Param [cursor] 开始取数据的游标位置。首次调用方法时可以不传,按用户加入子区时间的倒序获取数据。 /// - /// Param [limit] 每页期望返回的子区数。取值范围为 (1,50]。 + /// Param [limit] 每页期望返回的子区数。取值范围为 [1,50]。 /// /// **Return** 若调用成功,返回子区列表;失败则抛出异常。 /// @@ -290,7 +290,7 @@ class EMChatThreadManager { /// /// Param [cursor] The initial value can be empty or empty string. /// - /// Param [limit] The number of fetches at one time. Value range (0, 50]. + /// Param [limit] The number of fetches at one time. Value range [1, 50]. /// /// **Return** The result of [EMCursorResult], including the cursor for getting data next time and the chat thread member list. /// @@ -307,7 +307,7 @@ class EMChatThreadManager { /// /// Param [cursor] 开始获取数据的游标位置,首次调用方法时传 `null` 或空字符串,按成员加入子区时间的正序获取数据。 /// - /// Param [limit] 每页期望返回的成员数。取值范围为 (1,50]。 + /// Param [limit] 每页期望返回的成员数。取值范围为 [1,50]。 /// /// **Return** 若调用成功,返回子区成员列表;失败则抛出异常。 /// diff --git a/lib/src/internal/chat_method_keys.dart b/lib/src/internal/chat_method_keys.dart index 414d0dce..41ffadcd 100644 --- a/lib/src/internal/chat_method_keys.dart +++ b/lib/src/internal/chat_method_keys.dart @@ -77,6 +77,8 @@ class ChatMethodKeys { static const String deleteConversation = "deleteConversation"; static const String fetchHistoryMessages = "fetchHistoryMessages"; + static const String fetchHistoryMessagesByOptions = + "fetchHistoryMessagesByOptions"; static const String searchChatMsgFromDB = "searchChatMsgFromDB"; static const String getMessage = "getMessage"; static const String asyncFetchGroupAcks = "asyncFetchGroupAcks"; diff --git a/lib/src/models/em_conversation.dart b/lib/src/models/em_conversation.dart index d94abb28..8afa7bd1 100644 --- a/lib/src/models/em_conversation.dart +++ b/lib/src/models/em_conversation.dart @@ -391,6 +391,28 @@ class EMConversation { } } + /// ~english + /// Deletes messages sent or received in a certain period from the local database. + /// + /// Param [startTs] The starting UNIX timestamp for message deletion. The unit is millisecond. + /// + /// Param [endTs] The end UNIX timestamp for message deletion. The unit is millisecond. + /// + /// **Throws** A description of the exception. See [EMError]. + /// + /// ~end + /// + /// ~chinese + /// 从本地数据库中删除指定时间段内的消息。 + /// + /// Param [startTs] 删除消息的起始时间。UNIX 时间戳,单位为毫秒。 + /// + /// Param [endTs] 删除消息的结束时间。UNIX 时间戳,单位为毫秒。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end + Future deleteMessageWithTs(int startTs, int endTs) async {} + /// ~english /// Gets the message with a specific message ID. /// diff --git a/lib/src/models/em_error.dart b/lib/src/models/em_error.dart index 37882181..8ecb8138 100644 --- a/lib/src/models/em_error.dart +++ b/lib/src/models/em_error.dart @@ -47,3 +47,4 @@ class EMError { return "code: " + code.toString() + " desc: " + description; } } + diff --git a/lib/src/models/em_message.dart b/lib/src/models/em_message.dart index 4585c8c4..915bd936 100644 --- a/lib/src/models/em_message.dart +++ b/lib/src/models/em_message.dart @@ -213,6 +213,21 @@ class EMMessage { /// ~end Map? attributes; + /// ~english + /// Whether the message is delivered only when the recipient(s) is/are online: + /// + /// - `true`:The message is delivered only when the recipient(s) is/are online. If the recipient is offline, the message is discarded. + /// - `false` (Default) :The message is delivered when the recipient(s) is/are online. If the recipient(s) is/are offline, the message will not be delivered to them until they get online. + /// ~end + /// + /// ~chinese + /// 消息是否只投递给在线用户: + /// + /// - `true`:只有消息接收方在线时才能投递成功。若接收方离线,则消息会被丢弃。 + /// - `false`(默认):如果用户在线,则直接投递;如果用户离线,消息会在用户上线时投递。 + /// ~end + bool deliverOnlineOnly = false; + /// ~english /// Message body. We recommend you use [EMMessageBody]. /// ~end @@ -754,6 +769,7 @@ class EMMessage { if (_priority != null) { data.add("chatroomMessagePriority", _priority!.index); } + data.add('deliverOnlineOnly', deliverOnlineOnly); return data; } @@ -778,7 +794,8 @@ class EMMessage { ..localTime = map["localTime"] ?? 0 ..serverTime = map["serverTime"] ?? 0 ..isChatThreadMessage = map["isThread"] ?? false - ..onlineState = map["true"] ?? true + ..onlineState = map["onlineState"] ?? true + ..deliverOnlineOnly = map['deliverOnlineOnly'] ?? false ..status = messageStatusFromInt(map["status"]); } diff --git a/lib/src/models/fetch_message_options.dart b/lib/src/models/fetch_message_options.dart new file mode 100644 index 00000000..776bb317 --- /dev/null +++ b/lib/src/models/fetch_message_options.dart @@ -0,0 +1,153 @@ +import 'package:im_flutter_sdk/src/internal/inner_headers.dart'; + +/// ~english +/// The parameter configuration class for pulling historical messages from the server. +/// ~end +/// +/// ~chinese +/// 从服务端查询历史消息的参数配置类。 +/// ~end +class FetchMessageOptions { + /// ~english + /// The parameter configuration class for pulling historical messages from the server. + /// + /// Param [direction] The message search direction, Default is [EMSearchDirection.Up]. See [EMSearchDirection]. + /// + /// Param [from] The user ID of the message sender in the group conversation. + /// + /// Param [msgTypes] The array of message types for query. The default value is `null`, indicating that all types of messages are retrieved. + /// + /// Param [startTs] The start time for message query. The time is a UNIX time stamp in milliseconds. + /// The default value is `-1`, indicating that this parameter is ignored during message query. + /// If the [startTs] is set to a specific time spot and the [endTs] uses the default value `-1`, + /// the SDK returns messages that are sent and received in the period that is from the start time to the current time. + /// If the [startTs] uses the default value `-1` and the [endTs] is set to a specific time spot, + /// the SDK returns messages that are sent and received in the period that is from the timestamp of the first message to the current time. + /// + /// Param [endTs] The end time for message query. The time is a UNIX time stamp in milliseconds. + /// The default value is -1, indicating that this parameter is ignored during message query. + /// If the [startTs] is set to a specific time spot and the [endTs] uses the default value -1, + /// the SDK returns messages that are sent and received in the period that is from the start time to the current time. + /// If the [startTs] uses the default value -1 and the [endTs] is set to a specific time spot, + /// the SDK returns messages that are sent and received in the period that is from the timestamp of the first message to the current time. + /// + /// Param [needSave] Whether to save the retrieved messages to the database: + /// - `true`: save to database; + /// - `false`(Default):no save to database. + /// ~end + /// + /// ~chinese + /// 从服务端查询历史消息的参数配置类。 + /// + /// Param [direction] 消息搜索方向。默认为 [EMSearchDirection.Up] , 详见 [EMSearchDirection]。 + /// + /// Param [from] 群组会话中的消息发送方的用户 ID。 + /// + /// Param [msgTypes] 要查询的消息类型数组。默认值为 `null`,表示返回所有类型的消息。 + /// + /// Param [startTs] 消息查询的起始时间,Unix 时间戳,单位为毫秒。默认为 `-1`,表示消息查询时会忽略该参数。 + /// 若 [startTs] 设置为特定时间点,而 [endTs] 采用默认值 `-1`,则查询起始时间至当前时间的消息。 + /// 若 [startTs] 采用默认值 `-1`,而 [endTs] 设置了特定时间,SDK 返回从会话中最早的消息到结束时间点的消息。 + /// + /// Param [endTs] 消息查询的结束时间,Unix 时间戳,单位为毫秒。默认为 -1,表示消息查询时会忽略该参数。 + /// 若 [startTs] 设置为特定时间点,而 [endTs] 采用默认值 -1,则查询起始时间至当前时间的消息。 + /// 若 [startTs] 采用默认值 -1,而 [endTs] 设置了特定时间,SDK 返回从会话中最早的消息到结束时间点的消息。 + /// + /// Param [needSave] 获取的消息是否保存到数据库: + /// - `true`:保存到数据库; + /// - `false`(默认):不保存到数据库。 + /// ~end + const FetchMessageOptions({ + this.from, + this.msgTypes, + this.startTs = -1, + this.endTs = -1, + this.needSave = false, + this.direction = EMSearchDirection.Up, + }); + + /// ~english + /// The user ID of the message sender in the group conversation. + /// ~end + /// + /// ~chinese + /// 群组会话中的消息发送方的用户 ID。 + /// ~end + final String? from; + + /// ~english + /// The array of message types for query. The default value is `null`, indicating that all types of messages are retrieved. + /// ~end + /// + /// ~chinese + /// 要查询的消息类型数组。默认值为 `null`,表示返回所有类型的消息。 + /// ~end + final List? msgTypes; + + /// ~english + /// The start time for message query. The time is a UNIX time stamp in milliseconds. The default value is -1, + /// indicating that this parameter is ignored during message query. + /// If the [startTs] is set to a specific time spot and the [endTs] uses the default value -1, + /// the SDK returns messages that are sent and received in the period that is from the start time to the current time. + /// If the [startTs] uses the default value -1 and the [endTs] is set to a specific time spot, + /// the SDK returns messages that are sent and received in the period that is from the timestamp of the first message to the current time. + /// ~end + /// + /// ~chinese + /// 消息查询的起始时间,Unix 时间戳,单位为毫秒。默认为 -1,表示消息查询时会忽略该参数。 + /// 若 [startTs] 设置为特定时间点,而 [endTs] 采用默认值 -1,则查询起始时间至当前时间的消息。 + /// 若 [startTs] 采用默认值 -1,而 [endTs] 设置了特定时间,SDK 返回从会话中最早的消息到结束时间点的消息。 + /// ~end + final int startTs; + + /// ~english + /// The end time for message query. The time is a UNIX time stamp in milliseconds. + /// The default value is `-1`, indicating that this parameter is ignored during message query. + /// If the [startTs] is set to a specific time spot and the [endTs] uses the default value `-1`, + /// the SDK returns messages that are sent and received in the period that is from the start time to the current time. + /// If the [startTs] uses the default value `-1` and the [endTs] is set to a specific time spot, + /// the SDK returns messages that are sent and received in the period that is from the timestamp of the first message to the current time. + /// ~end + /// + /// ~chinese + /// 消息查询的结束时间,Unix 时间戳,单位为毫秒。默认为 `-1`,表示消息查询时会忽略该参数。 + /// 若 [startTs] 设置为特定时间点,而 [endTs] 采用默认值 `-1`,则查询起始时间至当前时间的消息。 + /// 若 [startTs] 采用默认值 `-1`,而 [endTs] 设置了特定时间,SDK 返回从会话中最早的消息到结束时间点的消息。 + /// ~end + final int endTs; + + /// ~english + /// The message search direction, Default is [EMSearchDirection.Up]. See [EMSearchDirection]. + /// ~end + /// + /// ~chinese + /// 消息搜索方向,默认为[EMSearchDirection.Up]。详见 [EMSearchDirection]。 + /// ~end + final EMSearchDirection direction; + + /// ~english + /// Whether to save the retrieved messages to the database: + /// - `true`: save to database; + /// - `false`(Default):no save to database. + /// ~end + /// + /// ~chinese + /// 获取的消息是否保存到数据库: + /// - `true`:保存到数据库; + /// - `false`(默认):不保存到数据库。 + /// ~end + final bool needSave; + + Map toJson() { + Map data = {}; + data.add('direction', direction == EMSearchDirection.Up ? "up" : "down"); + data.add('startTs', startTs); + data.add('endTs', endTs); + data.add('from', from); + data.add('needSave', needSave); + data.add('msgType', + msgTypes?.toSet().map((e) => messageTypeToTypeStr(e)).toList()); + + return data; + } +} From 5fa2aaead6eab70bc3f84c07b54c216c69592e6b Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Mon, 15 May 2023 18:07:59 +0800 Subject: [PATCH 07/49] add fetch history message method. --- .../im_flutter_sdk/EMChatManagerWrapper.java | 27 ++++++++ .../com/easemob/im_flutter_sdk/EMHelper.java | 65 +++++++++++++++++-- .../easemob/im_flutter_sdk/EMSDKMethod.java | 1 + ios/Classes/EMChatManagerWrapper.m | 25 +++++++ .../EMFetchServerMessagesOption+Helper.h | 16 +++++ .../EMFetchServerMessagesOption+Helper.m | 50 ++++++++++++++ ios/Classes/EMSDKMethod.h | 1 + lib/src/em_chat_manager.dart | 2 + lib/src/models/fetch_message_options.dart | 2 +- pubspec.yaml | 2 +- 10 files changed, 184 insertions(+), 7 deletions(-) create mode 100644 ios/Classes/EMFetchServerMessagesOption+Helper.h create mode 100644 ios/Classes/EMFetchServerMessagesOption+Helper.m diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java index 8457ee67..6fbdc583 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java @@ -87,6 +87,8 @@ public void onMethodCall(MethodCall call, Result result) { deleteConversation(param, call.method, result); } else if (EMSDKMethod.fetchHistoryMessages.equals(call.method)) { fetchHistoryMessages(param, call.method, result); + } else if (EMSDKMethod.fetchHistoryMessagesByOptions.equals(call.method)) { + fetchHistoryMessagesByOptions(param, call.method, result); } else if (EMSDKMethod.searchChatMsgFromDB.equals(call.method)) { searchChatMsgFromDB(param, call.method, result); } else if (EMSDKMethod.getMessage.equals(call.method)) { @@ -626,6 +628,31 @@ private void fetchHistoryMessages(JSONObject param, String channelName, Result r }); } + private void fetchHistoryMessagesByOptions(JSONObject param, String channelName, Result result) throws JSONException { + String conId = param.getString("con_id"); + EMConversationType type = EMConversationHelper.typeFromInt(param.getInt("type")); + int pageSize = param.getInt("pageSize"); + String cursor = null; + if (param.has("cursor")) { + cursor = param.getString("cursor"); + } + EMFetchMessageOption option = null; + if (param.has("options")) { + option = FetchHistoryOptionsHelper.fromJson(param.getJSONObject("options")); + } + + EMValueWrapperCallBack> callBack = new EMValueWrapperCallBack>(result, + channelName) { + @Override + public void onSuccess(EMCursorResult result) { + updateObject(EMCursorResultHelper.toJson(result)); + } + }; + + EMClient.getInstance().chatManager().asyncFetchHistoryMessages(conId, type, pageSize, cursor, option, callBack); + } + + private void searchChatMsgFromDB(JSONObject param, String channelName, Result result) throws JSONException { String keywords = param.getString("keywords"); long timestamp = param.getLong("timestamp"); diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java index 230e06f9..664b8681 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java @@ -1398,9 +1398,64 @@ static Map toJson(EMSilentModeResult modeResult) { } class FetchHistoryOptionsHelper { -// static EMFetchMessageOption fromJson(JSONObject obj) throws JSONException { -// EMFetchMessageOption options = new EMFetchMessageOption(); -// obj.has('') -// -// } + static EMFetchMessageOption fromJson(JSONObject json) throws JSONException { + EMFetchMessageOption options = new EMFetchMessageOption(); + if (json.getString("direction") == "up") { + options.setDirection(EMConversation.EMSearchDirection.UP); + }else { + options.setDirection(EMConversation.EMSearchDirection.DOWN); + } + options.setIsSave(json.getBoolean("needSave")); + options.setStartTime(json.getLong("startTs")); + options.setEndTime(json.getLong("endTs")); + if (json.has("from")){ + options.setFrom(json.getString("from")); + } + if (json.has("msgTypes")){ + List list = new ArrayList<>(); + JSONArray array = json.getJSONArray("msgTypes"); + for (int i = 0; i < array.length(); i++) { + String type = array.getString(i); + switch (type) { + case "txt": { + list.add(Type.TXT); + } + break; + case "img": { + list.add(Type.IMAGE); + } + break; + case "loc": { + list.add(Type.LOCATION); + } + break; + case "video": { + list.add(Type.VIDEO); + } + break; + case "voice": { + list.add(Type.VOICE); + } + break; + case "file": { + list.add(Type.FILE); + } + break; + case "cmd": { + list.add(Type.CMD); + } + break; + case "custom": { + list.add(Type.CUSTOM); + } + break; + } + } + if (list.size() > 0) { + options.setMsgTypes(list); + } + } + + return options; + } } \ No newline at end of file diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java index 3c2c595e..ee93fe63 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java @@ -73,6 +73,7 @@ public class EMSDKMethod { static final String getConversationsFromServer = "getConversationsFromServer"; static final String deleteConversation = "deleteConversation"; static final String fetchHistoryMessages = "fetchHistoryMessages"; + static final String fetchHistoryMessagesByOptions = "fetchHistoryMessagesByOptions"; static final String searchChatMsgFromDB = "searchChatMsgFromDB"; static final String getMessage = "getMessage"; static final String asyncFetchGroupAcks = "asyncFetchGroupAcks"; diff --git a/ios/Classes/EMChatManagerWrapper.m b/ios/Classes/EMChatManagerWrapper.m index 274001c9..a8c50af0 100644 --- a/ios/Classes/EMChatManagerWrapper.m +++ b/ios/Classes/EMChatManagerWrapper.m @@ -15,6 +15,7 @@ #import "EMCursorResult+Helper.h" #import "EMMessageReaction+Helper.h" #import "EMMessageReactionChange+Helper.h" +#import "EMFetchServerMessagesOption+Helper.h" @interface EMChatManagerWrapper () @property (nonatomic, strong) FlutterMethodChannel *messageChannel; @@ -122,6 +123,10 @@ - (void)handleMethodCall:(FlutterMethodCall*)call [self fetchHistoryMessages:call.arguments channelName:call.method result:result]; + } else if ([ChatFetchHistoryMessagesByOptions isEqualToString:call.method]) { + [self fetchHistoryMessagesByOptions:call.arguments + channelName:call.method + result:result]; } else if ([ChatSearchChatMsgFromDB isEqualToString:call.method]) { [self searchChatMsgFromDB:call.arguments channelName:call.method @@ -619,6 +624,26 @@ - (void)fetchHistoryMessages:(NSDictionary *)param }]; } +- (void)fetchHistoryMessagesByOptions:(NSDictionary *)param + channelName:(NSString *)aChannelName + result:(FlutterResult)result { + __weak typeof(self)weakSelf = self; + NSString *conversationId = param[@"con_id"]; + EMConversationType type = (EMConversationType)[param[@"type"] intValue]; + int pageSize = [param[@"pageSize"] intValue]; + NSString *cursor = param[@"cursor"]; + EMFetchServerMessagesOption *options; + if(param[@"options"]) { + options = [EMFetchServerMessagesOption formJson:param[@"options"]]; + } + [EMClient.sharedClient.chatManager fetchMessagesFromServerBy:conversationId conversationType:type cursor:cursor pageSize:pageSize option:options completion:^(EMCursorResult * _Nullable aResult, EMError * _Nullable aError) { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:aError + object:[aResult toJson]]; + }]; +} + - (void)fetchGroupReadAck:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult) result { diff --git a/ios/Classes/EMFetchServerMessagesOption+Helper.h b/ios/Classes/EMFetchServerMessagesOption+Helper.h new file mode 100644 index 00000000..2f77fd0d --- /dev/null +++ b/ios/Classes/EMFetchServerMessagesOption+Helper.h @@ -0,0 +1,16 @@ +// +// EMFetchServerMessagesOption+Helper.h +// im_flutter_sdk +// +// Created by 杜洁鹏 on 2023/5/15. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface EMFetchServerMessagesOption (Helper) ++ (EMFetchServerMessagesOption *)formJson:(NSDictionary *)dict; +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Classes/EMFetchServerMessagesOption+Helper.m b/ios/Classes/EMFetchServerMessagesOption+Helper.m new file mode 100644 index 00000000..5816bde6 --- /dev/null +++ b/ios/Classes/EMFetchServerMessagesOption+Helper.m @@ -0,0 +1,50 @@ +// +// EMFetchServerMessagesOption+Helper.m +// im_flutter_sdk +// +// Created by 杜洁鹏 on 2023/5/15. +// + +#import "EMFetchServerMessagesOption+Helper.h" +#import "EMConversation+Helper.h" + +@implementation EMFetchServerMessagesOption (Helper) ++ (EMFetchServerMessagesOption *)formJson:(NSDictionary *)dict { + EMFetchServerMessagesOption *options = [[EMFetchServerMessagesOption alloc] init]; + options.direction = [dict[@"direction"] isEqualToString:@"up"] ? EMMessageSearchDirectionUp : EMMessageSearchDirectionDown; + options.startTime = [dict[@"startTs"] intValue]; + options.endTime = [dict[@"endTs"] intValue]; + options.from = dict[@"from"]; + options.isSave = [dict[@"needSave"] boolValue]; + NSArray *types = dict[@"msgTypes"]; + NSMutableArray *list = [NSMutableArray new]; + if(types) { + for (int i = 0; i < types.count; i++) { + NSString *type = types[i]; + if ([type isEqualToString:@"txt"]) { + [list addObject:@(EMMessageBodyTypeText)]; + } else if ([type isEqualToString:@"img"]) { + [list addObject:@(EMMessageBodyTypeImage)]; + } else if ([type isEqualToString:@"loc"]) { + [list addObject:@(EMMessageBodyTypeLocation)]; + } else if ([type isEqualToString:@"video"]) { + [list addObject:@(EMMessageBodyTypeVideo)]; + } else if ([type isEqualToString:@"voice"]) { + [list addObject:@(EMMessageBodyTypeVoice)]; + } else if ([type isEqualToString:@"file"]) { + [list addObject:@(EMMessageBodyTypeFile)]; + } else if ([type isEqualToString:@"cmd"]) { + [list addObject:@(EMMessageBodyTypeCmd)]; + } else if ([type isEqualToString:@"custom"]) { + [list addObject:@(EMMessageBodyTypeCustom)]; + } + } + } + + if(list.count > 0) { + options.msgTypes = list; + } + + return options; +} +@end diff --git a/ios/Classes/EMSDKMethod.h b/ios/Classes/EMSDKMethod.h index 4686002d..c4ab5b6f 100644 --- a/ios/Classes/EMSDKMethod.h +++ b/ios/Classes/EMSDKMethod.h @@ -82,6 +82,7 @@ static NSString *const ChatGetConversationsFromServer = @"getConversationsFromSe static NSString *const ChatDeleteConversation = @"deleteConversation"; static NSString *const ChatFetchHistoryMessages = @"fetchHistoryMessages"; +static NSString *const ChatFetchHistoryMessagesByOptions = @"fetchHistoryMessagesByOptions"; static NSString *const ChatSearchChatMsgFromDB = @"searchChatMsgFromDB"; static NSString *const ChatGetMessage = @"getMessage"; static NSString *const ChatAsyncFetchGroupAcks = @"asyncFetchGroupAcks"; diff --git a/lib/src/em_chat_manager.dart b/lib/src/em_chat_manager.dart index d1e4c9c5..42b5c3fd 100644 --- a/lib/src/em_chat_manager.dart +++ b/lib/src/em_chat_manager.dart @@ -1001,6 +1001,8 @@ class EMChatManager { int pageSize = 50, }) async { Map req = Map(); + req.add('con_id', conversationId); + req.add('type', conversationTypeToInt(type)); req.add('pageSize', pageSize); req.add('cursor', cursor); req.add('options', options?.toJson()); diff --git a/lib/src/models/fetch_message_options.dart b/lib/src/models/fetch_message_options.dart index 776bb317..61262c49 100644 --- a/lib/src/models/fetch_message_options.dart +++ b/lib/src/models/fetch_message_options.dart @@ -145,7 +145,7 @@ class FetchMessageOptions { data.add('endTs', endTs); data.add('from', from); data.add('needSave', needSave); - data.add('msgType', + data.add('msgTypes', msgTypes?.toSet().map((e) => messageTypeToTypeStr(e)).toList()); return data; diff --git a/pubspec.yaml b/pubspec.yaml index 96a6bee9..dee7e745 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: im_flutter_sdk description: Integrate the Chat SDK to enjoy the global IM services with high reliability, ultra-low latency, and high concurrency. -version: 4.0.0+5 +version: 4.0.2 homepage: https://www.easemob.com/product/im environment: From e7f5bce36c985a8c92afbcd3f42dd4a2e0cdf4cf Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Wed, 17 May 2023 10:40:58 +0800 Subject: [PATCH 08/49] add group attributs methods. --- .../EMChatRoomManagerWrapper.java | 30 ++--- .../im_flutter_sdk/EMConversationWrapper.java | 21 +++ .../im_flutter_sdk/EMGroupManagerWrapper.java | 121 +++++++++++++---- .../easemob/im_flutter_sdk/EMSDKMethod.java | 6 + ios/Classes/EMChatManagerWrapper.m | 70 +++++++++- ios/Classes/EMChatMessage+Helper.h | 4 +- ios/Classes/EMChatMessage+Helper.m | 107 ++++++++------- ios/Classes/EMChatroomManagerWrapper.m | 44 +++--- ios/Classes/EMConversationWrapper.m | 19 +++ ios/Classes/EMGroupManagerWrapper.m | 127 ++++++++++++++---- ios/Classes/EMSDKMethod.h | 4 + lib/src/em_group_manager.dart | 111 +++++++++++++++ .../event_handler/manager_event_handler.dart | 36 +++++ lib/src/internal/chat_method_keys.dart | 7 + lib/src/internal/em_event_keys.dart | 82 +++++------ lib/src/models/em_chat_enums.dart | 10 ++ lib/src/models/em_conversation.dart | 13 +- 17 files changed, 625 insertions(+), 187 deletions(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java index 20c55c9e..a68af55e 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java @@ -665,7 +665,7 @@ public void onWhiteListAdded(String chatRoomId, List whitelist) { Map data = new HashMap<>(); data.put("roomId", chatRoomId); data.put("whitelist", whitelist); - data.put("type", "chatroomWhiteListAdded"); + data.put("type", "onRoomWhiteListAdded"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -679,7 +679,7 @@ public void onWhiteListRemoved(String chatRoomId, List whitelist) { Map data = new HashMap<>(); data.put("roomId", chatRoomId); data.put("whitelist", whitelist); - data.put("type", "chatroomWhiteListRemoved"); + data.put("type", "onRoomWhiteListRemoved"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -692,7 +692,7 @@ public void onAllMemberMuteStateChanged(String chatRoomId, boolean isMuted) { Map data = new HashMap<>(); data.put("roomId", chatRoomId); data.put("isMuted", isMuted); - data.put("type", "chatroomAllMemberMuteStateChanged"); + data.put("type", "onRoomAllMemberMuteStateChanged"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -706,7 +706,7 @@ public void onChatRoomDestroyed(String roomId, String roomName) { Map data = new HashMap<>(); data.put("roomId", roomId); data.put("roomName", roomName); - data.put("type", "chatroomDestroyed"); + data.put("type", "onRoomDestroyed"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -720,7 +720,7 @@ public void onMemberJoined(String roomId, String participant) { Map data = new HashMap<>(); data.put("roomId", roomId); data.put("participant", participant); - data.put("type", "chatroomMemberJoined"); + data.put("type", "onRoomMemberJoined"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -734,7 +734,7 @@ public void onMemberExited(String roomId, String roomName, String participant) { data.put("roomId", roomId); data.put("roomName", roomName); data.put("participant", participant); - data.put("type", "chatroomMemberExited"); + data.put("type", "onRoomMemberExited"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -749,7 +749,7 @@ public void onRemovedFromChatRoom(int reason, String roomId, String roomName, St data.put("roomId", roomId); data.put("roomName", roomName); data.put("participant", participant); - data.put("type", "chatroomRemoved"); + data.put("type", "onRoomRemoved"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -764,7 +764,7 @@ public void onMuteListAdded(String chatRoomId, List mutes, long expireTi data.put("roomId", chatRoomId); data.put("mutes", mutes); data.put("expireTime", String.valueOf(expireTime)); - data.put("type", "chatroomMuteListAdded"); + data.put("type", "onRoomMuteListAdded"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -777,7 +777,7 @@ public void onMuteListRemoved(String chatRoomId, List mutes) { Map data = new HashMap<>(); data.put("roomId", chatRoomId); data.put("mutes", mutes); - data.put("type", "chatroomMuteListRemoved"); + data.put("type", "onRoomMuteListRemoved"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -791,7 +791,7 @@ public void onAdminAdded(String chatRoomId, String admin) { Map data = new HashMap<>(); data.put("roomId", chatRoomId); data.put("admin", admin); - data.put("type", "chatroomAdminAdded"); + data.put("type", "onRoomAdminAdded"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -805,7 +805,7 @@ public void onAdminRemoved(String chatRoomId, String admin) { Map data = new HashMap<>(); data.put("roomId", chatRoomId); data.put("admin", admin); - data.put("type", "chatroomAdminRemoved"); + data.put("type", "onRoomAdminRemoved"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -819,7 +819,7 @@ public void onOwnerChanged(String chatRoomId, String newOwner, String oldOwner) data.put("roomId", chatRoomId); data.put("newOwner", newOwner); data.put("oldOwner", oldOwner); - data.put("type", "chatroomOwnerChanged"); + data.put("type", "onRoomOwnerChanged"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -833,7 +833,7 @@ public void onAnnouncementChanged(String chatRoomId, String announcement) { Map data = new HashMap<>(); data.put("roomId", chatRoomId); data.put("announcement", announcement); - data.put("type", "chatroomAnnouncementChanged"); + data.put("type", "onRoomAnnouncementChanged"); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); @@ -857,7 +857,7 @@ public void onAttributesUpdate(String chatRoomId, Map attributeM ()-> { Map data = new HashMap<>(); data.put("roomId", chatRoomId); - data.put("type", "chatroomAttributesDidUpdated"); + data.put("type", "onRoomAttributesDidUpdated"); data.put("attributes", attributeMap); data.put("fromId", from); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); @@ -872,7 +872,7 @@ public void onAttributesRemoved(String chatRoomId, List keyList, String Map data = new HashMap<>(); data.put("roomId", chatRoomId); data.put("keys", keyList); - data.put("type", "chatroomAttributesDidRemoved"); + data.put("type", "onRoomAttributesDidRemoved"); data.put("fromId", from); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java index 26fc6bf0..31d3485f 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java @@ -11,6 +11,7 @@ import com.hyphenate.chat.EMConversation; import com.hyphenate.chat.EMMessage; import com.hyphenate.chat.EMMessageBody; +import com.hyphenate.exceptions.HyphenateException; import org.json.JSONArray; import org.json.JSONException; @@ -58,6 +59,9 @@ else if (EMSDKMethod.getLatestMessageFromOthers.equals(call.method)) { else if (EMSDKMethod.clearAllMessages.equals(call.method)) { clearAllMessages(param, call.method, result); } + else if (EMSDKMethod.deleteMessagesWithTs.equals(call.method)) { + deleteMessagesWithTs(param, call.method, result); + } else if (EMSDKMethod.insertMessage.equals((call.method))) { insertMessage(param, call.method, result); } @@ -178,6 +182,23 @@ private void clearAllMessages(JSONObject params, String channelName, Result resu }); } + private void deleteMessagesWithTs(JSONObject params, String channelName, Result result) throws JSONException { + EMConversation conversation = conversationWithParam(params); + long startTs = params.getLong("startTs"); + long endTs = params.getLong("endTs"); + asyncRunnable(()->{ + boolean success = conversation.removeMessages(startTs, endTs); + if (success) { + onSuccess(result, channelName, true); + }else { + HyphenateException e = new HyphenateException(3, "Database operation error"); + onError(result, e); + } + }); + } + + + private void insertMessage(JSONObject params, String channelName, Result result) throws JSONException { EMConversation conversation = conversationWithParam(params); JSONObject msg = params.getJSONObject("msg"); diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java index 67ea07a5..7293abcd 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -131,6 +132,12 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) { acceptInvitationFromGroup(param, call.method, result); } else if (EMSDKMethod.declineInvitationFromGroup.equals(call.method)) { declineInvitationFromGroup(param, call.method, result); + } else if (EMSDKMethod.setMemberAttributesFromGroup.equals(call.method)) { + setMemberAttributes(param, call.method, result); + } else if (EMSDKMethod.fetchMemberAttributesFromGroup.equals(call.method)) { + fetchMemberAttributes(param, call.method, result); + } else if (EMSDKMethod.fetchMembersAttributesFromGroup.equals(call.method)) { + fetchMembersAttributes(param, call.method, result); } else { super.onMethodCall(call, result); } @@ -820,6 +827,53 @@ private void declineInvitationFromGroup(JSONObject param, String channelName, Re EMClient.getInstance().groupManager().asyncDeclineInvitation(groupId, username, reason, new EMWrapperCallBack(result, channelName, null)); } + private void setMemberAttributes(JSONObject param, String channelName, Result result) throws JSONException { + String groupId = param.getString("groupId"); + String userId = param.getString("userId"); + + Map attributes = new HashMap<>(); + + JSONObject jsonObject = param.getJSONObject("attributes"); + Iterator iterator = jsonObject.keys(); + while (iterator.hasNext()) { + String key = iterator.next().toString(); + attributes.put(key, jsonObject.getString(key)); + } + + EMClient.getInstance().groupManager().asyncSetGroupMemberAttributes(groupId, userId, attributes, new EMWrapperCallBack(result, channelName, null)); + } + + private void fetchMemberAttributes(JSONObject param, String channelName, Result result) throws JSONException { + String groupId = param.getString("groupId"); + String userId = param.getString("userId"); + + EMClient.getInstance().groupManager().asyncFetchGroupMemberAllAttributes(groupId, userId, new EMValueWrapperCallBack<>(result, channelName)); + } + + private void fetchMembersAttributes(JSONObject param, String channelName, Result result) throws JSONException { + String groupId = param.getString("groupId"); + JSONArray jUsers = param.getJSONArray("userIds"); + List userIds = new ArrayList<>(); + for (int i = 0; i < jUsers.length(); i++) { + userIds.add(jUsers.getString(i)); + } + List keys = new ArrayList<>(); + if (param.has("keys")) { + JSONArray jsonArray = param.getJSONArray("keys"); + for (int i = 0; i < jsonArray.length(); i++) { + keys.add(jsonArray.getString(i)); + } + } + EMValueWrapperCallBack callback = new EMValueWrapperCallBack>>(result, channelName) { + @Override + public void onSuccess(Map> object) { + updateObject(object); + } + }; + + EMClient.getInstance().groupManager().asyncFetchGroupMembersAttributes(groupId, userIds, keys, callback); + } + private void registerEaseListener() { groupChangeListener = new EMGroupChangeListener() { @@ -828,7 +882,7 @@ public void onWhiteListAdded(String groupId, List whitelist) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupWhiteListAdded"); + data.put("type", "onGroupWhiteListAdded"); data.put("groupId", groupId); data.put("whitelist", whitelist); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -841,7 +895,7 @@ public void onWhiteListRemoved(String groupId, List whitelist) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupWhiteListRemoved"); + data.put("type", "onGroupWhiteListRemoved"); data.put("groupId", groupId); data.put("whitelist", whitelist); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -854,7 +908,7 @@ public void onAllMemberMuteStateChanged(String groupId, boolean isMuted) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupAllMemberMuteStateChanged"); + data.put("type", "onGroupAllMemberMuteStateChanged"); data.put("groupId", groupId); data.put("isMuted", isMuted); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -867,7 +921,7 @@ public void onInvitationReceived(String groupId, String groupName, String invite EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupInvitationReceived"); + data.put("type", "onGroupInvitationReceived"); data.put("groupId", groupId); data.put("groupName", groupName); data.put("inviter", inviter); @@ -882,7 +936,7 @@ public void onRequestToJoinReceived(String groupId, String groupName, String app EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupRequestToJoinReceived"); + data.put("type", "onGroupRequestToJoinReceived"); data.put("groupId", groupId); data.put("groupName", groupName); data.put("applicant", applicant); @@ -898,7 +952,7 @@ public void onRequestToJoinAccepted(String groupId, String groupName, String acc EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupRequestToJoinAccepted"); + data.put("type", "onGroupRequestToJoinAccepted"); data.put("groupId", groupId); data.put("groupName", groupName); data.put("accepter", accepter); @@ -913,7 +967,7 @@ public void onRequestToJoinDeclined(String groupId, String groupName, String dec EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupRequestToJoinDeclined"); + data.put("type", "onGroupRequestToJoinDeclined"); data.put("groupId", groupId); data.put("groupName", groupName); data.put("decliner", decliner); @@ -929,7 +983,7 @@ public void onInvitationAccepted(String groupId, String invitee, String reason) EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupInvitationAccepted"); + data.put("type", "onGroupInvitationAccepted"); data.put("groupId", groupId); data.put("invitee", invitee); data.put("reason", reason); @@ -944,7 +998,7 @@ public void onInvitationDeclined(String groupId, String invitee, String reason) EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupInvitationDeclined"); + data.put("type", "onGroupInvitationDeclined"); data.put("groupId", groupId); data.put("invitee", invitee); data.put("reason", reason); @@ -959,7 +1013,7 @@ public void onUserRemoved(String groupId, String groupName) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupUserRemoved"); + data.put("type", "onGroupUserRemoved"); data.put("groupId", groupId); data.put("groupName", groupName); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -973,7 +1027,7 @@ public void onGroupDestroyed(String groupId, String groupName) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupDestroyed"); + data.put("type", "onGroupDestroyed"); data.put("groupId", groupId); data.put("groupName", groupName); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -987,7 +1041,7 @@ public void onAutoAcceptInvitationFromGroup(String groupId, String inviter, Stri EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupAutoAcceptInvitation"); + data.put("type", "onGroupAutoAcceptInvitation"); data.put("groupId", groupId); data.put("inviter", inviter); data.put("inviteMessage", inviteMessage); @@ -1002,7 +1056,7 @@ public void onMuteListAdded(String groupId, List mutes, long muteExpire) EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupMuteListAdded"); + data.put("type", "onGroupMuteListAdded"); data.put("groupId", groupId); data.put("mutes", mutes); data.put("muteExpire", muteExpire); @@ -1017,7 +1071,7 @@ public void onMuteListRemoved(String groupId, List mutes) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupMuteListRemoved"); + data.put("type", "onGroupMuteListRemoved"); data.put("groupId", groupId); data.put("mutes", mutes); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -1030,7 +1084,7 @@ public void onAdminAdded(String groupId, String administrator) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupAdminAdded"); + data.put("type", "onGroupAdminAdded"); data.put("groupId", groupId); data.put("administrator", administrator); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -1043,7 +1097,7 @@ public void onAdminRemoved(String groupId, String administrator) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupAdminRemoved"); + data.put("type", "onGroupAdminRemoved"); data.put("groupId", groupId); data.put("administrator", administrator); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -1056,7 +1110,7 @@ public void onOwnerChanged(String groupId, String newOwner, String oldOwner) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupOwnerChanged"); + data.put("type", "onGroupOwnerChanged"); data.put("groupId", groupId); data.put("newOwner", newOwner); data.put("oldOwner", oldOwner); @@ -1070,7 +1124,7 @@ public void onMemberJoined(String groupId, String member) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupMemberJoined"); + data.put("type", "onGroupMemberJoined"); data.put("groupId", groupId); data.put("member", member); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -1083,7 +1137,7 @@ public void onMemberExited(String groupId, String member) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupMemberExited"); + data.put("type", "onGroupMemberExited"); data.put("groupId", groupId); data.put("member", member); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -1096,7 +1150,7 @@ public void onAnnouncementChanged(String groupId, String announcement) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupAnnouncementChanged"); + data.put("type", "onGroupAnnouncementChanged"); data.put("groupId", groupId); data.put("announcement", announcement); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -1109,7 +1163,7 @@ public void onSharedFileAdded(String groupId, EMMucSharedFile sharedFile) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupSharedFileAdded"); + data.put("type", "onGroupSharedFileAdded"); data.put("groupId", groupId); data.put("sharedFile", EMMucSharedFileHelper.toJson(sharedFile)); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -1122,7 +1176,7 @@ public void onSharedFileDeleted(String groupId, String fileId) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupSharedFileDeleted"); + data.put("type", "onGroupSharedFileDeleted"); data.put("groupId", groupId); data.put("fileId", fileId); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); @@ -1135,7 +1189,7 @@ public void onSpecificationChanged(EMGroup group) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupSpecificationDidUpdate"); + data.put("type", "onGroupSpecificationDidUpdate"); data.put("group", EMGroupHelper.toJson(group)); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); } @@ -1147,13 +1201,32 @@ public void onStateChanged(EMGroup group, boolean isDisabled) { EMListenerHandle.getInstance().addHandle( ()-> { Map data = new HashMap<>(); - data.put("type", "groupStateChanged"); + data.put("type", "onGroupStateChanged"); data.put("groupId", group.getGroupId()); data.put("isDisabled", isDisabled); post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); } ); } + + @Override + public void onGroupMemberAttributeChanged(String groupId, String userId, Map attribute, String from) { + EMListenerHandle.getInstance().addHandle( + ()-> { + Map data = new HashMap<>(); + data.put("type", "onGroupAttributesChangedOfMember"); + data.put("groupId", groupId); + data.put("userId", userId); + if (from != null) { + data.put("operatorId", from); + } + if (attribute != null) { + data.put("attributes", attribute); + } + post(() -> channel.invokeMethod(EMSDKMethod.onGroupChanged, data)); + } + ); + } }; EMClient.getInstance().groupManager().addGroupChangeListener(groupChangeListener); } diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java index ee93fe63..12f43d4f 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java @@ -122,6 +122,8 @@ public class EMSDKMethod { static final String getLatestMessage = "getLatestMessage"; static final String getLatestMessageFromOthers = "getLatestMessageFromOthers"; static final String clearAllMessages = "clearAllMessages"; + + static final String deleteMessagesWithTs = "deleteMessagesWithTs"; static final String insertMessage = "insertMessage"; static final String appendMessage = "appendMessage"; static final String updateConversationMessage = "updateConversationMessage"; @@ -223,6 +225,10 @@ public class EMSDKMethod { static final String declineJoinApplication = "declineJoinApplication"; static final String acceptInvitationFromGroup = "acceptInvitationFromGroup"; static final String declineInvitationFromGroup = "declineInvitationFromGroup"; + static final String setMemberAttributesFromGroup = "setMemberAttributesFromGroup"; + static final String fetchMemberAttributesFromGroup = "fetchMemberAttributesFromGroup"; + + static final String fetchMembersAttributesFromGroup = "fetchMembersAttributesFromGroup"; /// EMGroupManagerListener static final String onGroupChanged = "onGroupChanged"; diff --git a/ios/Classes/EMChatManagerWrapper.m b/ios/Classes/EMChatManagerWrapper.m index a8c50af0..e8eb9769 100644 --- a/ios/Classes/EMChatManagerWrapper.m +++ b/ios/Classes/EMChatManagerWrapper.m @@ -470,8 +470,8 @@ - (void)downloadAttachment:(NSDictionary *)param result:(FlutterResult)result { __weak typeof(self) weakSelf = self; __block EMChatMessage *msg = [EMChatMessage fromJson:param[@"message"]]; - EMChatMessage *needDownMSg = [EMClient.sharedClient.chatManager getMessageWithMessageId:msg.messageId]; - [EMClient.sharedClient.chatManager downloadMessageAttachment:needDownMSg + EMChatMessage *needDownMsg = [EMClient.sharedClient.chatManager getMessageWithMessageId:msg.messageId]; + [EMClient.sharedClient.chatManager downloadMessageAttachment:needDownMsg progress:^(int progress) { [weakSelf.messageChannel invokeMethod:ChatOnMessageProgressUpdate @@ -482,13 +482,15 @@ - (void)downloadAttachment:(NSDictionary *)param } completion:^(EMChatMessage *message, EMError *error) { if (error) { + NSDictionary *msgDict = [self updateDownloadStatus:EMDownloadStatusFailed message:message thumbnail:NO]; [weakSelf.messageChannel invokeMethod:ChatOnMessageError arguments:@{ @"error":[error toJson], @"localId": msg.messageId, - @"message":[message toJson] + @"message":msgDict }]; }else { + NSDictionary *msgDict = [self updateDownloadStatus:EMDownloadStatusSucceed message:message thumbnail:NO]; [weakSelf.messageChannel invokeMethod:ChatOnMessageSuccess arguments:@{ @"message":[message toJson], @@ -497,10 +499,66 @@ - (void)downloadAttachment:(NSDictionary *)param } }]; + NSDictionary *msgDict = [self updateDownloadStatus:EMDownloadStatusDownloading message:msg thumbnail:NO]; [weakSelf wrapperCallBack:result channelName:aChannelName error:nil - object:[msg toJson]]; + object:msgDict]; +} + +// 用于修改下载状态。 +- (NSDictionary *)updateDownloadStatus:(EMDownloadStatus)status + message:(EMChatMessage *)msg + thumbnail:(BOOL)isThumbnail +{ + BOOL canUpdate = NO; + switch(msg.body.type){ + case EMMessageBodyTypeFile: + case EMMessageBodyTypeVoice:{ + if(isThumbnail) { + break; + } + } + case EMMessageBodyTypeVideo: + case EMMessageBodyTypeImage:{ + canUpdate = YES; + } + break; + default: + break; + } + + if(canUpdate) { + EMMessageBody *body = msg.body; + if(msg.body.type == EMMessageBodyTypeFile) { + EMFileMessageBody *tmpBody = (EMFileMessageBody *)body; + tmpBody.downloadStatus = status; + body = tmpBody; + }else if(msg.body.type == EMMessageBodyTypeVoice) { + EMVoiceMessageBody *tmpBody = (EMVoiceMessageBody *)body; + tmpBody.downloadStatus = status; + body = tmpBody; + }else if(msg.body.type == EMMessageBodyTypeImage) { + EMImageMessageBody *tmpBody = (EMImageMessageBody *)body; + if(isThumbnail) { + tmpBody.thumbnailDownloadStatus = status; + }else { + tmpBody.downloadStatus = status; + } + body = tmpBody; + }else if(msg.body.type == EMMessageBodyTypeVideo) { + EMVideoMessageBody *tmpBody = (EMVideoMessageBody *)body; + if(isThumbnail) { + tmpBody.thumbnailDownloadStatus = status; + }else { + tmpBody.downloadStatus = status; + } + body = tmpBody; + } + msg.body = body; + } + NSMutableDictionary *msgDict = [[msg toJson] mutableCopy]; + return msgDict; } - (void)downloadThumbnail:(NSDictionary *)param @@ -508,8 +566,8 @@ - (void)downloadThumbnail:(NSDictionary *)param result:(FlutterResult)result { __weak typeof(self) weakSelf = self; __block EMChatMessage *msg = [EMChatMessage fromJson:param[@"message"]]; - EMChatMessage *needDownMSg = [EMClient.sharedClient.chatManager getMessageWithMessageId:msg.messageId]; - [EMClient.sharedClient.chatManager downloadMessageThumbnail:needDownMSg + EMChatMessage *needDownMsg = [EMClient.sharedClient.chatManager getMessageWithMessageId:msg.messageId]; + [EMClient.sharedClient.chatManager downloadMessageThumbnail:needDownMsg progress:^(int progress) { [weakSelf.messageChannel invokeMethod:ChatOnMessageProgressUpdate diff --git a/ios/Classes/EMChatMessage+Helper.h b/ios/Classes/EMChatMessage+Helper.h index 6b23ab8e..71bad6fd 100644 --- a/ios/Classes/EMChatMessage+Helper.h +++ b/ios/Classes/EMChatMessage+Helper.h @@ -22,8 +22,8 @@ NS_ASSUME_NONNULL_BEGIN + (EMMessageBody *)fromJson:(NSDictionary *)aJson; - (NSDictionary *)toJson; + (EMMessageBodyType)typeFromString:(NSString *)aStrType; - - ++ (EMDownloadStatus)downloadStatusFromInt:(int)aStatus; ++ (int)downloadStatusToInt:(EMDownloadStatus)aStatus; @end NS_ASSUME_NONNULL_END diff --git a/ios/Classes/EMChatMessage+Helper.m b/ios/Classes/EMChatMessage+Helper.m index 006b3e4d..83dfddf1 100644 --- a/ios/Classes/EMChatMessage+Helper.m +++ b/ios/Classes/EMChatMessage+Helper.m @@ -265,6 +265,51 @@ + (EMMessageBodyType)typeFromString:(NSString *)aStrType { return ret; } + ++ (EMDownloadStatus)downloadStatusFromInt:(int)aStatus { + EMDownloadStatus ret = EMDownloadStatusPending; + switch (aStatus) { + case 0: + ret = EMDownloadStatusDownloading; + break; + case 1: + ret = EMDownloadStatusSucceed; + break; + case 2: + ret = EMDownloadStatusFailed; + break; + case 3: + ret = EMDownloadStatusPending; + break; + default: + break; + } + + return ret; +} + ++ (int)downloadStatusToInt:(EMDownloadStatus)aStatus { + int ret = 0; + switch (aStatus) { + case EMDownloadStatusDownloading: + ret = 0; + break; + case EMDownloadStatusSucceed: + ret = 1; + break; + case EMDownloadStatusFailed: + ret = 2; + break; + case EMDownloadStatusPending: + ret = 3; + break; + default: + break; + } + return ret; +} + + @end #pragma mark - txt @@ -407,7 +452,7 @@ + (EMMessageBody *)fromJson:(NSDictionary *)aJson { ret.secretKey = aJson[@"secret"]; ret.remotePath = aJson[@"remotePath"]; ret.fileLength = [aJson[@"fileSize"] longLongValue]; - ret.downloadStatus = [ret downloadStatusFromInt:[aJson[@"fileStatus"] intValue]]; + ret.downloadStatus = [EMMessageBody downloadStatusFromInt:[aJson[@"fileStatus"] intValue]]; return ret; } @@ -418,52 +463,10 @@ - (NSDictionary *)toJson { ret[@"secret"] = self.secretKey; ret[@"remotePath"] = self.remotePath; ret[@"fileSize"] = @(self.fileLength); - ret[@"fileStatus"] = @([self downloadStatusToInt:self.downloadStatus]); + ret[@"fileStatus"] = @([EMMessageBody downloadStatusToInt:self.downloadStatus]); return ret; } -- (EMDownloadStatus)downloadStatusFromInt:(int)aStatus { - EMDownloadStatus ret = EMDownloadStatusPending; - switch (aStatus) { - case 0: - ret = EMDownloadStatusDownloading; - break; - case 1: - ret = EMDownloadStatusSucceed; - break; - case 2: - ret = EMDownloadStatusFailed; - break; - case 3: - ret = EMDownloadStatusPending; - break; - default: - break; - } - - return ret; -} - -- (int)downloadStatusToInt:(EMDownloadStatus)aStatus { - int ret = 0; - switch (aStatus) { - case EMDownloadStatusDownloading: - ret = 0; - break; - case EMDownloadStatusSucceed: - ret = 1; - break; - case EMDownloadStatusFailed: - ret = 2; - break; - case EMDownloadStatusPending: - ret = 3; - break; - default: - break; - } - return ret; -} @end @@ -485,12 +488,12 @@ + (EMMessageBody *)fromJson:(NSDictionary *)aJson { ret.secretKey = aJson[@"secret"]; ret.remotePath = aJson[@"remotePath"]; ret.fileLength = [aJson[@"fileSize"] longLongValue]; - ret.downloadStatus = [ret downloadStatusFromInt:[aJson[@"fileStatus"] intValue]]; + ret.downloadStatus = [EMMessageBody downloadStatusFromInt:[aJson[@"fileStatus"] intValue]]; ret.thumbnailLocalPath = aJson[@"thumbnailLocalPath"]; ret.thumbnailRemotePath = aJson[@"thumbnailRemotePath"]; ret.thumbnailSecretKey = aJson[@"thumbnailSecret"]; ret.size = CGSizeMake([aJson[@"width"] floatValue], [aJson[@"height"] floatValue]); - ret.thumbnailDownloadStatus = [ret downloadStatusFromInt:[aJson[@"thumbnailStatus"] intValue]]; + ret.thumbnailDownloadStatus = [EMMessageBody downloadStatusFromInt:[aJson[@"thumbnailStatus"] intValue]]; ret.compressionRatio = [aJson[@"sendOriginalImage"] boolValue] ? 1.0 : 0.6; return ret; } @@ -500,8 +503,8 @@ - (NSDictionary *)toJson { ret[@"thumbnailLocalPath"] = self.thumbnailLocalPath; ret[@"thumbnailRemotePath"] = self.thumbnailRemotePath; ret[@"thumbnailSecret"] = self.thumbnailSecretKey; - ret[@"thumbnailStatus"] = @([self downloadStatusToInt:self.thumbnailDownloadStatus]); - ret[@"fileStatus"] = @([self downloadStatusToInt:self.downloadStatus]); + ret[@"thumbnailStatus"] = @([EMMessageBody downloadStatusToInt:self.thumbnailDownloadStatus]); + ret[@"fileStatus"] = @([EMMessageBody downloadStatusToInt:self.downloadStatus]); ret[@"width"] = @(self.size.width); ret[@"height"] = @(self.size.height); ret[@"fileSize"] = @(self.fileLength); @@ -533,7 +536,7 @@ + (EMVideoMessageBody *)fromJson:(NSDictionary *)aJson { ret.thumbnailLocalPath = aJson[@"thumbnailLocalPath"]; ret.thumbnailRemotePath = aJson[@"thumbnailRemotePath"]; ret.thumbnailSecretKey = aJson[@"thumbnailSecret"]; - ret.thumbnailDownloadStatus = [ret downloadStatusFromInt:[aJson[@"thumbnailStatus"] intValue]]; + ret.thumbnailDownloadStatus = [EMMessageBody downloadStatusFromInt:[aJson[@"thumbnailStatus"] intValue]]; ret.thumbnailSize = CGSizeMake([aJson[@"width"] floatValue], [aJson[@"height"] floatValue]); return ret; } @@ -546,7 +549,7 @@ - (NSDictionary *)toJson { ret[@"remotePath"] = self.remotePath; ret[@"thumbnailRemotePath"] = self.thumbnailRemotePath; ret[@"thumbnailSecretKey"] = self.thumbnailSecretKey; - ret[@"thumbnailStatus"] = @([self downloadStatusToInt:self.thumbnailDownloadStatus]); + ret[@"thumbnailStatus"] = @([EMMessageBody downloadStatusToInt:self.thumbnailDownloadStatus]); ret[@"width"] = @(self.thumbnailSize.width); ret[@"height"] = @(self.thumbnailSize.height); ret[@"fileSize"] = @(self.fileLength); @@ -571,7 +574,7 @@ + (EMVoiceMessageBody *)fromJson:(NSDictionary *)aJson { ret.secretKey = aJson[@"secret"]; ret.remotePath = aJson[@"remotePath"]; ret.duration = [aJson[@"duration"] intValue]; - ret.downloadStatus = [ret downloadStatusFromInt:[aJson[@"fileStatus"] intValue]]; + ret.downloadStatus = [EMMessageBody downloadStatusFromInt:[aJson[@"fileStatus"] intValue]]; return ret; } @@ -583,7 +586,7 @@ - (NSDictionary *)toJson { ret[@"fileSize"] = @(self.fileLength); ret[@"secret"] = self.secretKey; ret[@"remotePath"] = self.remotePath; - ret[@"fileStatus"] = @([self downloadStatusToInt:self.downloadStatus]);; + ret[@"fileStatus"] = @([EMMessageBody downloadStatusToInt:self.downloadStatus]);; return ret; } diff --git a/ios/Classes/EMChatroomManagerWrapper.m b/ios/Classes/EMChatroomManagerWrapper.m index 72b687b3..86609eae 100644 --- a/ios/Classes/EMChatroomManagerWrapper.m +++ b/ios/Classes/EMChatroomManagerWrapper.m @@ -667,7 +667,7 @@ - (void)unMuteAllChatRoomMembers:(NSDictionary *)param channelName:(NSString *)a }]; } -- (void)fetchChatRoomAttributes:(NSDictionary *)param channelName:(NSString *)channel result:(FlutterResult)result { +- (void)fetchChatRoomAttributes:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { NSString *roomId = param[@"roomId"]; NSArray *keys = param[@"keys"]; __weak typeof(self) weakSelf = self; @@ -675,14 +675,14 @@ - (void)fetchChatRoomAttributes:(NSDictionary *)param channelName:(NSString *)ch keys:keys completion:^(EMError * _Nullable aError, NSDictionary * _Nullable properties) { [weakSelf wrapperCallBack:result - channelName:channel + channelName:aChannelName error:aError object:properties]; }]; } -- (void)setChatRoomAttributes:(NSDictionary *)param channelName:(NSString *)channel result:(FlutterResult)result { +- (void)setChatRoomAttributes:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { NSString *roomId = param[@"roomId"]; NSDictionary *attributes = param[@"attributes"]; BOOL autoDelete = [param[@"autoDelete"] boolValue]; @@ -695,7 +695,7 @@ - (void)setChatRoomAttributes:(NSDictionary *)param channelName:(NSString *)chan tmp[key] = @(failureKeys[key].code); } [weakSelf wrapperCallBack:result - channelName:channel + channelName:aChannelName error:tmp.count == 0 ? error : nil object:tmp]; }; @@ -711,7 +711,7 @@ - (void)setChatRoomAttributes:(NSDictionary *)param channelName:(NSString *)chan } } -- (void)removeChatRoomAttributes:(NSDictionary *)param channelName:(NSString *)channel result:(FlutterResult)result { +- (void)removeChatRoomAttributes:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { NSString *roomId = param[@"roomId"]; NSArray *keys = param[@"keys"]; BOOL forced = [param[@"forced"] boolValue]; @@ -724,7 +724,7 @@ - (void)removeChatRoomAttributes:(NSDictionary *)param channelName:(NSString *)c tmp[key] = @(failureKeys[key].code); } [weakSelf wrapperCallBack:result - channelName:channel + channelName:aChannelName error:tmp.count == 0 ? error : nil object:tmp]; }; @@ -753,7 +753,7 @@ - (void)userDidJoinChatroom:(EMChatroom *)aChatroom __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomMemberJoined", + @"type":@"onRoomMemberJoined", @"roomId":aChatroom.chatroomId, @"participant":aUsername }; @@ -767,7 +767,7 @@ - (void)userDidLeaveChatroom:(EMChatroom *)aChatroom __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomMemberExited", + @"type":@"onRoomMemberExited", @"roomId":aChatroom.chatroomId, @"roomName":aChatroom.subject, @"participant":aUsername @@ -784,14 +784,14 @@ - (void)didDismissFromChatroom:(EMChatroom *)aChatroom NSString *type; NSDictionary *map; if (aReason == EMChatroomBeKickedReasonDestroyed) { - type = @"chatroomDestroyed"; + type = @"onRoomDestroyed"; map = @{ @"type":type, @"roomId":aChatroom.chatroomId, @"roomName":aChatroom.subject }; } else if (aReason == EMChatroomBeKickedReasonBeRemoved) { - type = @"chatroomRemoved"; + type = @"onRoomRemoved"; map = @{ @"type":type, @"roomId":aChatroom.chatroomId, @@ -811,7 +811,7 @@ - (void)chatroomMuteListDidUpdate:(EMChatroom *)aChatroom __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomMuteListAdded", + @"type":@"onRoomMuteListAdded", @"roomId":aChatroom.chatroomId, @"mutes":aMutes, @"expireTime":[NSString stringWithFormat:@"%ld", (long)aMuteExpire] @@ -826,7 +826,7 @@ - (void)chatroomMuteListDidUpdate:(EMChatroom *)aChatroom __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomMuteListRemoved", + @"type":@"onRoomMuteListRemoved", @"roomId":aChatroom.chatroomId, @"mutes":aMutes }; @@ -840,7 +840,7 @@ - (void)chatroomAdminListDidUpdate:(EMChatroom *)aChatroom __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomAdminAdded", + @"type":@"onRoomAdminAdded", @"roomId":aChatroom.chatroomId, @"admin":aAdmin }; @@ -854,7 +854,7 @@ - (void)chatroomAdminListDidUpdate:(EMChatroom *)aChatroom __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomAdminRemoved", + @"type":@"onRoomAdminRemoved", @"roomId":aChatroom.chatroomId, @"admin":aAdmin }; @@ -869,7 +869,7 @@ - (void)chatroomOwnerDidUpdate:(EMChatroom *)aChatroom __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomOwnerChanged", + @"type":@"onRoomOwnerChanged", @"roomId":aChatroom.chatroomId, @"newOwner":aNewOwner, @"oldOwner":aOldOwner @@ -883,7 +883,7 @@ - (void)chatroomAnnouncementDidUpdate:(EMChatroom *)aChatroom __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomAnnouncementChanged", + @"type":@"onRoomAnnouncementChanged", @"roomId":aChatroom.chatroomId, @"announcement":aAnnouncement }; @@ -897,7 +897,7 @@ - (void)chatroomWhiteListDidUpdate:(EMChatroom *)aChatroom __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomWhiteListAdded", + @"type":@"onRoomWhiteListAdded", @"roomId":aChatroom.chatroomId, @"whitelist":aMembers }; @@ -912,7 +912,7 @@ - (void)chatroomWhiteListDidUpdate:(EMChatroom *)aChatroom __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomWhiteListRemoved", + @"type":@"onRoomWhiteListRemoved", @"roomId":aChatroom.chatroomId, @"whitelist":aMembers }; @@ -927,7 +927,7 @@ - (void)chatroomAllMemberMuteChanged:(EMChatroom *)aChatroom __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomAllMemberMuteStateChanged", + @"type":@"onRoomAllMemberMuteStateChanged", @"roomId":aChatroom.chatroomId, @"isMuted":@(aMuted) }; @@ -939,7 +939,7 @@ - (void)chatroomSpecificationDidUpdate:(EMChatroom *)aChatroom { __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomSpecificationChanged", + @"type":@"onRoomSpecificationChanged", @"room":[aChatroom toJson] }; [weakSelf.channel invokeMethod:ChatChatroomChanged arguments:map]; @@ -952,7 +952,7 @@ - (void)chatroomAttributesDidUpdated:(NSString *)roomId __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomAttributesDidUpdated", + @"type":@"onRoomAttributesDidUpdated", @"roomId":roomId, @"attributes":attributeMap, @"fromId": fromId @@ -966,7 +966,7 @@ - (void)chatroomAttributesDidRemoved:(NSString *)roomId __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"chatroomAttributesDidRemoved", + @"type":@"onRoomAttributesDidRemoved", @"roomId":roomId, @"keys":attributes, @"fromId": fromId diff --git a/ios/Classes/EMConversationWrapper.m b/ios/Classes/EMConversationWrapper.m index ff34f93a..2d41cb95 100644 --- a/ios/Classes/EMConversationWrapper.m +++ b/ios/Classes/EMConversationWrapper.m @@ -81,6 +81,10 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { [self clearAllMessages:call.arguments channelName:call.method result:result]; + } else if ([ChatDeleteMessagesWithTs isEqualToString:call.method]) { + [self deleteMessagesWithTs:call.arguments + channelName:call.method + result:result]; } else if ([ChatInsertMsg isEqualToString:call.method]) { [self insertMessage:call.arguments channelName:call.method @@ -330,6 +334,21 @@ - (void)clearAllMessages:(NSDictionary *)param channelName:(NSString *)aChannelN }]; } +- (void)deleteMessagesWithTs:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result +{ + __weak typeof(self) weakSelf = self; + int startTs = [param[@"startTs"] intValue]; + int endTs = [param[@"endTs"] intValue]; + [self getConversationWithParam:param + completion:^(EMConversation *conversation){ + EMError *error = [conversation removeMessagesStart:startTs to:endTs]; + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:error + object:@(!error)]; + }]; +} + - (void)removeMsgFromServerWithMsgList:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self) weakSelf = self; diff --git a/ios/Classes/EMGroupManagerWrapper.m b/ios/Classes/EMGroupManagerWrapper.m index f5920656..d3d1bdfa 100644 --- a/ios/Classes/EMGroupManagerWrapper.m +++ b/ios/Classes/EMGroupManagerWrapper.m @@ -302,7 +302,15 @@ - (void)handleMethodCall:(FlutterMethodCall*)call channelName:call.method result:result]; } - + else if ([ChatSetMemberAttributesFromGroup isEqualToString:call.method]) { + [self setMemberAttributes:call.arguments channelName:call.method result:result]; + } + else if ([ChatFetchMemberAttributesFromGroup isEqualToString:call.method]) { + [self fetchMemberAttributes:call.arguments channelName:call.method result:result]; + } + else if ([ChatFetchMembersAttributesFromGroup isEqualToString:call.method]) { + [self fetchMembersAttributes:call.arguments channelName:call.method result:result]; + } else { [super handleMethodCall:call result:result]; @@ -921,6 +929,58 @@ - (void)declineInvitationFromGroup:(NSDictionary *)param channelName:(NSString * }]; } +- (void)setMemberAttributes:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { + __weak typeof(self) weakSelf = self; + + NSString *groupId = param[@"groupId"]; + NSString *userId = param[@"userId"]; + NSDictionary *attributes = param[@"attributes"]; + + [EMClient.sharedClient.groupManager setMemberAttribute:groupId + userId:userId + attributes:attributes + completion:^(EMError * _Nullable error) + { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:error + object:nil]; + }]; +} + +- (void)fetchMemberAttributes:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { + __weak typeof(self) weakSelf = self; + + NSString *groupId = param[@"groupId"]; + NSString *userId = param[@"userId"]; + + [EMClient.sharedClient.groupManager fetchMemberAttribute:groupId + userId:userId + completion:^(NSDictionary * properties, EMError * aError) + { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:aError + object:properties]; + }]; +} + +- (void)fetchMembersAttributes:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { + __weak typeof(self) weakSelf = self; + + NSString *groupId = param[@"groupId"]; + NSArray *userIds = param[@"userIds"]; + NSArray *keys = param[@"keys"]; + + [EMClient.sharedClient.groupManager fetchMembersAttributes:groupId userIds:userIds keys:keys completion:^(NSDictionary *> * _Nullable attributes, EMError * _Nullable error) { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:error + object:attributes]; + }]; +} + + #pragma mark - EMGroupManagerDelegate @@ -934,7 +994,7 @@ - (void)groupInvitationDidReceive:(NSString *)aGroupId __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupInvitationReceived", + @"type":@"onGroupInvitationReceived", @"groupId":aGroupId, @"groupName": aGroupName, @"inviter":aInviter, @@ -953,7 +1013,7 @@ - (void)groupInvitationDidAccept:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupInvitationAccepted", + @"type":@"onGroupInvitationAccepted", @"groupId":aGroup.groupId, @"invitee":aInvitee }; @@ -971,7 +1031,7 @@ - (void)groupInvitationDidDecline:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupInvitationDeclined", + @"type":@"onGroupInvitationDeclined", @"groupId":aGroup.groupId, @"invitee":aInvitee, @"reason":aReason @@ -989,7 +1049,7 @@ - (void)didJoinGroup:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupAutoAcceptInvitation", + @"type":@"onGroupAutoAcceptInvitation", @"groupId":aGroup.groupId, @"message":aMessage, @"inviter":aInviter @@ -1007,9 +1067,9 @@ - (void)didLeaveGroup:(EMGroup *)aGroup [EMListenerHandle.sharedInstance addHandle:^{ NSString *type; if (aReason == EMGroupLeaveReasonBeRemoved) { - type = @"groupUserRemoved"; + type = @"onGroupUserRemoved"; } else if (aReason == EMGroupLeaveReasonDestroyed) { - type = @"groupDestroyed"; + type = @"onGroupDestroyed"; } NSDictionary *map = @{ @"type":type, @@ -1030,7 +1090,7 @@ - (void)joinGroupRequestDidReceive:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupRequestToJoinReceived", + @"type":@"onGroupRequestToJoinReceived", @"groupId":aGroup.groupId, @"applicant":aUsername, @"reason":aReason @@ -1047,7 +1107,7 @@ - (void)joinGroupRequestDidDecline:(NSString *)aGroupId __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupRequestToJoinDeclined", + @"type":@"onGroupRequestToJoinDeclined", @"groupId":aGroupId, @"reason":aReason }; @@ -1062,7 +1122,7 @@ - (void)joinGroupRequestDidApprove:(EMGroup *)aGroup { __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupRequestToJoinAccepted", + @"type":@"onGroupRequestToJoinAccepted", @"groupId":aGroup.groupId, @"groupName":aGroup.groupName, @"accepter":aGroup.owner, @@ -1080,7 +1140,7 @@ - (void)groupMuteListDidUpdate:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupMuteListAdded", + @"type":@"onGroupMuteListAdded", @"groupId":aGroup.groupId, @"mutes":aMutedMembers, @"muteExpire":[NSNumber numberWithInteger:aMuteExpire] @@ -1095,7 +1155,7 @@ - (void)groupMuteListDidUpdate:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupMuteListRemoved", + @"type":@"onGroupMuteListRemoved", @"groupId":aGroup.groupId, @"mutes":aMutedMembers }; @@ -1111,7 +1171,7 @@ - (void)groupWhiteListDidUpdate:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupWhiteListAdded", + @"type":@"onGroupWhiteListAdded", @"groupId":aGroup.groupId, @"whitelist":aMembers }; @@ -1127,7 +1187,7 @@ - (void)groupWhiteListDidUpdate:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupWhiteListRemoved", + @"type":@"onGroupWhiteListRemoved", @"groupId":aGroup.groupId, @"whitelist":aMembers }; @@ -1143,7 +1203,7 @@ - (void)groupAllMemberMuteChanged:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupAllMemberMuteStateChanged", + @"type":@"onGroupAllMemberMuteStateChanged", @"groupId":aGroup.groupId, @"isMuted":@(aMuted) }; @@ -1159,7 +1219,7 @@ - (void)groupAdminListDidUpdate:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupAdminAdded", + @"type":@"onGroupAdminAdded", @"groupId":aGroup.groupId, @"administrator":aAdmin }; @@ -1175,7 +1235,7 @@ - (void)groupAdminListDidUpdate:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupAdminRemoved", + @"type":@"onGroupAdminRemoved", @"groupId":aGroup.groupId, @"administrator":aAdmin }; @@ -1192,7 +1252,7 @@ - (void)groupOwnerDidUpdate:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupOwnerChanged", + @"type":@"onGroupOwnerChanged", @"groupId":aGroup.groupId, @"newOwner":aNewOwner, @"oldOwner":aOldOwner @@ -1209,7 +1269,7 @@ - (void)userDidJoinGroup:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupMemberJoined", + @"type":@"onGroupMemberJoined", @"groupId":aGroup.groupId, @"member":aUsername }; @@ -1225,7 +1285,7 @@ - (void)userDidLeaveGroup:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupMemberExited", + @"type":@"onGroupMemberExited", @"groupId":aGroup.groupId, @"member":aUsername }; @@ -1241,7 +1301,7 @@ - (void)groupAnnouncementDidUpdate:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupAnnouncementChanged", + @"type":@"onGroupAnnouncementChanged", @"groupId":aGroup.groupId, @"announcement":aAnnouncement }; @@ -1257,7 +1317,7 @@ - (void)groupFileListDidUpdate:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupSharedFileAdded", + @"type":@"onGroupSharedFileAdded", @"groupId":aGroup.groupId, @"sharedFile":[aSharedFile toJson] }; @@ -1271,7 +1331,7 @@ - (void)groupFileListDidUpdate:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupSharedFileDeleted", + @"type":@"onGroupSharedFileDeleted", @"groupId":aGroup.groupId, @"fileId":aFileId }; @@ -1280,12 +1340,29 @@ - (void)groupFileListDidUpdate:(EMGroup *)aGroup }]; } +- (void)onAttributesChangedOfGroupMember:(NSString *)groupId + userId:(NSString *)userId + attributes:(NSDictionary *)attributes + operatorId:(NSString *)operatorId{ + __weak typeof(self) weakSelf = self; + [EMListenerHandle.sharedInstance addHandle:^{ + NSDictionary *map = @{ + @"type":@"onGroupAttributesChangedOfMember", + @"groupId":groupId, + @"userId":userId, + @"attributes": attributes, + @"operatorId": operatorId + }; + [weakSelf.channel invokeMethod:ChatOnGroupChanged + arguments:map]; + }]; +} - (void)groupSpecificationDidUpdate:(EMGroup *)aGroup { __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupSpecificationDidUpdate", + @"type":@"onGroupSpecificationDidUpdate", @"group": [aGroup toJson] }; [weakSelf.channel invokeMethod:ChatOnGroupChanged @@ -1297,7 +1374,7 @@ - (void)groupStateChanged:(EMGroup *)aGroup __weak typeof(self) weakSelf = self; [EMListenerHandle.sharedInstance addHandle:^{ NSDictionary *map = @{ - @"type":@"groupStateChanged", + @"type":@"onGroupStateChanged", @"groupId":aGroup.groupId, @"isDisabled":@(aDisabled) }; diff --git a/ios/Classes/EMSDKMethod.h b/ios/Classes/EMSDKMethod.h index c4ab5b6f..76399c36 100644 --- a/ios/Classes/EMSDKMethod.h +++ b/ios/Classes/EMSDKMethod.h @@ -134,6 +134,7 @@ static NSString *const ChatRemoveMsg = @"removeMessage"; static NSString *const ChatGetLatestMsg = @"getLatestMessage"; static NSString *const ChatGetLatestMsgFromOthers = @"getLatestMessageFromOthers"; static NSString *const ChatClearAllMsg = @"clearAllMessages"; +static NSString *const ChatDeleteMessagesWithTs = @"deleteMessagesWithTs"; static NSString *const ChatInsertMsg = @"insertMessage"; static NSString *const ChatAppendMsg = @"appendMessage"; static NSString *const ChatUpdateConversationMsg = @"updateConversationMessage"; @@ -238,6 +239,9 @@ static NSString *const ChatAcceptJoinApplication = @"acceptJoinApplication"; static NSString *const ChatDeclineJoinApplication = @"declineJoinApplication"; static NSString *const ChatAcceptInvitationFromGroup = @"acceptInvitationFromGroup"; static NSString *const ChatDeclineInvitationFromGroup = @"declineInvitationFromGroup"; +static NSString *const ChatSetMemberAttributesFromGroup = @"setMemberAttributesFromGroup"; +static NSString *const ChatFetchMemberAttributesFromGroup = @"fetchMemberAttributesFromGroup"; +static NSString *const ChatFetchMembersAttributesFromGroup = @"fetchMembersAttributesFromGroup"; static NSString *const ChatOnGroupChanged = @"onGroupChanged"; diff --git a/lib/src/em_group_manager.dart b/lib/src/em_group_manager.dart index 1c5ab922..4e4d12d8 100644 --- a/lib/src/em_group_manager.dart +++ b/lib/src/em_group_manager.dart @@ -1841,6 +1841,105 @@ class EMGroupManager { } } + /// ~english + /// Sets custom attributes of a group member. + /// + /// Param [groupId] The group ID. + /// + /// Param [userId] The user ID of the group member for whom the custom attributes are set. + /// + /// Param [attributes] The map of custom attributes in key-value format. In a key-value pair, + /// if the value is set to an empty string, the custom attribute will be deleted. + /// + /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 设置群成员自定义属性。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [userId] 要设置自定义属性的群成员的用户 ID。 + /// + /// Param [attributes] 要设置的群成员自定义属性的 map,为 key-value 格式。对于一个 key-value 键值对,若 value 设置空字符串即删除该自定义属性。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end + Future setMemberAttributes({ + required String groupId, + required String userId, + required Map attributes, + }) async { + Map req = {'groupId': groupId, 'userId': userId}; + req.add('attributes', attributes); + Map result = await _channel.invokeMethod( + ChatMethodKeys.setMemberAttributesFromGroup, req); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } + } + + /// ~english + /// Gets all custom attributes of a group member. + /// + /// Param [groupId] The group ID. + /// + /// Param [userId] The user ID of the group member whose all custom attributes are retrieved. + /// + /// **Return** The user attributes. + /// + /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 获取单个群成员所有自定义属性。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [userId] 要获取的自定义属性的群成员的用户 ID。 + /// + /// **Return** 需要查询的用户属性。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end + Future?> fetchMemberAttributes({ + required String groupId, + required String userId, + }) async { + Map req = {'groupId': groupId, 'userId': userId}; + Map result = await _channel.invokeMethod( + ChatMethodKeys.fetchMemberAttributesFromGroup, req); + try { + EMError.hasErrorFromResult(result); + return result[ChatMethodKeys.fetchMemberAttributesFromGroup] + ?.cast(); + } on EMError catch (e) { + throw e; + } + } + + Future>?> fetchMembersAttributes({ + required String groupId, + required List userIds, + List? keys, + }) async { + Map req = {'groupId': groupId, 'userIds': userIds}; + req.add("keys", keys); + Map result = await _channel.invokeMethod( + ChatMethodKeys.fetchMembersAttributesFromGroup, req); + try { + EMError.hasErrorFromResult(result); + + // TODO: 需要验证 + return result[ChatMethodKeys.fetchMembersAttributesFromGroup] + ?.cast>>(); + } on EMError catch (e) { + throw e; + } + } + Future _onGroupChanged(Map? map) async { var type = map!['type']; _eventHandlesMap.values.forEach((element) { @@ -1982,6 +2081,18 @@ class EMGroupManager { bool isDisable = map["isDisabled"] as bool; element.onDisableChanged?.call(groupId, isDisable); break; + case EMGroupChangeEvent.ON_ATTRIBUTES_CHANGED_OF_MEMBER: + String groupId = map["groupId"]; + String userId = map["userId"]; + Map? attributes = + map["attributes"].cast(); + String? operatorId = map["operatorId"]; + element.onAttributesChangedOfGroupMember?.call( + groupId, + userId, + attributes, + operatorId, + ); } }); } diff --git a/lib/src/event_handler/manager_event_handler.dart b/lib/src/event_handler/manager_event_handler.dart index b5c8872a..f3a30cc9 100644 --- a/lib/src/event_handler/manager_event_handler.dart +++ b/lib/src/event_handler/manager_event_handler.dart @@ -1392,6 +1392,37 @@ class EMGroupEventHandler { String? groupName, )? onUserRemovedFromGroup; + /// ~english + /// Occurs when a custom attribute(s) of a group member is/are changed. + /// + /// Param [groupId] The group ID. + /// + /// Param [userId] The user ID of the group member whose custom attributes are changed. + /// + /// Param [attributes] The modified custom attributes, in key-value format. + /// + /// Param [operatorId] The user ID of the operator. + /// + /// ~end + /// + /// ~chinese + /// 群组成员自定义属性有变更。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [userId] 自定义属性变更的群成员的用户 ID。 + /// + /// Param [attributes] 修改后的自定义属性,key-value 格式。 + /// + /// Param [operatorId] 操作者的用户 ID。 + /// ~end + final void Function( + String groupId, + String userId, + Map? attributes, + String? operatorId, + )? onAttributesChangedOfGroupMember; + /// ~english /// The group manager listener callback. /// @@ -1442,6 +1473,8 @@ class EMGroupEventHandler { /// Param [onSpecificationDidUpdate] Occurs when the group detail information is updated. /// /// Param [onDisableChanged] Occurs when the group is enabled or disabled. + /// + /// Param [onAttributesChangedOfGroupMember] Occurs when a custom attribute(s) of a group member is/are changed. /// ~end /// /// ~chinese @@ -1494,6 +1527,8 @@ class EMGroupEventHandler { /// Param [onSpecificationDidUpdate] 群详情变更回调。 /// /// Param [onDisableChanged] 群是禁用状态变更。 + /// + /// Param [onAttributesChangedOfGroupMember] 群组成员自定义属性有变更。 /// ~end EMGroupEventHandler({ this.onAdminAddedFromGroup, @@ -1520,6 +1555,7 @@ class EMGroupEventHandler { this.onUserRemovedFromGroup, this.onSpecificationDidUpdate, this.onDisableChanged, + this.onAttributesChangedOfGroupMember, }); } diff --git a/lib/src/internal/chat_method_keys.dart b/lib/src/internal/chat_method_keys.dart index 41ffadcd..b8a1500b 100644 --- a/lib/src/internal/chat_method_keys.dart +++ b/lib/src/internal/chat_method_keys.dart @@ -137,6 +137,7 @@ class ChatMethodKeys { static const String getLatestMessage = "getLatestMessage"; static const String getLatestMessageFromOthers = "getLatestMessageFromOthers"; static const String clearAllMessages = "clearAllMessages"; + static const String deleteMessagesWithTs = "deleteMessagesWithTs"; static const String insertMessage = "insertMessage"; static const String appendMessage = "appendMessage"; static const String updateConversationMessage = "updateConversationMessage"; @@ -252,6 +253,12 @@ class ChatMethodKeys { static const String declineJoinApplication = "declineJoinApplication"; static const String acceptInvitationFromGroup = "acceptInvitationFromGroup"; static const String declineInvitationFromGroup = "declineInvitationFromGroup"; + static const String setMemberAttributesFromGroup = + "setMemberAttributesFromGroup"; + static const String fetchMemberAttributesFromGroup = + "fetchMemberAttributesFromGroup"; + static const String fetchMembersAttributesFromGroup = + "fetchMembersAttributesFromGroup"; /// EMGroupManagerListener static const String onGroupChanged = "onGroupChanged"; diff --git a/lib/src/internal/em_event_keys.dart b/lib/src/internal/em_event_keys.dart index 88cc591c..fc8f947a 100644 --- a/lib/src/internal/em_event_keys.dart +++ b/lib/src/internal/em_event_keys.dart @@ -9,54 +9,56 @@ class EMContactChangeEvent { /// @nodoc class EMChatRoomEvent { - static const String ON_CHAT_ROOM_DESTROYED = "chatroomDestroyed"; - static const String ON_MEMBER_JOINED = "chatroomMemberJoined"; - static const String ON_MEMBER_EXITED = "chatroomMemberExited"; - static const String ON_REMOVED_FROM_CHAT_ROOM = "chatroomRemoved"; - static const String ON_MUTE_LIST_ADDED = "chatroomMuteListAdded"; - static const String ON_MUTE_LIST_REMOVED = "chatroomMuteListRemoved"; - static const String ON_ADMIN_ADDED = "chatroomAdminAdded"; - static const String ON_ADMIN_REMOVED = "chatroomAdminRemoved"; - static const String ON_OWNER_CHANGED = "chatroomOwnerChanged"; - static const String ON_ANNOUNCEMENT_CHANGED = "chatroomAnnouncementChanged"; - static const String ON_WHITE_LIST_REMOVED = "chatroomWhiteListRemoved"; - static const String ON_WHITE_LIST_ADDED = "chatroomWhiteListAdded"; + static const String ON_CHAT_ROOM_DESTROYED = "onRoomDestroyed"; + static const String ON_MEMBER_JOINED = "onRoomMemberJoined"; + static const String ON_MEMBER_EXITED = "onRoomMemberExited"; + static const String ON_REMOVED_FROM_CHAT_ROOM = "onRoomRemoved"; + static const String ON_MUTE_LIST_ADDED = "onRoomMuteListAdded"; + static const String ON_MUTE_LIST_REMOVED = "onRoomMuteListRemoved"; + static const String ON_ADMIN_ADDED = "onRoomAdminAdded"; + static const String ON_ADMIN_REMOVED = "onRoomAdminRemoved"; + static const String ON_OWNER_CHANGED = "onRoomOwnerChanged"; + static const String ON_ANNOUNCEMENT_CHANGED = "onRoomAnnouncementChanged"; + static const String ON_WHITE_LIST_REMOVED = "onRoomWhiteListRemoved"; + static const String ON_WHITE_LIST_ADDED = "onRoomWhiteListAdded"; static const String ON_ALL_MEMBER_MUTE_STATE_CHANGED = - "chatroomAllMemberMuteStateChanged"; - static const String ON_SPECIFICATION_CHANGED = "chatroomSpecificationChanged"; - static const String ON_ATTRIBUTES_UPDATED = "chatroomAttributesDidUpdated"; - static const String ON_ATTRIBUTES_REMOVED = "chatroomAttributesDidRemoved"; + "onRoomAllMemberMuteStateChanged"; + static const String ON_SPECIFICATION_CHANGED = "onRoomSpecificationChanged"; + static const String ON_ATTRIBUTES_UPDATED = "onRoomAttributesDidUpdated"; + static const String ON_ATTRIBUTES_REMOVED = "onRoomAttributesDidRemoved"; } /// @nodoc class EMGroupChangeEvent { - static const String ON_INVITATION_RECEIVED = "groupInvitationReceived"; - static const String ON_INVITATION_ACCEPTED = "groupInvitationAccepted"; - static const String ON_INVITATION_DECLINED = "groupInvitationDeclined"; - static const String ON_AUTO_ACCEPT_INVITATION = "groupAutoAcceptInvitation"; - static const String ON_USER_REMOVED = "groupUserRemoved"; + static const String ON_INVITATION_RECEIVED = "onGroupInvitationReceived"; + static const String ON_INVITATION_ACCEPTED = "onGroupInvitationAccepted"; + static const String ON_INVITATION_DECLINED = "onGroupInvitationDeclined"; + static const String ON_AUTO_ACCEPT_INVITATION = "onGroupAutoAcceptInvitation"; + static const String ON_USER_REMOVED = "onGroupUserRemoved"; static const String ON_REQUEST_TO_JOIN_RECEIVED = - "groupRequestToJoinReceived"; + "onGroupRequestToJoinReceived"; static const String ON_REQUEST_TO_JOIN_DECLINED = - "groupRequestToJoinDeclined"; + "onGroupRequestToJoinDeclined"; static const String ON_REQUEST_TO_JOIN_ACCEPTED = - "groupRequestToJoinAccepted"; - static const String ON_GROUP_DESTROYED = "groupDestroyed"; - static const String ON_MUTE_LIST_ADDED = "groupMuteListAdded"; - static const String ON_MUTE_LIST_REMOVED = "groupMuteListRemoved"; - static const String ON_ADMIN_ADDED = "groupAdminAdded"; - static const String ON_ADMIN_REMOVED = "groupAdminRemoved"; - static const String ON_OWNER_CHANGED = "groupOwnerChanged"; - static const String ON_MEMBER_JOINED = "groupMemberJoined"; - static const String ON_MEMBER_EXITED = "groupMemberExited"; - static const String ON_ANNOUNCEMENT_CHANGED = "groupAnnouncementChanged"; - static const String ON_SHARED_FILE_ADDED = "groupSharedFileAdded"; - static const String ON_SHARED_FILE__DELETED = "groupSharedFileDeleted"; - static const String ON_WHITE_LIST_REMOVED = "groupWhiteListRemoved"; - static const String ON_WHITE_LIST_ADDED = "groupWhiteListAdded"; + "onGroupRequestToJoinAccepted"; + static const String ON_GROUP_DESTROYED = "onGroupDestroyed"; + static const String ON_MUTE_LIST_ADDED = "onGroupMuteListAdded"; + static const String ON_MUTE_LIST_REMOVED = "onGroupMuteListRemoved"; + static const String ON_ADMIN_ADDED = "onGroupAdminAdded"; + static const String ON_ADMIN_REMOVED = "onGroupAdminRemoved"; + static const String ON_OWNER_CHANGED = "onGroupOwnerChanged"; + static const String ON_MEMBER_JOINED = "onGroupMemberJoined"; + static const String ON_MEMBER_EXITED = "onGroupMemberExited"; + static const String ON_ANNOUNCEMENT_CHANGED = "onGroupAnnouncementChanged"; + static const String ON_SHARED_FILE_ADDED = "onGroupSharedFileAdded"; + static const String ON_SHARED_FILE__DELETED = "onGroupSharedFileDeleted"; + static const String ON_WHITE_LIST_REMOVED = "onGroupWhiteListRemoved"; + static const String ON_WHITE_LIST_ADDED = "onGroupWhiteListAdded"; static const String ON_ALL_MEMBER_MUTE_STATE_CHANGED = - "groupAllMemberMuteStateChanged"; + "onGroupAllMemberMuteStateChanged"; static const String ON_SPECIFICATION_DID_UPDATE = - "groupSpecificationDidUpdate"; - static const String ON_STATE_CHANGED = "groupStateChanged"; + "onGroupSpecificationDidUpdate"; + static const String ON_STATE_CHANGED = "onGroupStateChanged"; + static const String ON_ATTRIBUTES_CHANGED_OF_MEMBER = + "onGroupAttributesChangedOfMember"; } diff --git a/lib/src/models/em_chat_enums.dart b/lib/src/models/em_chat_enums.dart index 8bceb79c..8c206274 100644 --- a/lib/src/models/em_chat_enums.dart +++ b/lib/src/models/em_chat_enums.dart @@ -780,6 +780,16 @@ enum EMMultiDevicesEvent { /// 用户 A 在设备 A1 上将其他用户踢出子区,则设备 A2 上会收到该事件。 /// ~end CHAT_THREAD_KICK, + + /// ~english + /// If user A modifies a custom member attribute on device A1, + /// this event is triggered on another device that the user logs in with the same account. + /// ~end + /// + /// ~chinese + /// 若用户 A 在设备 A1 上修改群成员自定义属性,该事件会在登录该账号的其他设备触发。 + /// ~end + GROUP_MEMBER_ATTRIBUTES_CHANGED, } /// ~english diff --git a/lib/src/models/em_conversation.dart b/lib/src/models/em_conversation.dart index 8afa7bd1..d436fc4b 100644 --- a/lib/src/models/em_conversation.dart +++ b/lib/src/models/em_conversation.dart @@ -411,7 +411,18 @@ class EMConversation { /// /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 /// ~end - Future deleteMessageWithTs(int startTs, int endTs) async {} + Future deleteMessagesWithTs(int startTs, int endTs) async { + Map req = this._toJson(); + req['startTs'] = startTs; + req['endTs'] = endTs; + Map result = await _emConversationChannel.invokeMethod( + ChatMethodKeys.deleteMessagesWithTs, req); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } + } /// ~english /// Gets the message with a specific message ID. From 03c7d10932f26bb369ddaaab63c096d0a0bb9788 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Wed, 17 May 2023 10:45:56 +0800 Subject: [PATCH 09/49] update --- ios/Classes/EMChatManagerWrapper.m | 80 +++++++++++++++--------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/ios/Classes/EMChatManagerWrapper.m b/ios/Classes/EMChatManagerWrapper.m index e8eb9769..bbb8f68d 100644 --- a/ios/Classes/EMChatManagerWrapper.m +++ b/ios/Classes/EMChatManagerWrapper.m @@ -493,7 +493,7 @@ - (void)downloadAttachment:(NSDictionary *)param NSDictionary *msgDict = [self updateDownloadStatus:EMDownloadStatusSucceed message:message thumbnail:NO]; [weakSelf.messageChannel invokeMethod:ChatOnMessageSuccess arguments:@{ - @"message":[message toJson], + @"message":msgDict, @"localId": msg.messageId }]; } @@ -506,6 +506,46 @@ - (void)downloadAttachment:(NSDictionary *)param object:msgDict]; } +- (void)downloadThumbnail:(NSDictionary *)param + channelName:(NSString *)aChannelName + result:(FlutterResult)result { + __weak typeof(self) weakSelf = self; + __block EMChatMessage *msg = [EMChatMessage fromJson:param[@"message"]]; + EMChatMessage *needDownMsg = [EMClient.sharedClient.chatManager getMessageWithMessageId:msg.messageId]; + [EMClient.sharedClient.chatManager downloadMessageThumbnail:needDownMsg + progress:^(int progress) + { + [weakSelf.messageChannel invokeMethod:ChatOnMessageProgressUpdate + arguments:@{ + @"progress":@(progress), + @"localId":msg.messageId + }]; + } completion:^(EMChatMessage *message, EMError *error) + { + if (error) { + NSDictionary *msgDict = [self updateDownloadStatus:EMDownloadStatusFailed message:message thumbnail:YES]; + [weakSelf.messageChannel invokeMethod:ChatOnMessageError + arguments:@{ + @"error":[error toJson], + @"localId":msg.messageId, + @"message":msgDict + }]; + }else { + NSDictionary *msgDict = [self updateDownloadStatus:EMDownloadStatusSucceed message:message thumbnail:YES]; + [weakSelf.messageChannel invokeMethod:ChatOnMessageSuccess + arguments:@{ + @"message":msgDict, + @"localId":msg.messageId + }]; + } + }]; + NSDictionary *msgDict = [self updateDownloadStatus:EMDownloadStatusDownloading message:msg thumbnail:YES]; + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:nil + object:msgDict]; +} + // 用于修改下载状态。 - (NSDictionary *)updateDownloadStatus:(EMDownloadStatus)status message:(EMChatMessage *)msg @@ -561,44 +601,6 @@ - (NSDictionary *)updateDownloadStatus:(EMDownloadStatus)status return msgDict; } -- (void)downloadThumbnail:(NSDictionary *)param - channelName:(NSString *)aChannelName - result:(FlutterResult)result { - __weak typeof(self) weakSelf = self; - __block EMChatMessage *msg = [EMChatMessage fromJson:param[@"message"]]; - EMChatMessage *needDownMsg = [EMClient.sharedClient.chatManager getMessageWithMessageId:msg.messageId]; - [EMClient.sharedClient.chatManager downloadMessageThumbnail:needDownMsg - progress:^(int progress) - { - [weakSelf.messageChannel invokeMethod:ChatOnMessageProgressUpdate - arguments:@{ - @"progress":@(progress), - @"localId":msg.messageId - }]; - } completion:^(EMChatMessage *message, EMError *error) - { - if (error) { - [weakSelf.messageChannel invokeMethod:ChatOnMessageError - arguments:@{ - @"error":[error toJson], - @"localId":msg.messageId, - @"message":[message toJson] - }]; - }else { - [weakSelf.messageChannel invokeMethod:ChatOnMessageSuccess - arguments:@{ - @"message":[message toJson], - @"localId":msg.messageId - }]; - } - }]; - - [weakSelf wrapperCallBack:result - channelName:aChannelName - error:nil - object:[msg toJson]]; -} - - (void)loadAllConversations:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { From 51f52d705cc13f7e5a0d564e9e4d93a4a7c7ff17 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Wed, 17 May 2023 11:59:00 +0800 Subject: [PATCH 10/49] add reaction operation files. --- .../im_flutter_sdk/EMChatManagerWrapper.java | 68 +++++++++++++++-- .../com/easemob/im_flutter_sdk/EMHelper.java | 24 +++++- ios/Classes/EMChatManagerWrapper.m | 4 +- ios/Classes/EMMessageReactionChange+Helper.m | 8 +- .../EMMessageReactionOperation+Helper.h | 16 ++++ .../EMMessageReactionOperation+Helper.m | 17 +++++ lib/src/em_group_manager.dart | 30 +++++++- lib/src/internal/inner_headers.dart | 1 + lib/src/models/em_chat_enums.dart | 31 +++++++- lib/src/models/em_message_reaction.dart | 17 +++++ lib/src/models/em_presence.dart | 4 +- lib/src/models/reaction_operation.dart | 73 +++++++++++++++++++ 12 files changed, 276 insertions(+), 17 deletions(-) create mode 100644 ios/Classes/EMMessageReactionOperation+Helper.h create mode 100644 ios/Classes/EMMessageReactionOperation+Helper.m create mode 100644 lib/src/models/reaction_operation.dart diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java index 6fbdc583..6a35bdfd 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java @@ -437,6 +437,7 @@ private void importMessages(JSONObject param, String channelName, Result result) }); } + private void downloadAttachment(JSONObject param, String channelName, Result result) throws JSONException { EMMessage tempMsg = EMMessageHelper.fromJson(param.getJSONObject("message")); final EMMessage msg = EMClient.getInstance().chatManager().getMessage(tempMsg.getMsgId()); @@ -445,7 +446,7 @@ private void downloadAttachment(JSONObject param, String channelName, Result res public void onSuccess() { post(() -> { Map map = new HashMap<>(); - map.put("message", EMMessageHelper.toJson(msg)); + map.put("message", updateDownloadStatus(EMFileMessageBody.EMDownloadStatus.SUCCESSED, msg, false)); map.put("localId", msg.getMsgId()); messageChannel.invokeMethod(EMSDKMethod.onMessageSuccess, map); }); @@ -468,7 +469,7 @@ public void onError(int code, String desc) { data.put("description", desc); post(() -> { Map map = new HashMap<>(); - map.put("message", EMMessageHelper.toJson(msg)); + map.put("message", updateDownloadStatus(EMFileMessageBody.EMDownloadStatus.FAILED, msg, false)); map.put("localId", msg.getMsgId()); map.put("error", data); messageChannel.invokeMethod(EMSDKMethod.onMessageError, map); @@ -477,7 +478,7 @@ public void onError(int code, String desc) { }); asyncRunnable(() -> { EMClient.getInstance().chatManager().downloadAttachment(msg); - onSuccess(result, channelName, EMMessageHelper.toJson(msg)); + onSuccess(result, channelName, updateDownloadStatus(EMFileMessageBody.EMDownloadStatus.DOWNLOADING, msg, false)); }); } @@ -489,7 +490,7 @@ private void downloadThumbnail(JSONObject param, String channelName, Result resu public void onSuccess() { post(() -> { Map map = new HashMap<>(); - map.put("message", EMMessageHelper.toJson(msg)); + map.put("message", updateDownloadStatus(EMFileMessageBody.EMDownloadStatus.SUCCESSED, msg, true)); map.put("localId", msg.getMsgId()); messageChannel.invokeMethod(EMSDKMethod.onMessageSuccess, map); }); @@ -512,7 +513,7 @@ public void onError(int code, String desc) { data.put("description", desc); post(() -> { Map map = new HashMap<>(); - map.put("message", EMMessageHelper.toJson(msg)); + map.put("message", updateDownloadStatus(EMFileMessageBody.EMDownloadStatus.FAILED, msg, true)); map.put("localId", msg.getMsgId()); map.put("error", data); messageChannel.invokeMethod(EMSDKMethod.onMessageError, map); @@ -521,10 +522,65 @@ public void onError(int code, String desc) { }); asyncRunnable(() -> { EMClient.getInstance().chatManager().downloadThumbnail(msg); - onSuccess(result, channelName, EMMessageHelper.toJson(msg)); + onSuccess(result, channelName, updateDownloadStatus(EMFileMessageBody.EMDownloadStatus.DOWNLOADING, msg, true)); }); } + private Map updateDownloadStatus(EMFileMessageBody.EMDownloadStatus downloadStatus, EMMessage msg, boolean isThumbnail) { + boolean canUpdate = false; + switch (msg.getType()) { + case FILE: + case VOICE: { + if (isThumbnail) { + break; + } + } + case IMAGE: + case VIDEO: + { + canUpdate = true; + } + break; + default: + break; + } + if (canUpdate) { + EMMessageBody body = msg.getBody(); + if (msg.getType() == EMMessage.Type.FILE) { + EMFileMessageBody tmpBody = (EMFileMessageBody) body; + tmpBody.setDownloadStatus(downloadStatus); + body = tmpBody; + }else if (msg.getType() == EMMessage.Type.VOICE) { + EMVoiceMessageBody tmpBody = (EMVoiceMessageBody) body; + tmpBody.setDownloadStatus(downloadStatus); + body = tmpBody; + }else if (msg.getType() == EMMessage.Type.IMAGE) { + EMImageMessageBody tmpBody = (EMImageMessageBody) body; + if (isThumbnail) { + // android not support now. + // tmpBody.setThumbnailDownloadStatus(downloadStatus); + }else { + tmpBody.setDownloadStatus(downloadStatus); + } + + body = tmpBody; + }else if (msg.getType() == EMMessage.Type.VIDEO) { + EMVideoMessageBody tmpBody = (EMVideoMessageBody) body; + if (isThumbnail) { + // android not support now. + // tmpBody.setThumbnailDownloadStatus(downloadStatus); + }else { + tmpBody.setDownloadStatus(downloadStatus); + } + + body = tmpBody; + } + + msg.setBody(body); + } + return EMMessageHelper.toJson(msg); + } + private void loadAllConversations(JSONObject param, String channelName, Result result) throws JSONException { if (EMClient.getInstance().getCurrentUser() == null || EMClient.getInstance().getCurrentUser().length() == 0) { onSuccess(result, channelName, new ArrayList<>()); diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java index 664b8681..462eefce 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java @@ -26,6 +26,7 @@ import com.hyphenate.chat.EMMessage.Type; import com.hyphenate.chat.EMMessageReaction; import com.hyphenate.chat.EMMessageReactionChange; +import com.hyphenate.chat.EMMessageReactionOperation; import com.hyphenate.chat.EMMucSharedFile; import com.hyphenate.chat.EMNormalFileMessageBody; import com.hyphenate.chat.EMOptions; @@ -1241,11 +1242,28 @@ static Map toJson(EMMessageReactionChange change) { Map data = new HashMap<>(); data.put("conversationId", change.getConversionID()); data.put("messageId", change.getMessageId()); - ArrayList> list = new ArrayList<>(); + ArrayList> reactions = new ArrayList<>(); for (int i = 0; i < change.getMessageReactionList().size(); i++) { - list.add(EMMessageReactionHelper.toJson(change.getMessageReactionList().get(i))); + reactions.add(EMMessageReactionHelper.toJson(change.getMessageReactionList().get(i))); } - data.put("reactions", list); + data.put("reactions", reactions); + + ArrayList> operations = new ArrayList<>(); + for (int i = 0; i < change.getOperations().size(); i++) { + operations.add(EMMessageReactionOperationHelper.toJson(change.getOperations().get(i))); + } + data.put("operations", operations); + + return data; + } +} + +class EMMessageReactionOperationHelper { + static Map toJson(EMMessageReactionOperation operation) { + Map data = new HashMap<>(); + data.put("userId", operation.getUserId()); + data.put("reaction", operation.getReaction()); + data.put("operate", operation.getOperation() == EMMessageReactionOperation.Operation.REMOVE ? 0 : 1); return data; } diff --git a/ios/Classes/EMChatManagerWrapper.m b/ios/Classes/EMChatManagerWrapper.m index bbb8f68d..5a9b9dbc 100644 --- a/ios/Classes/EMChatManagerWrapper.m +++ b/ios/Classes/EMChatManagerWrapper.m @@ -597,8 +597,8 @@ - (NSDictionary *)updateDownloadStatus:(EMDownloadStatus)status } msg.body = body; } - NSMutableDictionary *msgDict = [[msg toJson] mutableCopy]; - return msgDict; + + return [msg toJson]; } - (void)loadAllConversations:(NSDictionary *)param diff --git a/ios/Classes/EMMessageReactionChange+Helper.m b/ios/Classes/EMMessageReactionChange+Helper.m index 5cc11904..d1d8d201 100644 --- a/ios/Classes/EMMessageReactionChange+Helper.m +++ b/ios/Classes/EMMessageReactionChange+Helper.m @@ -7,6 +7,7 @@ #import "EMMessageReactionChange+Helper.h" #import "EMMessageReaction+Helper.h" +#import "EMMessageReactionOperation+Helper.h" @implementation EMMessageReactionChange (Helper) @@ -18,8 +19,13 @@ - (nonnull NSDictionary *)toJson { for (EMMessageReaction *reaction in self.reactions) { [reactions addObject:[reaction toJson]]; } - ret[@"reactions"] = reactions; + + NSMutableArray *operations = [NSMutableArray array]; + for (EMMessageReactionOperation *operation in self.operations) { + [operations addObject:[operation toJson]]; + }; + ret[@"operations"] = operations; return ret; } diff --git a/ios/Classes/EMMessageReactionOperation+Helper.h b/ios/Classes/EMMessageReactionOperation+Helper.h new file mode 100644 index 00000000..21c6b515 --- /dev/null +++ b/ios/Classes/EMMessageReactionOperation+Helper.h @@ -0,0 +1,16 @@ +// +// EMMessageReactionOperation+Helper.h +// im_flutter_sdk +// +// Created by 杜洁鹏 on 2023/5/17. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface EMMessageReactionOperation (Helper) +-(NSDictionary *)toJson; +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Classes/EMMessageReactionOperation+Helper.m b/ios/Classes/EMMessageReactionOperation+Helper.m new file mode 100644 index 00000000..25322bdc --- /dev/null +++ b/ios/Classes/EMMessageReactionOperation+Helper.m @@ -0,0 +1,17 @@ +// +// EMMessageReactionOperation+Helper.m +// im_flutter_sdk +// +// Created by 杜洁鹏 on 2023/5/17. +// + +#import "EMMessageReactionOperation+Helper.h" + +@implementation EMMessageReactionOperation (Helper) +- (NSDictionary *)toJson { + return @{@"userId": self.userId, + @"reaction": self.reaction, + @"operate": @(self.operate) + }; +} +@end diff --git a/lib/src/em_group_manager.dart b/lib/src/em_group_manager.dart index 4e4d12d8..cfe18805 100644 --- a/lib/src/em_group_manager.dart +++ b/lib/src/em_group_manager.dart @@ -1902,7 +1902,7 @@ class EMGroupManager { /// /// **Return** 需要查询的用户属性。 /// - /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 /// ~end Future?> fetchMemberAttributes({ required String groupId, @@ -1920,6 +1920,34 @@ class EMGroupManager { } } + /// ~english + /// Gets custom attributes of multiple group members by attribute key. + /// + /// Param [groupId] The group ID. + /// + /// Param [userIds] The array of user IDs of group members whose custom attributes are retrieved.(limitation is ten.More than callback error. ) + /// + /// Param [keys] The array of keys of custom attributes to be retrieved. + /// + /// **Return** The users attributes. + /// + /// **Throws** A description of the exception. See [EMError]. + /// + /// ~end + /// + /// ~chinese + /// 根据指定的属性 key 获取多个群成员的自定义属性 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [userIds] 要获取自定义属性的群成员的用户 ID 数组。(最多10个,多则报错) + /// + /// Param [keys] 要获取自定义属性的 key 的数组。 + /// + /// **Return** 需要查询的用户属性。 + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end Future>?> fetchMembersAttributes({ required String groupId, required List userIds, diff --git a/lib/src/internal/inner_headers.dart b/lib/src/internal/inner_headers.dart index 0f0b0c37..b1250778 100644 --- a/lib/src/internal/inner_headers.dart +++ b/lib/src/internal/inner_headers.dart @@ -19,6 +19,7 @@ export '../models/em_group_options.dart'; export '../models/em_group_shared_file.dart'; export '../models/em_group.dart'; export '../models/em_message_reaction.dart'; +export '../models/reaction_operation.dart'; export '../models/em_message.dart'; export '../models/em_options.dart'; export '../models/em_page_result.dart'; diff --git a/lib/src/models/em_chat_enums.dart b/lib/src/models/em_chat_enums.dart index 8c206274..4f0398c1 100644 --- a/lib/src/models/em_chat_enums.dart +++ b/lib/src/models/em_chat_enums.dart @@ -782,10 +782,10 @@ enum EMMultiDevicesEvent { CHAT_THREAD_KICK, /// ~english - /// If user A modifies a custom member attribute on device A1, + /// If user A modifies a custom member attribute on device A1, /// this event is triggered on another device that the user logs in with the same account. /// ~end - /// + /// /// ~chinese /// 若用户 A 在设备 A1 上修改群成员自定义属性,该事件会在登录该账号的其他设备触发。 /// ~end @@ -980,3 +980,30 @@ enum ChatRoomMessagePriority { /// ~end Low, } + +/// ~english +/// Operation type of reaction. +/// ~end +/// +/// ~chinese +/// reaction 操作种类。 +/// ~end +enum ReactionOperate { + /// ~english + /// Remove + /// ~end + /// + /// ~chinese + /// 删除 + /// ~end + Remove, + + /// ~english + /// Add + /// ~end + /// + /// ~chinese + /// 添加 + /// ~end + Add, +} diff --git a/lib/src/models/em_message_reaction.dart b/lib/src/models/em_message_reaction.dart index 0ff7a0d4..6c272c76 100644 --- a/lib/src/models/em_message_reaction.dart +++ b/lib/src/models/em_message_reaction.dart @@ -120,10 +120,20 @@ class EMMessageReactionEvent { /// ~end final List reactions; + /// ~english + /// Details of changed operation. + /// ~end + /// + /// ~chinese + /// 发生变化的操作详情。 + /// ~end + final List operations; + EMMessageReactionEvent._private({ required this.conversationId, required this.messageId, required this.reactions, + required this.operations, }); /// @nodoc @@ -134,10 +144,17 @@ class EMMessageReactionEvent { map["reactions"]?.forEach((element) { reactions.add(EMMessageReaction.fromJson(element)); }); + + List operations = []; + map["operations"]?.forEach((e) { + operations.add(ReactionOperation.fromJson(e)); + }); + return EMMessageReactionEvent._private( conversationId: conversationId, messageId: messageId, reactions: reactions, + operations: operations, ); } } diff --git a/lib/src/models/em_presence.dart b/lib/src/models/em_presence.dart index 40d8a0dc..17ef285c 100644 --- a/lib/src/models/em_presence.dart +++ b/lib/src/models/em_presence.dart @@ -81,11 +81,11 @@ class EMPresence { /// ~end class EMPresenceStatusDetail { /// ~english - /// The platform used by the current online device of the publisher, which can be "ios", "android", "linux", "windows", or "webim". + /// The platform used by the current online device of the publisher, which can be "ios", "android", "linux", "win", or "webim". /// ~end /// /// ~chinese - /// 发布在线设备,可能是 "ios", "android", "linux", "windows", "webim"。 + /// 发布在线设备,可能是 "ios", "android", "linux", "win", "webim"。 /// ~end final String device; diff --git a/lib/src/models/reaction_operation.dart b/lib/src/models/reaction_operation.dart new file mode 100644 index 00000000..4ccd8a21 --- /dev/null +++ b/lib/src/models/reaction_operation.dart @@ -0,0 +1,73 @@ +import 'em_chat_enums.dart'; + +/// ~english +/// Reaction Operation +/// ~end +/// +/// ~chinese +/// Reaction 操作 +/// ~end +class ReactionOperation { + /// ~english + /// Reaction Operation + /// + /// Param [userId] Operator userId. + /// + /// Param [reaction] Changed reaction. + /// + /// Param [operate] Operate type. + /// ~end + /// + /// ~chinese + /// Reaction 操作 + /// + /// Param [userId] 操作者。 + /// + /// Param [reaction] 发生变化的 reaction。 + /// + /// Param [operate] 具体操作类型。 + /// ~end + const ReactionOperation._private( + this.userId, + this.reaction, + this.operate, + ); + + /// ~english + /// Operator userId. + /// ~end + /// + /// ~chinese + /// 操作者。 + /// ~end + final String userId; + + /// ~english + /// Changed reaction. + /// ~end + /// + /// ~chinese + /// 发生变化的 reaction。 + /// ~end + final String reaction; + + /// ~english + /// Operate type. + /// ~end + /// + /// ~chinese + /// 具体操作类型。 + /// ~end + final ReactionOperate operate; + + /// @nodoc + factory ReactionOperation.fromJson(Map map) { + String userId = map["userId"]; + String reaction = map["reaction"]; + + ReactionOperate operate = + map["operate"] ?? 0 == 0 ? ReactionOperate.Remove : ReactionOperate.Add; + + return ReactionOperation._private(userId, reaction, operate); + } +} From a36d0b1d61b62c885da26c96e2a0fd8da57940bf Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Fri, 19 May 2023 11:29:29 +0800 Subject: [PATCH 11/49] change fetchGroupMember attributes method. --- ios/Classes/EMGroupManagerWrapper.m | 3 +++ lib/im_flutter_sdk.dart | 3 ++- lib/src/internal/inner_headers.dart | 2 +- lib/src/models/em_options.dart | 12 ++++++------ .../tools/{area_code.dart => chat_area_code.dart} | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) rename lib/src/tools/{area_code.dart => chat_area_code.dart} (90%) diff --git a/ios/Classes/EMGroupManagerWrapper.m b/ios/Classes/EMGroupManagerWrapper.m index d3d1bdfa..8d7e951d 100644 --- a/ios/Classes/EMGroupManagerWrapper.m +++ b/ios/Classes/EMGroupManagerWrapper.m @@ -971,6 +971,9 @@ - (void)fetchMembersAttributes:(NSDictionary *)param channelName:(NSString *)aCh NSString *groupId = param[@"groupId"]; NSArray *userIds = param[@"userIds"]; NSArray *keys = param[@"keys"]; + if(!keys) { + keys = [NSArray new]; + } [EMClient.sharedClient.groupManager fetchMembersAttributes:groupId userIds:userIds keys:keys completion:^(NSDictionary *> * _Nullable attributes, EMError * _Nullable error) { [weakSelf wrapperCallBack:result diff --git a/lib/im_flutter_sdk.dart b/lib/im_flutter_sdk.dart index 7ed7f3fe..2e8d7ee5 100644 --- a/lib/im_flutter_sdk.dart +++ b/lib/im_flutter_sdk.dart @@ -31,6 +31,7 @@ export 'src/models/em_group_shared_file.dart'; export 'src/models/em_group_options.dart'; export 'src/models/fetch_message_options.dart'; export 'src/models/em_chat_enums.dart'; +export 'src/models/reaction_operation.dart'; export 'src/models/em_message.dart'; export 'src/models/em_download_callback.dart'; @@ -38,4 +39,4 @@ export 'src/models/em_message_reaction.dart'; export 'src/models/em_chat_thread.dart'; export 'src/models/chat_silent_mode.dart'; export 'src/event_handler/manager_event_handler.dart'; -export 'src/tools/area_code.dart'; +export 'src/tools/chat_area_code.dart'; diff --git a/lib/src/internal/inner_headers.dart b/lib/src/internal/inner_headers.dart index b1250778..5a1e89c0 100644 --- a/lib/src/internal/inner_headers.dart +++ b/lib/src/internal/inner_headers.dart @@ -44,5 +44,5 @@ export '../em_presence_manager.dart'; export '../em_push_manager.dart'; export '../em_userInfo_manager.dart'; export '../event_handler/manager_event_handler.dart'; -export '../tools/area_code.dart'; +export '../tools/chat_area_code.dart'; export '../tools/em_tools.dart'; diff --git a/lib/src/models/em_options.dart b/lib/src/models/em_options.dart index 42ad625c..438acfa3 100644 --- a/lib/src/models/em_options.dart +++ b/lib/src/models/em_options.dart @@ -272,7 +272,7 @@ class EMOptions { /// 此属性用于限制可访问边缘节点的范围。缺省值为AreaCodeGLOB。 /// 此属性只能在调用[EMClient.init]时设置。在应用程序运行期间不能更改属性设置。 /// ~end - final int serverAreaCode; + final int chatAreaCode; EMPushConfig _pushConfig = EMPushConfig(); @@ -429,7 +429,7 @@ class EMOptions { /// /// Param [imServer] The IM server URL for private deployment. /// - /// Param [serverAreaCode] The area code. + /// Param [chatAreaCode] The area code. /// /// ~end /// @@ -501,7 +501,7 @@ class EMOptions { /// /// Param [imServer] 私有部署时的 IM 服务器地址。 /// - /// Param [serverAreaCode] server 区域码. + /// Param [chatAreaCode] server 区域码. /// ~end EMOptions({ required this.appKey, @@ -523,7 +523,7 @@ class EMOptions { this.restServer, this.imPort, this.imServer, - this.serverAreaCode = AreaCode.GLOB, + this.chatAreaCode = ChatAreaCode.GLOB, }); /// @nodoc @@ -550,7 +550,7 @@ class EMOptions { imServer: json["imServer"], restServer: json["restServer"], dnsUrl: json["dnsUrl"], - serverAreaCode: json["areaCode"] ?? AreaCode.GLOB, + chatAreaCode: json["areaCode"] ?? ChatAreaCode.GLOB, ); ret._pushConfig = EMPushConfig(); @@ -589,7 +589,7 @@ class EMOptions { data["usingHttpsOnly"] = this.usingHttpsOnly; data["pushConfig"] = this._pushConfig.toJson(); - data["areaCode"] = this.serverAreaCode; + data["areaCode"] = this.chatAreaCode; return data; } diff --git a/lib/src/tools/area_code.dart b/lib/src/tools/chat_area_code.dart similarity index 90% rename from lib/src/tools/area_code.dart rename to lib/src/tools/chat_area_code.dart index d0a044df..faa7e95a 100644 --- a/lib/src/tools/area_code.dart +++ b/lib/src/tools/chat_area_code.dart @@ -1,4 +1,4 @@ -class AreaCode { +class ChatAreaCode { static const int CN = 1; static const int NA = 2; static const int EU = 4; From d5e81ebad4b634731483b086c3a443e94140eeaa Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Fri, 19 May 2023 16:44:18 +0800 Subject: [PATCH 12/49] fix android bugs. --- .../com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java index 7293abcd..03a3582d 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java @@ -847,7 +847,13 @@ private void fetchMemberAttributes(JSONObject param, String channelName, Result String groupId = param.getString("groupId"); String userId = param.getString("userId"); - EMClient.getInstance().groupManager().asyncFetchGroupMemberAllAttributes(groupId, userId, new EMValueWrapperCallBack<>(result, channelName)); + EMClient.getInstance().groupManager().asyncFetchGroupMemberAllAttributes(groupId, userId, new EMValueWrapperCallBack>>(result, channelName){ + + @Override + public void onSuccess(Map> object) { + updateObject(object.get(userId)); + } + }); } private void fetchMembersAttributes(JSONObject param, String channelName, Result result) throws JSONException { From 5d5a650dbf3249716eaa044c6049d0b0e2a05917 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Mon, 22 May 2023 10:49:27 +0800 Subject: [PATCH 13/49] fix callback execute multiple times when hot reload. --- .../com/easemob/im_flutter_sdk/EMChatManagerWrapper.java | 7 +++++++ .../easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java | 4 ++++ .../im_flutter_sdk/EMChatThreadManagerWrapper.java | 3 +++ .../java/com/easemob/im_flutter_sdk/EMClientWrapper.java | 9 +++++++++ .../easemob/im_flutter_sdk/EMContactManagerWrapper.java | 5 +++++ .../easemob/im_flutter_sdk/EMGroupManagerWrapper.java | 4 ++++ .../easemob/im_flutter_sdk/EMPresenceManagerWrapper.java | 4 ++++ 7 files changed, 36 insertions(+) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java index 6a35bdfd..07a63bcc 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java @@ -870,6 +870,10 @@ public void unRegisterEaseListener() { private void registerEaseListener() { + if (messageListener != null) { + EMClient.getInstance().chatManager().removeMessageListener(messageListener); + } + messageListener = new EMMessageListener() { @Override public void onMessageReceived(List messages) { @@ -946,6 +950,9 @@ public void onReactionChanged(List messageReactionChang } }; + if (conversationListener != null) { + EMClient.getInstance().chatManager().removeConversationListener(conversationListener); + } conversationListener = new EMConversationListener() { @Override diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java index a68af55e..3021bbc4 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java @@ -656,6 +656,10 @@ public void removeChatRoomAttributes(JSONObject param, String channelName, Metho private void registerEaseListener() { + if (chatRoomChangeListener != null) { + EMClient.getInstance().chatroomManager().removeChatRoomListener(chatRoomChangeListener); + } + chatRoomChangeListener = new EMChatRoomChangeListener() { @Override diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatThreadManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatThreadManagerWrapper.java index 3ad2b1b0..add5d549 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatThreadManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatThreadManagerWrapper.java @@ -204,6 +204,9 @@ private void destroyChatThread(JSONObject param, String channelName, MethodChann private void registerEaseListener() { + if (chatThreadChangeListener != null) { + EMClient.getInstance().chatThreadManager().removeChatThreadChangeListener(chatThreadChangeListener); + } chatThreadChangeListener = new EMChatThreadChangeListener() { @Override public void onChatThreadCreated(EMChatThreadEvent event) { diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java index 1aff9131..a4d844b4 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java @@ -349,6 +349,11 @@ public void unRegisterEaseListener() { private void registerEaseListener() { + if (multiDeviceListener != null) { + EMClient.getInstance().removeMultiDeviceListener(multiDeviceListener); + } + + multiDeviceListener = new EMMultiDeviceListener() { @Override public void onContactEvent(int event, String target, String ext) { @@ -377,6 +382,10 @@ public void onChatThreadEvent(int event, String target, List usernames) } }; + if (connectionListener != null) { + EMClient.getInstance().removeConnectionListener(connectionListener); + } + connectionListener = new EMConnectionListener() { @Override public void onConnected() { diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMContactManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMContactManagerWrapper.java index 12a37485..c1f8f56e 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMContactManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMContactManagerWrapper.java @@ -191,6 +191,11 @@ private void getSelfIdsOnOtherPlatform(JSONObject params, String channelName, Re private void registerEaseListener() { + + if (contactListener != null) { + EMClient.getInstance().contactManager().removeContactListener(contactListener); + } + contactListener = new EMContactListener() { @Override public void onContactAdded(String userName) { diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java index 03a3582d..6bc15f1a 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java @@ -881,6 +881,10 @@ public void onSuccess(Map> object) { } private void registerEaseListener() { + + if (groupChangeListener != null) { + EMClient.getInstance().groupManager().removeGroupChangeListener(groupChangeListener); + } groupChangeListener = new EMGroupChangeListener() { @Override diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMPresenceManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMPresenceManagerWrapper.java index e567401a..96e135a3 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMPresenceManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMPresenceManagerWrapper.java @@ -131,6 +131,10 @@ public void onSuccess(List object) { } private void registerEaseListener() { + if (presenceListener != null) { + EMClient.getInstance().presenceManager().removeListener(presenceListener); + } + presenceListener = presences -> { Map data = new HashMap<>(); List list = new ArrayList<>(); From b9b92e1b64b6ca9bea13aab48daa020df16631ce Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Mon, 22 May 2023 17:22:21 +0800 Subject: [PATCH 14/49] fix callback execute multiple times when hot reload on ios --- .../im_flutter_sdk/EMClientWrapper.java | 8 +++-- .../com/easemob/im_flutter_sdk/EMWrapper.java | 2 -- .../im_flutter_sdk/ImFlutterSdkPlugin.java | 28 ++++------------ .../com/example/quick_start/MainActivity.kt | 32 ++++++++++++++++++- example/ios/Runner/AppDelegate.swift | 11 +++++++ ios/Classes/EMChatManagerWrapper.m | 1 - ios/Classes/EMClientWrapper.m | 24 ++++++++++---- ios/Classes/EMWrapper.m | 3 +- ios/Classes/ImFlutterSdkPlugin.h | 1 - ios/Classes/ImFlutterSdkPlugin.m | 18 ++--------- 10 files changed, 76 insertions(+), 52 deletions(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java index a4d844b4..e86824c2 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java @@ -44,10 +44,10 @@ public class EMClientWrapper extends EMWrapper implements MethodCallHandler { private EMMultiDeviceListener multiDeviceListener; private EMConnectionListener connectionListener; + private EMOptions options; EMClientWrapper(FlutterPlugin.FlutterPluginBinding flutterPluginBinding, String channelName) { super(flutterPluginBinding, channelName); - } public void sendDataToFlutter(final Map data) { @@ -273,7 +273,11 @@ private void kickAllDevices(JSONObject param, String channelName, Result result) } private void init(JSONObject param, String channelName, Result result) throws JSONException { - EMOptions options = EMOptionsHelper.fromJson(param, this.context); + if (options != null) { + onSuccess(result, channelName, null); + return; + } + options = EMOptionsHelper.fromJson(param, this.context); EMClient.getInstance().init(this.context, options); EMClient.getInstance().setDebugMode(param.getBoolean("debugModel")); diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMWrapper.java index 7ace4c82..b32dde14 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMWrapper.java @@ -69,6 +69,4 @@ public void onError(MethodChannel.Result result, HyphenateException e) { public void onMethodCall(MethodCall call, MethodChannel.Result result) { result.notImplemented(); } - - } diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/ImFlutterSdkPlugin.java b/android/src/main/java/com/easemob/im_flutter_sdk/ImFlutterSdkPlugin.java index efcd45f0..db961ecb 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/ImFlutterSdkPlugin.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/ImFlutterSdkPlugin.java @@ -21,19 +21,16 @@ /** * ImFlutterSdkPlugin */ -public class ImFlutterSdkPlugin implements FlutterPlugin, MethodChannel.MethodCallHandler { +public class ImFlutterSdkPlugin implements FlutterPlugin { static final Handler handler = new Handler(Looper.getMainLooper()); - static EMClientWrapper clientWrapper; + EMClientWrapper clientWrapper; public ImFlutterSdkPlugin() { } - static public void clearWrapper(){ - clientWrapper = null; - } - static public void sendDataToFlutter(final Map data) { + public void sendDataToFlutter(final Map data) { if (clientWrapper != null) { clientWrapper.sendDataToFlutter(data); } @@ -41,22 +38,12 @@ static public void sendDataToFlutter(final Map data) { @Override public void onAttachedToEngine(FlutterPlugin.FlutterPluginBinding flutterPluginBinding) { - final MethodChannel channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "chat_client"); - if (clientWrapper != null) { - clientWrapper.unRegisterEaseListener(); - } clientWrapper = new EMClientWrapper(flutterPluginBinding, "chat_client"); - channel.setMethodCallHandler(clientWrapper); } @Override public void onDetachedFromEngine(FlutterPlugin.FlutterPluginBinding flutterPluginBinding) { - - } - - @Override - public void onMethodCall(MethodCall call, MethodChannel.Result result) { - + clientWrapper.unRegisterEaseListener(); } } @@ -116,18 +103,17 @@ class EMDownloadCallback implements EMCallBack { @Override public void onSuccess() { -// EMClientWrapper.getInstance().progressManager.sendDownloadSuccessToFlutter(fileId, savePath); + } @Override public void onError(int code, String error) { -// HyphenateException e = new HyphenateException(code, error); -// EMClientWrapper.getInstance().progressManager.sendDownloadErrorToFlutter(fileId, e); + } @Override public void onProgress(int progress, String status) { -// EMClientWrapper.getInstance().progressManager.sendDownloadProgressToFlutter(fileId, progress); + } } diff --git a/example/android/app/src/main/kotlin/com/example/quick_start/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/quick_start/MainActivity.kt index 2b28dce5..b1d3d6f1 100644 --- a/example/android/app/src/main/kotlin/com/example/quick_start/MainActivity.kt +++ b/example/android/app/src/main/kotlin/com/example/quick_start/MainActivity.kt @@ -1,6 +1,36 @@ package com.example.quick_start + +import android.content.Context +import android.os.Bundle +import android.os.PersistableBundle +import android.util.AttributeSet +import android.view.ActionMode +import android.view.View +import com.easemob.im_flutter_sdk.ImFlutterSdkPlugin import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.engine.FlutterEngine +import java.util.* + class MainActivity: FlutterActivity() { -} + + override fun configureFlutterEngine(flutterEngine: FlutterEngine) { + super.configureFlutterEngine(flutterEngine) + + val task: TimerTask = object : TimerTask() { + override fun run() { + testCode(); + } + } + val timer = Timer() + timer.schedule(task, 3000) + } + + fun testCode() { +// if (flutterEngine?.plugins?.has(ImFlutterSdkPlugin::class.java) == true){ +// var p = flutterEngine?.plugins?.get(ImFlutterSdkPlugin::class.java) as ImFlutterSdkPlugin +// p.sendDataToFlutter(mapOf("key" to "Value")); +// } + } + } diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 70693e4a..473f1299 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -1,5 +1,6 @@ import UIKit import Flutter +import im_flutter_sdk @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { @@ -8,6 +9,16 @@ import Flutter didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) + +// Timer.scheduledTimer(withTimeInterval: 3, repeats: false) { t in +// if(self.hasPlugin("ImFlutterSdkPlugin")) { +// print("find") +// let wrapper = self.valuePublished(byPlugin: "ImFlutterSdkPlugin") as! EMClientWrapper +// wrapper.sendData(toFlutter: ["key":"value"]) +// }else { +// print("no find") +// } +// } return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } diff --git a/ios/Classes/EMChatManagerWrapper.m b/ios/Classes/EMChatManagerWrapper.m index 5a9b9dbc..7fa057a7 100644 --- a/ios/Classes/EMChatManagerWrapper.m +++ b/ios/Classes/EMChatManagerWrapper.m @@ -28,7 +28,6 @@ - (instancetype)initWithChannelName:(NSString *)aChannelName if(self = [super initWithChannelName:aChannelName registrar:registrar]) { [EMClient.sharedClient.chatManager addDelegate:self delegateQueue:nil]; - FlutterJSONMethodCodec *codec = [FlutterJSONMethodCodec sharedInstance]; self.messageChannel = [FlutterMethodChannel methodChannelWithName:@"com.chat.im/chat_message" binaryMessenger:[registrar messenger] diff --git a/ios/Classes/EMClientWrapper.m b/ios/Classes/EMClientWrapper.m index 9b257733..1b98f24e 100644 --- a/ios/Classes/EMClientWrapper.m +++ b/ios/Classes/EMClientWrapper.m @@ -38,7 +38,9 @@ @interface EMClientWrapper () *)registrar { if(self = [super initWithChannelName:aChannelName registrar:registrar]) { - [registrar addApplicationDelegate:self]; + } return self; } @@ -171,14 +173,21 @@ - (void)initSDKWithDict:(NSDictionary *)param channelName:(NSString *)aChannelNa __weak typeof(self) weakSelf = self; - EMOptions *options = [EMOptions fromJson:param]; + if(_options) { + [weakSelf wrapperCallBack:result + channelName:ChatInit + error:nil + object:nil]; + return; + } + + _options = [EMOptions fromJson:param]; - [EMClient.sharedClient initializeSDKWithOptions:options]; + [EMClient.sharedClient initializeSDKWithOptions:_options]; [EMClient.sharedClient addDelegate:self delegateQueue:nil]; [EMClient.sharedClient addMultiDevicesDelegate:self delegateQueue:nil]; [self registerManagers]; - [weakSelf wrapperCallBack:result channelName:ChatInit error:nil @@ -187,6 +196,7 @@ - (void)initSDKWithDict:(NSDictionary *)param channelName:(NSString *)aChannelNa - (void)registerManagers { + [self clearAllListener]; _chatManager = [[EMChatManagerWrapper alloc] initWithChannelName:EMChannelName(@"chat_manager")registrar:self.flutterPluginRegister]; _contactManager = [[EMContactManagerWrapper alloc] initWithChannelName:EMChannelName(@"chat_contact_manager") registrar:self.flutterPluginRegister]; _conversationManager = [[EMConversationWrapper alloc] initWithChannelName:EMChannelName(@"chat_conversation") registrar:self.flutterPluginRegister]; @@ -214,12 +224,14 @@ - (void)clearAllListener { [_threadManager unRegisterEaseListener]; [_msgWrapper unRegisterEaseListener]; [super unRegisterEaseListener]; + [EMClient.sharedClient removeDelegate:self]; + [EMClient.sharedClient removeMultiDevicesDelegate:self]; } +// 由父类调用,不需要调用 clearAllListener方法,每个manager中都由父类调用。 - (void)unRegisterEaseListener { [EMClient.sharedClient removeDelegate:self]; [EMClient.sharedClient removeMultiDevicesDelegate:self]; - [self clearAllListener]; } - (EMProgressManager *)progressManager { diff --git a/ios/Classes/EMWrapper.m b/ios/Classes/EMWrapper.m index df66bdfd..292fcd55 100644 --- a/ios/Classes/EMWrapper.m +++ b/ios/Classes/EMWrapper.m @@ -27,7 +27,6 @@ - (instancetype)initWithChannelName:(NSString *)aChannelName codec:codec]; self.channel = channel; [registrar addMethodCallDelegate:self channel:channel]; - } return self; } @@ -66,7 +65,7 @@ + (void)registerWithRegistrar:(nonnull NSObject *)regist } - (void)detachFromEngineForRegistrar:(NSObject*)registrar { - + [self unRegisterEaseListener]; } -(void)dealloc{ diff --git a/ios/Classes/ImFlutterSdkPlugin.h b/ios/Classes/ImFlutterSdkPlugin.h index 07c83656..cd751929 100644 --- a/ios/Classes/ImFlutterSdkPlugin.h +++ b/ios/Classes/ImFlutterSdkPlugin.h @@ -1,5 +1,4 @@ #import @interface ImFlutterSdkPlugin : NSObject -+ (void)sendDataToFlutter:(NSDictionary *)aData; @end diff --git a/ios/Classes/ImFlutterSdkPlugin.m b/ios/Classes/ImFlutterSdkPlugin.m index df4c586d..3dd572a7 100644 --- a/ios/Classes/ImFlutterSdkPlugin.m +++ b/ios/Classes/ImFlutterSdkPlugin.m @@ -12,23 +12,9 @@ @implementation ImFlutterSdkPlugin -static EMClientWrapper *wrapper; - + (void)registerWithRegistrar:(NSObject*)registrar { - wrapper = [[EMClientWrapper alloc] initWithChannelName:EMChannelName(@"chat_client") registrar:registrar]; -} - -+ (void)clearWrapper{ - wrapper = nil; -} - -+ (void)sendDataToFlutter:(NSDictionary *)aData { - if (wrapper) { - [wrapper sendDataToFlutter:aData]; - } -} - -- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { + EMClientWrapper *wrapper = [[EMClientWrapper alloc] initWithChannelName:EMChannelName(@"chat_client") registrar:registrar]; + [registrar publish:wrapper]; } @end From bfe03978be03e54cd16c5bba681e87ea4c077044 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Wed, 24 May 2023 14:23:38 +0800 Subject: [PATCH 15/49] add multi device roam message removed event. --- .../im_flutter_sdk/EMClientWrapper.java | 8 ++++++ .../easemob/im_flutter_sdk/EMSDKMethod.java | 2 ++ ios/Classes/EMClientWrapper.m | 7 ++++++ ios/Classes/EMSDKMethod.h | 1 + lib/src/em_client.dart | 11 ++++++++ .../event_handler/manager_event_handler.dart | 25 +++++++++++++++++++ lib/src/internal/chat_method_keys.dart | 1 + 7 files changed, 55 insertions(+) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java index e86824c2..a36a3acb 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java @@ -384,6 +384,14 @@ public void onChatThreadEvent(int event, String target, List usernames) data.put("users", usernames); post(()-> channel.invokeMethod(EMSDKMethod.onMultiDeviceThreadEvent, data)); } + + @Override + public void onMessageRemoved(String conversationId, String deviceId) { + Map data = new HashMap<>(); + data.put("convId", conversationId); + data.put("deviceId", deviceId); + post(()-> channel.invokeMethod(EMSDKMethod.onMultiDeviceRemoveMessagesEvent, data)); + } }; if (connectionListener != null) { diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java index 12f43d4f..f42c53ac 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java @@ -34,6 +34,8 @@ public class EMSDKMethod { static final String onMultiDeviceGroupEvent = "onMultiDeviceGroupEvent"; static final String onMultiDeviceContactEvent = "onMultiDeviceContactEvent"; static final String onMultiDeviceThreadEvent = "onMultiDeviceThreadEvent"; + + static final String onMultiDeviceRemoveMessagesEvent = "onMultiDeviceRemoveMessagesEvent"; static final String onSendDataToFlutter = "onSendDataToFlutter"; static final String onTokenWillExpire = "onTokenWillExpire"; static final String onTokenDidExpire = "onTokenDidExpire"; diff --git a/ios/Classes/EMClientWrapper.m b/ios/Classes/EMClientWrapper.m index 1b98f24e..f77b0298 100644 --- a/ios/Classes/EMClientWrapper.m +++ b/ios/Classes/EMClientWrapper.m @@ -547,6 +547,13 @@ - (void)multiDevicesChatThreadEventDidReceive:(EMMultiDevicesEvent)aEvent [self.channel invokeMethod:ChatOnMultiDeviceThreadEvent arguments:data]; } +- (void)multiDevicesMessageBeRemoved:(NSString *)conversationId deviceId:(NSString *)deviceId { + NSMutableDictionary *data = [NSMutableDictionary dictionary]; + data[@"convId"] = conversationId; + data[@"deviceId"] = deviceId; + [self.channel invokeMethod:ChatOnMultiDeviceRemoveMessagesEvent arguments:data]; +} + - (void)applicationDidEnterBackground:(UIApplication *)application { [[EMClient sharedClient] applicationDidEnterBackground:application]; diff --git a/ios/Classes/EMSDKMethod.h b/ios/Classes/EMSDKMethod.h index 76399c36..49d1acae 100644 --- a/ios/Classes/EMSDKMethod.h +++ b/ios/Classes/EMSDKMethod.h @@ -31,6 +31,7 @@ static NSString *const ChatIsConnected = @"isConnected"; static NSString *const ChatOnMultiDeviceGroupEvent = @"onMultiDeviceGroupEvent"; static NSString *const ChatOnMultiDeviceContactEvent = @"onMultiDeviceContactEvent"; static NSString *const ChatOnMultiDeviceThreadEvent = @"onMultiDeviceThreadEvent"; +static NSString *const ChatOnMultiDeviceRemoveMessagesEvent = @"onMultiDeviceRemoveMessagesEvent"; #pragma mark - EMClientDelegate static NSString *const ChatOnConnected = @"onConnected"; static NSString *const ChatOnDisconnected = @"onDisconnected"; diff --git a/lib/src/em_client.dart b/lib/src/em_client.dart index dc925c3c..6bf24366 100644 --- a/lib/src/em_client.dart +++ b/lib/src/em_client.dart @@ -105,6 +105,9 @@ class EMClient { _onMultiDeviceContactEvent(argMap!); } else if (call.method == ChatMethodKeys.onMultiDeviceThreadEvent) { _onMultiDeviceThreadEvent(argMap!); + } else if (call.method == + ChatMethodKeys.onMultiDeviceRemoveMessagesEvent) { + _onMultiDeviceRoamMessagesRemovedEvent(argMap!); } else if (call.method == ChatMethodKeys.onSendDataToFlutter) { _onReceiveCustomData(argMap!); } else if (call.method == ChatMethodKeys.onTokenWillExpire) { @@ -841,6 +844,14 @@ class EMClient { } } + Future _onMultiDeviceRoamMessagesRemovedEvent(Map map) async { + String convId = map['convId']; + String deviceId = map['deviceId']; + for (var handler in _multiDeviceEventHandler.values) { + handler.onRemoteMessagesRemoved?.call(convId, deviceId); + } + } + void _onReceiveCustomData(Map map) { customEventHandler?.call(map); } diff --git a/lib/src/event_handler/manager_event_handler.dart b/lib/src/event_handler/manager_event_handler.dart index f3a30cc9..86b0dc94 100644 --- a/lib/src/event_handler/manager_event_handler.dart +++ b/lib/src/event_handler/manager_event_handler.dart @@ -274,6 +274,26 @@ class EMMultiDeviceEventHandler { List userIds, )? onChatThreadEvent; + /// ~english + /// Callback to other devices after conversation deleted message from server after enabling multiple devices. + /// + /// Param [conversationId] The conversation id. + /// + /// Param [deviceId] The device id. + /// ~end + /// + /// ~chinese + /// 开启多设备后对单个会话删除漫游消息后对其他设备的回调。 + /// + /// Param [conversationId] 被删除的会话id。 + /// + /// Param [deviceId] 操作删除的设备id。 + /// ~end + final void Function( + String conversationId, + String deviceId, + )? onRemoteMessagesRemoved; + /// ~english /// The multi-device event handler. /// @@ -282,6 +302,8 @@ class EMMultiDeviceEventHandler { /// Param [onGroupEvent] The multi-device event of group. /// /// Param [onChatThreadEvent] The multi-device event of thread. + /// + /// Param [onRemoteMessagesRemoved] The multi-device event of roam messages removed. /// ~end /// /// ~chinese @@ -292,11 +314,14 @@ class EMMultiDeviceEventHandler { /// Param [onGroupEvent] 多设备群组事件。 /// /// Param [onChatThreadEvent] 多设备 Thread 事件。 + /// + /// Param [onRemoteMessagesRemoved] 多设备漫游消息删除事件。 /// ~end EMMultiDeviceEventHandler({ this.onContactEvent, this.onGroupEvent, this.onChatThreadEvent, + this.onRemoteMessagesRemoved, }); } diff --git a/lib/src/internal/chat_method_keys.dart b/lib/src/internal/chat_method_keys.dart index b8a1500b..2f09e769 100644 --- a/lib/src/internal/chat_method_keys.dart +++ b/lib/src/internal/chat_method_keys.dart @@ -25,6 +25,7 @@ class ChatMethodKeys { static const String onMultiDeviceGroupEvent = "onMultiDeviceGroupEvent"; static const String onMultiDeviceContactEvent = "onMultiDeviceContactEvent"; static const String onMultiDeviceThreadEvent = "onMultiDeviceThreadEvent"; + static const String onMultiDeviceRemoveMessagesEvent = "onMultiDeviceRemoveMessagesEvent"; static const String onConnected = "onConnected"; static const String onDisconnected = "onDisconnected"; static const String onUserDidLoginFromOtherDevice = From ef3701a6aa7024e3a42ecbfe8aa48f50cdc5882e Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Mon, 29 May 2023 13:43:14 +0800 Subject: [PATCH 16/49] fix fetchChatRoomAttributes crash when keys is null. --- .../com/easemob/im_flutter_sdk/EMChatManagerWrapper.java | 3 +-- lib/src/em_chat_room_manager.dart | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java index 07a63bcc..20feaa65 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java @@ -567,8 +567,7 @@ private Map updateDownloadStatus(EMFileMessageBody.EMDownloadSta }else if (msg.getType() == EMMessage.Type.VIDEO) { EMVideoMessageBody tmpBody = (EMVideoMessageBody) body; if (isThumbnail) { - // android not support now. - // tmpBody.setThumbnailDownloadStatus(downloadStatus); + tmpBody.setThumbnailDownloadStatus(downloadStatus); }else { tmpBody.setDownloadStatus(downloadStatus); } diff --git a/lib/src/em_chat_room_manager.dart b/lib/src/em_chat_room_manager.dart index 12ae4260..5bee0453 100644 --- a/lib/src/em_chat_room_manager.dart +++ b/lib/src/em_chat_room_manager.dart @@ -1329,9 +1329,12 @@ class EMChatRoomManager { ) async { Map req = { "roomId": roomId, - "keys": keys, }; + if (keys != null) { + req['keys'] = keys; + } + Map result = await _channel.invokeMethod( ChatMethodKeys.fetchChatRoomAttributes, req, From 4e607cb61ceb2234f543b37bb9cb986e176fe52c Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Mon, 29 May 2023 15:46:43 +0800 Subject: [PATCH 17/49] add onAppActiveNumberReachLimit callback. --- .../easemob/im_flutter_sdk/EMClientWrapper.java | 3 +++ .../com/easemob/im_flutter_sdk/EMSDKMethod.java | 2 +- ios/Classes/EMClientWrapper.m | 14 +++++++++++--- ios/Classes/EMSDKMethod.h | 1 + lib/src/em_client.dart | 8 ++++++++ lib/src/event_handler/manager_event_handler.dart | 15 +++++++++++++++ lib/src/internal/chat_method_keys.dart | 5 ++++- 7 files changed, 43 insertions(+), 5 deletions(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java index a36a3acb..a588cdd5 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java @@ -437,6 +437,9 @@ else if (errorCode == 202) { EMListenerHandle.getInstance().clearHandle(); post(() -> channel.invokeMethod(EMSDKMethod.onUserAuthenticationFailed, null)); } + else if (errorCode == 8) { + post(() -> channel.invokeMethod(EMSDKMethod.onAppActiveNumberReachLimit, null)); + } else { post(() -> channel.invokeMethod(EMSDKMethod.onDisconnected, null)); } diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java index f42c53ac..eb060d94 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java @@ -30,7 +30,7 @@ public class EMSDKMethod { static final String onUserDidLoginTooManyDevice = "onUserDidLoginTooManyDevice"; static final String onUserKickedByOtherDevice = "onUserKickedByOtherDevice"; static final String onUserAuthenticationFailed = "onUserAuthenticationFailed"; - + static final String onAppActiveNumberReachLimit = "onAppActiveNumberReachLimit"; static final String onMultiDeviceGroupEvent = "onMultiDeviceGroupEvent"; static final String onMultiDeviceContactEvent = "onMultiDeviceContactEvent"; static final String onMultiDeviceThreadEvent = "onMultiDeviceThreadEvent"; diff --git a/ios/Classes/EMClientWrapper.m b/ios/Classes/EMClientWrapper.m index f77b0298..f5e203f5 100644 --- a/ios/Classes/EMClientWrapper.m +++ b/ios/Classes/EMClientWrapper.m @@ -464,13 +464,20 @@ - (void)connectionStateDidChange:(EMConnectionState)aConnectionState { } - (void)autoLoginDidCompleteWithError:(EMError *)aError { - + if (aError.code == EMErrorServerServingForbidden) { + [self userDidForbidByServer]; + }else if (aError.code == EMAppActiveNumbersReachLimitation) { + [self activeNumbersReachLimitation]; + } +} + +- (void)activeNumbersReachLimitation { + [self.channel invokeMethod:ChatOnAppActiveNumberReachLimit arguments:nil]; } // 声网token即将过期 - (void)tokenWillExpire:(EMErrorCode)aErrorCode { - [self.channel invokeMethod:ChatOnTokenWillExpire - arguments:nil]; + [self.channel invokeMethod:ChatOnTokenWillExpire arguments:nil]; } // 声网token过期 @@ -498,6 +505,7 @@ - (void)userDidForbidByServer { arguments:nil]; } + - (void)userAccountDidForcedToLogout:(EMError *)aError { [EMListenerHandle.sharedInstance clearHandle]; if (aError.code == EMErrorUserKickedByChangePassword) { diff --git a/ios/Classes/EMSDKMethod.h b/ios/Classes/EMSDKMethod.h index 49d1acae..9a15f0b3 100644 --- a/ios/Classes/EMSDKMethod.h +++ b/ios/Classes/EMSDKMethod.h @@ -46,6 +46,7 @@ static NSString *const ChatOnUserAuthenticationFailed = @"onUserAuthenticationFa static NSString *const ChatSendDataToFlutter = @"onSendDataToFlutter"; static NSString *const ChatOnTokenWillExpire = @"onTokenWillExpire"; static NSString *const ChatOnTokenDidExpire = @"onTokenDidExpire"; +static NSString *const ChatOnAppActiveNumberReachLimit = @"onAppActiveNumberReachLimit"; #pragma mark - EMContactManagerWrapper static NSString *const ChatAddContact = @"addContact"; diff --git a/lib/src/em_client.dart b/lib/src/em_client.dart index 6bf24366..76a020fe 100644 --- a/lib/src/em_client.dart +++ b/lib/src/em_client.dart @@ -114,6 +114,8 @@ class EMClient { _onTokenWillExpire(argMap); } else if (call.method == ChatMethodKeys.onTokenDidExpire) { _onTokenDidExpire(argMap); + } else if (call.method == ChatMethodKeys.onAppActiveNumberReachLimit) { + _onAppActiveNumberReachLimit(argMap); } }); } @@ -814,6 +816,12 @@ class EMClient { } } + void _onAppActiveNumberReachLimit(Map? map) { + for (var item in _connectionEventHandler.values) { + item.onAppActiveNumberReachLimit?.call(); + } + } + Future _onMultiDeviceGroupEvent(Map map) async { EMMultiDevicesEvent event = convertIntToEMMultiDevicesEvent(map['event'])!; String target = map['target']; diff --git a/lib/src/event_handler/manager_event_handler.dart b/lib/src/event_handler/manager_event_handler.dart index 86b0dc94..8b03e50c 100644 --- a/lib/src/event_handler/manager_event_handler.dart +++ b/lib/src/event_handler/manager_event_handler.dart @@ -139,6 +139,15 @@ class EMConnectionEventHandler { /// ~end final VoidCallback? onTokenDidExpire; + /// ~english + /// The number of daily active users (DAU) or monthly active users (MAU) for the app has reached the upper limit . + /// ~end + /// + /// ~chinese + /// 应用程序的日活跃用户数量(DAU)或月活跃用户数量(MAU)达到上限。 + /// ~end + final VoidCallback? onAppActiveNumberReachLimit; + /// ~english /// The chat connection listener callback. /// @@ -163,6 +172,9 @@ class EMConnectionEventHandler { /// Param [onTokenWillExpire] The token is about to expire callback. /// /// Param [onTokenDidExpire] The token has expired callback. + /// + /// Param [onAppActiveNumberReachLimit] The number of daily active users (DAU) or monthly active users (MAU) for the app has reached the upper limit callback. + /// /// ~end /// /// ~chinese @@ -189,6 +201,8 @@ class EMConnectionEventHandler { /// Param [onTokenWillExpire] Agora token 即将过期时回调。 /// /// Param [onTokenDidExpire] Agora token 已过期时回调。 + /// + /// Param [onAppActiveNumberReachLimit] 应用程序的日活跃用户数量(DAU)或月活跃用户数量(MAU)达到上限时回调。 /// ~end EMConnectionEventHandler({ this.onConnected, @@ -202,6 +216,7 @@ class EMConnectionEventHandler { this.onUserAuthenticationFailed, this.onTokenWillExpire, this.onTokenDidExpire, + this.onAppActiveNumberReachLimit, }); } diff --git a/lib/src/internal/chat_method_keys.dart b/lib/src/internal/chat_method_keys.dart index 2f09e769..adb45893 100644 --- a/lib/src/internal/chat_method_keys.dart +++ b/lib/src/internal/chat_method_keys.dart @@ -25,7 +25,8 @@ class ChatMethodKeys { static const String onMultiDeviceGroupEvent = "onMultiDeviceGroupEvent"; static const String onMultiDeviceContactEvent = "onMultiDeviceContactEvent"; static const String onMultiDeviceThreadEvent = "onMultiDeviceThreadEvent"; - static const String onMultiDeviceRemoveMessagesEvent = "onMultiDeviceRemoveMessagesEvent"; + static const String onMultiDeviceRemoveMessagesEvent = + "onMultiDeviceRemoveMessagesEvent"; static const String onConnected = "onConnected"; static const String onDisconnected = "onDisconnected"; static const String onUserDidLoginFromOtherDevice = @@ -41,6 +42,8 @@ class ChatMethodKeys { static const String onSendDataToFlutter = "onSendDataToFlutter"; static const String onTokenWillExpire = "onTokenWillExpire"; static const String onTokenDidExpire = "onTokenDidExpire"; + static const String onAppActiveNumberReachLimit = + 'onAppActiveNumberReachLimit'; /// EMContactManager methods static const String addContact = "addContact"; From 371aa66d543bb83b6a1c030402acf0623716ea33 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Tue, 30 May 2023 17:36:05 +0800 Subject: [PATCH 18/49] update: fetch message method to support direction. --- CHANGELOG.md | 27 +++++++++++++++++++ .../im_flutter_sdk/EMChatManagerWrapper.java | 3 ++- ios/Classes/EMChatManagerWrapper.m | 8 ++---- lib/src/em_chat_manager.dart | 6 +++++ 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7940cb9d..3f2f9abf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,32 @@ ## NEXT +## 4.0.2 + +#### 新增: +- 增加 `GroupManager#setMemberAttributes` 方法,用于设置群成员属性; +- 增加 `GroupManager#fetchMemberAttributes` 和 `GroupManager#fetchMembersAttributes` 方法用户获取群成员属性; +- 增加 `GroupEventHandler#onAttributesChangedOfGroupMember` 群成员属性变更回调; +- 增加 `ChatManager#fetchHistoryMessagesByOption` 方法; +- 增加 `Conversation#deleteMessagesWithTs` 方法; +- 增加 `Message#deliverOnlineOnly` 属性用于设置只向在线用户投递消息; + +#### 修复: +- 修复安卓 hot reload 后回调多次的问题; +- 修复iOS 获取聊天室属性key传null导致的崩溃问题; + +#### 优化: +- 增加 + +## 4.0.0+7 + +#### 修复 +- 修复初始化无返回的问题。 + +## 4.0.0+6 + +#### 修复 +- 修复下载附件结束后状态不准确的问题。 + ## 4.0.0+5 #### 修复 diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java index 20feaa65..c819a2bc 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java @@ -672,10 +672,11 @@ private void fetchHistoryMessages(JSONObject param, String channelName, Result r EMConversationType type = EMConversationHelper.typeFromInt(param.getInt("type")); int pageSize = param.getInt("pageSize"); String startMsgId = param.getString("startMsgId"); + EMSearchDirection direction = param.optInt("direction") == 0 ? EMSearchDirection.UP : EMSearchDirection.DOWN; asyncRunnable(() -> { try { EMCursorResult cursorResult = EMClient.getInstance().chatManager().fetchHistoryMessages(conId, - type, pageSize, startMsgId); + type, pageSize, startMsgId, direction); onSuccess(result, channelName, EMCursorResultHelper.toJson(cursorResult)); } catch (HyphenateException e) { onError(result, e); diff --git a/ios/Classes/EMChatManagerWrapper.m b/ios/Classes/EMChatManagerWrapper.m index 7fa057a7..4c455298 100644 --- a/ios/Classes/EMChatManagerWrapper.m +++ b/ios/Classes/EMChatManagerWrapper.m @@ -670,12 +670,8 @@ - (void)fetchHistoryMessages:(NSDictionary *)param EMConversationType type = (EMConversationType)[param[@"type"] intValue]; int pageSize = [param[@"pageSize"] intValue]; NSString *startMsgId = param[@"startMsgId"]; - [EMClient.sharedClient.chatManager asyncFetchHistoryMessagesFromServer:conversationId - conversationType:type - startMessageId:startMsgId - pageSize:pageSize - completion:^(EMCursorResult *aResult, EMError *aError) - { + EMMessageFetchHistoryDirection direction = [param[@"direction"] intValue] == 0 ? EMMessageFetchHistoryDirectionUp : EMMessageFetchHistoryDirectionDown; + [EMClient.sharedClient.chatManager asyncFetchHistoryMessagesFromServer:conversationId conversationType:type startMessageId:startMsgId fetchDirection:direction pageSize:pageSize completion:^(EMCursorResult * _Nullable aResult, EMError * _Nullable aError) { [weakSelf wrapperCallBack:result channelName:aChannelName error:aError diff --git a/lib/src/em_chat_manager.dart b/lib/src/em_chat_manager.dart index 42b5c3fd..9c036941 100644 --- a/lib/src/em_chat_manager.dart +++ b/lib/src/em_chat_manager.dart @@ -919,6 +919,8 @@ class EMChatManager { /// /// Param [pageSize] The number of messages per page. /// + /// Param [direction] The direction of the search to be fetched. See [EMSearchDirection]. + /// /// Param [startMsgId] The ID of the message from which you start to get the historical messages. If `null` is passed, the SDK gets messages in reverse chronological order. /// /// **Return** The obtained messages and the cursor for the next fetch action. @@ -935,6 +937,8 @@ class EMChatManager { /// /// Param [pageSize] 每页获取的消息数量。 /// + /// Param [direction] 要搜索的消息方向. 见 [EMSearchDirection]. + /// /// Param [startMsgId] 获取历史消息的开始消息 ID,如果为空,从最新的消息向前开始获取。 /// /// **Return** 返回消息列表和用于继续获取历史消息的 [EMCursorResult] @@ -945,6 +949,7 @@ class EMChatManager { required String conversationId, EMConversationType type = EMConversationType.Chat, int pageSize = 20, + EMSearchDirection direction = EMSearchDirection.Up, String startMsgId = '', }) async { Map req = Map(); @@ -952,6 +957,7 @@ class EMChatManager { req['type'] = conversationTypeToInt(type); req['pageSize'] = pageSize; req['startMsgId'] = startMsgId; + req['direction'] = direction.index; Map result = await ChatChannel.invokeMethod( ChatMethodKeys.fetchHistoryMessages, req); try { From 56ec6ef8c9ec41a6985a3cdd93a6fdc2f90134d0 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Tue, 30 May 2023 17:37:29 +0800 Subject: [PATCH 19/49] update --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f2f9abf..73516cce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ - 修复iOS 获取聊天室属性key传null导致的崩溃问题; #### 优化: -- 增加 +- 为`ChatManager#fetchHistoryMessages` 方法增加获取方向; ## 4.0.0+7 From 304aa8362d76ca209f094e13bc60bc573a1c7e1e Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Fri, 9 Jun 2023 17:15:51 +0800 Subject: [PATCH 20/49] optimize android --- .../im_flutter_sdk/EMClientWrapper.java | 26 +++++++++++----- .../EMContactManagerWrapper.java | 6 ++-- .../im_flutter_sdk/EMConversationWrapper.java | 1 - .../im_flutter_sdk/EMGroupManagerWrapper.java | 30 +++++++++++-------- .../im_flutter_sdk/EMPushManagerWrapper.java | 7 +++-- ios/Classes/EMChatMessage+Helper.m | 4 ++- 6 files changed, 47 insertions(+), 27 deletions(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java index a588cdd5..33cc5be9 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java @@ -195,7 +195,9 @@ private void changeAppKey(JSONObject param, String channelName, Result result) t } private void getCurrentUser(JSONObject param, String channelName, Result result) throws JSONException { - onSuccess(result, channelName, EMClient.getInstance().getCurrentUser()); + asyncRunnable(()->{ + onSuccess(result, channelName, EMClient.getInstance().getCurrentUser()); + }); } private void loginWithAgoraToken(JSONObject param, String channelName, Result result) throws JSONException { @@ -216,15 +218,21 @@ public void onSuccess() { } private void getToken(JSONObject param, String channelName, Result result) throws JSONException { - onSuccess(result, channelName, EMClient.getInstance().getAccessToken()); + asyncRunnable(()->{ + onSuccess(result, channelName, EMClient.getInstance().getAccessToken()); + }); } private void isLoggedInBefore(JSONObject param, String channelName, Result result) throws JSONException { - onSuccess(result, channelName, EMClient.getInstance().isLoggedInBefore()); + asyncRunnable(()->{ + onSuccess(result, channelName, EMClient.getInstance().isLoggedInBefore()); + }); } private void isConnected(JSONObject param, String channelName, Result result) throws JSONException{ - onSuccess(result, channelName, EMClient.getInstance().isConnected()); + asyncRunnable(()->{ + onSuccess(result, channelName, EMClient.getInstance().isConnected()); + }); } private void uploadLog(JSONObject param, String channelName, Result result) throws JSONException { @@ -269,7 +277,6 @@ private void kickAllDevices(JSONObject param, String channelName, Result result) onError(result, e); } }); - } private void init(JSONObject param, String channelName, Result result) throws JSONException { @@ -283,19 +290,22 @@ private void init(JSONObject param, String channelName, Result result) throws JS bindingManagers(); registerEaseListener(); + onSuccess(result, channelName, null); } private void renewToken(JSONObject param, String channelName, Result result) throws JSONException { String agoraToken = param.getString("agora_token"); - EMClient.getInstance().renewToken(agoraToken); - onSuccess(result, channelName, null); + asyncRunnable(()->{ + EMClient.getInstance().renewToken(agoraToken); + onSuccess(result, channelName, null); + }); } private void getLoggedInDevicesFromServer(JSONObject param, String channelName, Result result) throws JSONException { String username = param.getString("username"); String password = param.getString("password"); - new Thread(() -> { + asyncRunnable(()->{ try { List devices = EMClient.getInstance().getLoggedInDevicesFromServer(username, password); List jsonList = new ArrayList <>(); diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMContactManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMContactManagerWrapper.java index c1f8f56e..663ab912 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMContactManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMContactManagerWrapper.java @@ -150,8 +150,10 @@ private void getBlockListFromServer(JSONObject params, String channelName, Resul } private void getBlockListFromDB(JSONObject params, String channelName, Result result) throws JSONException { - List contacts = EMClient.getInstance().contactManager().getBlackListUsernames(); - onSuccess(result, channelName, contacts); + asyncRunnable(()->{ + List contacts = EMClient.getInstance().contactManager().getBlackListUsernames(); + onSuccess(result, channelName, contacts); + }); } private void acceptInvitation(JSONObject params, String channelName, Result result) throws JSONException { diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java index 31d3485f..069bad39 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java @@ -106,7 +106,6 @@ else if (EMSDKMethod.removeMsgFromServerWithTimeStamp.equals(call.method)) { private void getUnreadMsgCount(JSONObject params, String channelName, Result result) throws JSONException { EMConversation conversation = conversationWithParam(params); - asyncRunnable(()->{ onSuccess(result, channelName, conversation.getUnreadMsgCount()); }); diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java index 6bc15f1a..62b7de0c 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java @@ -148,22 +148,26 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) { private void getGroupWithId(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - EMGroup group = EMClient.getInstance().groupManager().getGroup(groupId); - if (group != null) { - onSuccess(result, channelName, EMGroupHelper.toJson(group)); - } else { - onSuccess(result, channelName, null); - } + asyncRunnable(() -> { + EMGroup group = EMClient.getInstance().groupManager().getGroup(groupId); + if (group != null) { + onSuccess(result, channelName, EMGroupHelper.toJson(group)); + } else { + onSuccess(result, channelName, null); + } + }); } private void getJoinedGroups(JSONObject param, String channelName, Result result) throws JSONException { - EMClient.getInstance().groupManager().loadAllGroups(); - List groups = EMClient.getInstance().groupManager().getAllGroups(); - List groupList = new ArrayList<>(); - for (EMGroup group : groups) { - groupList.add(EMGroupHelper.toJson(group)); - } - onSuccess(result, channelName, groupList); + asyncRunnable(() -> { + EMClient.getInstance().groupManager().loadAllGroups(); + List groups = EMClient.getInstance().groupManager().getAllGroups(); + List groupList = new ArrayList<>(); + for (EMGroup group : groups) { + groupList.add(EMGroupHelper.toJson(group)); + } + onSuccess(result, channelName, groupList); + }); } private void getJoinedGroupsFromServer(JSONObject param, String channelName, Result result) throws JSONException { diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMPushManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMPushManagerWrapper.java index a1d10370..e0faf3c6 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMPushManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMPushManagerWrapper.java @@ -113,8 +113,11 @@ else if (EMSDKMethod.setPushTemplate.equals(call.method)) { } private void getImPushConfig(JSONObject params, String channelName, Result result) throws JSONException { - EMPushConfigs configs = EMClient.getInstance().pushManager().getPushConfigs(); - onSuccess(result, channelName, EMPushConfigsHelper.toJson(configs)); + asyncRunnable(()->{ + EMPushConfigs configs = EMClient.getInstance().pushManager().getPushConfigs(); + onSuccess(result, channelName, EMPushConfigsHelper.toJson(configs)); + }); + } private void getImPushConfigFromServer(JSONObject params, String channelName, Result result) throws JSONException { diff --git a/ios/Classes/EMChatMessage+Helper.m b/ios/Classes/EMChatMessage+Helper.m index 83dfddf1..7c1186b9 100644 --- a/ios/Classes/EMChatMessage+Helper.m +++ b/ios/Classes/EMChatMessage+Helper.m @@ -533,7 +533,9 @@ + (EMVideoMessageBody *)fromJson:(NSDictionary *)aJson { ret.secretKey = aJson[@"secret"]; ret.remotePath = aJson[@"remotePath"]; ret.fileLength = [aJson[@"fileSize"] longLongValue]; - ret.thumbnailLocalPath = aJson[@"thumbnailLocalPath"]; + if (aJson[@"thumbnailLocalPath"]) { + ret.thumbnailLocalPath = aJson[@"thumbnailLocalPath"]; + } ret.thumbnailRemotePath = aJson[@"thumbnailRemotePath"]; ret.thumbnailSecretKey = aJson[@"thumbnailSecret"]; ret.thumbnailDownloadStatus = [EMMessageBody downloadStatusFromInt:[aJson[@"thumbnailStatus"] intValue]]; From 4381877b6aec3e1ed30bafb245999d874c8d99ef Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Fri, 9 Jun 2023 18:47:01 +0800 Subject: [PATCH 21/49] optimize android --- .../java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java index 62b7de0c..ef399fde 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java @@ -160,7 +160,6 @@ private void getGroupWithId(JSONObject param, String channelName, Result result) private void getJoinedGroups(JSONObject param, String channelName, Result result) throws JSONException { asyncRunnable(() -> { - EMClient.getInstance().groupManager().loadAllGroups(); List groups = EMClient.getInstance().groupManager().getAllGroups(); List groupList = new ArrayList<>(); for (EMGroup group : groups) { From b343592bf6278feed04822525a9ccbdeccc8d2c2 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Fri, 16 Jun 2023 10:46:16 +0800 Subject: [PATCH 22/49] reset ignore files. --- .gitignore | 91 +++++++--------- example/ios/Podfile.lock | 29 ++++++ example/pubspec.lock | 220 +++++++++++++++++++++++++++++++++++++++ im_flutter_sdk.iml | 19 ---- pubspec.lock | 165 +++++++++++++++++++++++++++++ 5 files changed, 450 insertions(+), 74 deletions(-) create mode 100644 example/ios/Podfile.lock create mode 100644 example/pubspec.lock delete mode 100644 im_flutter_sdk.iml create mode 100644 pubspec.lock diff --git a/.gitignore b/.gitignore index 64300f43..8d9f1809 100644 --- a/.gitignore +++ b/.gitignore @@ -1,63 +1,44 @@ - +# Miscellaneous +*.class +*.log +*.pyc +*.swp .DS_Store -.dart_tool/ -.idea +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. .vscode -# *.iml -gitpull.sh -gitpush.sh +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies .packages +.pub-cache/ .pub/ +/build/ -build/ -*.lock -*.*~ -example/*.lock -example/ios/Podfile.lock.classpath -.project -.settings -**/*.classpath - -# Android related -# **/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -# **/android/gradlew -# **/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java -**/android/key.properties -*.jks +# Symbolication related +app.*.symbols -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* -# android/gradle/wrapper/gradle-wrapper.properties +# Obfuscation related +app.*.map.json -.history/ -**/*/.flutter-plugins-dependencies -.fvm/ \ No newline at end of file +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock new file mode 100644 index 00000000..03a60fb4 --- /dev/null +++ b/example/ios/Podfile.lock @@ -0,0 +1,29 @@ +PODS: + - Flutter (1.0.0) + - HyphenateChat (4.0.2) + - im_flutter_sdk (0.0.1): + - Flutter + - HyphenateChat (= 4.0.2) + +DEPENDENCIES: + - Flutter (from `Flutter`) + - im_flutter_sdk (from `.symlinks/plugins/im_flutter_sdk/ios`) + +SPEC REPOS: + trunk: + - HyphenateChat + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + im_flutter_sdk: + :path: ".symlinks/plugins/im_flutter_sdk/ios" + +SPEC CHECKSUMS: + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + HyphenateChat: add908a7200ba951a5b27a0fa2514ea6f532e69c + im_flutter_sdk: 9d47f25fb0815b9ae5a7c157e1ccda245fb3a321 + +PODFILE CHECKSUM: 7368163408c647b7eb699d0d788ba6718e18fb8d + +COCOAPODS: 1.11.3 diff --git a/example/pubspec.lock b/example/pubspec.lock new file mode 100644 index 00000000..d2243315 --- /dev/null +++ b/example/pubspec.lock @@ -0,0 +1,220 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" + source: hosted + version: "1.17.1" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" + source: hosted + version: "1.0.5" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 + url: "https://pub.dev" + source: hosted + version: "1.0.4" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + http: + dependency: "direct main" + description: + name: http + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + url: "https://pub.dev" + source: hosted + version: "0.13.6" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + im_flutter_sdk: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "4.0.2" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + lints: + dependency: transitive + description: + name: lints + sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c + url: "https://pub.dev" + source: hosted + version: "1.0.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" + source: hosted + version: "0.12.15" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" + source: hosted + version: "0.5.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" +sdks: + dart: ">=3.0.0-0 <4.0.0" + flutter: ">=2.0.0" diff --git a/im_flutter_sdk.iml b/im_flutter_sdk.iml deleted file mode 100644 index 429df7da..00000000 --- a/im_flutter_sdk.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 00000000..5762bdc0 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,165 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" + source: hosted + version: "1.17.1" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + matcher: + dependency: transitive + description: + name: matcher + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" + source: hosted + version: "0.12.15" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" + source: hosted + version: "0.5.1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" +sdks: + dart: ">=3.0.0-0 <4.0.0" + flutter: ">=2.0.0" From 74319080519529efe9f5b6d44c1d51ab33775f91 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Fri, 16 Jun 2023 12:55:16 +0800 Subject: [PATCH 23/49] fix fetch group member attributes error. --- .../im_flutter_sdk/EMGroupManagerWrapper.java | 33 ++++++- .../easemob/im_flutter_sdk/EMSDKMethod.java | 2 +- ios/Classes/EMGroupManagerWrapper.m | 36 ++++++- ios/Classes/EMSDKMethod.h | 1 + lib/src/em_chat_room_manager.dart | 6 +- lib/src/em_group_manager.dart | 98 +++++++++++++++---- lib/src/internal/chat_method_keys.dart | 10 +- 7 files changed, 153 insertions(+), 33 deletions(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java index ef399fde..9137d2b4 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMGroupManagerWrapper.java @@ -134,6 +134,8 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) { declineInvitationFromGroup(param, call.method, result); } else if (EMSDKMethod.setMemberAttributesFromGroup.equals(call.method)) { setMemberAttributes(param, call.method, result); + } else if (EMSDKMethod.removeMemberAttributesFromGroup.equals(call.method)) { + removeMemberAttributes(param, call.method, result); } else if (EMSDKMethod.fetchMemberAttributesFromGroup.equals(call.method)) { fetchMemberAttributes(param, call.method, result); } else if (EMSDKMethod.fetchMembersAttributesFromGroup.equals(call.method)) { @@ -832,8 +834,10 @@ private void declineInvitationFromGroup(JSONObject param, String channelName, Re private void setMemberAttributes(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String userId = param.getString("userId"); - + String userId = param.optString("userId"); + if (userId == "") { + userId = EMClient.getInstance().getCurrentUser(); + } Map attributes = new HashMap<>(); JSONObject jsonObject = param.getJSONObject("attributes"); @@ -846,15 +850,34 @@ private void setMemberAttributes(JSONObject param, String channelName, Result re EMClient.getInstance().groupManager().asyncSetGroupMemberAttributes(groupId, userId, attributes, new EMWrapperCallBack(result, channelName, null)); } - private void fetchMemberAttributes(JSONObject param, String channelName, Result result) throws JSONException { + private void removeMemberAttributes(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String userId = param.getString("userId"); + String userId = param.optString("userId"); + if (userId == "") { + userId = EMClient.getInstance().getCurrentUser(); + } + Map attributes = new HashMap<>(); + + JSONArray ja = param.getJSONArray("keys"); + for (int i = 0; i < ja.length(); i++) { + attributes.put(ja.optString(i),"" ); + } + EMClient.getInstance().groupManager().asyncSetGroupMemberAttributes(groupId, userId, attributes, new EMWrapperCallBack(result, channelName, null)); + } + + private void fetchMemberAttributes(JSONObject param, String channelName, Result result) throws JSONException { + String groupId = param.getString("groupId"); + String userId = param.optString("userId"); + if (userId == "") { + userId = EMClient.getInstance().getCurrentUser(); + } + String finalUserId = userId; EMClient.getInstance().groupManager().asyncFetchGroupMemberAllAttributes(groupId, userId, new EMValueWrapperCallBack>>(result, channelName){ @Override public void onSuccess(Map> object) { - updateObject(object.get(userId)); + updateObject(object.get(finalUserId)); } }); } diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java index eb060d94..61046ba9 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java @@ -228,8 +228,8 @@ public class EMSDKMethod { static final String acceptInvitationFromGroup = "acceptInvitationFromGroup"; static final String declineInvitationFromGroup = "declineInvitationFromGroup"; static final String setMemberAttributesFromGroup = "setMemberAttributesFromGroup"; + static final String removeMemberAttributesFromGroup = "removeMemberAttributesFromGroup"; static final String fetchMemberAttributesFromGroup = "fetchMemberAttributesFromGroup"; - static final String fetchMembersAttributesFromGroup = "fetchMembersAttributesFromGroup"; /// EMGroupManagerListener diff --git a/ios/Classes/EMGroupManagerWrapper.m b/ios/Classes/EMGroupManagerWrapper.m index 8d7e951d..081e2e0b 100644 --- a/ios/Classes/EMGroupManagerWrapper.m +++ b/ios/Classes/EMGroupManagerWrapper.m @@ -305,6 +305,9 @@ - (void)handleMethodCall:(FlutterMethodCall*)call else if ([ChatSetMemberAttributesFromGroup isEqualToString:call.method]) { [self setMemberAttributes:call.arguments channelName:call.method result:result]; } + else if ([ChatRemoveMemberAttributesFromGroup isEqualToString:call.method]) { + [self removeMemberAttributes:call.arguments channelName:call.method result:result]; + } else if ([ChatFetchMemberAttributesFromGroup isEqualToString:call.method]) { [self fetchMemberAttributes:call.arguments channelName:call.method result:result]; } @@ -934,6 +937,9 @@ - (void)setMemberAttributes:(NSDictionary *)param channelName:(NSString *)aChann NSString *groupId = param[@"groupId"]; NSString *userId = param[@"userId"]; + if(userId == nil){ + userId = EMClient.sharedClient.currentUsername; + } NSDictionary *attributes = param[@"attributes"]; [EMClient.sharedClient.groupManager setMemberAttribute:groupId @@ -948,12 +954,40 @@ - (void)setMemberAttributes:(NSDictionary *)param channelName:(NSString *)aChann }]; } -- (void)fetchMemberAttributes:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { +- (void)removeMemberAttributes:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self) weakSelf = self; NSString *groupId = param[@"groupId"]; NSString *userId = param[@"userId"]; + if(userId == nil){ + userId = EMClient.sharedClient.currentUsername; + } + NSArray *keys = param[@"keys"]; + NSMutableDictionary *attrs = [NSMutableDictionary dictionary]; + for (NSString *key in keys) { + attrs[key] = @""; + } + + [EMClient.sharedClient.groupManager setMemberAttribute:groupId + userId:userId + attributes:attrs + completion:^(EMError * _Nullable error) + { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:error + object:nil]; + }]; +} +- (void)fetchMemberAttributes:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { + __weak typeof(self) weakSelf = self; + + NSString *groupId = param[@"groupId"]; + NSString *userId = param[@"userId"]; + if(userId == nil){ + userId = EMClient.sharedClient.currentUsername; + } [EMClient.sharedClient.groupManager fetchMemberAttribute:groupId userId:userId completion:^(NSDictionary * properties, EMError * aError) diff --git a/ios/Classes/EMSDKMethod.h b/ios/Classes/EMSDKMethod.h index 9a15f0b3..fc9df04e 100644 --- a/ios/Classes/EMSDKMethod.h +++ b/ios/Classes/EMSDKMethod.h @@ -242,6 +242,7 @@ static NSString *const ChatDeclineJoinApplication = @"declineJoinApplication"; static NSString *const ChatAcceptInvitationFromGroup = @"acceptInvitationFromGroup"; static NSString *const ChatDeclineInvitationFromGroup = @"declineInvitationFromGroup"; static NSString *const ChatSetMemberAttributesFromGroup = @"setMemberAttributesFromGroup"; +static NSString *const ChatRemoveMemberAttributesFromGroup = @"removeMemberAttributesFromGroup"; static NSString *const ChatFetchMemberAttributesFromGroup = @"fetchMemberAttributesFromGroup"; static NSString *const ChatFetchMembersAttributesFromGroup = @"fetchMembersAttributesFromGroup"; diff --git a/lib/src/em_chat_room_manager.dart b/lib/src/em_chat_room_manager.dart index 5bee0453..65b75aac 100644 --- a/lib/src/em_chat_room_manager.dart +++ b/lib/src/em_chat_room_manager.dart @@ -1323,10 +1323,10 @@ class EMChatRoomManager { /// /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 /// ~end - Future?> fetchChatRoomAttributes( - String roomId, + Future?> fetchChatRoomAttributes({ + required String roomId, List? keys, - ) async { + }) async { Map req = { "roomId": roomId, }; diff --git a/lib/src/em_group_manager.dart b/lib/src/em_group_manager.dart index cfe18805..f60732cc 100644 --- a/lib/src/em_group_manager.dart +++ b/lib/src/em_group_manager.dart @@ -1,7 +1,6 @@ // ignore_for_file: deprecated_member_use_from_same_package import 'dart:async'; - import 'package:flutter/services.dart'; import 'internal/inner_headers.dart'; @@ -1846,7 +1845,7 @@ class EMGroupManager { /// /// Param [groupId] The group ID. /// - /// Param [userId] The user ID of the group member for whom the custom attributes are set. + /// Param [userId] The user ID of the group member for whom the custom attributes are set, The default is the current user. /// /// Param [attributes] The map of custom attributes in key-value format. In a key-value pair, /// if the value is set to an empty string, the custom attribute will be deleted. @@ -1859,7 +1858,7 @@ class EMGroupManager { /// /// Param [groupId] 群组 ID。 /// - /// Param [userId] 要设置自定义属性的群成员的用户 ID。 + /// Param [userId] 要设置自定义属性的群成员的用户 ID,默认为当前用户。 /// /// Param [attributes] 要设置的群成员自定义属性的 map,为 key-value 格式。对于一个 key-value 键值对,若 value 设置空字符串即删除该自定义属性。 /// @@ -1867,10 +1866,15 @@ class EMGroupManager { /// ~end Future setMemberAttributes({ required String groupId, - required String userId, required Map attributes, + String? userId, }) async { - Map req = {'groupId': groupId, 'userId': userId}; + Map req = { + 'groupId': groupId, + }; + if (userId != null) { + req.add('userId', userId); + } req.add('attributes', attributes); Map result = await _channel.invokeMethod( ChatMethodKeys.setMemberAttributesFromGroup, req); @@ -1881,12 +1885,57 @@ class EMGroupManager { } } + /// ~english + /// Removes custom attributes of a group member. + /// + /// Param [groupId] The group ID. + /// + /// Param [keys] The custom attributes corresponding key. + /// + /// Param [userId] The user ID of the group member for whom the custom attributes are remove, The default is the current user. + /// + /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 设置群成员自定义属性。 + /// + /// Param [groupId] 群组 ID。 + /// + /// Param [keys] 要删除群成员自定义属性对应的key。 + /// + /// Param [userId] 要设置自定义属性的群成员的用户 ID,默认为当前用户。 + /// + /// + /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 + /// ~end + Future removeMemberAttributes({ + required String groupId, + required List keys, + String? userId, + }) async { + Map req = { + 'groupId': groupId, + }; + if (userId != null) { + req.add('userId', userId); + } + req.add('keys', keys); + Map result = await _channel.invokeMethod( + ChatMethodKeys.removeMemberAttributesFromGroup, req); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } + } + /// ~english /// Gets all custom attributes of a group member. /// /// Param [groupId] The group ID. /// - /// Param [userId] The user ID of the group member whose all custom attributes are retrieved. + /// Param [userId] The user ID of the group member whose all custom attributes are retrieved. The default is the current user. /// /// **Return** The user attributes. /// @@ -1898,23 +1947,30 @@ class EMGroupManager { /// /// Param [groupId] 群组 ID。 /// - /// Param [userId] 要获取的自定义属性的群成员的用户 ID。 + /// Param [userId] 要获取的自定义属性的群成员的用户 ID, 默认为当前用户。 /// /// **Return** 需要查询的用户属性。 /// /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 /// ~end - Future?> fetchMemberAttributes({ + Future> fetchMemberAttributes({ required String groupId, - required String userId, + String? userId, }) async { - Map req = {'groupId': groupId, 'userId': userId}; + Map req = {'groupId': groupId}; + if (userId != null) { + req.add('userId', userId); + } Map result = await _channel.invokeMethod( ChatMethodKeys.fetchMemberAttributesFromGroup, req); try { EMError.hasErrorFromResult(result); - return result[ChatMethodKeys.fetchMemberAttributesFromGroup] - ?.cast(); + Map ret = {}; + result[ChatMethodKeys.fetchMemberAttributesFromGroup] + .forEach((key, value) { + ret[key] = value; + }); + return ret; } on EMError catch (e) { throw e; } @@ -1948,7 +2004,7 @@ class EMGroupManager { /// /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 /// ~end - Future>?> fetchMembersAttributes({ + Future>> fetchMembersAttributes({ required String groupId, required List userIds, List? keys, @@ -1959,10 +2015,18 @@ class EMGroupManager { ChatMethodKeys.fetchMembersAttributesFromGroup, req); try { EMError.hasErrorFromResult(result); - - // TODO: 需要验证 - return result[ChatMethodKeys.fetchMembersAttributesFromGroup] - ?.cast>>(); + var map = result[ChatMethodKeys.fetchMembersAttributesFromGroup]; + Map> ret = {}; + if (map is Map) { + map.keys.forEach((element) { + if (map[element] is Map) { + Map value = + Map.from(map[element] ?? {}); + ret[element] = value; + } + }); + } + return ret; } on EMError catch (e) { throw e; } diff --git a/lib/src/internal/chat_method_keys.dart b/lib/src/internal/chat_method_keys.dart index adb45893..c43b9b59 100644 --- a/lib/src/internal/chat_method_keys.dart +++ b/lib/src/internal/chat_method_keys.dart @@ -257,12 +257,10 @@ class ChatMethodKeys { static const String declineJoinApplication = "declineJoinApplication"; static const String acceptInvitationFromGroup = "acceptInvitationFromGroup"; static const String declineInvitationFromGroup = "declineInvitationFromGroup"; - static const String setMemberAttributesFromGroup = - "setMemberAttributesFromGroup"; - static const String fetchMemberAttributesFromGroup = - "fetchMemberAttributesFromGroup"; - static const String fetchMembersAttributesFromGroup = - "fetchMembersAttributesFromGroup"; + static const String setMemberAttributesFromGroup = "setMemberAttributesFromGroup"; + static const String removeMemberAttributesFromGroup = "removeMemberAttributesFromGroup"; + static const String fetchMemberAttributesFromGroup = "fetchMemberAttributesFromGroup"; + static const String fetchMembersAttributesFromGroup = "fetchMembersAttributesFromGroup"; /// EMGroupManagerListener static const String onGroupChanged = "onGroupChanged"; From 3cc568e4969f18db787acf7e7cc1fc3893ba32b8 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Fri, 16 Jun 2023 13:38:55 +0800 Subject: [PATCH 24/49] fix: ios fetchMessagesByOptions error. --- ios/Classes/EMFetchServerMessagesOption+Helper.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/Classes/EMFetchServerMessagesOption+Helper.m b/ios/Classes/EMFetchServerMessagesOption+Helper.m index 5816bde6..525f750c 100644 --- a/ios/Classes/EMFetchServerMessagesOption+Helper.m +++ b/ios/Classes/EMFetchServerMessagesOption+Helper.m @@ -12,8 +12,8 @@ @implementation EMFetchServerMessagesOption (Helper) + (EMFetchServerMessagesOption *)formJson:(NSDictionary *)dict { EMFetchServerMessagesOption *options = [[EMFetchServerMessagesOption alloc] init]; options.direction = [dict[@"direction"] isEqualToString:@"up"] ? EMMessageSearchDirectionUp : EMMessageSearchDirectionDown; - options.startTime = [dict[@"startTs"] intValue]; - options.endTime = [dict[@"endTs"] intValue]; + options.startTime = [dict[@"startTs"] longValue]; + options.endTime = [dict[@"endTs"] longValue]; options.from = dict[@"from"]; options.isSave = [dict[@"needSave"] boolValue]; NSArray *types = dict[@"msgTypes"]; From 082e4af326572d132eb7be5f0e8b211f37ec50f6 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Fri, 16 Jun 2023 16:35:41 +0800 Subject: [PATCH 25/49] fix: ios deleteMessagesWithTs error. --- ios/Classes/EMConversationWrapper.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/Classes/EMConversationWrapper.m b/ios/Classes/EMConversationWrapper.m index 2d41cb95..37cc25fa 100644 --- a/ios/Classes/EMConversationWrapper.m +++ b/ios/Classes/EMConversationWrapper.m @@ -337,8 +337,8 @@ - (void)clearAllMessages:(NSDictionary *)param channelName:(NSString *)aChannelN - (void)deleteMessagesWithTs:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self) weakSelf = self; - int startTs = [param[@"startTs"] intValue]; - int endTs = [param[@"endTs"] intValue]; + long startTs = [param[@"startTs"] longValue]; + long endTs = [param[@"endTs"] longValue]; [self getConversationWithParam:param completion:^(EMConversation *conversation){ EMError *error = [conversation removeMessagesStart:startTs to:endTs]; From 772545ef9a6944cf2a39c7eb1bc03d7711bf63c7 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Tue, 20 Jun 2023 13:58:41 +0800 Subject: [PATCH 26/49] dart files format --- lib/src/event_handler/manager_event_handler.dart | 2 +- lib/src/internal/chat_method_keys.dart | 12 ++++++++---- lib/src/models/em_error.dart | 1 - 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/src/event_handler/manager_event_handler.dart b/lib/src/event_handler/manager_event_handler.dart index 8b03e50c..c379975d 100644 --- a/lib/src/event_handler/manager_event_handler.dart +++ b/lib/src/event_handler/manager_event_handler.dart @@ -201,7 +201,7 @@ class EMConnectionEventHandler { /// Param [onTokenWillExpire] Agora token 即将过期时回调。 /// /// Param [onTokenDidExpire] Agora token 已过期时回调。 - /// + /// /// Param [onAppActiveNumberReachLimit] 应用程序的日活跃用户数量(DAU)或月活跃用户数量(MAU)达到上限时回调。 /// ~end EMConnectionEventHandler({ diff --git a/lib/src/internal/chat_method_keys.dart b/lib/src/internal/chat_method_keys.dart index c43b9b59..a0dab2f6 100644 --- a/lib/src/internal/chat_method_keys.dart +++ b/lib/src/internal/chat_method_keys.dart @@ -257,10 +257,14 @@ class ChatMethodKeys { static const String declineJoinApplication = "declineJoinApplication"; static const String acceptInvitationFromGroup = "acceptInvitationFromGroup"; static const String declineInvitationFromGroup = "declineInvitationFromGroup"; - static const String setMemberAttributesFromGroup = "setMemberAttributesFromGroup"; - static const String removeMemberAttributesFromGroup = "removeMemberAttributesFromGroup"; - static const String fetchMemberAttributesFromGroup = "fetchMemberAttributesFromGroup"; - static const String fetchMembersAttributesFromGroup = "fetchMembersAttributesFromGroup"; + static const String setMemberAttributesFromGroup = + "setMemberAttributesFromGroup"; + static const String removeMemberAttributesFromGroup = + "removeMemberAttributesFromGroup"; + static const String fetchMemberAttributesFromGroup = + "fetchMemberAttributesFromGroup"; + static const String fetchMembersAttributesFromGroup = + "fetchMembersAttributesFromGroup"; /// EMGroupManagerListener static const String onGroupChanged = "onGroupChanged"; diff --git a/lib/src/models/em_error.dart b/lib/src/models/em_error.dart index 8ecb8138..37882181 100644 --- a/lib/src/models/em_error.dart +++ b/lib/src/models/em_error.dart @@ -47,4 +47,3 @@ class EMError { return "code: " + code.toString() + " desc: " + description; } } - From 4567d12a7bf9c2a53c1e2f56006d256badace9c1 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Sun, 25 Jun 2023 16:46:37 +0800 Subject: [PATCH 27/49] update ios to 403 --- .../im_flutter_sdk/EMChatManagerWrapper.java | 12 +- .../im_flutter_sdk/EMConversationWrapper.java | 4 +- .../com/easemob/im_flutter_sdk/EMHelper.java | 2 +- ios/Classes/EMChatManagerWrapper.m | 71 +++- ios/Classes/EMChatMessage+Helper.m | 6 +- ios/Classes/EMClientWrapper.m | 16 +- ios/Classes/EMConversation+Helper.m | 2 +- ios/Classes/EMConversationWrapper.m | 2 +- ios/Classes/EMOptions+Helper.m | 2 + ios/Classes/EMSDKMethod.h | 6 +- ios/Classes/ImFlutterSdkPlugin.m | 11 + ios/im_flutter_sdk.podspec | 2 +- lib/src/em_chat_manager.dart | 375 ++++++++++++------ lib/src/em_chat_room_manager.dart | 8 +- lib/src/em_chat_thread_manager.dart | 8 +- lib/src/em_client.dart | 12 + lib/src/em_contact_manager.dart | 2 +- lib/src/em_group_manager.dart | 34 +- lib/src/em_userInfo_manager.dart | 16 +- .../event_handler/manager_event_handler.dart | 28 +- lib/src/internal/chat_method_keys.dart | 8 + lib/src/internal/em_push_config.dart | 30 +- lib/src/internal/em_transform_tools.dart | 8 + lib/src/models/chat_silent_mode.dart | 10 +- lib/src/models/em_chat_enums.dart | 28 ++ lib/src/models/em_chat_room.dart | 22 +- lib/src/models/em_conversation.dart | 63 ++- lib/src/models/em_deviceInfo.dart | 6 +- lib/src/models/em_group.dart | 30 +- lib/src/models/em_group_options.dart | 2 +- lib/src/models/em_group_shared_file.dart | 10 +- lib/src/models/em_message.dart | 115 +++--- lib/src/models/em_options.dart | 61 ++- lib/src/models/fetch_message_options.dart | 13 +- lib/src/tools/em_extension.dart | 2 +- pubspec.yaml | 2 +- 36 files changed, 700 insertions(+), 329 deletions(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java index c819a2bc..1b3eba12 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java @@ -256,7 +256,7 @@ private void ackGroupMessageRead(JSONObject param, String channelName, Result re } private void ackConversationRead(JSONObject param, String channelName, Result result) throws JSONException { - String conversationId = param.getString("con_id"); + String conversationId = param.getString("convId"); asyncRunnable(() -> { try { EMClient.getInstance().chatManager().ackConversationRead(conversationId); @@ -299,7 +299,7 @@ private void getMessage(JSONObject param, String channelName, Result result) thr } private void getConversation(JSONObject param, String channelName, Result result) throws JSONException { - String conId = param.getString("con_id"); + String conId = param.getString("convId"); boolean createIfNeed = true; if (param.has("createIfNeed")) { createIfNeed = param.getBoolean("createIfNeed"); @@ -315,7 +315,7 @@ private void getConversation(JSONObject param, String channelName, Result result } private void getThreadConversation(JSONObject param, String channelName, Result result) throws JSONException { - String conId = param.getString("con_id"); + String conId = param.getString("convId"); asyncRunnable(() -> { EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conId, EMConversationType.GroupChat, true, true); onSuccess(result, channelName, conversation != null ? EMConversationHelper.toJson(conversation) : null); @@ -659,7 +659,7 @@ public int compare(EMConversation o1, EMConversation o2) { } private void deleteConversation(JSONObject param, String channelName, Result result) throws JSONException { - String conId = param.getString("con_id"); + String conId = param.getString("convId"); boolean isDelete = param.getBoolean("deleteMessages"); asyncRunnable(() -> { boolean ret = EMClient.getInstance().chatManager().deleteConversation(conId, isDelete); @@ -668,7 +668,7 @@ private void deleteConversation(JSONObject param, String channelName, Result res } private void fetchHistoryMessages(JSONObject param, String channelName, Result result) throws JSONException { - String conId = param.getString("con_id"); + String conId = param.getString("convId"); EMConversationType type = EMConversationHelper.typeFromInt(param.getInt("type")); int pageSize = param.getInt("pageSize"); String startMsgId = param.getString("startMsgId"); @@ -685,7 +685,7 @@ private void fetchHistoryMessages(JSONObject param, String channelName, Result r } private void fetchHistoryMessagesByOptions(JSONObject param, String channelName, Result result) throws JSONException { - String conId = param.getString("con_id"); + String conId = param.getString("convId"); EMConversationType type = EMConversationHelper.typeFromInt(param.getInt("type")); int pageSize = param.getInt("pageSize"); String cursor = null; diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java index 069bad39..d8d4ea85 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java @@ -355,9 +355,9 @@ private void removeMsgFromServerWithTimeStamp(JSONObject params, String channelN } private EMConversation conversationWithParam(JSONObject params ) throws JSONException { - String con_id = params.getString("con_id"); + String convId = params.getString("convId"); EMConversation.EMConversationType type = EMConversationHelper.typeFromInt(params.getInt("type")); - EMConversation conversation = EMClient.getInstance().chatManager().getConversation(con_id, type, true); + EMConversation conversation = EMClient.getInstance().chatManager().getConversation(convId, type, true); return conversation; } diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java index 462eefce..76af57a4 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java @@ -956,7 +956,7 @@ class EMConversationHelper { static Map toJson(EMConversation conversation) { Map data = new HashMap<>(); - data.put("con_id", conversation.conversationId()); + data.put("convId", conversation.conversationId()); data.put("type", typeToInt(conversation.getType())); data.put("isThread", conversation.isChatThread()); try { diff --git a/ios/Classes/EMChatManagerWrapper.m b/ios/Classes/EMChatManagerWrapper.m index 4c455298..7690b7e5 100644 --- a/ios/Classes/EMChatManagerWrapper.m +++ b/ios/Classes/EMChatManagerWrapper.m @@ -182,7 +182,14 @@ - (void)handleMethodCall:(FlutterMethodCall*)call [self removeMessagesFromServerWithTs:call.arguments channelName:call.method result:result]; + } else if ([GetConversationsFromServerWithCursor isEqualToString:call.method]) { + [self getConversationsFromServerWithCursor:call.arguments channelName:call.method result:result]; + } else if ([GetPinnedConversationsFromServerWithCursor isEqualToString:call.method]) { + [self getPinnedConversationsFromServerWithCursor:call.arguments channelName:call.method result:result]; + } else if ([PinConversation isEqualToString:call.method]) { + [self pinConversation:call.arguments channelName:call.method result:result]; } + else { [super handleMethodCall:call result:result]; } @@ -314,7 +321,7 @@ - (void)ackConversationRead:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self) weakSelf = self; - NSString *conversationId = param[@"con_id"]; + NSString *conversationId = param[@"convId"]; [EMClient.sharedClient.chatManager ackConversationRead:conversationId completion:^(EMError *aError) { @@ -365,7 +372,7 @@ - (void)getConversation:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self) weakSelf = self; - NSString *conId = param[@"con_id"]; + NSString *conId = param[@"convId"]; EMConversationType type = [EMConversation typeFromInt:[param[@"type"] intValue]]; BOOL needCreate = [param[@"createIfNeed"] boolValue]; EMConversation *con = [EMClient.sharedClient.chatManager getConversation:conId @@ -382,7 +389,7 @@ - (void)getThreadConversation:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self) weakSelf = self; - NSString *conId = param[@"con_id"]; + NSString *conId = param[@"convId"]; EMConversation *conversation = [EMClient.sharedClient.chatManager getConversation:conId type:EMConversationTypeGroupChat createIfNotExist:YES @@ -603,16 +610,10 @@ - (NSDictionary *)updateDownloadStatus:(EMDownloadStatus)status - (void)loadAllConversations:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { - NSArray *conversations = [EMClient.sharedClient.chatManager getAllConversations]; - NSArray *sortedList = [conversations sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) { - if (((EMConversation *)obj1).latestMessage.timestamp > ((EMConversation *)obj2).latestMessage.timestamp) { - return NSOrderedAscending; - }else { - return NSOrderedDescending; - } - }]; + NSArray *conversations = [EMClient.sharedClient.chatManager getAllConversations:YES]; + NSMutableArray *conList = [NSMutableArray array]; - for (EMConversation *conversation in sortedList) { + for (EMConversation *conversation in conversations) { [conList addObject:[conversation toJson]]; } @@ -649,7 +650,7 @@ - (void)deleteConversation:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self)weakSelf = self; - NSString *conversationId = param[@"con_id"]; + NSString *conversationId = param[@"convId"]; BOOL isDeleteMsgs = [param[@"deleteMessages"] boolValue]; [EMClient.sharedClient.chatManager deleteConversation:conversationId isDeleteMessages:isDeleteMsgs @@ -666,7 +667,7 @@ - (void)fetchHistoryMessages:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self)weakSelf = self; - NSString *conversationId = param[@"con_id"]; + NSString *conversationId = param[@"convId"]; EMConversationType type = (EMConversationType)[param[@"type"] intValue]; int pageSize = [param[@"pageSize"] intValue]; NSString *startMsgId = param[@"startMsgId"]; @@ -683,7 +684,7 @@ - (void)fetchHistoryMessagesByOptions:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self)weakSelf = self; - NSString *conversationId = param[@"con_id"]; + NSString *conversationId = param[@"convId"]; EMConversationType type = (EMConversationType)[param[@"type"] intValue]; int pageSize = [param[@"pageSize"] intValue]; NSString *cursor = param[@"cursor"]; @@ -1006,6 +1007,46 @@ - (void)removeMessagesFromServerWithTs:(NSDictionary *)param object:@(!aError)]; }]; } + +- (void)getConversationsFromServerWithCursor:(NSDictionary *)param + channelName:(NSString *)aChannelName + result:(FlutterResult)result { + __weak typeof(self) weakSelf = self; + NSString *cursor = param[@"cursor"]; + int pageSize = [param[@"pageSize"] intValue]; + [EMClient.sharedClient.chatManager getConversationsFromServerWithCursor:cursor pageSize:pageSize completion:^(EMCursorResult * _Nullable ret, EMError * _Nullable error) { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:error + object:[ret toJson]]; + }]; +} + +- (void)getPinnedConversationsFromServerWithCursor:(NSDictionary *)param + channelName:(NSString *)aChannelName + result:(FlutterResult)result { + __weak typeof(self) weakSelf = self; + NSString *cursor = param[@"cursor"]; + int pageSize = [param[@"pageSize"] intValue]; + [EMClient.sharedClient.chatManager getPinnedConversationsFromServerWithCursor:cursor pageSize:pageSize completion:^(EMCursorResult * _Nullable ret, EMError * _Nullable error) { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:error + object:[ret toJson]]; + }]; +} + +- (void)pinConversation:(NSDictionary *)param + channelName:(NSString *)aChannelName + result:(FlutterResult)result { + __weak typeof(self) weakSelf = self; + NSString *convId = param[@"convId"]; + BOOL isPinned = [param[@"isPinned"] boolValue]; + [EMClient.sharedClient.chatManager pinConversation:convId isPinned:isPinned completionBlock:^(EMError * _Nullable error) { + [weakSelf wrapperCallBack:result channelName:aChannelName error:error object:@(!error)]; + }]; +} + #pragma mark - EMChatManagerDelegate diff --git a/ios/Classes/EMChatMessage+Helper.m b/ios/Classes/EMChatMessage+Helper.m index 7c1186b9..30ef8d18 100644 --- a/ios/Classes/EMChatMessage+Helper.m +++ b/ios/Classes/EMChatMessage+Helper.m @@ -60,6 +60,10 @@ + (EMChatMessage *)fromJson:(NSDictionary *)aJson msg.priority = [aJson[@"chatroomMessagePriority"] integerValue]; } + if(aJson[@"receiverList"]) { + msg.receiverList = aJson[@"receiverList"]; + } + return msg; } @@ -85,7 +89,7 @@ - (NSDictionary *)toJson ret[@"body"] = [self.body toJson]; ret[@"onlineState"] = @(self.onlineState); ret[@"deliverOnlineOnly"] = @(self.deliverOnlineOnly); - + ret[@"receiverList"] = self.receiverList; return ret; } diff --git a/ios/Classes/EMClientWrapper.m b/ios/Classes/EMClientWrapper.m index f5e203f5..b805ab6b 100644 --- a/ios/Classes/EMClientWrapper.m +++ b/ios/Classes/EMClientWrapper.m @@ -562,14 +562,14 @@ - (void)multiDevicesMessageBeRemoved:(NSString *)conversationId deviceId:(NSStri [self.channel invokeMethod:ChatOnMultiDeviceRemoveMessagesEvent arguments:data]; } -- (void)applicationDidEnterBackground:(UIApplication *)application -{ - [[EMClient sharedClient] applicationDidEnterBackground:application]; -} - -- (void)applicationWillEnterForeground:(UIApplication *)application -{ - [[EMClient sharedClient] applicationWillEnterForeground:application]; +- (void)multiDevicesConversationEvent:(EMMultiDevicesEvent)event + conversationId:(NSString *)conversationId + conversationType:(EMConversationType)conversationType { + NSMutableDictionary *data = [NSMutableDictionary dictionary]; + data[@"event"] = @(event); + data[@"convId"] = conversationId; + data[@"convType"] = @(conversationType); + [self.channel invokeMethod:ChatOnMultiDevicesConversationEvent arguments:data]; } diff --git a/ios/Classes/EMConversation+Helper.m b/ios/Classes/EMConversation+Helper.m index b0c97fb1..8dd32e9b 100644 --- a/ios/Classes/EMConversation+Helper.m +++ b/ios/Classes/EMConversation+Helper.m @@ -11,7 +11,7 @@ @implementation EMConversation (Helper) - (NSDictionary *)toJson { NSMutableDictionary *ret = [NSMutableDictionary dictionary]; - ret[@"con_id"] = self.conversationId; + ret[@"convId"] = self.conversationId; ret[@"type"] = @([self.class typeToInt:self.type]); ret[@"ext"] = self.ext; ret[@"isThread"] = @(self.isChatThread); diff --git a/ios/Classes/EMConversationWrapper.m b/ios/Classes/EMConversationWrapper.m index 37cc25fa..7e833ff7 100644 --- a/ios/Classes/EMConversationWrapper.m +++ b/ios/Classes/EMConversationWrapper.m @@ -120,7 +120,7 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - (void)getConversationWithParam:(NSDictionary *)param completion:(void(^)(EMConversation *conversation))aCompletion { - __weak NSString *conversationId = param[@"con_id"]; + __weak NSString *conversationId = param[@"convId"]; EMConversationType type = [EMConversation typeFromInt:[param[@"type"] intValue]]; EMConversation *conversation = [EMClient.sharedClient.chatManager getConversation:conversationId type:type diff --git a/ios/Classes/EMOptions+Helper.m b/ios/Classes/EMOptions+Helper.m index e736acda..b05dda88 100644 --- a/ios/Classes/EMOptions+Helper.m +++ b/ios/Classes/EMOptions+Helper.m @@ -24,6 +24,7 @@ - (NSDictionary *)toJson { data[@"isAutoDownload"] = @(self.autoDownloadThumbnail); data[@"isChatRoomOwnerLeaveAllowed"] = @(self.canChatroomOwnerLeave); data[@"serverTransfer"] = @(self.isAutoTransferMessageAttachments); + data[@"loadEmptyConversations"] = @(self.loadEmptyConversations); data[@"usingHttpsOnly"] = @(self.usingHttpsOnly); data[@"pushConfig"] = @{@"pushConfig": @{@"apnsCertName": self.apnsCertName}}; data[@"enableDNSConfig"] = @(self.enableDnsConfig); @@ -49,6 +50,7 @@ + (EMOptions *)fromJson:(NSDictionary *)aJson { options.autoDownloadThumbnail = [aJson[@"isAutoDownload"] boolValue]; options.canChatroomOwnerLeave = [aJson[@"isChatRoomOwnerLeaveAllowed"] boolValue]; options.isAutoTransferMessageAttachments = [aJson[@"serverTransfer"] boolValue]; + options.loadEmptyConversations = [aJson[@"loadEmptyConversations"] boolValue]; options.usingHttpsOnly = [aJson[@"usingHttpsOnly"] boolValue]; options.apnsCertName = aJson[@"pushConfig"][@"apnsCertName"]; options.enableDnsConfig = [aJson[@"enableDNSConfig"] boolValue]; diff --git a/ios/Classes/EMSDKMethod.h b/ios/Classes/EMSDKMethod.h index fc9df04e..f32364e2 100644 --- a/ios/Classes/EMSDKMethod.h +++ b/ios/Classes/EMSDKMethod.h @@ -27,11 +27,12 @@ static NSString *const ChatGetCurrentUser = @"getCurrentUser"; static NSString *const ChatIsLoggedInBefore = @"isLoggedInBefore"; static NSString *const ChatIsConnected = @"isConnected"; - static NSString *const ChatOnMultiDeviceGroupEvent = @"onMultiDeviceGroupEvent"; static NSString *const ChatOnMultiDeviceContactEvent = @"onMultiDeviceContactEvent"; static NSString *const ChatOnMultiDeviceThreadEvent = @"onMultiDeviceThreadEvent"; static NSString *const ChatOnMultiDeviceRemoveMessagesEvent = @"onMultiDeviceRemoveMessagesEvent"; +static NSString *const ChatOnMultiDevicesConversationEvent = @"onMultiDevicesConversationEvent"; + #pragma mark - EMClientDelegate static NSString *const ChatOnConnected = @"onConnected"; static NSString *const ChatOnDisconnected = @"onDisconnected"; @@ -103,6 +104,9 @@ static NSString *const ChatFetchConversationsFromServerWithPage = @"fetchConvers static NSString *const ChatRemoveMessagesFromServerWithMsgIds = @"removeMessagesFromServerWithMsgIds"; static NSString *const ChatRemoveMessagesFromServerWithTs = @"removeMessagesFromServerWithTs"; +static NSString *const GetConversationsFromServerWithCursor = @"getConversationsFromServerWithCursor"; +static NSString *const GetPinnedConversationsFromServerWithCursor = @"getPinnedConversationsFromServerWithCursor"; +static NSString *const PinConversation = @"pinConversation"; #pragma mark - EMChatManagerDelegate static NSString *const ChatOnMessagesReceived = @"onMessagesReceived"; diff --git a/ios/Classes/ImFlutterSdkPlugin.m b/ios/Classes/ImFlutterSdkPlugin.m index 3dd572a7..a7f6b33a 100644 --- a/ios/Classes/ImFlutterSdkPlugin.m +++ b/ios/Classes/ImFlutterSdkPlugin.m @@ -17,5 +17,16 @@ + (void)registerWithRegistrar:(NSObject*)registrar { [registrar publish:wrapper]; } +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + [[EMClient sharedClient] applicationDidEnterBackground:application]; +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + [[EMClient sharedClient] applicationWillEnterForeground:application]; +} + + @end diff --git a/ios/im_flutter_sdk.podspec b/ios/im_flutter_sdk.podspec index d4803d2a..bd9262de 100644 --- a/ios/im_flutter_sdk.podspec +++ b/ios/im_flutter_sdk.podspec @@ -21,7 +21,7 @@ A new flutter plugin project. s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' - s.dependency 'HyphenateChat','4.0.2' + s.dependency 'HyphenateChat','4.0.3' s.ios.deployment_target = '11.0' end diff --git a/lib/src/em_chat_manager.dart b/lib/src/em_chat_manager.dart index 9c036941..4cd1fb62 100644 --- a/lib/src/em_chat_manager.dart +++ b/lib/src/em_chat_manager.dart @@ -297,7 +297,7 @@ class EMChatManager { "msg_id": msgId, "group_id": groupId, }; - req.add("content", content); + req.putIfNotNull("content", content); Map result = await ChatChannel.invokeMethod(ChatMethodKeys.ackGroupMessageRead, req); @@ -335,7 +335,7 @@ class EMChatManager { /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 /// ~end Future sendConversationReadAck(String conversationId) async { - Map req = {"con_id": conversationId}; + Map req = {"convId": conversationId}; Map result = await ChatChannel.invokeMethod(ChatMethodKeys.ackConversationRead, req); try { @@ -447,7 +447,7 @@ class EMChatManager { bool createIfNeed = true, }) async { Map req = { - "con_id": conversationId, + "convId": conversationId, "type": conversationTypeToInt(type), "createIfNeed": createIfNeed }; @@ -487,7 +487,7 @@ class EMChatManager { Future getThreadConversation(String threadId) async { Map result = await ChatChannel.invokeMethod( ChatMethodKeys.getThreadConversation, - {"con_id", threadId}, + {"convId", threadId}, ); try { @@ -705,6 +705,8 @@ class EMChatManager { } } + @Deprecated('Use [fetchConversation] instead') + /// ~english /// Gets the conversation list from the server. /// @@ -739,6 +741,8 @@ class EMChatManager { } } + @Deprecated('Use [fetchConversation] instead') + /// ~english /// fetch the conversations from the server. /// @@ -787,6 +791,59 @@ class EMChatManager { } } + /// ~english + /// Get the list of conversations from the server with pagination. + /// + /// The SDK retrieves the list of conversations in the reverse chronological order of their active time (the timestamp of the last message). + /// If there is no message in the conversation, the SDK retrieves the list of conversations in the reverse chronological order of their creation time. + /// + /// Param [cursor] The position from which to start getting data. the SDK retrieves conversations from the latest active one if no set. + /// + /// Param [pageSize] The number of conversations that you expect to get on each page. The value range is [1,50]. + /// + /// **Return** The conversation list of the current user. + /// + /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 分页从服务器获取获取会话列表。 + /// + /// SDK 按照会话活跃时间(会话的最后一条消息的时间戳)倒序返回会话列表。 + /// 若会话中没有消息,则 SDK 按照会话创建时间的倒序返回会话列表。 + /// + /// Param [cursor] 查询的开始位置,如不传, SDK 从最新活跃的会话开始获取。 + /// + /// Param [pageSize] 每页期望返回的会话数量。取值范围为 [1,50]。 + /// + /// **Return** 当前用户的会话列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end + Future> fetchConversation({ + String? cursor, + int pageSize = 20, + }) async { + Map map = { + "pageSize": pageSize, + }; + map.putIfNotNull('cursor', cursor); + Map result = await ChatChannel.invokeMethod( + ChatMethodKeys.getConversationsFromServerWithCursor, + map, + ); + try { + EMError.hasErrorFromResult(result); + return EMCursorResult.fromJson( + result[ChatMethodKeys.getConversationsFromServerWithCursor], + dataItemCallback: (map) { + return EMConversation.fromJson(map); + }); + } on EMError catch (e) { + throw e; + } + } + /// ~english /// Unidirectionally removes historical message by message ID from the server. /// @@ -899,7 +956,7 @@ class EMChatManager { String conversationId, { bool deleteMessages = true, }) async { - Map req = {"con_id": conversationId, "deleteMessages": deleteMessages}; + Map req = {"convId": conversationId, "deleteMessages": deleteMessages}; Map result = await ChatChannel.invokeMethod(ChatMethodKeys.deleteConversation, req); try { @@ -953,7 +1010,7 @@ class EMChatManager { String startMsgId = '', }) async { Map req = Map(); - req['con_id'] = conversationId; + req['convId'] = conversationId; req['type'] = conversationTypeToInt(type); req['pageSize'] = pageSize; req['startMsgId'] = startMsgId; @@ -1007,11 +1064,11 @@ class EMChatManager { int pageSize = 50, }) async { Map req = Map(); - req.add('con_id', conversationId); - req.add('type', conversationTypeToInt(type)); - req.add('pageSize', pageSize); - req.add('cursor', cursor); - req.add('options', options?.toJson()); + req.putIfNotNull('convId', conversationId); + req.putIfNotNull('type', conversationTypeToInt(type)); + req.putIfNotNull('pageSize', pageSize); + req.putIfNotNull('cursor', cursor); + req.putIfNotNull('options', options?.toJson()); Map result = await ChatChannel.invokeMethod( ChatMethodKeys.fetchHistoryMessagesByOptions, req); try { @@ -1133,7 +1190,7 @@ class EMChatManager { }) async { Map req = {"msg_id": msgId, "group_id": groupId}; req["pageSize"] = pageSize; - req.add("ack_id", startAckId); + req.putIfNotNull("ack_id", startAckId); Map result = await ChatChannel.invokeMethod(ChatMethodKeys.asyncFetchGroupAcks, req); @@ -1232,104 +1289,6 @@ class EMChatManager { } } - Future _onMessagesReceived(List messages) async { - List messageList = []; - for (var message in messages) { - messageList.add(EMMessage.fromJson(message)); - } - - for (var item in _eventHandlesMap.values) { - item.onMessagesReceived?.call(messageList); - } - } - - Future _onCmdMessagesReceived(List messages) async { - List list = []; - for (var message in messages) { - list.add(EMMessage.fromJson(message)); - } - - for (var item in _eventHandlesMap.values) { - item.onCmdMessagesReceived?.call(list); - } - } - - Future _onMessagesRead(List messages) async { - List list = []; - for (var message in messages) { - list.add(EMMessage.fromJson(message)); - } - - for (var item in _eventHandlesMap.values) { - item.onMessagesRead?.call(list); - } - } - - Future _onGroupMessageRead(List messages) async { - List list = []; - for (var message in messages) { - list.add(EMGroupMessageAck.fromJson(message)); - } - - for (var item in _eventHandlesMap.values) { - item.onGroupMessageRead?.call(list); - } - } - - Future _onReadAckForGroupMessageUpdated(List messages) async { - for (var item in _eventHandlesMap.values) { - item.onReadAckForGroupMessageUpdated?.call(); - } - } - - Future _onMessagesDelivered(List messages) async { - List list = []; - for (var message in messages) { - list.add(EMMessage.fromJson(message)); - } - - for (var item in _eventHandlesMap.values) { - item.onMessagesDelivered?.call(list); - } - } - - Future _onMessagesRecalled(List messages) async { - List list = []; - for (var message in messages) { - list.add(EMMessage.fromJson(message)); - } - - for (var item in _eventHandlesMap.values) { - item.onMessagesRecalled?.call(list); - } - } - - Future _onConversationsUpdate(dynamic obj) async { - for (var item in _eventHandlesMap.values) { - item.onConversationsUpdate?.call(); - } - } - - Future _onConversationHasRead(dynamic obj) async { - String from = (obj as Map)['from']; - String to = obj['to']; - - for (var item in _eventHandlesMap.values) { - item.onConversationRead?.call(from, to); - } - } - - Future _messageReactionDidChange(List reactionChangeList) async { - List list = []; - for (var reactionChange in reactionChangeList) { - list.add(EMMessageReactionEvent.fromJson(reactionChange)); - } - - for (var item in _eventHandlesMap.values) { - item.onMessageReactionDidChange?.call(list); - } - } - /// ~english /// Reports an inappropriate message. /// @@ -1470,7 +1429,7 @@ class EMChatManager { "msgIds": messageIds, "chatType": chatTypeToInt(chatType), }; - req.add("groupId", groupId); + req.putIfNotNull("groupId", groupId); Map result = await ChatChannel.invokeMethod( ChatMethodKeys.fetchReactionList, req, @@ -1533,8 +1492,8 @@ class EMChatManager { "msgId": messageId, "reaction": reaction, }; - req.add("cursor", cursor); - req.add("pageSize", pageSize); + req.putIfNotNull("cursor", cursor); + req.putIfNotNull("pageSize", pageSize); Map result = await ChatChannel.invokeMethod(ChatMethodKeys.fetchReactionDetail, req); @@ -1620,6 +1579,98 @@ class EMChatManager { } } + /// ~english + /// Gets the list of pinned conversations from the server with pagination. + /// + /// The SDK returns the pinned conversations in the reverse chronological order of their pinning. + /// + /// Param [cursor] The position from which to start getting data. the SDK retrieves conversations from the latest pinned one if no set. + /// + /// Param [pageSize] The number of conversations that you expect to get on each page. The value range is [1,50]. + /// + /// **Return** The pinned conversation list of the current user. + /// + /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 分页从服务器获取置顶会话。 + /// + /// SDK 按照会话的置顶时间的倒序返回会话列表。 + /// + /// Param [cursor] 查询的开始位置,如不传, SDK 从最新置顶的会话开始查询。 + /// + /// Param [pageSize] 每页期望返回的会话数量。取值范围为 [1,50]。 + /// + /// **Return** 当前用户的置顶会话列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end + Future> fetchPinnedConversations({ + String? cursor, + int pageSize = 20, + }) async { + Map map = { + "pageSize": pageSize, + }; + map.putIfNotNull('cursor', cursor); + Map result = await ChatChannel.invokeMethod( + ChatMethodKeys.getPinnedConversationsFromServerWithCursor, + map, + ); + try { + EMError.hasErrorFromResult(result); + return EMCursorResult.fromJson( + result[ChatMethodKeys.getPinnedConversationsFromServerWithCursor], + dataItemCallback: (map) { + return EMConversation.fromJson(map); + }); + } on EMError catch (e) { + throw e; + } + } + + /// ~english + /// Sets whether to pin a conversation. + /// + /// Param [conversationId] The conversation ID. + /// + /// Param [isPinned] Whether to pin a conversation: + /// - true: Pin the conversation. + /// - false: Unpin the conversation. + /// + /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 设置是否置顶会话。 + /// + /// Param [conversationId] 会话 ID。 + /// + /// Param [isPinned] 是否置顶会话: + /// - true: 置顶会话。 + /// - false: 取消置顶会话。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end + Future pinConversation( + {required String conversationId, required bool isPinned}) async { + Map map = { + 'convId': conversationId, + 'isPinned': 'isPinned', + }; + + Map result = await ChatChannel.invokeMethod( + ChatMethodKeys.pinConversation, + map, + ); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } + } + /// ~english /// Adds a message status listener. /// @@ -1664,6 +1715,104 @@ class EMChatManager { void clearMessageEvent() { MessageCallBackManager.getInstance.clearAllMessageEvents(); } + + Future _onMessagesReceived(List messages) async { + List messageList = []; + for (var message in messages) { + messageList.add(EMMessage.fromJson(message)); + } + + for (var item in _eventHandlesMap.values) { + item.onMessagesReceived?.call(messageList); + } + } + + Future _onCmdMessagesReceived(List messages) async { + List list = []; + for (var message in messages) { + list.add(EMMessage.fromJson(message)); + } + + for (var item in _eventHandlesMap.values) { + item.onCmdMessagesReceived?.call(list); + } + } + + Future _onMessagesRead(List messages) async { + List list = []; + for (var message in messages) { + list.add(EMMessage.fromJson(message)); + } + + for (var item in _eventHandlesMap.values) { + item.onMessagesRead?.call(list); + } + } + + Future _onGroupMessageRead(List messages) async { + List list = []; + for (var message in messages) { + list.add(EMGroupMessageAck.fromJson(message)); + } + + for (var item in _eventHandlesMap.values) { + item.onGroupMessageRead?.call(list); + } + } + + Future _onReadAckForGroupMessageUpdated(List messages) async { + for (var item in _eventHandlesMap.values) { + item.onReadAckForGroupMessageUpdated?.call(); + } + } + + Future _onMessagesDelivered(List messages) async { + List list = []; + for (var message in messages) { + list.add(EMMessage.fromJson(message)); + } + + for (var item in _eventHandlesMap.values) { + item.onMessagesDelivered?.call(list); + } + } + + Future _onMessagesRecalled(List messages) async { + List list = []; + for (var message in messages) { + list.add(EMMessage.fromJson(message)); + } + + for (var item in _eventHandlesMap.values) { + item.onMessagesRecalled?.call(list); + } + } + + Future _onConversationsUpdate(dynamic obj) async { + for (var item in _eventHandlesMap.values) { + item.onConversationsUpdate?.call(); + } + } + + Future _onConversationHasRead(dynamic obj) async { + String from = (obj as Map)['from']; + String to = obj['to']; + + for (var item in _eventHandlesMap.values) { + item.onConversationRead?.call(from, to); + } + } + + Future _messageReactionDidChange(List reactionChangeList) async { + List list = []; + for (var reactionChange in reactionChangeList) { + list.add(EMMessageReactionEvent.fromJson(reactionChange)); + } + + for (var item in _eventHandlesMap.values) { + item.onMessageReactionDidChange?.call(list); + } + } } /// ~english diff --git a/lib/src/em_chat_room_manager.dart b/lib/src/em_chat_room_manager.dart index 65b75aac..ce7df5fd 100644 --- a/lib/src/em_chat_room_manager.dart +++ b/lib/src/em_chat_room_manager.dart @@ -427,9 +427,9 @@ class EMChatRoomManager { Map req = Map(); req['subject'] = name; req['maxUserCount'] = maxUserCount; - req.add("desc", desc); - req.add("welcomeMsg", welcomeMsg); - req.add("members", members); + req.putIfNotNull("desc", desc); + req.putIfNotNull("welcomeMsg", welcomeMsg); + req.putIfNotNull("members", members); Map result = await _channel.invokeMethod(ChatMethodKeys.createChatRoom, req); try { @@ -581,7 +581,7 @@ class EMChatRoomManager { int pageSize = 200, }) async { Map req = {"roomId": roomId, "pageSize": pageSize}; - req.add("cursor", cursor); + req.putIfNotNull("cursor", cursor); Map result = await _channel.invokeMethod(ChatMethodKeys.fetchChatRoomMembers, req); try { diff --git a/lib/src/em_chat_thread_manager.dart b/lib/src/em_chat_thread_manager.dart index 7ed9418e..afbcd426 100644 --- a/lib/src/em_chat_thread_manager.dart +++ b/lib/src/em_chat_thread_manager.dart @@ -164,7 +164,7 @@ class EMChatThreadManager { int limit = 20, }) async { Map req = {"pageSize": limit}; - req.add("cursor", cursor); + req.putIfNotNull("cursor", cursor); Map result = await _channel.invokeMethod(ChatMethodKeys.fetchJoinedChatThreads, req); try { @@ -215,7 +215,7 @@ class EMChatThreadManager { "parentId": parentId, "pageSize": limit, }; - req.add("cursor", cursor); + req.putIfNotNull("cursor", cursor); Map result = await _channel.invokeMethod( ChatMethodKeys.fetchChatThreadsWithParentId, req); try { @@ -266,7 +266,7 @@ class EMChatThreadManager { "parentId": parentId, "pageSize": limit, }; - req.add("cursor", cursor); + req.putIfNotNull("cursor", cursor); Map result = await _channel.invokeMethod( ChatMethodKeys.fetchJoinedChatThreadsWithParentId, req); try { @@ -322,7 +322,7 @@ class EMChatThreadManager { "pageSize": limit, "threadId": chatThreadId, }; - req.add("cursor", cursor); + req.putIfNotNull("cursor", cursor); Map result = await _channel.invokeMethod( ChatMethodKeys.fetchChatThreadMember, req, diff --git a/lib/src/em_client.dart b/lib/src/em_client.dart index 76a020fe..eb2e62bc 100644 --- a/lib/src/em_client.dart +++ b/lib/src/em_client.dart @@ -108,6 +108,9 @@ class EMClient { } else if (call.method == ChatMethodKeys.onMultiDeviceRemoveMessagesEvent) { _onMultiDeviceRoamMessagesRemovedEvent(argMap!); + } else if (call.method == + ChatMethodKeys.onMultiDevicesConversationEvent) { + _onMultiDevicesConversationEvent(argMap!); } else if (call.method == ChatMethodKeys.onSendDataToFlutter) { _onReceiveCustomData(argMap!); } else if (call.method == ChatMethodKeys.onTokenWillExpire) { @@ -860,6 +863,15 @@ class EMClient { } } + Future _onMultiDevicesConversationEvent(Map map) async { + EMMultiDevicesEvent event = convertIntToEMMultiDevicesEvent(map['event'])!; + String convId = map['convId']; + EMConversationType type = conversationTypeFromInt(map['convType']); + for (var handler in _multiDeviceEventHandler.values) { + handler.onConversationEvent?.call(event, convId, type); + } + } + void _onReceiveCustomData(Map map) { customEventHandler?.call(map); } diff --git a/lib/src/em_contact_manager.dart b/lib/src/em_contact_manager.dart index b42cb76b..04a75bc6 100644 --- a/lib/src/em_contact_manager.dart +++ b/lib/src/em_contact_manager.dart @@ -150,7 +150,7 @@ class EMContactManager { Map req = { 'username': userId, }; - req.add("reason", reason); + req.putIfNotNull("reason", reason); Map result = await _channel.invokeMethod(ChatMethodKeys.addContact, req); try { diff --git a/lib/src/em_group_manager.dart b/lib/src/em_group_manager.dart index f60732cc..7d244c0d 100644 --- a/lib/src/em_group_manager.dart +++ b/lib/src/em_group_manager.dart @@ -249,7 +249,7 @@ class EMGroupManager { String? cursor, }) async { Map req = {'pageSize': pageSize}; - req.add("cursor", cursor); + req.putIfNotNull("cursor", cursor); Map result = await _channel.invokeMethod( ChatMethodKeys.getPublicGroupsFromServer, req); try { @@ -325,10 +325,10 @@ class EMGroupManager { required EMGroupOptions options, }) async { Map req = {'options': options.toJson()}; - req.add("groupName", groupName); - req.add("desc", desc); - req.add("inviteMembers", inviteMembers); - req.add("inviteReason", inviteReason); + req.putIfNotNull("groupName", groupName); + req.putIfNotNull("desc", desc); + req.putIfNotNull("inviteMembers", inviteMembers); + req.putIfNotNull("inviteReason", inviteReason); Map result = await _channel.invokeMethod(ChatMethodKeys.createGroup, req); try { @@ -429,7 +429,7 @@ class EMGroupManager { 'groupId': groupId, 'pageSize': pageSize, }; - req.add("cursor", cursor); + req.putIfNotNull("cursor", cursor); Map result = await _channel.invokeMethod( ChatMethodKeys.getGroupMemberListFromServer, req, @@ -738,7 +738,7 @@ class EMGroupManager { String? welcome, }) async { Map req = {'groupId': groupId, 'members': members}; - req.add("welcome", welcome); + req.putIfNotNull("welcome", welcome); Map result = await _channel.invokeMethod(ChatMethodKeys.addMembers, req); try { EMError.hasErrorFromResult(result); @@ -789,7 +789,7 @@ class EMGroupManager { 'groupId': groupId, 'members': members, }; - req.add("reason", reason); + req.putIfNotNull("reason", reason); Map result = await _channel.invokeMethod( ChatMethodKeys.inviterUser, @@ -1672,7 +1672,7 @@ class EMGroupManager { String? reason, }) async { Map req = {'groupId': groupId}; - req.add('reason', reason); + req.putIfNotNull('reason', reason); Map result = await _channel.invokeMethod( ChatMethodKeys.requestToJoinPublicGroup, req); try { @@ -1752,7 +1752,7 @@ class EMGroupManager { String? reason, }) async { Map req = {'groupId': groupId, 'username': username}; - req.add('reason', reason); + req.putIfNotNull('reason', reason); Map result = await _channel.invokeMethod(ChatMethodKeys.declineJoinApplication, req); @@ -1830,7 +1830,7 @@ class EMGroupManager { String? reason, }) async { Map req = {'groupId': groupId, 'inviter': inviter}; - req.add('reason', reason); + req.putIfNotNull('reason', reason); Map result = await _channel.invokeMethod( ChatMethodKeys.declineInvitationFromGroup, req); try { @@ -1873,9 +1873,9 @@ class EMGroupManager { 'groupId': groupId, }; if (userId != null) { - req.add('userId', userId); + req.putIfNotNull('userId', userId); } - req.add('attributes', attributes); + req.putIfNotNull('attributes', attributes); Map result = await _channel.invokeMethod( ChatMethodKeys.setMemberAttributesFromGroup, req); try { @@ -1918,9 +1918,9 @@ class EMGroupManager { 'groupId': groupId, }; if (userId != null) { - req.add('userId', userId); + req.putIfNotNull('userId', userId); } - req.add('keys', keys); + req.putIfNotNull('keys', keys); Map result = await _channel.invokeMethod( ChatMethodKeys.removeMemberAttributesFromGroup, req); try { @@ -1959,7 +1959,7 @@ class EMGroupManager { }) async { Map req = {'groupId': groupId}; if (userId != null) { - req.add('userId', userId); + req.putIfNotNull('userId', userId); } Map result = await _channel.invokeMethod( ChatMethodKeys.fetchMemberAttributesFromGroup, req); @@ -2010,7 +2010,7 @@ class EMGroupManager { List? keys, }) async { Map req = {'groupId': groupId, 'userIds': userIds}; - req.add("keys", keys); + req.putIfNotNull("keys", keys); Map result = await _channel.invokeMethod( ChatMethodKeys.fetchMembersAttributesFromGroup, req); try { diff --git a/lib/src/em_userInfo_manager.dart b/lib/src/em_userInfo_manager.dart index 8846e262..c64841f8 100644 --- a/lib/src/em_userInfo_manager.dart +++ b/lib/src/em_userInfo_manager.dart @@ -83,14 +83,14 @@ class EMUserInfoManager { String? ext, }) async { Map req = {}; - req.add("nickName", nickname); - req.add("avatarUrl", avatarUrl); - req.add("mail", mail); - req.add("phone", phone); - req.add("gender", gender); - req.add("sign", sign); - req.add("birth", birth); - req.add("ext", ext); + req.putIfNotNull("nickName", nickname); + req.putIfNotNull("avatarUrl", avatarUrl); + req.putIfNotNull("mail", mail); + req.putIfNotNull("phone", phone); + req.putIfNotNull("gender", gender); + req.putIfNotNull("sign", sign); + req.putIfNotNull("birth", birth); + req.putIfNotNull("ext", ext); try { Map result = diff --git a/lib/src/event_handler/manager_event_handler.dart b/lib/src/event_handler/manager_event_handler.dart index c379975d..4c4511f0 100644 --- a/lib/src/event_handler/manager_event_handler.dart +++ b/lib/src/event_handler/manager_event_handler.dart @@ -291,24 +291,29 @@ class EMMultiDeviceEventHandler { /// ~english /// Callback to other devices after conversation deleted message from server after enabling multiple devices. - /// - /// Param [conversationId] The conversation id. - /// - /// Param [deviceId] The device id. /// ~end /// /// ~chinese /// 开启多设备后对单个会话删除漫游消息后对其他设备的回调。 - /// - /// Param [conversationId] 被删除的会话id。 - /// - /// Param [deviceId] 操作删除的设备id。 /// ~end final void Function( String conversationId, String deviceId, )? onRemoteMessagesRemoved; + /// ~english + /// The multi-device event callback for the operation of a single conversation. + /// ~end + /// + /// ~chinese + /// 开启多设备后对单个会话删除漫游消息后对其他设备的回调。 + /// ~end + final void Function( + EMMultiDevicesEvent event, + String conversationId, + EMConversationType type, + )? onConversationEvent; + /// ~english /// The multi-device event handler. /// @@ -319,6 +324,9 @@ class EMMultiDeviceEventHandler { /// Param [onChatThreadEvent] The multi-device event of thread. /// /// Param [onRemoteMessagesRemoved] The multi-device event of roam messages removed. + /// + /// Param [onConversationEvent] The multi-device event callback for the operation of a single conversation. + /// /// ~end /// /// ~chinese @@ -331,12 +339,16 @@ class EMMultiDeviceEventHandler { /// Param [onChatThreadEvent] 多设备 Thread 事件。 /// /// Param [onRemoteMessagesRemoved] 多设备漫游消息删除事件。 + /// + /// Param [onConversationEvent] 多设备单个会话操作事件。 + /// /// ~end EMMultiDeviceEventHandler({ this.onContactEvent, this.onGroupEvent, this.onChatThreadEvent, this.onRemoteMessagesRemoved, + this.onConversationEvent, }); } diff --git a/lib/src/internal/chat_method_keys.dart b/lib/src/internal/chat_method_keys.dart index a0dab2f6..6219bc29 100644 --- a/lib/src/internal/chat_method_keys.dart +++ b/lib/src/internal/chat_method_keys.dart @@ -27,6 +27,8 @@ class ChatMethodKeys { static const String onMultiDeviceThreadEvent = "onMultiDeviceThreadEvent"; static const String onMultiDeviceRemoveMessagesEvent = "onMultiDeviceRemoveMessagesEvent"; + static const String onMultiDevicesConversationEvent = + "onMultiDevicesConversationEvent"; static const String onConnected = "onConnected"; static const String onDisconnected = "onDisconnected"; static const String onUserDidLoginFromOtherDevice = @@ -106,6 +108,12 @@ class ChatMethodKeys { static const String removeMessagesFromServerWithTs = "removeMessagesFromServerWithTs"; + static const String getConversationsFromServerWithCursor = + 'getConversationsFromServerWithCursor'; + static const String getPinnedConversationsFromServerWithCursor = + 'getPinnedConversationsFromServerWithCursor'; + static const String pinConversation = 'pinConversation'; + /// EMChatManager listener static const String onMessagesReceived = "onMessagesReceived"; static const String onCmdMessagesReceived = "onCmdMessagesReceived"; diff --git a/lib/src/internal/em_push_config.dart b/lib/src/internal/em_push_config.dart index 14c17d12..a9c30ba6 100644 --- a/lib/src/internal/em_push_config.dart +++ b/lib/src/internal/em_push_config.dart @@ -53,21 +53,21 @@ class EMPushConfig { /// @nodoc Map toJson() { final Map data = new Map(); - data.add("mzAppId", mzAppId); - data.add("mzAppKey", mzAppKey); - data.add("oppoAppKey", oppoAppKey); - data.add("oppoAppSecret", oppoAppSecret); - data.add("miAppId", miAppId); - data.add("miAppKey", miAppKey); - data.add("fcmId", fcmId); - data.add("apnsCertName", apnsCertName); - data.add("enableMeiZuPush", enableMeiZuPush); - data.add("enableOppoPush", enableOppoPush); - data.add("enableMiPush", enableMiPush); - data.add("enableFCM", enableFCM); - data.add("enableHWPush", enableHWPush); - data.add("enableVivoPush", enableVivoPush); - data.add("enableAPNS", enableAPNS); + data.putIfNotNull("mzAppId", mzAppId); + data.putIfNotNull("mzAppKey", mzAppKey); + data.putIfNotNull("oppoAppKey", oppoAppKey); + data.putIfNotNull("oppoAppSecret", oppoAppSecret); + data.putIfNotNull("miAppId", miAppId); + data.putIfNotNull("miAppKey", miAppKey); + data.putIfNotNull("fcmId", fcmId); + data.putIfNotNull("apnsCertName", apnsCertName); + data.putIfNotNull("enableMeiZuPush", enableMeiZuPush); + data.putIfNotNull("enableOppoPush", enableOppoPush); + data.putIfNotNull("enableMiPush", enableMiPush); + data.putIfNotNull("enableFCM", enableFCM); + data.putIfNotNull("enableHWPush", enableHWPush); + data.putIfNotNull("enableVivoPush", enableVivoPush); + data.putIfNotNull("enableAPNS", enableAPNS); return data; } diff --git a/lib/src/internal/em_transform_tools.dart b/lib/src/internal/em_transform_tools.dart index c2a25bf6..e1ea5694 100644 --- a/lib/src/internal/em_transform_tools.dart +++ b/lib/src/internal/em_transform_tools.dart @@ -65,6 +65,14 @@ EMMultiDevicesEvent? convertIntToEMMultiDevicesEvent(int? i) { return EMMultiDevicesEvent.CHAT_THREAD_KICK; case 45: return EMMultiDevicesEvent.CHAT_THREAD_UPDATE; + case 46: + return EMMultiDevicesEvent.GROUP_MEMBER_ATTRIBUTES_CHANGED; + case 60: + return EMMultiDevicesEvent.CONVERSATION_PINNED; + case 61: + return EMMultiDevicesEvent.CONVERSATION_UNPINNED; + case 62: + return EMMultiDevicesEvent.CONVERSATION_DELETE; } return null; } diff --git a/lib/src/models/chat_silent_mode.dart b/lib/src/models/chat_silent_mode.dart index 0cd84f34..4d200695 100644 --- a/lib/src/models/chat_silent_mode.dart +++ b/lib/src/models/chat_silent_mode.dart @@ -104,11 +104,11 @@ class ChatSilentModeParam { Map toJson() { Map data = Map(); - data.add("paramType", chatSilentModeParamTypeToInt(_paramType)); - data.add("remindType", chatPushRemindTypeToInt(remindType)); - data.add("startTime", startTime?.toJson()); - data.add("endTime", endTime?.toJson()); - data.add("duration", silentDuration); + data.putIfNotNull("paramType", chatSilentModeParamTypeToInt(_paramType)); + data.putIfNotNull("remindType", chatPushRemindTypeToInt(remindType)); + data.putIfNotNull("startTime", startTime?.toJson()); + data.putIfNotNull("endTime", endTime?.toJson()); + data.putIfNotNull("duration", silentDuration); return data; } } diff --git a/lib/src/models/em_chat_enums.dart b/lib/src/models/em_chat_enums.dart index 4f0398c1..eaeb219c 100644 --- a/lib/src/models/em_chat_enums.dart +++ b/lib/src/models/em_chat_enums.dart @@ -447,6 +447,7 @@ enum EMSearchDirection { /// /// 本枚举类以用户 A 同时登录设备 A1 和 设备 A2 为例,描述多设备登录各事件的触发时机。 /// ~end + enum EMMultiDevicesEvent { /// ~english /// The current user removed a contact on another device. @@ -790,6 +791,33 @@ enum EMMultiDevicesEvent { /// 若用户 A 在设备 A1 上修改群成员自定义属性,该事件会在登录该账号的其他设备触发。 /// ~end GROUP_MEMBER_ATTRIBUTES_CHANGED, + + /// ~english + /// If user A pins a conversation on device A1, this event is triggered on device A2 + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 置顶会话,则设备 A2 上会收到该事件。 + /// ~end + CONVERSATION_PINNED, + + /// ~english + /// If user A unpins a conversation on device A1, this event is triggered on device A2. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1取消置顶会话,则设备 A2 上会收到该事件。 + /// ~end + CONVERSATION_UNPINNED, + + /// ~english + /// If user A deletes a conversation on device A1, this event is triggered on device A2. + /// ~end + /// + /// ~chinese + /// 用户 A 在设备 A1 删除会话,则设备 A2 上会收到该事件。 + /// ~end + CONVERSATION_DELETE, } /// ~english diff --git a/lib/src/models/em_chat_room.dart b/lib/src/models/em_chat_room.dart index ee8a0f3b..057d61d6 100644 --- a/lib/src/models/em_chat_room.dart +++ b/lib/src/models/em_chat_room.dart @@ -54,17 +54,17 @@ class EMChatRoom { Map toJson() { final Map data = new Map(); data['roomId'] = roomId; - data.add("name", name); - data.add("desc", description); - data.add("owner", owner); - data.add("memberCount", memberCount); - data.add("maxUsers", maxUsers); - data.add("adminList", adminList); - data.add("memberList", memberList); - data.add("blockList", blockList); - data.add("muteList", muteList); - data.add("announcement", announcement); - data.add("isAllMemberMuted", isAllMemberMuted); + data.putIfNotNull("name", name); + data.putIfNotNull("desc", description); + data.putIfNotNull("owner", owner); + data.putIfNotNull("memberCount", memberCount); + data.putIfNotNull("maxUsers", maxUsers); + data.putIfNotNull("adminList", adminList); + data.putIfNotNull("memberList", memberList); + data.putIfNotNull("blockList", blockList); + data.putIfNotNull("muteList", muteList); + data.putIfNotNull("announcement", announcement); + data.putIfNotNull("isAllMemberMuted", isAllMemberMuted); data['permissionType'] = chatRoomPermissionTypeToInt(permissionType); return data; diff --git a/lib/src/models/em_conversation.dart b/lib/src/models/em_conversation.dart index d436fc4b..31c804cc 100644 --- a/lib/src/models/em_conversation.dart +++ b/lib/src/models/em_conversation.dart @@ -25,16 +25,25 @@ import '../internal/inner_headers.dart'; /// ``` /// ~end class EMConversation { - EMConversation._private(this.id, this.type, this._ext, this.isChatThread); + EMConversation._private( + this.id, + this.type, + this._ext, + this.isChatThread, + this.isPinned, + this.pinnedTime, + ); /// @nodoc factory EMConversation.fromJson(Map map) { Map? ext = map["ext"]?.cast(); EMConversation ret = EMConversation._private( - map["con_id"], + map["convId"], conversationTypeFromInt(map["type"]), ext, map["isThread"] ?? false, + map["isPinned"] ?? false, + map["pinnedTime"] ?? 0, ); return ret; @@ -44,7 +53,7 @@ class EMConversation { Map _toJson() { final Map data = new Map(); data["type"] = conversationTypeToInt(this.type); - data["con_id"] = this.id; + data["convId"] = this.id; data["isThread"] = this.isChatThread; return data; } @@ -90,16 +99,58 @@ class EMConversation { /// ~end final bool isChatThread; + /// ~english + /// Whether the conversation is pinned: + /// - `true`: Yes; + /// - `false`: No. + /// ~end + /// + /// ~chinese + /// 是否为置顶会话: + /// - `true`:是; + /// - `false`:否。 + /// ~end + final bool isPinned; + + /// ~english + /// The UNIX timestamp when the conversation is pinned. The unit is millisecond. This value is `0` when the conversation is not pinned. + /// ~end + /// + /// ~chinese + /// 会话置顶的 UNIX 时间戳,单位为毫秒。未置顶时值为 `0`。 + /// ~end + final int pinnedTime; + Map? _ext; static const MethodChannel _emConversationChannel = const MethodChannel('com.chat.im/chat_conversation', JSONMethodCodec()); + /// ~english + /// The conversation extension attribute. + /// + /// This attribute is not available for thread conversations. + /// ~end + /// ~chinese + /// 获取会话扩展属性。 + /// + /// 子区功能目前版本暂不可设置。 + /// ~end Map? get ext => _ext; + /// ~english + /// Set the conversation extension attribute. + /// + /// This attribute is not available for thread conversations. + /// ~end + /// ~chinese + /// 设置会话扩展属性。 + /// + /// 子区功能目前版本暂不可设置。 + /// ~end Future setExt(Map? ext) async { Map req = this._toJson(); - req.add("ext", ext); + req.putIfNotNull("ext", ext); Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.syncConversationExt, req); try { @@ -518,7 +569,7 @@ class EMConversation { req['timestamp'] = timestamp; req['count'] = count; req['direction'] = direction == EMSearchDirection.Up ? "up" : "down"; - req.add("sender", sender); + req.putIfNotNull("sender", sender); Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.loadMsgWithMsgType, req); try { @@ -648,7 +699,7 @@ class EMConversation { req['count'] = count; req['timestamp'] = timestamp; req['direction'] = direction == EMSearchDirection.Up ? "up" : "down"; - req.add("sender", sender); + req.putIfNotNull("sender", sender); Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.loadMsgWithKeywords, req); diff --git a/lib/src/models/em_deviceInfo.dart b/lib/src/models/em_deviceInfo.dart index 7374c1f9..9d5199c0 100644 --- a/lib/src/models/em_deviceInfo.dart +++ b/lib/src/models/em_deviceInfo.dart @@ -17,9 +17,9 @@ class EMDeviceInfo { /// @nodoc Map toJson() { Map data = Map(); - data.add("resource", resource); - data.add("deviceUUID", deviceUUID); - data.add("deviceName", deviceName); + data.putIfNotNull("resource", resource); + data.putIfNotNull("deviceUUID", deviceUUID); + data.putIfNotNull("deviceName", deviceName); return data; } diff --git a/lib/src/models/em_group.dart b/lib/src/models/em_group.dart index fdef7e45..cec675f2 100644 --- a/lib/src/models/em_group.dart +++ b/lib/src/models/em_group.dart @@ -392,21 +392,21 @@ class EMGroup { /// @nodoc Map toJson() { Map data = Map(); - data.add("groupId", groupId); - data.add("name", name); - data.add("desc", description); - data.add("owner", owner); - data.add("announcement", announcement); - data.add("memberCount", memberCount); - data.add("memberList", memberList); - data.add("adminList", adminList); - data.add("blockList", blockList); - data.add("muteList", muteList); - data.add("messageBlocked", messageBlocked); - data.add("isDisabled", isDisabled); - data.add("isAllMemberMuted", isAllMemberMuted); - data.add("options", _options?.toJson()); - data.add("permissionType", permissionTypeToInt(permissionType)); + data.putIfNotNull("groupId", groupId); + data.putIfNotNull("name", name); + data.putIfNotNull("desc", description); + data.putIfNotNull("owner", owner); + data.putIfNotNull("announcement", announcement); + data.putIfNotNull("memberCount", memberCount); + data.putIfNotNull("memberList", memberList); + data.putIfNotNull("adminList", adminList); + data.putIfNotNull("blockList", blockList); + data.putIfNotNull("muteList", muteList); + data.putIfNotNull("messageBlocked", messageBlocked); + data.putIfNotNull("isDisabled", isDisabled); + data.putIfNotNull("isAllMemberMuted", isAllMemberMuted); + data.putIfNotNull("options", _options?.toJson()); + data.putIfNotNull("permissionType", permissionTypeToInt(permissionType)); return data; } diff --git a/lib/src/models/em_group_options.dart b/lib/src/models/em_group_options.dart index 3c3caa82..db35d3a4 100644 --- a/lib/src/models/em_group_options.dart +++ b/lib/src/models/em_group_options.dart @@ -115,7 +115,7 @@ class EMGroupOptions { data['style'] = groupStyleTypeToInt(style); data['maxCount'] = maxCount; data['inviteNeedConfirm'] = inviteNeedConfirm; - data.add("ext", ext); + data.putIfNotNull("ext", ext); return data; } diff --git a/lib/src/models/em_group_shared_file.dart b/lib/src/models/em_group_shared_file.dart index aeb30f4a..241f6cf0 100644 --- a/lib/src/models/em_group_shared_file.dart +++ b/lib/src/models/em_group_shared_file.dart @@ -96,11 +96,11 @@ class EMGroupSharedFile { /// @nodoc Map toJson() { Map data = Map(); - data.add("fileId", _fileId); - data.add("name", _fileName); - data.add("owner", _fileOwner); - data.add("createTime", _createTime); - data.add("fileSize", _fileSize); + data.putIfNotNull("fileId", _fileId); + data.putIfNotNull("name", _fileName); + data.putIfNotNull("owner", _fileOwner); + data.putIfNotNull("createTime", _createTime); + data.putIfNotNull("fileSize", _fileSize); return data; } } diff --git a/lib/src/models/em_message.dart b/lib/src/models/em_message.dart index 915bd936..1785e59e 100644 --- a/lib/src/models/em_message.dart +++ b/lib/src/models/em_message.dart @@ -228,6 +228,19 @@ class EMMessage { /// ~end bool deliverOnlineOnly = false; + /// ~english + /// The recipient list of a targeted message. + /// + /// This property is used only for messages in groups and chat rooms. + /// ~end + /// + /// ~chinese + /// 定向消息的接收方。 + /// + /// 该属性仅对群组和聊天室中的消息有效,则消息发送给群组或聊天室的所有成员。 + /// ~end + List? receiverList; + /// ~english /// Message body. We recommend you use [EMMessageBody]. /// ~end @@ -749,27 +762,30 @@ class EMMessage { /// @nodoc Map toJson() { final Map data = new Map(); - data.add("from", from); - data.add("to", to); - data.add("body", body.toJson()); - data.add("attributes", attributes); - data.add( + data.putIfNotNull("from", from); + data.putIfNotNull("to", to); + data.putIfNotNull("body", body.toJson()); + data.putIfNotNull("attributes", attributes); + data.putIfNotNull( "direction", this.direction == MessageDirection.SEND ? 'send' : 'rec'); - data.add("hasRead", hasRead); - data.add("hasReadAck", hasReadAck); - data.add("hasDeliverAck", hasDeliverAck); - data.add("needGroupAck", needGroupAck); - data.add("msgId", msgId); - data.add("conversationId", this.conversationId ?? this.to); - data.add("chatType", chatTypeToInt(chatType)); - data.add("localTime", localTime); - data.add("serverTime", serverTime); - data.add("status", messageStatusToInt(this.status)); - data.add("isThread", isChatThreadMessage); + data.putIfNotNull("hasRead", hasRead); + data.putIfNotNull("hasReadAck", hasReadAck); + data.putIfNotNull("hasDeliverAck", hasDeliverAck); + data.putIfNotNull("needGroupAck", needGroupAck); + data.putIfNotNull("msgId", msgId); + data.putIfNotNull("conversationId", this.conversationId ?? this.to); + data.putIfNotNull("chatType", chatTypeToInt(chatType)); + data.putIfNotNull("localTime", localTime); + data.putIfNotNull("serverTime", serverTime); + data.putIfNotNull("status", messageStatusToInt(this.status)); + data.putIfNotNull("isThread", isChatThreadMessage); if (_priority != null) { - data.add("chatroomMessagePriority", _priority!.index); + data.putIfNotNull("chatroomMessagePriority", _priority!.index); + } + data.putIfNotNull('deliverOnlineOnly', deliverOnlineOnly); + if (receiverList != null) { + data.putIfNotNull('receiverList', receiverList); } - data.add('deliverOnlineOnly', deliverOnlineOnly); return data; } @@ -796,7 +812,8 @@ class EMMessage { ..isChatThreadMessage = map["isThread"] ?? false ..onlineState = map["onlineState"] ?? true ..deliverOnlineOnly = map['deliverOnlineOnly'] ?? false - ..status = messageStatusFromInt(map["status"]); + ..status = messageStatusFromInt(map["status"]) + ..receiverList = map["receiverList"]?.cast(); } static EMMessageBody? _bodyFromMap(Map map) { @@ -1003,8 +1020,8 @@ class EMCmdMessageBody extends EMMessageBody { @override Map toJson() { final Map data = super.toJson(); - data.add("action", action); - data.add("deliverOnlineOnly", deliverOnlineOnly); + data.putIfNotNull("action", action); + data.putIfNotNull("deliverOnlineOnly", deliverOnlineOnly); return data; } @@ -1090,8 +1107,8 @@ class EMLocationMessageBody extends EMMessageBody { final Map data = super.toJson(); data['latitude'] = this.latitude; data['longitude'] = this.longitude; - data.add("address", this._address); - data.add("buildingName", this._buildingName); + data.putIfNotNull("address", this._address); + data.putIfNotNull("buildingName", this._buildingName); return data; } @@ -1190,12 +1207,12 @@ class EMFileMessageBody extends EMMessageBody { @override Map toJson() { final Map data = super.toJson(); - data.add("secret", this.secret); - data.add("remotePath", this.remotePath); - data.add("fileSize", this.fileSize); - data.add("localPath", this.localPath); - data.add("displayName", this.displayName); - data.add("fileStatus", downloadStatusToInt(this.fileStatus)); + data.putIfNotNull("secret", this.secret); + data.putIfNotNull("remotePath", this.remotePath); + data.putIfNotNull("fileSize", this.fileSize); + data.putIfNotNull("localPath", this.localPath); + data.putIfNotNull("displayName", this.displayName); + data.putIfNotNull("fileStatus", downloadStatusToInt(this.fileStatus)); return data; } @@ -1342,13 +1359,14 @@ class EMImageMessageBody extends EMFileMessageBody { @override Map toJson() { final Map data = super.toJson(); - data.add("thumbnailLocalPath", thumbnailLocalPath); - data.add("thumbnailRemotePath", thumbnailRemotePath); - data.add("thumbnailSecret", thumbnailSecret); - data.add("sendOriginalImage", sendOriginalImage); - data.add("height", height ?? 0.0); - data.add("width", width ?? 0.0); - data.add("thumbnailStatus", downloadStatusToInt(this.thumbnailStatus)); + data.putIfNotNull("thumbnailLocalPath", thumbnailLocalPath); + data.putIfNotNull("thumbnailRemotePath", thumbnailRemotePath); + data.putIfNotNull("thumbnailSecret", thumbnailSecret); + data.putIfNotNull("sendOriginalImage", sendOriginalImage); + data.putIfNotNull("height", height ?? 0.0); + data.putIfNotNull("width", width ?? 0.0); + data.putIfNotNull( + "thumbnailStatus", downloadStatusToInt(this.thumbnailStatus)); return data; } @@ -1464,8 +1482,8 @@ class EMTextMessageBody extends EMMessageBody { Map toJson() { final Map data = super.toJson(); data['content'] = this.content; - data.add("targetLanguages", this.targetLanguages); - data.add("translations", this.translations); + data.putIfNotNull("targetLanguages", this.targetLanguages); + data.putIfNotNull("translations", this.translations); return data; } @@ -1572,13 +1590,14 @@ class EMVideoMessageBody extends EMFileMessageBody { @override Map toJson() { final Map data = super.toJson(); - data.add("duration", duration); - data.add("thumbnailLocalPath", thumbnailLocalPath); - data.add("thumbnailRemotePath", thumbnailRemotePath); - data.add("thumbnailSecret", thumbnailSecret); - data.add("height", height ?? 0.0); - data.add("width", width ?? 0.0); - data.add("thumbnailStatus", downloadStatusToInt(this.thumbnailStatus)); + data.putIfNotNull("duration", duration); + data.putIfNotNull("thumbnailLocalPath", thumbnailLocalPath); + data.putIfNotNull("thumbnailRemotePath", thumbnailRemotePath); + data.putIfNotNull("thumbnailSecret", thumbnailSecret); + data.putIfNotNull("height", height ?? 0.0); + data.putIfNotNull("width", width ?? 0.0); + data.putIfNotNull( + "thumbnailStatus", downloadStatusToInt(this.thumbnailStatus)); return data; } @@ -1700,7 +1719,7 @@ class EMVoiceMessageBody extends EMFileMessageBody { @override Map toJson() { final Map data = super.toJson(); - data.add("duration", duration); + data.putIfNotNull("duration", duration); return data; } @@ -1743,8 +1762,8 @@ class EMCustomMessageBody extends EMMessageBody { @override Map toJson() { final Map data = super.toJson(); - data.add("event", event); - data.add("params", params); + data.putIfNotNull("event", event); + data.putIfNotNull("params", params); return data; } diff --git a/lib/src/models/em_options.dart b/lib/src/models/em_options.dart index 438acfa3..8a85550a 100644 --- a/lib/src/models/em_options.dart +++ b/lib/src/models/em_options.dart @@ -19,7 +19,7 @@ class EMOptions { /// ~chinese /// 创建 app 时在 console 后台上注册的 app 唯一识别符。 /// ~end - late final String appKey; + final String appKey; /// ~english /// Whether to enable automatic login. @@ -274,6 +274,17 @@ class EMOptions { /// ~end final int chatAreaCode; + /// ~english + /// Whether to include empty conversations when the SDK loads conversations from the local database: + /// - `true`: Yes; + /// - `false`: (Default) No. + /// ~end + /// + /// ~chinese + /// 是否使用自定义 IM 服务的端口。用于私有化部署。 + /// ~end + final bool enableEmptyConversation; + EMPushConfig _pushConfig = EMPushConfig(); /// ~english @@ -431,6 +442,8 @@ class EMOptions { /// /// Param [chatAreaCode] The area code. /// + /// Param [enableEmptyConversation] Whether to include empty conversations when the SDK loads conversations from the local database. + /// /// ~end /// /// ~chinese @@ -502,6 +515,9 @@ class EMOptions { /// Param [imServer] 私有部署时的 IM 服务器地址。 /// /// Param [chatAreaCode] server 区域码. + /// + /// Param [enableEmptyConversation] 从本地数据库加载会话时是否包括空会话。 + /// /// ~end EMOptions({ required this.appKey, @@ -524,6 +540,7 @@ class EMOptions { this.imPort, this.imServer, this.chatAreaCode = ChatAreaCode.GLOB, + this.enableEmptyConversation = false, }); /// @nodoc @@ -538,6 +555,7 @@ class EMOptions { acceptInvitationAlways: json.boolValue('acceptInvitationAlways'), autoAcceptGroupInvitation: json.boolValue('autoAcceptGroupInvitation'), deleteMessagesAsExitGroup: json.boolValue('deleteMessagesAsExitGroup'), + enableEmptyConversation: json.boolValue('loadEmptyConversations'), deleteMessagesAsExitChatRoom: json.boolValue('deleteMessagesAsExitChatRoom'), isAutoDownloadThumbnail: json.boolValue('isAutoDownload'), @@ -564,28 +582,31 @@ class EMOptions { /// @nodoc Map toJson() { Map data = new Map(); - data.add("appKey", appKey); - data.add("autoLogin", autoLogin); - data.add("debugModel", debugModel); - data.add("acceptInvitationAlways", acceptInvitationAlways); - data.add( + data.putIfNotNull("appKey", appKey); + data.putIfNotNull("autoLogin", autoLogin); + data.putIfNotNull("debugModel", debugModel); + data.putIfNotNull("acceptInvitationAlways", acceptInvitationAlways); + data.putIfNotNull( "autoAcceptGroupInvitation", autoAcceptGroupInvitation, ); - data.add("deleteMessagesAsExitGroup", deleteMessagesAsExitGroup); - data.add("deleteMessagesAsExitChatRoom", deleteMessagesAsExitChatRoom); - data.add("dnsUrl", dnsUrl); - data.add("enableDNSConfig", enableDNSConfig); - data.add("imPort", imPort); - data.add("imServer", imServer); - data.add("isAutoDownload", isAutoDownloadThumbnail); - data.add("isChatRoomOwnerLeaveAllowed", isChatRoomOwnerLeaveAllowed); - data.add("requireAck", requireAck); - data.add("requireDeliveryAck", requireDeliveryAck); - data.add("restServer", restServer); - data.add("serverTransfer", serverTransfer); - data.add("sortMessageByServerTime", sortMessageByServerTime); - data.add("usingHttpsOnly", usingHttpsOnly); + data.putIfNotNull("deleteMessagesAsExitGroup", deleteMessagesAsExitGroup); + data.putIfNotNull( + "deleteMessagesAsExitChatRoom", deleteMessagesAsExitChatRoom); + data.putIfNotNull("dnsUrl", dnsUrl); + data.putIfNotNull("enableDNSConfig", enableDNSConfig); + data.putIfNotNull("imPort", imPort); + data.putIfNotNull("imServer", imServer); + data.putIfNotNull("isAutoDownload", isAutoDownloadThumbnail); + data.putIfNotNull( + "isChatRoomOwnerLeaveAllowed", isChatRoomOwnerLeaveAllowed); + data.putIfNotNull("requireAck", requireAck); + data.putIfNotNull("requireDeliveryAck", requireDeliveryAck); + data.putIfNotNull("restServer", restServer); + data.putIfNotNull("serverTransfer", serverTransfer); + data.putIfNotNull("sortMessageByServerTime", sortMessageByServerTime); + data.putIfNotNull("usingHttpsOnly", usingHttpsOnly); + data.putIfNotNull('loadEmptyConversations', enableEmptyConversation); data["usingHttpsOnly"] = this.usingHttpsOnly; data["pushConfig"] = this._pushConfig.toJson(); diff --git a/lib/src/models/fetch_message_options.dart b/lib/src/models/fetch_message_options.dart index 61262c49..a7776edf 100644 --- a/lib/src/models/fetch_message_options.dart +++ b/lib/src/models/fetch_message_options.dart @@ -140,12 +140,13 @@ class FetchMessageOptions { Map toJson() { Map data = {}; - data.add('direction', direction == EMSearchDirection.Up ? "up" : "down"); - data.add('startTs', startTs); - data.add('endTs', endTs); - data.add('from', from); - data.add('needSave', needSave); - data.add('msgTypes', + data.putIfNotNull( + 'direction', direction == EMSearchDirection.Up ? "up" : "down"); + data.putIfNotNull('startTs', startTs); + data.putIfNotNull('endTs', endTs); + data.putIfNotNull('from', from); + data.putIfNotNull('needSave', needSave); + data.putIfNotNull('msgTypes', msgTypes?.toSet().map((e) => messageTypeToTypeStr(e)).toList()); return data; diff --git a/lib/src/tools/em_extension.dart b/lib/src/tools/em_extension.dart index caa31c6f..857c0f0a 100644 --- a/lib/src/tools/em_extension.dart +++ b/lib/src/tools/em_extension.dart @@ -19,7 +19,7 @@ extension MapExtension on Map { } } - void add(String key, dynamic value) { + void putIfNotNull(String key, dynamic value) { if (value == null) { return; } diff --git a/pubspec.yaml b/pubspec.yaml index dee7e745..4e829052 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: im_flutter_sdk description: Integrate the Chat SDK to enjoy the global IM services with high reliability, ultra-low latency, and high concurrency. -version: 4.0.2 +version: 4.0.3 homepage: https://www.easemob.com/product/im environment: From 03d0ed74eb3104fd61dc81fac8e22f0d955330fa Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Sun, 25 Jun 2023 17:53:44 +0800 Subject: [PATCH 28/49] update android to 403 --- android/build.gradle | 2 +- .../im_flutter_sdk/EMChatManagerWrapper.java | 35 ++++++++++++++++-- .../im_flutter_sdk/EMClientWrapper.java | 12 +++++++ .../com/easemob/im_flutter_sdk/EMHelper.java | 18 +++++++++- .../easemob/im_flutter_sdk/EMSDKMethod.java | 5 ++- lib/src/em_chat_manager.dart | 2 +- lib/src/models/em_options.dart | 36 ------------------- 7 files changed, 68 insertions(+), 42 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 6aebee0a..0891523f 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -48,5 +48,5 @@ tasks.withType(JavaCompile){ dependencies { api 'androidx.appcompat:appcompat:1.1.0' - implementation 'io.hyphenate:hyphenate-chat:4.0.2' + implementation 'io.hyphenate:hyphenate-chat:4.0.3' } diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java index 1b3eba12..47d1c559 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java @@ -119,8 +119,13 @@ public void onMethodCall(MethodCall call, Result result) { removeMessagesFromServerWithMsgIds(param, call.method, result); } else if (EMSDKMethod.removeMessagesFromServerWithTs.equals(call.method)) { removeMessagesFromServerWithTs(param, call.method, result); - } - else { + } else if (EMSDKMethod.getConversationsFromServerWithCursor.equals(call.method)) { + getConversationsFromServerWithCursor(param, call.method, result); + } else if (EMSDKMethod.getPinnedConversationsFromServerWithCursor.equals(call.method)) { + getPinnedConversationsFromServerWithCursor(param, call.method, result); + } else if (EMSDKMethod.pinConversation.equals(call.method)) { + pinConversation(param, call.method, result); + } else { super.onMethodCall(call, result); } } catch (JSONException ignored) { @@ -862,6 +867,32 @@ private void reportMessage(JSONObject param, String channelName, Result result) EMClient.getInstance().chatManager().asyncReportMessage(msgId, tag, reason, new EMWrapperCallBack(result, channelName, true)); } + private void getConversationsFromServerWithCursor(JSONObject param, String channelName, Result result) throws JSONException { + String cursor = param.optString("cursor"); + int pageSize = param.optInt("pageSize"); + EMClient.getInstance().chatManager().asyncFetchConversationsFromServer(pageSize, cursor, new EMValueWrapperCallBack>(result, channelName){ + @Override + public void onSuccess(EMCursorResult object) { + super.updateObject(EMCursorResultHelper.toJson(object)); + } + }); + } + private void getPinnedConversationsFromServerWithCursor(JSONObject param, String channelName, Result result) throws JSONException { + String cursor = param.optString("cursor"); + int pageSize = param.optInt("pageSize"); + EMClient.getInstance().chatManager().asyncFetchPinnedConversationsFromServer(pageSize, cursor, new EMValueWrapperCallBack>(result, channelName){ + @Override + public void onSuccess(EMCursorResult object) { + super.updateObject(EMCursorResultHelper.toJson(object)); + } + }); + } + private void pinConversation(JSONObject param, String channelName, Result result) throws JSONException { + String convId = param.optString("convId"); + Boolean isPinned = param.optBoolean("isPinned", false); + EMClient.getInstance().chatManager().asyncPinConversation(convId, isPinned, new EMWrapperCallBack(result, channelName, null)); + } + @Override public void unRegisterEaseListener() { EMClient.getInstance().chatManager().removeMessageListener(messageListener); diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java index 33cc5be9..bfe0ec46 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java @@ -1,5 +1,7 @@ package com.easemob.im_flutter_sdk; +import static com.easemob.im_flutter_sdk.EMConversationHelper.typeToInt; + import java.util.ArrayList; import java.util.Map; @@ -18,6 +20,7 @@ import com.hyphenate.EMConnectionListener; import com.hyphenate.EMMultiDeviceListener; import com.hyphenate.chat.EMClient; +import com.hyphenate.chat.EMConversation; import com.hyphenate.chat.EMMessage; import com.hyphenate.chat.EMOptions; import com.hyphenate.chat.EMDeviceInfo; @@ -402,6 +405,15 @@ public void onMessageRemoved(String conversationId, String deviceId) { data.put("deviceId", deviceId); post(()-> channel.invokeMethod(EMSDKMethod.onMultiDeviceRemoveMessagesEvent, data)); } + + @Override + public void onConversationEvent(int event, String conversationId, EMConversation.EMConversationType type) { + Map data = new HashMap<>(); + data.put("event", Integer.valueOf(event)); + data.put("convId", conversationId); + data.put("convType", typeToInt(type)); + post(()-> channel.invokeMethod(EMSDKMethod.onMultiDevicesConversationEvent, data)); + } }; if (connectionListener != null) { diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java index 76af57a4..a02d5bf4 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java @@ -74,6 +74,7 @@ static EMOptions fromJson(JSONObject json, Context context) throws JSONException options.setAreaCode(json.getInt("areaCode")); options.setUsingHttpsOnly(json.getBoolean("usingHttpsOnly")); options.enableDNSConfig(json.getBoolean("enableDNSConfig")); + options.setLoadEmptyConversations(json.optBoolean("loadEmptyConversations", false)); if (!json.getBoolean("enableDNSConfig")) { if (json.has("imPort")) { options.setImPort(json.getInt("imPort")); @@ -430,7 +431,6 @@ static EMMessage fromJson(JSONObject json) throws JSONException { if (json.has("from")) { message.setFrom(json.getString("from")); } - message.setAcked(json.getBoolean("hasReadAck")); if (statusFromInt(json.getInt("status")) == EMMessage.Status.SUCCESS) { message.setUnread(!json.getBoolean("hasRead")); @@ -487,6 +487,16 @@ static EMMessage fromJson(JSONObject json) throws JSONException { } } } + + if (json.has("receiverList")) { + ArrayList receiverList = new ArrayList<>(); + JSONArray ja = json.getJSONArray("receiverList"); + for (int i = 0; i < ja.length(); i++) { + receiverList.add((String) ja.get(i)); + } + message.setReceiverList(receiverList); + } + return message; } @@ -959,6 +969,8 @@ static Map toJson(EMConversation conversation) { data.put("convId", conversation.conversationId()); data.put("type", typeToInt(conversation.getType())); data.put("isThread", conversation.isChatThread()); + data.put("isPinned", conversation.isPinned()); + data.put("pinnedTime", conversation.getPinnedTime()); try { data.put("ext", jsonStringToMap(conversation.getExtField())); } catch (JSONException e) { @@ -1088,6 +1100,10 @@ static Map toJson(EMCursorResult result) { if (obj instanceof EMChatThread) { jsonList.add(EMChatThreadHelper.toJson((EMChatThread) obj)); } + + if (obj instanceof EMConversation) { + jsonList.add(EMConversationHelper.toJson((EMConversation) obj)); + } } } data.put("list", jsonList); diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java index 61046ba9..456c547e 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java @@ -34,8 +34,8 @@ public class EMSDKMethod { static final String onMultiDeviceGroupEvent = "onMultiDeviceGroupEvent"; static final String onMultiDeviceContactEvent = "onMultiDeviceContactEvent"; static final String onMultiDeviceThreadEvent = "onMultiDeviceThreadEvent"; - static final String onMultiDeviceRemoveMessagesEvent = "onMultiDeviceRemoveMessagesEvent"; + static final String onMultiDevicesConversationEvent = "onMultiDevicesConversationEvent"; static final String onSendDataToFlutter = "onSendDataToFlutter"; static final String onTokenWillExpire = "onTokenWillExpire"; static final String onTokenDidExpire = "onTokenDidExpire"; @@ -94,6 +94,9 @@ public class EMSDKMethod { static final String removeMessagesFromServerWithMsgIds = "removeMessagesFromServerWithMsgIds"; static final String removeMessagesFromServerWithTs = "removeMessagesFromServerWithTs"; + static final String getConversationsFromServerWithCursor = "getConversationsFromServerWithCursor"; + static final String getPinnedConversationsFromServerWithCursor = "getPinnedConversationsFromServerWithCursor"; + static final String pinConversation = "pinConversation"; /// EMChatManager listener static final String onMessagesReceived = "onMessagesReceived"; static final String onCmdMessagesReceived = "onCmdMessagesReceived"; diff --git a/lib/src/em_chat_manager.dart b/lib/src/em_chat_manager.dart index 4cd1fb62..629fb954 100644 --- a/lib/src/em_chat_manager.dart +++ b/lib/src/em_chat_manager.dart @@ -1657,7 +1657,7 @@ class EMChatManager { {required String conversationId, required bool isPinned}) async { Map map = { 'convId': conversationId, - 'isPinned': 'isPinned', + 'isPinned': isPinned, }; Map result = await ChatChannel.invokeMethod( diff --git a/lib/src/models/em_options.dart b/lib/src/models/em_options.dart index 8a85550a..99d65f08 100644 --- a/lib/src/models/em_options.dart +++ b/lib/src/models/em_options.dart @@ -543,42 +543,6 @@ class EMOptions { this.enableEmptyConversation = false, }); - /// @nodoc - factory EMOptions.fromJson(Map json) { - var ret = EMOptions( - appKey: json['appKey'], - autoLogin: json.boolValue('autoLogin'), - debugModel: json.boolValue('debugModel'), - requireAck: json.boolValue('requireAck'), - requireDeliveryAck: json.boolValue('requireDeliveryAck'), - sortMessageByServerTime: json.boolValue('sortMessageByServerTime'), - acceptInvitationAlways: json.boolValue('acceptInvitationAlways'), - autoAcceptGroupInvitation: json.boolValue('autoAcceptGroupInvitation'), - deleteMessagesAsExitGroup: json.boolValue('deleteMessagesAsExitGroup'), - enableEmptyConversation: json.boolValue('loadEmptyConversations'), - deleteMessagesAsExitChatRoom: - json.boolValue('deleteMessagesAsExitChatRoom'), - isAutoDownloadThumbnail: json.boolValue('isAutoDownload'), - isChatRoomOwnerLeaveAllowed: - json.boolValue('isChatRoomOwnerLeaveAllowed'), - serverTransfer: json.boolValue('serverTransfer'), - usingHttpsOnly: json.boolValue('usingHttpsOnly'), - enableDNSConfig: json.boolValue('enableDNSConfig'), - imPort: json["imPort"], - imServer: json["imServer"], - restServer: json["restServer"], - dnsUrl: json["dnsUrl"], - chatAreaCode: json["areaCode"] ?? ChatAreaCode.GLOB, - ); - - ret._pushConfig = EMPushConfig(); - if (json['pushConfig'] != null) { - ret._pushConfig.updateFromJson(json); - } - - return ret; - } - /// @nodoc Map toJson() { Map data = new Map(); From 1d8be1779859fb7ea2dffcca18eb304ef69f384a Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Mon, 26 Jun 2023 17:28:05 +0800 Subject: [PATCH 29/49] add leave chatroom reason --- .../im_flutter_sdk/EMChatRoomManagerWrapper.java | 1 + ios/Classes/EMChatroomManagerWrapper.m | 6 ++++-- lib/src/em_chat_room_manager.dart | 10 +++++++++- lib/src/event_handler/manager_event_handler.dart | 5 +++-- lib/src/models/em_chat_enums.dart | 5 +++++ 5 files changed, 22 insertions(+), 5 deletions(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java index 3021bbc4..c4068162 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatRoomManagerWrapper.java @@ -754,6 +754,7 @@ public void onRemovedFromChatRoom(int reason, String roomId, String roomName, St data.put("roomName", roomName); data.put("participant", participant); data.put("type", "onRoomRemoved"); + data.put("reason", reason); post(() -> channel.invokeMethod(EMSDKMethod.chatRoomChange, data)); } ); diff --git a/ios/Classes/EMChatroomManagerWrapper.m b/ios/Classes/EMChatroomManagerWrapper.m index 86609eae..8ca6a554 100644 --- a/ios/Classes/EMChatroomManagerWrapper.m +++ b/ios/Classes/EMChatroomManagerWrapper.m @@ -788,7 +788,8 @@ - (void)didDismissFromChatroom:(EMChatroom *)aChatroom map = @{ @"type":type, @"roomId":aChatroom.chatroomId, - @"roomName":aChatroom.subject + @"roomName":aChatroom.subject, + @"reason": @(aReason) }; } else if (aReason == EMChatroomBeKickedReasonBeRemoved) { type = @"onRoomRemoved"; @@ -796,7 +797,8 @@ - (void)didDismissFromChatroom:(EMChatroom *)aChatroom @"type":type, @"roomId":aChatroom.chatroomId, @"roomName":aChatroom.subject, - @"participant":[[EMClient sharedClient] currentUsername] + @"participant":[[EMClient sharedClient] currentUsername], + @"reason": @(aReason) }; } diff --git a/lib/src/em_chat_room_manager.dart b/lib/src/em_chat_room_manager.dart index ce7df5fd..62f92c1b 100644 --- a/lib/src/em_chat_room_manager.dart +++ b/lib/src/em_chat_room_manager.dart @@ -71,7 +71,15 @@ class EMChatRoomManager { String roomId = event['roomId']; String? roomName = event['roomName']; String participant = event['participant']; - item.onRemovedFromChatRoom?.call(roomId, roomName, participant); + LeaveReason? reason; + int iReason = event['reason'] ?? -1; + if (iReason == 0) { + reason = LeaveReason.Kicked; + } else if (iReason == 2) { + reason = LeaveReason.Offline; + } + item.onRemovedFromChatRoom + ?.call(roomId, roomName, participant, reason); break; case EMChatRoomEvent.ON_MUTE_LIST_ADDED: String roomId = event['roomId']; diff --git a/lib/src/event_handler/manager_event_handler.dart b/lib/src/event_handler/manager_event_handler.dart index 4c4511f0..5eafd3d4 100644 --- a/lib/src/event_handler/manager_event_handler.dart +++ b/lib/src/event_handler/manager_event_handler.dart @@ -732,16 +732,17 @@ class EMChatRoomEventHandler { )? onOwnerChangedFromChatRoom; /// ~english - /// Occurs when a member is dismissed from a chat room. + /// Occurs when a you is dismissed from a chat room. /// ~end /// /// ~chinese - /// 聊天室成员被移出聊天室回调。 + /// 当前用户被移出聊天室回调。 /// ~end final void Function( String roomId, String? roomName, String? participant, + LeaveReason? reason, )? onRemovedFromChatRoom; /// ~english diff --git a/lib/src/models/em_chat_enums.dart b/lib/src/models/em_chat_enums.dart index eaeb219c..e6407519 100644 --- a/lib/src/models/em_chat_enums.dart +++ b/lib/src/models/em_chat_enums.dart @@ -1035,3 +1035,8 @@ enum ReactionOperate { /// ~end Add, } + +enum LeaveReason { + Kicked, + Offline, +} From 662105ddfb09d38730b44c4b6969b11fe375d708 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Tue, 11 Jul 2023 14:35:37 +0800 Subject: [PATCH 30/49] update --- example/ios/Podfile.lock | 8 ++++---- example/pubspec.lock | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 03a60fb4..844d6704 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,9 +1,9 @@ PODS: - Flutter (1.0.0) - - HyphenateChat (4.0.2) + - HyphenateChat (4.0.3) - im_flutter_sdk (0.0.1): - Flutter - - HyphenateChat (= 4.0.2) + - HyphenateChat (= 4.0.3) DEPENDENCIES: - Flutter (from `Flutter`) @@ -21,8 +21,8 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 - HyphenateChat: add908a7200ba951a5b27a0fa2514ea6f532e69c - im_flutter_sdk: 9d47f25fb0815b9ae5a7c157e1ccda245fb3a321 + HyphenateChat: 35826ebaa42ebac897b39e29a06f2215a060011a + im_flutter_sdk: bbcfbe596ef4682c9518604e1cb319e967f6b163 PODFILE CHECKSUM: 7368163408c647b7eb699d0d788ba6718e18fb8d diff --git a/example/pubspec.lock b/example/pubspec.lock index d2243315..6b244eba 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -97,7 +97,7 @@ packages: path: ".." relative: true source: path - version: "4.0.2" + version: "4.0.3" js: dependency: transitive description: From 5395c135de5c555a14eea6157bce859c5ac84187 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Tue, 11 Jul 2023 16:24:08 +0800 Subject: [PATCH 31/49] fix reaction operation error. --- lib/src/models/reaction_operation.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/src/models/reaction_operation.dart b/lib/src/models/reaction_operation.dart index 4ccd8a21..9b9d1d72 100644 --- a/lib/src/models/reaction_operation.dart +++ b/lib/src/models/reaction_operation.dart @@ -65,8 +65,9 @@ class ReactionOperation { String userId = map["userId"]; String reaction = map["reaction"]; - ReactionOperate operate = - map["operate"] ?? 0 == 0 ? ReactionOperate.Remove : ReactionOperate.Add; + ReactionOperate operate = (map["operate"] ?? 0) == 0 + ? ReactionOperate.Remove + : ReactionOperate.Add; return ReactionOperation._private(userId, reaction, operate); } From 056597b65a7726ed315bd4904394d7a06e97241e Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Thu, 13 Jul 2023 14:23:31 +0800 Subject: [PATCH 32/49] add flutter side code. --- lib/src/em_chat_manager.dart | 84 ++++++++++++++ lib/src/em_client.dart | 103 +++++++++++++---- .../event_handler/manager_event_handler.dart | 20 +++- lib/src/internal/chat_method_keys.dart | 4 + lib/src/internal/em_transform_tools.dart | 2 + lib/src/models/em_chat_enums.dart | 9 ++ lib/src/models/em_message.dart | 106 +++++++++++++++++- lib/src/models/em_options.dart | 27 +++++ 8 files changed, 333 insertions(+), 22 deletions(-) diff --git a/lib/src/em_chat_manager.dart b/lib/src/em_chat_manager.dart index 629fb954..0dfc3a93 100644 --- a/lib/src/em_chat_manager.dart +++ b/lib/src/em_chat_manager.dart @@ -56,6 +56,8 @@ class EMChatManager { return _onConversationHasRead(call.arguments); } else if (call.method == ChatMethodKeys.onMessageReactionDidChange) { return _messageReactionDidChange(call.arguments); + } else if (call.method == ChatMethodKeys.onMessageContentChanged) { + return _onMessageContentChanged(call.arguments); } return null; }); @@ -1671,6 +1673,79 @@ class EMChatManager { } } + /// ~english + /// Modifies a local message or a message at the server side. + /// + /// You can call this method to only modify a text message in one-to-one chats or group chats, but not in chat rooms. + /// + /// Param [messageId] The ID of the message to modify. + /// + /// Param [msgBody] The modified message body [EMTextMessageBody]. + /// + /// **Return** The modified message. + /// + /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 修改本地以及服务端的消息内容。 + /// + /// 只能调用该方法修改单聊和群聊中的文本消息,不能修改聊天室消息。 + /// + /// Param [messageId] 消息实例id。 + /// + /// Param [msgBody] 文本消息体实例 [EMTextMessageBody]。 + /// + /// **Return** 修改后的消息实例。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end + Future modifyMessage({ + required String messageId, + required EMTextMessageBody msgBody, + }) async { + Map map = { + 'msgId': messageId, + 'body': msgBody.toJson(), + }; + + Map result = await ChatChannel.invokeMethod( + ChatMethodKeys.modifyMessage, + map, + ); + try { + EMError.hasErrorFromResult(result); + return EMMessage.fromJson(result[ChatMethodKeys.modifyMessage]); + } on EMError catch (e) { + throw e; + } + } + + Future> downloadAndParseCombineMessage({ + required EMMessage message, + }) async { + Map map = { + 'message': message.toJson(), + }; + + Map result = await ChatChannel.invokeMethod( + ChatMethodKeys.downloadAndParseCombineMessage, + map, + ); + + try { + EMError.hasErrorFromResult(result); + List messages = []; + List list = result[ChatMethodKeys.downloadAndParseCombineMessage]; + list.forEach((element) { + messages.add(EMMessage.fromJson(element)); + }); + return messages; + } on EMError catch (e) { + throw e; + } + } + /// ~english /// Adds a message status listener. /// @@ -1813,6 +1888,15 @@ class EMChatManager { item.onMessageReactionDidChange?.call(list); } } + + Future _onMessageContentChanged(dynamic obj) async { + EMMessage msg = EMMessage.fromJson(obj["message"]); + String operator = obj["operator"] ?? ""; + int operationTime = obj["operationTime"] ?? 0; + for (var item in _eventHandlesMap.values) { + item.onMessageContentChanged?.call(msg, operator, operationTime); + } + } } /// ~english diff --git a/lib/src/em_client.dart b/lib/src/em_client.dart index eb2e62bc..35acc7b3 100644 --- a/lib/src/em_client.dart +++ b/lib/src/em_client.dart @@ -86,7 +86,8 @@ class EMClient { } else if (call.method == ChatMethodKeys.onDisconnected) { return _onDisconnected(); } else if (call.method == ChatMethodKeys.onUserDidLoginFromOtherDevice) { - _onUserDidLoginFromOtherDevice(); + String deviceName = argMap?['deviceName'] ?? ""; + _onUserDidLoginFromOtherDevice(deviceName); } else if (call.method == ChatMethodKeys.onUserDidRemoveFromServer) { _onUserDidRemoveFromServer(); } else if (call.method == ChatMethodKeys.onUserDidForbidByServer) { @@ -641,6 +642,8 @@ class EMClient { } } + @Deprecated('Use [fetchLoggedInDevices] instead') + /// ~english /// Gets all the information about the logged in devices under the specified account. /// @@ -648,7 +651,7 @@ class EMClient { /// /// Param [password] The password. /// - /// **Return** TThe list of the logged-in devices. + /// **Return** The list of the logged-in devices. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -666,7 +669,6 @@ class EMClient { /// ~end Future> getLoggedInDevicesFromServer( {required String userId, required String password}) async { - EMLog.v('getLoggedInDevicesFromServer: $userId, "******"'); Map req = {'username': userId, 'password': password}; Map result = await ClientChannel.invokeMethod( ChatMethodKeys.getLoggedInDevicesFromServer, req); @@ -682,12 +684,59 @@ class EMClient { } } + /// ~english + /// Gets all the information about the logged in devices under the specified account. + /// + /// Param [userId] The username you want to get the device information. + /// + /// Param [pwdOrToken] The password or token. + /// + /// Param [isPwd] Whether it is a password, the default is true. + /// + /// **Return** The list of the logged-in devices. + /// + /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 获取指定账号下登录的在线设备列表。 + /// + /// Param [userId] 用户 ID。 + /// + /// Param [pwdOrToken] 密码 或者 token。 + /// + /// Param [isPwd] 是否是密码,默认为 true。 + /// + /// **Return** 获取到到设备列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end + Future> fetchLoggedInDevices({ + required String userId, + required String pwdOrToken, + bool isPwd = true, + }) async { + Map req = {'username': userId, 'pwdOrToken': pwdOrToken, 'isPwd': isPwd}; + Map result = await ClientChannel.invokeMethod( + ChatMethodKeys.getLoggedInDevicesFromServer, req); + try { + EMError.hasErrorFromResult(result); + List list = []; + result[ChatMethodKeys.getLoggedInDevicesFromServer]?.forEach((info) { + list.add(EMDeviceInfo.fromJson(info)); + }); + return list; + } on EMError catch (e) { + throw e; + } + } + /// ~english /// Forces the specified account to log out from the specified device. /// /// Param [userId] The account you want to force logout. /// - /// Param [password] The account's password. + /// Param [pwdOrToken] The account's password or token. /// /// Param [resource] The device ID. For how to fetch the device ID, See [EMDeviceInfo.resource]. /// @@ -695,22 +744,29 @@ class EMClient { /// ~end /// /// ~chinese - /// 在指定账号下,根据设备 ID,将指定设备下线,设备 ID:{@link EMDeviceInfo#resource}。 + /// 在指定账号下,根据设备 ID,将指定设备下线,设备 ID:[EMDeviceInfo.resource]。 /// /// Param [userId] 用户 ID。 /// - /// Param [password] 密码。 + /// Param [pwdOrToken] 密码 / token。 /// - /// Param [resource] 设备 ID,详见 {@link EMDeviceInfo#resource}。 + /// Param [resource] 设备 ID,详见 [EMDeviceInfo.resource]。 /// /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 /// ~end - Future kickDevice( - {required String userId, - required String password, - required String resource}) async { + Future kickDevice({ + required String userId, + required String pwdOrToken, + required String resource, + bool isPwd = true, + }) async { EMLog.v('kickDevice: $userId, "******"'); - Map req = {'username': userId, 'password': password, 'resource': resource}; + Map req = { + 'username': userId, + 'pwdOrToken': pwdOrToken, + 'resource': resource, + 'isPwd': isPwd, + }; Map result = await ClientChannel.invokeMethod(ChatMethodKeys.kickDevice, req); try { @@ -726,7 +782,9 @@ class EMClient { /// /// Param [userId] The account you want to log out from all the devices. /// - /// Param [password] The password. + /// Param [pwdOrToken] The password or token. + /// + /// Param [isPwd] Whether it is a password, the default is true. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -736,14 +794,19 @@ class EMClient { /// /// Param [userId] 用户 ID。 /// - /// Param [password] 密码。 + /// Param [pwdOrToken] 密码 或 token。 + /// + /// Param [isPwd] 是否是密码,默认为 true。 /// /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// /// ~end - Future kickAllDevices( - {required String userId, required String password}) async { - EMLog.v('kickAllDevices: $userId, "******"'); - Map req = {'username': userId, 'password': password}; + Future kickAllDevices({ + required String userId, + required String pwdOrToken, + bool isPwd = true, + }) async { + Map req = {'username': userId, 'password': pwdOrToken, 'isPwd': isPwd}; Map result = await ClientChannel.invokeMethod(ChatMethodKeys.kickAllDevices, req); try { @@ -765,9 +828,9 @@ class EMClient { } } - Future _onUserDidLoginFromOtherDevice() async { + Future _onUserDidLoginFromOtherDevice(String deviceName) async { for (var handler in _connectionEventHandler.values) { - handler.onUserDidLoginFromOtherDevice?.call(); + handler.onUserDidLoginFromOtherDevice?.call(deviceName); } } diff --git a/lib/src/event_handler/manager_event_handler.dart b/lib/src/event_handler/manager_event_handler.dart index 5eafd3d4..ef70b8c2 100644 --- a/lib/src/event_handler/manager_event_handler.dart +++ b/lib/src/event_handler/manager_event_handler.dart @@ -65,7 +65,7 @@ class EMConnectionEventHandler { /// ~chinese /// 其他设备登录回调。 /// ~end - final VoidCallback? onUserDidLoginFromOtherDevice; + final void Function(String deviceName)? onUserDidLoginFromOtherDevice; /// ~english /// Occurs when the current chat user is removed from the server. @@ -497,6 +497,19 @@ class EMChatEventHandler { final void Function(List events)? onMessageReactionDidChange; + /// ~english + /// Occurs when the message content is modified. + /// ~end + /// + /// ~chinese + /// 收到消息内容变化。 + /// ~end + final void Function( + EMMessage message, + String operatorId, + int operationTime, + )? onMessageContentChanged; + /// ~english /// The chat event handler. /// @@ -519,6 +532,8 @@ class EMChatEventHandler { /// Param [onConversationRead] Conversation read receipt is received callback. /// /// Param [onMessageReactionDidChange] Reaction data changes callback. + /// + /// Param [onMessageContentChanged] Message content is modified callback. /// ~end /// /// ~chinese @@ -543,6 +558,8 @@ class EMChatEventHandler { /// Param [onConversationRead] 收到会话已读回执的回调。 /// /// Param [onMessageReactionDidChange] 消息表情回复(Reaction)变化监听器。 + /// + /// Param [onMessageContentChanged] 收到消息内容变化。 /// ~end EMChatEventHandler({ this.onMessagesReceived, @@ -555,6 +572,7 @@ class EMChatEventHandler { this.onConversationsUpdate, this.onConversationRead, this.onMessageReactionDidChange, + this.onMessageContentChanged, }); } diff --git a/lib/src/internal/chat_method_keys.dart b/lib/src/internal/chat_method_keys.dart index 6219bc29..38b97025 100644 --- a/lib/src/internal/chat_method_keys.dart +++ b/lib/src/internal/chat_method_keys.dart @@ -113,6 +113,9 @@ class ChatMethodKeys { static const String getPinnedConversationsFromServerWithCursor = 'getPinnedConversationsFromServerWithCursor'; static const String pinConversation = 'pinConversation'; + static const String modifyMessage = 'modifyMessage'; + static const String downloadAndParseCombineMessage = + 'downloadAndParseCombineMessage'; /// EMChatManager listener static const String onMessagesReceived = "onMessagesReceived"; @@ -129,6 +132,7 @@ class ChatMethodKeys { static const String onConversationHasRead = "onConversationHasRead"; static const String onMessageReactionDidChange = "messageReactionDidChange"; + static const String onMessageContentChanged = "onMessageContentChanged"; /// EMMessage listener static const String onMessageProgressUpdate = "onMessageProgressUpdate"; diff --git a/lib/src/internal/em_transform_tools.dart b/lib/src/internal/em_transform_tools.dart index e1ea5694..a1e255ec 100644 --- a/lib/src/internal/em_transform_tools.dart +++ b/lib/src/internal/em_transform_tools.dart @@ -95,6 +95,8 @@ String messageTypeToTypeStr(MessageType type) { return 'video'; case MessageType.VOICE: return 'voice'; + case MessageType.COMBINE: + return 'combine'; } } diff --git a/lib/src/models/em_chat_enums.dart b/lib/src/models/em_chat_enums.dart index e6407519..a53b5620 100644 --- a/lib/src/models/em_chat_enums.dart +++ b/lib/src/models/em_chat_enums.dart @@ -317,6 +317,15 @@ enum MessageType { /// 自定义消息。 /// ~end CUSTOM, + + /// ~english + /// The combine message. + /// ~end + /// + /// ~chinese + /// 合并消息。 + /// ~end + COMBINE, } /// ~english diff --git a/lib/src/models/em_message.dart b/lib/src/models/em_message.dart index 1785e59e..2397b13b 100644 --- a/lib/src/models/em_message.dart +++ b/lib/src/models/em_message.dart @@ -967,7 +967,11 @@ abstract class EMMessageBody { EMMessageBody.fromJson({ required Map map, required this.type, - }); + }) { + _operatorTime = map["operatorTime"]; + _operatorId = map["operatorId"]; + _operatorCount = map["operatorCount"]; + } /// @nodoc Map toJson() { @@ -989,6 +993,33 @@ abstract class EMMessageBody { /// 获取消息类型。 /// ~end MessageType type; + + /// ~english + /// Get the user ID of the operator that modified the message last time. + /// ~end + /// + /// ~chinese + /// 获取最后一次消息修改的操作者的用户 ID。 + /// ~end + String? _operatorId; + + /// ~english + /// Get the UNIX timestamp of the last message modification, in milliseconds. + /// ~end + /// + /// ~chinese + /// 获取最后一次消息修改的时间戳,单位为毫秒。 + /// ~end + int? _operatorTime; + + /// ~english + /// Get the number of times a message is modified. + /// ~end + /// + /// ~chinese + /// 获取消息修改次数。 + /// ~end + int? _operatorCount; } /// ~english @@ -1513,6 +1544,33 @@ class EMTextMessageBody extends EMMessageBody { /// 译文。 /// ~end Map? translations; + + /// ~english + /// Get the user ID of the operator that modified the message last time. + /// ~end + /// + /// ~chinese + /// 获取最后一次消息修改的操作者的用户 ID。 + /// ~end + String? get operatorId => _operatorId; + + /// ~english + /// Get the UNIX timestamp of the last message modification, in milliseconds. + /// ~end + /// + /// ~chinese + /// 获取最后一次消息修改的时间戳,单位为毫秒。 + /// ~end + int? get operatorTime => _operatorTime; + + /// ~english + /// Get the number of times a message is modified. + /// ~end + /// + /// ~chinese + /// 获取消息修改次数。 + /// ~end + int? get operatorCount => _operatorCount; } /// ~english @@ -1786,3 +1844,49 @@ class EMCustomMessageBody extends EMMessageBody { /// ~end Map? params; } + +class EMCombineMessageBody extends EMMessageBody { + EMCombineMessageBody({ + this.title, + this.summary, + List? messageList, + String? compatibleText, + }) : _compatibleText = compatibleText, + _messageList = messageList, + super(type: MessageType.COMBINE); + + final String? title; + final String? summary; + final List? _messageList; + late final String? _compatibleText; + + String? _localPath; + String? _remotePath; + String? _secret; + + /// @nodoc + @override + Map toJson() { + final Map data = super.toJson(); + data.putIfNotNull("title", title); + data.putIfNotNull("summary", summary); + data.putIfNotNull("messageList", _messageList); + data.putIfNotNull("compatibleText", _compatibleText); + data.putIfNotNull("localPath", _localPath); + data.putIfNotNull("remotePath", _remotePath); + data.putIfNotNull("secret", _secret); + return data; + } + + /// @nodoc + factory EMCombineMessageBody.fromJson({required Map map}) { + var body = EMCombineMessageBody( + title: map["title"], + summary: map["summary"], + ); + body._localPath = map["localPath"]; + body._remotePath = map["remotePath"]; + body._secret = map["secret"]; + return body; + } +} diff --git a/lib/src/models/em_options.dart b/lib/src/models/em_options.dart index 99d65f08..b0c68334 100644 --- a/lib/src/models/em_options.dart +++ b/lib/src/models/em_options.dart @@ -285,6 +285,24 @@ class EMOptions { /// ~end final bool enableEmptyConversation; + /// ~english + /// Custom device name + /// ~end + /// + /// ~chinese + /// 自定义设备名称 + /// ~end + final String? deviceName; + + /// ~english + /// Custom system type + /// ~end + /// + /// ~chinese + /// 自定义系统类型 + /// ~end + final int? osType; + EMPushConfig _pushConfig = EMPushConfig(); /// ~english @@ -541,6 +559,8 @@ class EMOptions { this.imServer, this.chatAreaCode = ChatAreaCode.GLOB, this.enableEmptyConversation = false, + this.deviceName, + this.osType, }); /// @nodoc @@ -575,6 +595,13 @@ class EMOptions { data["usingHttpsOnly"] = this.usingHttpsOnly; data["pushConfig"] = this._pushConfig.toJson(); data["areaCode"] = this.chatAreaCode; + if (deviceName != null) { + data["customDeviceName"] = this.deviceName; + } + if (osType != null) { + data["customOSType"] = this.osType; + } + return data; } From 9657cbdf79f038518f89d972f7d4b2e8a2bbde3a Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Thu, 13 Jul 2023 15:31:43 +0800 Subject: [PATCH 33/49] add ios side code. --- ios/Classes/EMChatManagerWrapper.m | 50 +++++++++++- ios/Classes/EMChatMessage+Helper.h | 5 ++ ios/Classes/EMChatMessage+Helper.m | 50 ++++++++++++ ios/Classes/EMClientWrapper.m | 121 +++++++++++++++++++---------- ios/Classes/EMOptions+Helper.m | 7 +- ios/Classes/EMSDKMethod.h | 4 + lib/src/em_client.dart | 4 +- lib/src/models/em_message.dart | 8 +- lib/src/models/em_options.dart | 8 +- 9 files changed, 202 insertions(+), 55 deletions(-) diff --git a/ios/Classes/EMChatManagerWrapper.m b/ios/Classes/EMChatManagerWrapper.m index 7690b7e5..7195d065 100644 --- a/ios/Classes/EMChatManagerWrapper.m +++ b/ios/Classes/EMChatManagerWrapper.m @@ -188,8 +188,11 @@ - (void)handleMethodCall:(FlutterMethodCall*)call [self getPinnedConversationsFromServerWithCursor:call.arguments channelName:call.method result:result]; } else if ([PinConversation isEqualToString:call.method]) { [self pinConversation:call.arguments channelName:call.method result:result]; + } else if ([modifyMessage isEqualToString:call.method]) { + [self modifyMessage:call.arguments channelName:call.method result:result]; + } else if ([downloadAndParseCombineMessage isEqualToString:call.method]) { + [self downloadAndParseCombineMessage:call.arguments channelName:call.method result:result]; } - else { [super handleMethodCall:call result:result]; } @@ -1047,6 +1050,41 @@ - (void)pinConversation:(NSDictionary *)param }]; } +- (void)modifyMessage:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { + __weak typeof(self) weakSelf = self; + NSString *msgId = param[@"msgId"]; + EMTextMessageBody *body = [EMTextMessageBody fromJson:param[@"body"]]; + [EMClient.sharedClient.chatManager modifyMessage:msgId + body:body + completion:^(EMError * _Nullable error, EMChatMessage * _Nullable message) + { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:error + object:[message toJson]]; + }]; +} + +- (void)downloadAndParseCombineMessage:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { + __weak typeof(self) weakSelf = self; + EMChatMessage *msg = [EMChatMessage fromJson:param[@"message"]]; + + [EMClient.sharedClient.chatManager downloadAndParseCombineMessage:msg + completion:^(NSArray * _Nullable messages, EMError * _Nullable error) + { + NSMutableArray *msgJsonAry = [NSMutableArray array]; + for (EMChatMessage *msg in messages) { + [msgJsonAry addObject:[msg toJson]]; + } + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:error + object:msgJsonAry]; + }]; +} + + + #pragma mark - EMChatManagerDelegate @@ -1148,5 +1186,15 @@ - (EMMessageSearchDirection)searchDirectionFromString:(NSString *)aDirection { return [aDirection isEqualToString:@"up"] ? EMMessageSearchDirectionUp : EMMessageSearchDirectionDown; } +- (void)onMessageContentChanged:(EMChatMessage *)message operatorId:(NSString *)operatorId operationTime:(NSUInteger)operationTime { + NSDictionary *dict = @{ + @"message": [message toJson], + @"operator": operatorId, + @"operationTime": @(operationTime) + }; + + [self.channel invokeMethod:onMessageContentChanged + arguments:dict]; +} @end diff --git a/ios/Classes/EMChatMessage+Helper.h b/ios/Classes/EMChatMessage+Helper.h index 71bad6fd..7f0dd871 100644 --- a/ios/Classes/EMChatMessage+Helper.h +++ b/ios/Classes/EMChatMessage+Helper.h @@ -26,4 +26,9 @@ NS_ASSUME_NONNULL_BEGIN + (int)downloadStatusToInt:(EMDownloadStatus)aStatus; @end +@interface EMTextMessageBody (Helper) ++ (EMTextMessageBody *)fromJson:(NSDictionary *)aJson; +- (NSDictionary *)toJson; +@end + NS_ASSUME_NONNULL_END diff --git a/ios/Classes/EMChatMessage+Helper.m b/ios/Classes/EMChatMessage+Helper.m index 30ef8d18..c993a82d 100644 --- a/ios/Classes/EMChatMessage+Helper.m +++ b/ios/Classes/EMChatMessage+Helper.m @@ -205,6 +205,8 @@ + (EMMessageBody *)fromJson:(NSDictionary *)bodyJson { ret = [EMCmdMessageBody fromJson:bodyJson]; } else if ([type isEqualToString:@"custom"]) { ret = [EMCustomMessageBody fromJson:bodyJson]; + } else if ([type isEqualToString:@"combine"]) { + ret = [EMCombineMessageBody fromJson:bodyJson]; } return ret; } @@ -237,10 +239,16 @@ - (NSDictionary *)toJson { case EMMessageBodyTypeVoice: type = @"voice"; break; + case EMMessageBodyTypeCombine: + type = @"combine"; + break; default: break; } ret[@"type"] = type; + ret[@"operatorId"] = self.operatorId; + ret[@"operatorTime"] = @(self.operationTime); + ret[@"operatorCount"] = @(self.operatorCount); return ret; } @@ -439,6 +447,48 @@ - (NSDictionary *)toJson { @end +@interface EMCombineMessageBody (Helper) ++ (EMCombineMessageBody *)fromJson:(NSDictionary *)aJson; +- (NSDictionary *)toJson; +@end + +@implementation EMCombineMessageBody (Helper) + ++ (EMCombineMessageBody *)fromJson:(NSDictionary *)aJson { + + NSString *title = aJson[@"title"]; + NSString *summary = aJson[@"summary"]; + NSArray *msgList = aJson[@"messageList"]; + NSString *compatibleText = aJson[@"compatibleText"]; + NSString *localPath = aJson[@"localPath"]; + NSString *remotePath = aJson[@"remotePath"]; + NSString *secret = aJson[@"secret"]; + + EMCombineMessageBody *ret = [[EMCombineMessageBody alloc] initWithTitle:title + summary:summary + compatibleText:compatibleText + messageIdList:msgList]; + + ret.remotePath = remotePath; + ret.secretKey = secret; + ret.localPath = localPath; + return ret; +} + +- (NSDictionary *)toJson { + NSMutableDictionary *ret = [[super toJson] mutableCopy]; + ret[@"title"] = self.title; + ret[@"summary"] = self.summary; + ret[@"messageList"] = self.messageIdList; + ret[@"compatibleText"] = self.compatibleText; + ret[@"localPath"] = self.localPath; + ret[@"remotePath"] = self.remotePath; + ret[@"secret"] = self.secretKey; + return ret; +} + +@end + #pragma mark - file @interface EMFileMessageBody (Helper) diff --git a/ios/Classes/EMClientWrapper.m b/ios/Classes/EMClientWrapper.m index b805ab6b..284a930a 100644 --- a/ios/Classes/EMClientWrapper.m +++ b/ios/Classes/EMClientWrapper.m @@ -340,34 +340,53 @@ - (void)compressLogs:(NSDictionary *)param channelName:(NSString *)aChannelName - (void)kickDevice:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self)weakSelf = self; NSString *username = param[@"username"]; - NSString *password = param[@"password"]; + NSString *pwdOrToken = param[@"password"]; NSString *resource = param[@"resource"]; - - [EMClient.sharedClient kickDeviceWithUsername:username - password:password - resource:resource - completion:^(EMError *aError) - { - [weakSelf wrapperCallBack:result - channelName:aChannelName - error:aError - object:nil]; - }]; + bool isPwd = [param[@"isPwd"] boolValue]; + if(isPwd) { + [EMClient.sharedClient kickDeviceWithUsername:username + password:pwdOrToken + resource:resource + completion:^(EMError *aError) + { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:aError + object:nil]; + }]; + }else { + [EMClient.sharedClient kickDeviceWithUserId:username token:pwdOrToken resource:resource completion:^(EMError * _Nullable aError) { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:aError + object:nil]; + }]; + } } - (void)kickAllDevices:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self)weakSelf = self; NSString *username = param[@"username"]; - NSString *password = param[@"password"]; - [EMClient.sharedClient kickAllDevicesWithUsername:username - password:password - completion:^(EMError *aError) - { - [weakSelf wrapperCallBack:result - channelName:aChannelName - error:aError - object:nil]; - }]; + NSString *pwdOrToken = param[@"password"]; + bool isPwd = [param[@"isPwd"] boolValue]; + if(isPwd) { + [EMClient.sharedClient kickAllDevicesWithUsername:username + password:pwdOrToken + completion:^(EMError *aError) + { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:aError + object:nil]; + }]; + }else { + [EMClient.sharedClient kickAllDevicesWithUserId:username token:pwdOrToken completion:^(EMError * _Nullable aError) { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:aError + object:nil]; + }]; + } } - (void)isLoggedInBefore:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { @@ -422,23 +441,43 @@ - (void)renewToken:(NSDictionary *)param channelName:(NSString *)aChannelName re - (void)getLoggedInDevicesFromServer:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self)weakSelf = self; NSString *username = param[@"username"]; - NSString *password = param[@"password"]; - [EMClient.sharedClient getLoggedInDevicesFromServerWithUsername:username - password:password - completion:^(NSArray *aList, EMError *aError) - { - - NSMutableArray *list = [NSMutableArray array]; - for (EMDeviceConfig *deviceInfo in aList) { - [list addObject:[deviceInfo toJson]]; - } - - - [weakSelf wrapperCallBack:result - channelName:aChannelName - error:aError - object:nil]; - }]; + NSString *pwdOrToken = param[@"password"]; + bool isPwd = [param[@"isPwd"] boolValue]; + if(isPwd) { + [EMClient.sharedClient getLoggedInDevicesFromServerWithUsername:username + password:pwdOrToken + completion:^(NSArray *aList, EMError *aError) + { + + NSMutableArray *list = [NSMutableArray array]; + for (EMDeviceConfig *deviceInfo in aList) { + [list addObject:[deviceInfo toJson]]; + } + + + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:aError + object:nil]; + }]; + }else { + [EMClient.sharedClient getLoggedInDevicesFromServerWithUserId:username + token:pwdOrToken + completion:^(NSArray * _Nullable aList, EMError * _Nullable aError) + { + NSMutableArray *list = [NSMutableArray array]; + for (EMDeviceConfig *deviceInfo in aList) { + [list addObject:[deviceInfo toJson]]; + } + + + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:aError + object:nil]; + }]; + } + } - (void)startCallBack:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result{ @@ -487,10 +526,10 @@ - (void)tokenDidExpire:(EMErrorCode)aErrorCode { arguments:nil]; } -- (void)userAccountDidLoginFromOtherDevice { +- (void)userAccountDidLoginFromOtherDevice:(NSString *)aDeviceName { [EMListenerHandle.sharedInstance clearHandle]; [self.channel invokeMethod:ChatOnUserDidLoginFromOtherDevice - arguments:nil]; + arguments:@{@"deviceName": aDeviceName}]; } - (void)userAccountDidRemoveFromServer { diff --git a/ios/Classes/EMOptions+Helper.m b/ios/Classes/EMOptions+Helper.m index b05dda88..b172b955 100644 --- a/ios/Classes/EMOptions+Helper.m +++ b/ios/Classes/EMOptions+Helper.m @@ -33,6 +33,8 @@ - (NSDictionary *)toJson { data[@"restServer"] = self.restServer; data[@"dnsUrl"] = self.dnsURL; data[@"areaCode"] = @(self.area); + data[@"deviceName"] = self.customDeviceName; + data[@"osType"] = @(self.customOSType); return data; } @@ -59,7 +61,10 @@ + (EMOptions *)fromJson:(NSDictionary *)aJson { options.restServer = aJson[@"restServer"]; options.dnsURL = aJson[@"dnsURL"]; options.area = [aJson[@"areaCode"] intValue]; - + options.customDeviceName = aJson[@"deviceName"]; + if(aJson[@"osType"]) { + options.customOSType = [aJson[@"osType"] intValue]; + } return options; } @end diff --git a/ios/Classes/EMSDKMethod.h b/ios/Classes/EMSDKMethod.h index f32364e2..9b04b435 100644 --- a/ios/Classes/EMSDKMethod.h +++ b/ios/Classes/EMSDKMethod.h @@ -107,6 +107,8 @@ static NSString *const ChatRemoveMessagesFromServerWithTs = @"removeMessagesFrom static NSString *const GetConversationsFromServerWithCursor = @"getConversationsFromServerWithCursor"; static NSString *const GetPinnedConversationsFromServerWithCursor = @"getPinnedConversationsFromServerWithCursor"; static NSString *const PinConversation = @"pinConversation"; +static NSString *const modifyMessage = @"modifyMessage"; +static NSString *const downloadAndParseCombineMessage = @"downloadAndParseCombineMessage"; #pragma mark - EMChatManagerDelegate static NSString *const ChatOnMessagesReceived = @"onMessagesReceived"; @@ -122,6 +124,8 @@ static NSString *const ChatOnConversationHasRead = @"onConversationHasRead"; static NSString *const ChatOnMessageReactionDidChange = @"messageReactionDidChange"; +static NSString *const onMessageContentChanged = @"onMessageContentChanged"; + #pragma mark - EMMessageListener static NSString *const ChatOnMessageProgressUpdate = @"onMessageProgressUpdate"; static NSString *const ChatOnMessageSuccess = @"onMessageSuccess"; diff --git a/lib/src/em_client.dart b/lib/src/em_client.dart index 35acc7b3..5355c7a6 100644 --- a/lib/src/em_client.dart +++ b/lib/src/em_client.dart @@ -716,7 +716,7 @@ class EMClient { required String pwdOrToken, bool isPwd = true, }) async { - Map req = {'username': userId, 'pwdOrToken': pwdOrToken, 'isPwd': isPwd}; + Map req = {'username': userId, 'password': pwdOrToken, 'isPwd': isPwd}; Map result = await ClientChannel.invokeMethod( ChatMethodKeys.getLoggedInDevicesFromServer, req); try { @@ -763,7 +763,7 @@ class EMClient { EMLog.v('kickDevice: $userId, "******"'); Map req = { 'username': userId, - 'pwdOrToken': pwdOrToken, + 'password': pwdOrToken, 'resource': resource, 'isPwd': isPwd, }; diff --git a/lib/src/models/em_message.dart b/lib/src/models/em_message.dart index 2397b13b..d0b303a6 100644 --- a/lib/src/models/em_message.dart +++ b/lib/src/models/em_message.dart @@ -843,6 +843,9 @@ class EMMessage { case 'voice': body = EMVoiceMessageBody.fromJson(map: map); break; + case 'combine': + body = EMCombineMessageBody.fromJson(map: map); + break; default: } @@ -1496,10 +1499,7 @@ class EMTextMessageBody extends EMMessageBody { /// @nodoc EMTextMessageBody.fromJson({required Map map}) - : super.fromJson( - map: map, - type: MessageType.TXT, - ) { + : super.fromJson(map: map, type: MessageType.TXT) { this.content = map["content"] ?? ""; this.targetLanguages = map.getList("targetLanguages"); if (map.containsKey("translations")) { diff --git a/lib/src/models/em_options.dart b/lib/src/models/em_options.dart index b0c68334..c5a67eb2 100644 --- a/lib/src/models/em_options.dart +++ b/lib/src/models/em_options.dart @@ -591,16 +591,12 @@ class EMOptions { data.putIfNotNull("sortMessageByServerTime", sortMessageByServerTime); data.putIfNotNull("usingHttpsOnly", usingHttpsOnly); data.putIfNotNull('loadEmptyConversations', enableEmptyConversation); + data.putIfNotNull('deviceName', deviceName); + data.putIfNotNull('osType', osType); data["usingHttpsOnly"] = this.usingHttpsOnly; data["pushConfig"] = this._pushConfig.toJson(); data["areaCode"] = this.chatAreaCode; - if (deviceName != null) { - data["customDeviceName"] = this.deviceName; - } - if (osType != null) { - data["customOSType"] = this.osType; - } return data; } From 1025acc12159f60e8b01ed8600a61f979a9e1006 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Fri, 14 Jul 2023 15:10:20 +0800 Subject: [PATCH 34/49] add android sied code. --- .../im_flutter_sdk/EMChatManagerWrapper.java | 40 ++++- .../im_flutter_sdk/EMClientWrapper.java | 110 ++++++++---- .../im_flutter_sdk/EMConversationWrapper.java | 1 + .../com/easemob/im_flutter_sdk/EMHelper.java | 169 +++++++++++++----- .../easemob/im_flutter_sdk/EMSDKMethod.java | 4 + ios/Classes/EMChatMessage+Helper.m | 3 +- .../EMFetchServerMessagesOption+Helper.m | 2 + 7 files changed, 252 insertions(+), 77 deletions(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java index 47d1c559..3b053c49 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java @@ -2,7 +2,6 @@ import com.hyphenate.EMConversationListener; import com.hyphenate.EMMessageListener; -import com.hyphenate.EMValueCallBack; import com.hyphenate.chat.EMClient; import com.hyphenate.chat.*; import com.hyphenate.chat.EMConversation.EMSearchDirection; @@ -10,7 +9,6 @@ import com.hyphenate.chat.EMCursorResult; import com.hyphenate.chat.EMMessage; -import com.hyphenate.chat.adapter.message.EMAMessage; import com.hyphenate.exceptions.HyphenateException; import java.util.ArrayList; @@ -31,7 +29,7 @@ import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; -import io.flutter.plugin.common.PluginRegistry.Registrar; + public class EMChatManagerWrapper extends EMWrapper implements MethodCallHandler { @@ -125,7 +123,12 @@ public void onMethodCall(MethodCall call, Result result) { getPinnedConversationsFromServerWithCursor(param, call.method, result); } else if (EMSDKMethod.pinConversation.equals(call.method)) { pinConversation(param, call.method, result); - } else { + } else if (EMSDKMethod.modifyMessage.equals(call.method)) { + modifyMessage(param, call.method, result); + } else if (EMSDKMethod.downloadAndParseCombineMessage.equals(call.method)) { + downloadAndParseCombineMessage(param, call.method, result); + } + else { super.onMethodCall(call, result); } } catch (JSONException ignored) { @@ -893,6 +896,25 @@ private void pinConversation(JSONObject param, String channelName, Result result EMClient.getInstance().chatManager().asyncPinConversation(convId, isPinned, new EMWrapperCallBack(result, channelName, null)); } + private void modifyMessage(JSONObject param, String channelName, Result result) throws JSONException { + String msgId = param.optString("msgId"); + EMTextMessageBody body = EMMessageBodyHelper.textBodyFromJson(param.optJSONObject("body")); + EMClient.getInstance().chatManager().asyncModifyMessage(msgId, body, new EMWrapperCallBack(result, channelName, null)); + } + private void downloadAndParseCombineMessage(JSONObject param, String channelName, Result result) throws JSONException { + EMMessage msg = EMMessageHelper.fromJson(param.optJSONObject("message")); + EMClient.getInstance().chatManager().downloadAndParseCombineMessage(msg, new EMValueWrapperCallBack>(result, channelName){ + @Override + public void onSuccess(List msgList) { + List messages = new ArrayList<>(); + for(EMMessage msg: msgList) { + messages.add(EMMessageHelper.toJson(msg)); + } + updateObject(messages); + } + }); + } + @Override public void unRegisterEaseListener() { EMClient.getInstance().chatManager().removeMessageListener(messageListener); @@ -979,6 +1001,16 @@ public void onReactionChanged(List messageReactionChang } post(() -> channel.invokeMethod(EMSDKMethod.onMessageReactionDidChange, list)); } + + @Override + public void onMessageContentChanged(EMMessage messageModified, String operatorId, long operationTime) { + Map msgMap = EMMessageHelper.toJson(messageModified); + Map map = new HashMap<>(); + map.put("message", msgMap); + map.put("operator", operatorId); + map.put("operationTime", operationTime); + post(() -> channel.invokeMethod(EMSDKMethod.onMessageContentChanged, map)); + } }; if (conversationListener != null) { diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java index bfe0ec46..f2830f70 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java @@ -258,28 +258,51 @@ private void kickDevice(JSONObject param, String channelName, Result result) thr String username = param.getString("username"); String password = param.getString("password"); String resource = param.getString("resource"); - asyncRunnable(()->{ - try { - EMClient.getInstance().kickDevice(username, password, resource); - onSuccess(result, channelName, true); - } catch (HyphenateException e) { - onError(result, e); - } - }); + boolean isPwd = param.optBoolean("isPwd"); + if (isPwd) { + asyncRunnable(()->{ + try { + EMClient.getInstance().kickDevice(username, password, resource); + onSuccess(result, channelName, true); + } catch (HyphenateException e) { + onError(result, e); + } + }); + }else { + asyncRunnable(()->{ + try { + EMClient.getInstance().kickDeviceWithToken(username, password, resource); + onSuccess(result, channelName, true); + } catch (HyphenateException e) { + onError(result, e); + } + }); + } } private void kickAllDevices(JSONObject param, String channelName, Result result) throws JSONException { String username = param.getString("username"); String password = param.getString("password"); - - asyncRunnable(()->{ - try { - EMClient.getInstance().kickAllDevices(username, password); - onSuccess(result, channelName, true); - } catch (HyphenateException e) { - onError(result, e); - } - }); + boolean isPwd = param.optBoolean("isPwd"); + if (isPwd) { + asyncRunnable(()->{ + try { + EMClient.getInstance().kickAllDevices(username, password); + onSuccess(result, channelName, true); + } catch (HyphenateException e) { + onError(result, e); + } + }); + }else { + asyncRunnable(()->{ + try { + EMClient.getInstance().kickAllDevicesWithToken(username, password); + onSuccess(result, channelName, true); + } catch (HyphenateException e) { + onError(result, e); + } + }); + } } private void init(JSONObject param, String channelName, Result result) throws JSONException { @@ -308,18 +331,34 @@ private void renewToken(JSONObject param, String channelName, Result result) thr private void getLoggedInDevicesFromServer(JSONObject param, String channelName, Result result) throws JSONException { String username = param.getString("username"); String password = param.getString("password"); - asyncRunnable(()->{ - try { - List devices = EMClient.getInstance().getLoggedInDevicesFromServer(username, password); - List jsonList = new ArrayList <>(); - for (EMDeviceInfo info: devices) { - jsonList.add(EMDeviceInfoHelper.toJson(info)); + boolean isPwd = param.optBoolean("isPwd"); + if (isPwd) { + asyncRunnable(()->{ + try { + List devices = EMClient.getInstance().getLoggedInDevicesFromServer(username, password); + List jsonList = new ArrayList <>(); + for (EMDeviceInfo info: devices) { + jsonList.add(EMDeviceInfoHelper.toJson(info)); + } + onSuccess(result, channelName, jsonList); + } catch (HyphenateException e) { + onError(result, e); } - onSuccess(result, channelName, jsonList); - } catch (HyphenateException e) { - onError(result, e); - } - }); + }); + }else { + asyncRunnable(()->{ + try { + List devices = EMClient.getInstance().getLoggedInDevicesFromServerWithToken(username, password); + List jsonList = new ArrayList <>(); + for (EMDeviceInfo info: devices) { + jsonList.add(EMDeviceInfoHelper.toJson(info)); + } + onSuccess(result, channelName, jsonList); + } catch (HyphenateException e) { + onError(result, e); + } + }); + } } private void startCallback(JSONObject param, String channelName, Result result) { @@ -436,8 +475,9 @@ public void onLogout(int errorCode) { @Override public void onDisconnected(int errorCode) { if (errorCode == 206) { - EMListenerHandle.getInstance().clearHandle(); - post(() -> channel.invokeMethod(EMSDKMethod.onUserDidLoginFromOtherDevice, null)); + // 这部分实现放到onLogout中。 +// EMListenerHandle.getInstance().clearHandle(); +// post(() -> channel.invokeMethod(EMSDKMethod.onUserDidLoginFromOtherDevice, null)); }else if (errorCode == 207) { EMListenerHandle.getInstance().clearHandle(); post(() -> channel.invokeMethod(EMSDKMethod.onUserDidRemoveFromServer, null)); @@ -476,6 +516,16 @@ public void onTokenExpired() { public void onTokenWillExpire() { post(()-> channel.invokeMethod(EMSDKMethod.onTokenWillExpire, null)); } + + @Override + public void onLogout(int errorCode, String info) { + if (errorCode == 206) { + EMListenerHandle.getInstance().clearHandle(); + Map attributes = new HashMap<>(); + attributes.put("deviceName", info); + post(() -> channel.invokeMethod(EMSDKMethod.onUserDidLoginFromOtherDevice, attributes)); + } + } }; EMClient.getInstance().addConnectionListener(connectionListener); diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java index d8d4ea85..98a58411 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMConversationWrapper.java @@ -301,6 +301,7 @@ private void loadMsgWithMsgType(JSONObject params, String channelName, Result re case "img" : type = EMMessage.Type.IMAGE; break; case "video" : type = EMMessage.Type.VIDEO; break; case "voice" : type = EMMessage.Type.VOICE; break; + case "combine" : type = EMMessage.Type.COMBINE; break; } EMMessage.Type finalType = type; diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java index a02d5bf4..0a7a965c 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java @@ -8,6 +8,7 @@ import com.hyphenate.chat.EMChatThread; import com.hyphenate.chat.EMChatThreadEvent; import com.hyphenate.chat.EMCmdMessageBody; +import com.hyphenate.chat.EMCombineMessageBody; import com.hyphenate.chat.EMConversation; import com.hyphenate.chat.EMCursorResult; import com.hyphenate.chat.EMCustomMessageBody; @@ -75,6 +76,12 @@ static EMOptions fromJson(JSONObject json, Context context) throws JSONException options.setUsingHttpsOnly(json.getBoolean("usingHttpsOnly")); options.enableDNSConfig(json.getBoolean("enableDNSConfig")); options.setLoadEmptyConversations(json.optBoolean("loadEmptyConversations", false)); + if (json.has("deviceName")) { + options.setCustomDeviceName(json.optString("deviceName")); + } + if (json.has("osType")) { + options.setCustomOSPlatform(json.optInt("osType")); + } if (!json.getBoolean("enableDNSConfig")) { if (json.has("imPort")) { options.setImPort(json.getInt("imPort")); @@ -372,6 +379,10 @@ static EMMessage fromJson(JSONObject json) throws JSONException { message.addBody(EMMessageBodyHelper.customBodyFromJson(bodyJson)); } break; + case "combine": { + message = EMMessage.createSendMessage(Type.COMBINE); + message.addBody(EMMessageBodyHelper.combineBodyFromJson(bodyJson)); + } } if (message != null) { message.setDirection(EMMessage.Direct.SEND); @@ -381,43 +392,52 @@ static EMMessage fromJson(JSONObject json) throws JSONException { case "txt": { message = EMMessage.createReceiveMessage(Type.TXT); message.addBody(EMMessageBodyHelper.textBodyFromJson(bodyJson)); - } break; + } case "img": { message = EMMessage.createReceiveMessage(Type.IMAGE); message.addBody(EMMessageBodyHelper.imageBodyFromJson(bodyJson)); - } break; + } + case "loc": { message = EMMessage.createReceiveMessage(Type.LOCATION); message.addBody(EMMessageBodyHelper.localBodyFromJson(bodyJson)); - } break; + } + case "video": { message = EMMessage.createReceiveMessage(Type.VIDEO); message.addBody(EMMessageBodyHelper.videoBodyFromJson(bodyJson)); - } break; + } + case "voice": { message = EMMessage.createReceiveMessage(Type.VOICE); message.addBody(EMMessageBodyHelper.voiceBodyFromJson(bodyJson)); - } break; + } case "file": { message = EMMessage.createReceiveMessage(Type.FILE); message.addBody(EMMessageBodyHelper.fileBodyFromJson(bodyJson)); - } break; + } case "cmd": { message = EMMessage.createReceiveMessage(Type.CMD); message.addBody(EMMessageBodyHelper.cmdBodyFromJson(bodyJson)); - } break; + } case "custom": { message = EMMessage.createReceiveMessage(Type.CUSTOM); message.addBody(EMMessageBodyHelper.customBodyFromJson(bodyJson)); + break; + } + + case "combine": { + message = EMMessage.createReceiveMessage(Type.COMBINE); + message.addBody(EMMessageBodyHelper.combineBodyFromJson(bodyJson)); + break; } - break; } if (message != null) { message.setDirection(EMMessage.Direct.RECEIVE); @@ -503,38 +523,42 @@ static EMMessage fromJson(JSONObject json) throws JSONException { static Map toJson(EMMessage message) { Map data = new HashMap<>(); switch (message.getType()) { - case TXT: { - data.put("body", EMMessageBodyHelper.textBodyToJson((EMTextMessageBody) message.getBody())); - } - break; - case IMAGE: { - data.put("body", EMMessageBodyHelper.imageBodyToJson((EMImageMessageBody) message.getBody())); - } - break; - case LOCATION: { - data.put("body", EMMessageBodyHelper.localBodyToJson((EMLocationMessageBody) message.getBody())); - } - break; - case CMD: { - data.put("body", EMMessageBodyHelper.cmdBodyToJson((EMCmdMessageBody) message.getBody())); - } - break; - case CUSTOM: { - data.put("body", EMMessageBodyHelper.customBodyToJson((EMCustomMessageBody) message.getBody())); - } - break; - case FILE: { - data.put("body", EMMessageBodyHelper.fileBodyToJson((EMNormalFileMessageBody) message.getBody())); - } - break; - case VIDEO: { - data.put("body", EMMessageBodyHelper.videoBodyToJson((EMVideoMessageBody) message.getBody())); - } - break; - case VOICE: { - data.put("body", EMMessageBodyHelper.voiceBodyToJson((EMVoiceMessageBody) message.getBody())); - } - break; + case TXT: { + data.put("body", EMMessageBodyHelper.textBodyToJson((EMTextMessageBody) message.getBody())); + } + break; + case IMAGE: { + data.put("body", EMMessageBodyHelper.imageBodyToJson((EMImageMessageBody) message.getBody())); + } + break; + case LOCATION: { + data.put("body", EMMessageBodyHelper.localBodyToJson((EMLocationMessageBody) message.getBody())); + } + break; + case CMD: { + data.put("body", EMMessageBodyHelper.cmdBodyToJson((EMCmdMessageBody) message.getBody())); + } + break; + case CUSTOM: { + data.put("body", EMMessageBodyHelper.customBodyToJson((EMCustomMessageBody) message.getBody())); + } + break; + case FILE: { + data.put("body", EMMessageBodyHelper.fileBodyToJson((EMNormalFileMessageBody) message.getBody())); + } + break; + case VIDEO: { + data.put("body", EMMessageBodyHelper.videoBodyToJson((EMVideoMessageBody) message.getBody())); + } + break; + case VOICE: { + data.put("body", EMMessageBodyHelper.voiceBodyToJson((EMVoiceMessageBody) message.getBody())); + } + break; + case COMBINE:{ + data.put("body", EMMessageBodyHelper.combineBodyToJson((EMCombineMessageBody) message.getBody())); + } + break; } if (message.ext().size() > 0 && null != message.ext()) { @@ -631,9 +655,9 @@ class EMGroupAckHelper { } -class EMMessageBodyHelper { + class EMMessageBodyHelper { - static EMTextMessageBody textBodyFromJson(JSONObject json) throws JSONException { + public static EMTextMessageBody textBodyFromJson(JSONObject json) throws JSONException { String content = json.getString("content"); List list = new ArrayList<>(); if (json.has("targetLanguages")) { @@ -927,6 +951,63 @@ static Map voiceBodyToJson(EMVoiceMessageBody body) { return data; } + static EMCombineMessageBody combineBodyFromJson(JSONObject json) throws JSONException { + String title = json.optString("title"); + String summary = json.optString("summary"); + String compatibleText = json.optString("compatibleText"); + String localPath = json.optString("localPath"); + String remotePath = json.optString("remotePath"); + String secret = json.optString("secret"); + List msgIds = new ArrayList<>(); + if (json.has("messageList")){ + JSONArray array = json.getJSONArray("messageList"); + for (int i = 0; i < array.length(); i++) { + msgIds.add(array.getString(i)); + } + } + + EMCombineMessageBody ret = new EMCombineMessageBody(); + ret.setTitle(title); + ret.setSummary(summary); + ret.setCompatibleText(compatibleText); + ret.setLocalUrl(localPath); + ret.setRemoteUrl(remotePath); + ret.setSecret(secret); + ret.setMessageList(msgIds); + + return ret; + } + static Map combineBodyToJson(EMCombineMessageBody body) { + Map ret = new HashMap<>(); + if (body.getTitle() != null) { + ret.put("title", body.getTitle()); + } + + if (body.getSummary() != null) { + ret.put("summary", body.getSummary()); + } + + if (body.getCompatibleText() != null) { + ret.put("compatibleText", body.getCompatibleText()); + } + + if (body.getLocalUrl() != null) { + ret.put("localPath", body.getLocalUrl()); + } + + if (body.getRemoteUrl() != null) { + ret.put("remotePath", body.getRemoteUrl()); + } + + if (body.getSecret() != null) { + ret.put("secret", body.getSecret()); + } + + ret.put("type", "combine"); + + return ret; + } + private static EMFileMessageBody.EMDownloadStatus downloadStatusFromInt(int downloadStatus) { switch (downloadStatus) { case 0: @@ -1483,6 +1564,10 @@ static EMFetchMessageOption fromJson(JSONObject json) throws JSONException { list.add(Type.CUSTOM); } break; + case "combine": { + list.add(Type.COMBINE); + } + break; } } if (list.size() > 0) { diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java index 456c547e..957aa83a 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMSDKMethod.java @@ -97,6 +97,8 @@ public class EMSDKMethod { static final String getConversationsFromServerWithCursor = "getConversationsFromServerWithCursor"; static final String getPinnedConversationsFromServerWithCursor = "getPinnedConversationsFromServerWithCursor"; static final String pinConversation = "pinConversation"; + static final String modifyMessage = "modifyMessage"; + static final String downloadAndParseCombineMessage = "downloadAndParseCombineMessage"; /// EMChatManager listener static final String onMessagesReceived = "onMessagesReceived"; static final String onCmdMessagesReceived = "onCmdMessagesReceived"; @@ -110,6 +112,8 @@ public class EMSDKMethod { static final String onConversationHasRead = "onConversationHasRead"; static final String onMessageReactionDidChange = "messageReactionDidChange"; + static final String onMessageContentChanged = "onMessageContentChanged"; + /// EMMessage listener static final String onMessageProgressUpdate = "onMessageProgressUpdate"; diff --git a/ios/Classes/EMChatMessage+Helper.m b/ios/Classes/EMChatMessage+Helper.m index c993a82d..eab7874a 100644 --- a/ios/Classes/EMChatMessage+Helper.m +++ b/ios/Classes/EMChatMessage+Helper.m @@ -273,6 +273,8 @@ + (EMMessageBodyType)typeFromString:(NSString *)aStrType { ret = EMMessageBodyTypeVideo; } else if ([aStrType isEqualToString:@"voice"]) { ret = EMMessageBodyTypeVoice; + } else if ([aStrType isEqualToString:@"combine"]) { + ret = EMMessageBodyTypeCombine; } return ret; } @@ -479,7 +481,6 @@ - (NSDictionary *)toJson { NSMutableDictionary *ret = [[super toJson] mutableCopy]; ret[@"title"] = self.title; ret[@"summary"] = self.summary; - ret[@"messageList"] = self.messageIdList; ret[@"compatibleText"] = self.compatibleText; ret[@"localPath"] = self.localPath; ret[@"remotePath"] = self.remotePath; diff --git a/ios/Classes/EMFetchServerMessagesOption+Helper.m b/ios/Classes/EMFetchServerMessagesOption+Helper.m index 525f750c..fa8d9655 100644 --- a/ios/Classes/EMFetchServerMessagesOption+Helper.m +++ b/ios/Classes/EMFetchServerMessagesOption+Helper.m @@ -37,6 +37,8 @@ + (EMFetchServerMessagesOption *)formJson:(NSDictionary *)dict { [list addObject:@(EMMessageBodyTypeCmd)]; } else if ([type isEqualToString:@"custom"]) { [list addObject:@(EMMessageBodyTypeCustom)]; + } else if ([type isEqualToString:@"combine"]) { + [list addObject:@(EMMessageBodyTypeCombine)]; } } } From 8f003b43cbf451e702e52c6e12605530874576ee Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Fri, 14 Jul 2023 18:14:48 +0800 Subject: [PATCH 35/49] fix ios connection callback nonexecution. --- ios/Classes/EMClientWrapper.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/Classes/EMClientWrapper.m b/ios/Classes/EMClientWrapper.m index 284a930a..b8d43ae9 100644 --- a/ios/Classes/EMClientWrapper.m +++ b/ios/Classes/EMClientWrapper.m @@ -185,8 +185,6 @@ - (void)initSDKWithDict:(NSDictionary *)param channelName:(NSString *)aChannelNa [EMClient.sharedClient initializeSDKWithOptions:_options]; - [EMClient.sharedClient addDelegate:self delegateQueue:nil]; - [EMClient.sharedClient addMultiDevicesDelegate:self delegateQueue:nil]; [self registerManagers]; [weakSelf wrapperCallBack:result channelName:ChatInit @@ -197,6 +195,8 @@ - (void)initSDKWithDict:(NSDictionary *)param channelName:(NSString *)aChannelNa - (void)registerManagers { [self clearAllListener]; + [EMClient.sharedClient addDelegate:self delegateQueue:nil]; + [EMClient.sharedClient addMultiDevicesDelegate:self delegateQueue:nil]; _chatManager = [[EMChatManagerWrapper alloc] initWithChannelName:EMChannelName(@"chat_manager")registrar:self.flutterPluginRegister]; _contactManager = [[EMContactManagerWrapper alloc] initWithChannelName:EMChannelName(@"chat_contact_manager") registrar:self.flutterPluginRegister]; _conversationManager = [[EMConversationWrapper alloc] initWithChannelName:EMChannelName(@"chat_conversation") registrar:self.flutterPluginRegister]; From 901af3c634d08daec0675bb40883a5fad9758daa Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Mon, 17 Jul 2023 11:35:46 +0800 Subject: [PATCH 36/49] fix ios error. --- ios/Classes/EMChatManagerWrapper.m | 16 +++-- lib/src/models/em_message.dart | 106 ++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 5 deletions(-) diff --git a/ios/Classes/EMChatManagerWrapper.m b/ios/Classes/EMChatManagerWrapper.m index 7195d065..48440436 100644 --- a/ios/Classes/EMChatManagerWrapper.m +++ b/ios/Classes/EMChatManagerWrapper.m @@ -1058,10 +1058,18 @@ - (void)modifyMessage:(NSDictionary *)param channelName:(NSString *)aChannelName body:body completion:^(EMError * _Nullable error, EMChatMessage * _Nullable message) { - [weakSelf wrapperCallBack:result - channelName:aChannelName - error:error - object:[message toJson]]; + if(error) { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:error + object:nil]; + }else { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:error + object:[message toJson]]; + } + }]; } diff --git a/lib/src/models/em_message.dart b/lib/src/models/em_message.dart index d0b303a6..77b0df6c 100644 --- a/lib/src/models/em_message.dart +++ b/lib/src/models/em_message.dart @@ -285,6 +285,8 @@ class EMMessage { /// /// Param [body] The message body. /// + /// Param [chatType] The chat type, default is single chat, if it is group chat or chat room, see [ChatType]. + /// /// **Return** The message instance. /// ~end /// @@ -293,6 +295,8 @@ class EMMessage { /// /// Param [body] 消息体。 /// + /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考[ChatType]。 + /// /// **Return** 消息实例。 /// ~end EMMessage.createReceiveMessage({ @@ -313,6 +317,8 @@ class EMMessage { /// - For a group chat, it is the group ID. /// - For a chat room, it is the chat room ID. /// + /// Param [chatType] The chat type, default is single chat, if it is group chat or chat room, see [ChatType]. + /// /// **Return** The message instance. /// ~end /// @@ -326,6 +332,8 @@ class EMMessage { /// - 群组:群组 ID; /// - 聊天室:聊天室 ID。 /// + /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考[ChatType]。 + /// /// **Return** 消息对象。 /// ~end EMMessage.createSendMessage({ @@ -353,6 +361,8 @@ class EMMessage { /// /// Param [targetLanguages] Target languages. /// + /// Param [chatType] The chat type, default is single chat, if it is group chat or chat room, see [ChatType]. + /// /// **Return** The message instance. /// ~end /// @@ -366,6 +376,10 @@ class EMMessage { /// /// Param [content] 文本消息内容。 /// + /// Param [targetLanguages] 目标语言。 + /// + /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考[ChatType]。 + /// /// **Return** 消息体实例。 /// ~end EMMessage.createTxtSendMessage({ @@ -396,6 +410,8 @@ class EMMessage { /// /// Param [fileSize] The file size in bytes. /// + /// Param [chatType] The chat type, default is single chat, if it is group chat or chat room, see [ChatType]. + /// /// **Return** The message instance. /// ~end /// @@ -413,14 +429,16 @@ class EMMessage { /// /// Param [fileSize] 文件大小,单位为字节。 /// + /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考[ChatType]。 + /// /// **Return** 消息体实例。 /// ~end EMMessage.createFileSendMessage({ required String targetId, required String filePath, String? displayName, - ChatType chatType = ChatType.Chat, int? fileSize, + ChatType chatType = ChatType.Chat, }) : this.createSendMessage( chatType: chatType, to: targetId, @@ -454,6 +472,8 @@ class EMMessage { /// /// Param [height] The image height in pixels. /// + /// Param [chatType] The chat type, default is single chat, if it is group chat or chat room, see [ChatType]. + /// /// **Return** The message instance. /// ~end /// @@ -481,6 +501,8 @@ class EMMessage { /// /// Param [height] 图片的高,单位是像素。 /// + /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考[ChatType]。 + /// /// **Return** 图片实例。 /// ~end EMMessage.createImageSendMessage({ @@ -527,6 +549,8 @@ class EMMessage { /// /// Param [height] The height of the video thumbnail, in pixels. /// + /// Param [chatType] The chat type, default is single chat, if it is group chat or chat room, see [ChatType]. + /// /// **Return** The message instance. /// ~end /// @@ -552,6 +576,8 @@ class EMMessage { /// /// Param [height] 缩略图高度,单位是像素。 /// + /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考[ChatType]。 + /// /// **Return** 消息体实例。 /// ~end EMMessage.createVideoSendMessage({ @@ -593,6 +619,8 @@ class EMMessage { /// /// Param [displayName] The name of the voice file which ends with a suffix that indicates the format of the file. For example "voice.mp3". /// + /// Param [chatType] The chat type, default is single chat, if it is group chat or chat room, see [ChatType]. + /// /// **Return** The message instance. /// ~end /// @@ -612,6 +640,8 @@ class EMMessage { /// /// Param [displayName] 文件名。 /// + /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考[ChatType]。 + /// /// **Return** 消息体实例。 /// ~end EMMessage.createVoiceSendMessage({ @@ -646,6 +676,8 @@ class EMMessage { /// /// Param [buildingName] The building name. /// + /// Param [chatType] The chat type, default is single chat, if it is group chat or chat room, see [ChatType]. + /// /// **Return** The message instance. /// ~end /// @@ -665,6 +697,8 @@ class EMMessage { /// /// Param [buildingName] 建筑物名称。 /// + /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考[ChatType]。 + /// /// **Return** 消息体实例。 /// ~end EMMessage.createLocationSendMessage({ @@ -694,6 +728,10 @@ class EMMessage { /// /// Param [action] The command action. /// + /// Param [deliverOnlineOnly] Whether to send only to online users. + /// + /// Param [chatType] The chat type, default is single chat, if it is group chat or chat room, see [ChatType]. + /// /// **Return** The message instance. /// ~end /// @@ -707,6 +745,10 @@ class EMMessage { /// /// Param [action] 命令内容。 /// + /// Param [deliverOnlineOnly] 是否只发送在线用户。 + /// + /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考[ChatType]。 + /// /// **Return** 消息体实例。 /// ~end EMMessage.createCmdSendMessage({ @@ -732,6 +774,8 @@ class EMMessage { /// /// Param [params] The params map. /// + /// Param [chatType] The chat type, default is single chat, if it is group chat or chat room, see [ChatType]. + /// /// **Return** The message instance. /// ~end /// @@ -747,6 +791,8 @@ class EMMessage { /// /// Param [params] 自定义消息的键值对 Map 列表。 /// + /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考[ChatType]。 + /// /// **Return** 消息体实例。 /// ~end EMMessage.createCustomSendMessage({ @@ -759,6 +805,64 @@ class EMMessage { to: targetId, body: EMCustomMessageBody(event: event, params: params)); + /// ~english + /// Creates a combine message for sending. + /// + /// Param [targetId] The ID of the message recipient. + /// - For a one-to-one chat, it is the username of the peer user. + /// - For a group chat, it is the group ID. + /// - For a chat room, it is the chat room ID. + /// + /// Param [title] The message title. + /// + /// Param [summary] The message summary. + /// + /// Param [compatibleText] The compatible text. + /// + /// Param [msgIds] The list of combined messages. + /// + /// Param [chatType] The chat type, default is single chat, if it is group chat or chat room, see [ChatType]. + /// + /// **Return** The message instance. + /// ~end + /// + /// ~chinese + /// 创建一条待发送的合并消息。 + /// + /// Param [targetId] 消息接收方,可以是: + /// - 用户:用户 ID; + /// - 群组:群组 ID; + /// - 聊天室:聊天室 ID。 + /// + /// Param [title] 消息标题。 + /// + /// Param [summary] 消息概要。 + /// + /// Param [compatibleText] 兼容文本。 + /// + /// Param [msgIds] 合并的消息列表。 + /// + /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考[ChatType]。 + /// + /// **Return** 消息体实例。 + /// ~end + EMMessage.createCombineSendMessage({ + required String targetId, + String? title, + String? summary, + String? compatibleText, + required List msgIds, + ChatType chatType = ChatType.Chat, + }) : this.createSendMessage( + chatType: chatType, + to: targetId, + body: EMCombineMessageBody( + title: title, + summary: summary, + compatibleText: compatibleText, + messageList: msgIds, + )); + /// @nodoc Map toJson() { final Map data = new Map(); From 88a8f175cb98fc6b19c44472cee8034557443681 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Tue, 18 Jul 2023 11:56:26 +0800 Subject: [PATCH 37/49] fix android attributes error. --- CHANGELOG.md | 37 ++++++++++++++++++++++++++------- lib/src/tools/em_extension.dart | 3 ++- pubspec.yaml | 2 +- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73516cce..87cf0cc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,37 @@ -## NEXT +## 4.1.0 + +#### 新增: +- 增加 `EMOptions#osType`属性和`EMOptions#deviceName`属性,用户设置设备类型和设备名称; +- 增加 `Combine` 消息类型,用于合并转发消息; +- 增加 `EMChatManager#downloadAndParseCombineMessage` 方法; +- 增加 `EMChatManager#modifyMessage` 方法用户修改已发送的消息,目前只支持文本消息消息; +- 增加 `EMChatEventHandler#onMessageContentChanged` 回调,用户监听消息编辑实现; +- 增加 `EMClient#fetchLoggedInDevices` 方法,可是使用token获取已登录的设备列表; +- 增加 `EMClient#kickDevice` 方法,可以使用 token 踢掉指定设备; +- 增加 `EMClient#kickAllDevices` 方法,可以使用 token 踢掉所有已登录设备; +- 增加 `EMChatManager#fetchConversation` 方法,获取服务器会话列表,原方法 `EMChatManager#getConversationsFromServer` 作废; +- 增加 `EMChatManager#pinConversation` 方法,实现在服务器会话列表中 置顶/取消置顶 会话; +- 增加 `hatManager#fetchPinnedConversations` 方法,从服务器获取已置顶会话; +- 增加 `EMMessage#receiverList` 属性,用于在群组/聊天室中发送定向消息; + +#### 修复: +- 修复 ios 中无法收到 `EMConnectionEventHandler#onConnected` 和 `EMConnectionEventHandler#onDisconnected` 的问题; +- 修复 安卓消息中,发送方ext设置string类型,接收方变为int类型; + +#### 优化: +- 离开聊天室 `EMChatRoomEventHandler#onRemovedFromChatRoom` 回调中增加离开原因; +- 被其他设备踢下线 `EMConnectionEventHandler#onUserDidLoginFromOtherDevice` 回调中增加操作人deviceName; + ## 4.0.2 #### 新增: -- 增加 `GroupManager#setMemberAttributes` 方法,用于设置群成员属性; -- 增加 `GroupManager#fetchMemberAttributes` 和 `GroupManager#fetchMembersAttributes` 方法用户获取群成员属性; -- 增加 `GroupEventHandler#onAttributesChangedOfGroupMember` 群成员属性变更回调; -- 增加 `ChatManager#fetchHistoryMessagesByOption` 方法; -- 增加 `Conversation#deleteMessagesWithTs` 方法; -- 增加 `Message#deliverOnlineOnly` 属性用于设置只向在线用户投递消息; +- 增加 `EMGroupManager#setMemberAttributes` 方法,用于设置群成员属性; +- 增加 `EMGroupManager#fetchMemberAttributes` 和 `GroupManager#fetchMembersAttributes` 方法用户获取群成员属性; +- 增加 `EMGroupEventHandler#onAttributesChangedOfGroupMember` 群成员属性变更回调; +- 增加 `EMChatManager#fetchHistoryMessagesByOption` 方法; +- 增加 `EMConversation#deleteMessagesWithTs` 方法; +- 增加 `EMMessage#deliverOnlineOnly` 属性用于设置只向在线用户投递消息; #### 修复: - 修复安卓 hot reload 后回调多次的问题; diff --git a/lib/src/tools/em_extension.dart b/lib/src/tools/em_extension.dart index 857c0f0a..d82c9d43 100644 --- a/lib/src/tools/em_extension.dart +++ b/lib/src/tools/em_extension.dart @@ -32,7 +32,8 @@ extension MapExtension on Map { Map tmpMap = this[key]; for (var tmpKey in tmpMap.keys) { dynamic value = tmpMap[tmpKey]; - if (value is String) { + if (value is String && (value.startsWith("{") && value.endsWith("}")) || + value is String && (value.startsWith("[") && value.endsWith("]"))) { do { try { dynamic data = convert.jsonDecode(value); diff --git a/pubspec.yaml b/pubspec.yaml index 4e829052..be0d216c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: im_flutter_sdk description: Integrate the Chat SDK to enjoy the global IM services with high reliability, ultra-low latency, and high concurrency. -version: 4.0.3 +version: 4.1.0 homepage: https://www.easemob.com/product/im environment: From 58525aba920ded4fba992f7003310e42ca76bad9 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Tue, 18 Jul 2023 18:26:11 +0800 Subject: [PATCH 38/49] fix android isLoggedInBefore logic. --- .../main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java index f2830f70..baa5f867 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMClientWrapper.java @@ -228,7 +228,8 @@ private void getToken(JSONObject param, String channelName, Result result) throw private void isLoggedInBefore(JSONObject param, String channelName, Result result) throws JSONException { asyncRunnable(()->{ - onSuccess(result, channelName, EMClient.getInstance().isLoggedInBefore()); + EMOptions emOptions = EMClient.getInstance().getOptions(); + onSuccess(result, channelName, EMClient.getInstance().isLoggedInBefore() && emOptions.getAutoLogin()); }); } From 5757d30446d1d8953057c3ad2f37b43052f47829 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Wed, 19 Jul 2023 12:00:21 +0800 Subject: [PATCH 39/49] fix ios multi event error. --- CHANGELOG.md | 2 +- ios/Classes/EMChatroomManagerWrapper.m | 1 - ios/Classes/EMConversation+Helper.m | 2 ++ lib/src/internal/em_transform_tools.dart | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87cf0cc9..10a4ca94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ #### 修复: - 修复 ios 中无法收到 `EMConnectionEventHandler#onConnected` 和 `EMConnectionEventHandler#onDisconnected` 的问题; -- 修复 安卓消息中,发送方ext设置string类型,接收方变为int类型; +- 修复 安卓消息中,发送方`attributes` 中包含string类型,接收方变为int类型的问题; #### 优化: - 离开聊天室 `EMChatRoomEventHandler#onRemovedFromChatRoom` 回调中增加离开原因; diff --git a/ios/Classes/EMChatroomManagerWrapper.m b/ios/Classes/EMChatroomManagerWrapper.m index 8ca6a554..0a76b4d7 100644 --- a/ios/Classes/EMChatroomManagerWrapper.m +++ b/ios/Classes/EMChatroomManagerWrapper.m @@ -789,7 +789,6 @@ - (void)didDismissFromChatroom:(EMChatroom *)aChatroom @"type":type, @"roomId":aChatroom.chatroomId, @"roomName":aChatroom.subject, - @"reason": @(aReason) }; } else if (aReason == EMChatroomBeKickedReasonBeRemoved) { type = @"onRoomRemoved"; diff --git a/ios/Classes/EMConversation+Helper.m b/ios/Classes/EMConversation+Helper.m index 8dd32e9b..fe4790a2 100644 --- a/ios/Classes/EMConversation+Helper.m +++ b/ios/Classes/EMConversation+Helper.m @@ -15,6 +15,8 @@ - (NSDictionary *)toJson { ret[@"type"] = @([self.class typeToInt:self.type]); ret[@"ext"] = self.ext; ret[@"isThread"] = @(self.isChatThread); + ret[@"isPinned"] = @(self.isPinned); + ret[@"pinnedTime"] = @(self.pinnedTime); return ret; } diff --git a/lib/src/internal/em_transform_tools.dart b/lib/src/internal/em_transform_tools.dart index a1e255ec..7d45bb9e 100644 --- a/lib/src/internal/em_transform_tools.dart +++ b/lib/src/internal/em_transform_tools.dart @@ -65,7 +65,7 @@ EMMultiDevicesEvent? convertIntToEMMultiDevicesEvent(int? i) { return EMMultiDevicesEvent.CHAT_THREAD_KICK; case 45: return EMMultiDevicesEvent.CHAT_THREAD_UPDATE; - case 46: + case 52: return EMMultiDevicesEvent.GROUP_MEMBER_ATTRIBUTES_CHANGED; case 60: return EMMultiDevicesEvent.CONVERSATION_PINNED; From 24177975b9df98b10b6e4b8e17f3926586d41f8b Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Wed, 19 Jul 2023 17:13:34 +0800 Subject: [PATCH 40/49] fix android modify message error. --- .../com/easemob/im_flutter_sdk/EMHelper.java | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java index 0a7a965c..1d3b8505 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java @@ -25,6 +25,7 @@ import com.hyphenate.chat.EMLocationMessageBody; import com.hyphenate.chat.EMMessage; import com.hyphenate.chat.EMMessage.Type; +import com.hyphenate.chat.EMMessageBody; import com.hyphenate.chat.EMMessageReaction; import com.hyphenate.chat.EMMessageReactionChange; import com.hyphenate.chat.EMMessageReactionOperation; @@ -657,6 +658,21 @@ class EMGroupAckHelper { class EMMessageBodyHelper { + static Map getParentMap(EMMessageBody body){ + Map data = new HashMap<>(); + if (body.operatorId() != null) { + data.put("operatorId", body.operatorId()); + } + if (body.operationTime() != 0) { + data.put("operatorTime", body.operationTime()); + } + + if (body.operationCount() != 0) { + data.put("operatorCount", body.operationCount()); + } + return data; + } + public static EMTextMessageBody textBodyFromJson(JSONObject json) throws JSONException { String content = json.getString("content"); List list = new ArrayList<>(); @@ -672,7 +688,7 @@ public static EMTextMessageBody textBodyFromJson(JSONObject json) throws JSONExc } static Map textBodyToJson(EMTextMessageBody body) { - Map data = new HashMap<>(); + Map data = getParentMap(body); data.put("content", body.getMessage()); data.put("type", "txt"); if (body.getTargetLanguages() != null) { @@ -710,7 +726,7 @@ static EMLocationMessageBody localBodyFromJson(JSONObject json) throws JSONExcep } static Map localBodyToJson(EMLocationMessageBody body) { - Map data = new HashMap<>(); + Map data = getParentMap(body); data.put("latitude", body.getLatitude()); data.put("longitude", body.getLongitude()); data.put("buildingName", body.getBuildingName()); @@ -730,7 +746,7 @@ static EMCmdMessageBody cmdBodyFromJson(JSONObject json) throws JSONException { } static Map cmdBodyToJson(EMCmdMessageBody body) { - Map data = new HashMap<>(); + Map data = getParentMap(body); data.put("deliverOnlineOnly", body.isDeliverOnlineOnly()); data.put("action", body.action()); data.put("type", "cmd"); @@ -755,7 +771,7 @@ static EMCustomMessageBody customBodyFromJson(JSONObject json) throws JSONExcept } static Map customBodyToJson(EMCustomMessageBody body) { - Map data = new HashMap<>(); + Map data = getParentMap(body); data.put("event", body.event()); data.put("params", body.getParams()); data.put("type", "custom"); @@ -785,7 +801,7 @@ static EMFileMessageBody fileBodyFromJson(JSONObject json) throws JSONException } static Map fileBodyToJson(EMNormalFileMessageBody body) { - Map data = new HashMap<>(); + Map data = getParentMap(body); data.put("localPath", body.getLocalUrl()); data.put("fileSize", body.getFileSize()); data.put("displayName", body.getFileName()); @@ -839,7 +855,7 @@ static EMImageMessageBody imageBodyFromJson(JSONObject json) throws JSONExceptio } static Map imageBodyToJson(EMImageMessageBody body) { - Map data = new HashMap<>(); + Map data = getParentMap(body); data.put("localPath", body.getLocalUrl()); data.put("displayName", body.getFileName()); data.put("remotePath", body.getRemoteUrl()); @@ -898,7 +914,7 @@ static EMVideoMessageBody videoBodyFromJson(JSONObject json) throws JSONExceptio } static Map videoBodyToJson(EMVideoMessageBody body) { - Map data = new HashMap<>(); + Map data = getParentMap(body); data.put("localPath", body.getLocalUrl()); data.put("thumbnailLocalPath", body.getLocalThumbUri()); data.put("duration", body.getDuration()); @@ -939,7 +955,7 @@ static EMVoiceMessageBody voiceBodyFromJson(JSONObject json) throws JSONExceptio } static Map voiceBodyToJson(EMVoiceMessageBody body) { - Map data = new HashMap<>(); + Map data = getParentMap(body); data.put("localPath", body.getLocalUrl()); data.put("duration", body.getLength()); data.put("displayName", body.getFileName()); @@ -978,34 +994,34 @@ static EMCombineMessageBody combineBodyFromJson(JSONObject json) throws JSONExce return ret; } static Map combineBodyToJson(EMCombineMessageBody body) { - Map ret = new HashMap<>(); + Map data = getParentMap(body); if (body.getTitle() != null) { - ret.put("title", body.getTitle()); + data.put("title", body.getTitle()); } if (body.getSummary() != null) { - ret.put("summary", body.getSummary()); + data.put("summary", body.getSummary()); } if (body.getCompatibleText() != null) { - ret.put("compatibleText", body.getCompatibleText()); + data.put("compatibleText", body.getCompatibleText()); } if (body.getLocalUrl() != null) { - ret.put("localPath", body.getLocalUrl()); + data.put("localPath", body.getLocalUrl()); } if (body.getRemoteUrl() != null) { - ret.put("remotePath", body.getRemoteUrl()); + data.put("remotePath", body.getRemoteUrl()); } if (body.getSecret() != null) { - ret.put("secret", body.getSecret()); + data.put("secret", body.getSecret()); } - ret.put("type", "combine"); + data.put("type", "combine"); - return ret; + return data; } private static EMFileMessageBody.EMDownloadStatus downloadStatusFromInt(int downloadStatus) { From 25998429550d6acf7dfb9e22fab2293d8c767a57 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Wed, 19 Jul 2023 17:18:15 +0800 Subject: [PATCH 41/49] change api referance. --- lib/src/em_chat_manager.dart | 21 ++++++++++++++++++++- lib/src/models/em_message.dart | 6 +++--- lib/src/models/em_options.dart | 2 +- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/src/em_chat_manager.dart b/lib/src/em_chat_manager.dart index 0dfc3a93..43173b4e 100644 --- a/lib/src/em_chat_manager.dart +++ b/lib/src/em_chat_manager.dart @@ -1721,7 +1721,26 @@ class EMChatManager { } } - Future> downloadAndParseCombineMessage({ + /// ~english + /// fetch combine message detail. + /// + /// Param [message] The combine message. + /// + /// **Return** The combined message list. + /// + /// **Throws** A description of the exception. See [EMError]. + /// ~end + /// + /// ~chinese + /// 获取合并消息详情。 + /// + /// Param [message] 合并消息。 + /// + /// **Return** 合并后的消息列表。 + /// + /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 + /// ~end + Future> fetchCombineMessageDetail({ required EMMessage message, }) async { Map map = { diff --git a/lib/src/models/em_message.dart b/lib/src/models/em_message.dart index 77b0df6c..68a3df44 100644 --- a/lib/src/models/em_message.dart +++ b/lib/src/models/em_message.dart @@ -1656,7 +1656,7 @@ class EMTextMessageBody extends EMMessageBody { /// ~chinese /// 获取最后一次消息修改的操作者的用户 ID。 /// ~end - String? get operatorId => _operatorId; + String? get lastModifyOperatorId => _operatorId; /// ~english /// Get the UNIX timestamp of the last message modification, in milliseconds. @@ -1665,7 +1665,7 @@ class EMTextMessageBody extends EMMessageBody { /// ~chinese /// 获取最后一次消息修改的时间戳,单位为毫秒。 /// ~end - int? get operatorTime => _operatorTime; + int? get lastModifyTime => _operatorTime; /// ~english /// Get the number of times a message is modified. @@ -1674,7 +1674,7 @@ class EMTextMessageBody extends EMMessageBody { /// ~chinese /// 获取消息修改次数。 /// ~end - int? get operatorCount => _operatorCount; + int? get modifyCount => _operatorCount; } /// ~english diff --git a/lib/src/models/em_options.dart b/lib/src/models/em_options.dart index c5a67eb2..03870f1b 100644 --- a/lib/src/models/em_options.dart +++ b/lib/src/models/em_options.dart @@ -281,7 +281,7 @@ class EMOptions { /// ~end /// /// ~chinese - /// 是否使用自定义 IM 服务的端口。用于私有化部署。 + /// 从本地数据库加载会话时是否包括空会话。 /// ~end final bool enableEmptyConversation; From 0ea8291e7121841247d1b5927fc990b479391ecd Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Wed, 26 Jul 2023 11:32:34 +0800 Subject: [PATCH 42/49] add ios bind fcm token method. --- ios/Classes/EMPushManagerWrapper.m | 2 +- ios/Classes/EMSDKMethod.h | 2 ++ lib/src/em_push_manager.dart | 16 +++++++--------- lib/src/event_handler/manager_event_handler.dart | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ios/Classes/EMPushManagerWrapper.m b/ios/Classes/EMPushManagerWrapper.m index 54e80241..1033f424 100644 --- a/ios/Classes/EMPushManagerWrapper.m +++ b/ios/Classes/EMPushManagerWrapper.m @@ -47,7 +47,7 @@ - (void)handleMethodCall:(FlutterMethodCall*)call [self updateGroupPushService:call.arguments channelName:call.method result:result]; - } else if ([ChatBindDeviceToken isEqualToString:call.method]) { + } else if ([ChatBindDeviceToken isEqualToString:call.method] || [UpdateFCMPushToken isEqualToString:call.method]) { [self bindDeviceToken:call.arguments channelName:call.method result:result]; diff --git a/ios/Classes/EMSDKMethod.h b/ios/Classes/EMSDKMethod.h index 9b04b435..a62f3b50 100644 --- a/ios/Classes/EMSDKMethod.h +++ b/ios/Classes/EMSDKMethod.h @@ -269,6 +269,8 @@ static NSString *const ChatGetNoPushGroups = @"getNoPushGroups"; static NSString *const ChatUpdateUserPushService = @"updateUserPushService"; static NSString *const ChatGetNoPushUsers = @"getNoPushUsers"; static NSString *const ChatBindDeviceToken = @"updateAPNsPushToken"; +static NSString *const UpdateFCMPushToken = @"updateFCMPushToken"; + static NSString *const ChatReportPushAction = @"reportPushAction"; static NSString *const ChatSetConversationSilentMode = @"setConversationSilentMode"; diff --git a/lib/src/em_push_manager.dart b/lib/src/em_push_manager.dart index 4c144cb1..6308c996 100644 --- a/lib/src/em_push_manager.dart +++ b/lib/src/em_push_manager.dart @@ -131,15 +131,13 @@ class EMPushManager { /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 /// ~end Future updateFCMPushToken(String token) async { - if (Platform.isAndroid) { - Map req = {'token': token}; - Map result = await PushChannel.invokeMethod( - ChatMethodKeys.updateFCMPushToken, req); - try { - EMError.hasErrorFromResult(result); - } on EMError catch (e) { - throw e; - } + Map req = {'token': token}; + Map result = + await PushChannel.invokeMethod(ChatMethodKeys.updateFCMPushToken, req); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; } } diff --git a/lib/src/event_handler/manager_event_handler.dart b/lib/src/event_handler/manager_event_handler.dart index ef70b8c2..3436b43e 100644 --- a/lib/src/event_handler/manager_event_handler.dart +++ b/lib/src/event_handler/manager_event_handler.dart @@ -72,7 +72,7 @@ class EMConnectionEventHandler { /// ~end /// /// ~chinese - /// 被服务器移除回调。 + /// 当前用户被服务器移除回调。 /// ~end final VoidCallback? onUserDidRemoveFromServer; @@ -306,7 +306,7 @@ class EMMultiDeviceEventHandler { /// ~end /// /// ~chinese - /// 开启多设备后对单个会话删除漫游消息后对其他设备的回调。 + /// 开启多设备后单个会话操作的多设备事件回调。 /// ~end final void Function( EMMultiDevicesEvent event, From dc421c08782bf3bb65c5c042fe42cce749927c52 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Thu, 27 Jul 2023 17:36:49 +0800 Subject: [PATCH 43/49] upgrade native dependencies --- android/build.gradle | 3 ++- .../com/easemob/im_flutter_sdk/EMChatManagerWrapper.java | 7 ++++++- ios/im_flutter_sdk.podspec | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 0891523f..cf4a06f0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -48,5 +48,6 @@ tasks.withType(JavaCompile){ dependencies { api 'androidx.appcompat:appcompat:1.1.0' - implementation 'io.hyphenate:hyphenate-chat:4.0.3' + implementation 'io.hyphenate:hyphenate-chat:4.1.0' + // implementation files('libs/hyphenatechat_4.1.0.jar') } diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java index 3b053c49..7f2b8477 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMChatManagerWrapper.java @@ -899,7 +899,12 @@ private void pinConversation(JSONObject param, String channelName, Result result private void modifyMessage(JSONObject param, String channelName, Result result) throws JSONException { String msgId = param.optString("msgId"); EMTextMessageBody body = EMMessageBodyHelper.textBodyFromJson(param.optJSONObject("body")); - EMClient.getInstance().chatManager().asyncModifyMessage(msgId, body, new EMWrapperCallBack(result, channelName, null)); + EMClient.getInstance().chatManager().asyncModifyMessage(msgId, body, new EMValueWrapperCallBack(result, channelName) { + @Override + public void onSuccess(EMMessage object) { + updateObject(EMMessageHelper.toJson(object)); + } + }); } private void downloadAndParseCombineMessage(JSONObject param, String channelName, Result result) throws JSONException { EMMessage msg = EMMessageHelper.fromJson(param.optJSONObject("message")); diff --git a/ios/im_flutter_sdk.podspec b/ios/im_flutter_sdk.podspec index bd9262de..bc72e3e4 100644 --- a/ios/im_flutter_sdk.podspec +++ b/ios/im_flutter_sdk.podspec @@ -21,7 +21,7 @@ A new flutter plugin project. s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' - s.dependency 'HyphenateChat','4.0.3' + s.dependency 'HyphenateChat','4.1.0' s.ios.deployment_target = '11.0' end From e4869d304f225adcfe4f3ea5f691cd44b44ada38 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Wed, 2 Aug 2023 16:58:40 +0800 Subject: [PATCH 44/49] fix bugs. --- CHANGELOG.md | 2 +- .../java/com/easemob/im_flutter_sdk/EMHelper.java | 2 +- ios/Classes/EMChatMessage+Helper.m | 12 +++++++++--- ios/Classes/EMClientWrapper.m | 4 ++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10a4ca94..e93ba329 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ #### 新增: - 增加 `EMOptions#osType`属性和`EMOptions#deviceName`属性,用户设置设备类型和设备名称; - 增加 `Combine` 消息类型,用于合并转发消息; -- 增加 `EMChatManager#downloadAndParseCombineMessage` 方法; +- 增加 `EMChatManager#fetchCombineMessageDetail` 方法; - 增加 `EMChatManager#modifyMessage` 方法用户修改已发送的消息,目前只支持文本消息消息; - 增加 `EMChatEventHandler#onMessageContentChanged` 回调,用户监听消息编辑实现; - 增加 `EMClient#fetchLoggedInDevices` 方法,可是使用token获取已登录的设备列表; diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java index 1d3b8505..f9db774c 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMHelper.java @@ -660,7 +660,7 @@ class EMMessageBodyHelper { static Map getParentMap(EMMessageBody body){ Map data = new HashMap<>(); - if (body.operatorId() != null) { + if (body.operatorId() != null && body.operatorId().length() > 0) { data.put("operatorId", body.operatorId()); } if (body.operationTime() != 0) { diff --git a/ios/Classes/EMChatMessage+Helper.m b/ios/Classes/EMChatMessage+Helper.m index eab7874a..fb6bd237 100644 --- a/ios/Classes/EMChatMessage+Helper.m +++ b/ios/Classes/EMChatMessage+Helper.m @@ -246,9 +246,15 @@ - (NSDictionary *)toJson { break; } ret[@"type"] = type; - ret[@"operatorId"] = self.operatorId; - ret[@"operatorTime"] = @(self.operationTime); - ret[@"operatorCount"] = @(self.operatorCount); + if(self.operatorId && self.operatorId.length > 0) { + ret[@"operatorId"] = self.operatorId; + } + if(self.operationTime > 0) { + ret[@"operatorTime"] = @(self.operationTime); + } + if(self.operatorCount > 0) { + ret[@"operatorCount"] = @(self.operatorCount); + } return ret; } diff --git a/ios/Classes/EMClientWrapper.m b/ios/Classes/EMClientWrapper.m index b8d43ae9..093b2645 100644 --- a/ios/Classes/EMClientWrapper.m +++ b/ios/Classes/EMClientWrapper.m @@ -458,7 +458,7 @@ - (void)getLoggedInDevicesFromServer:(NSDictionary *)param channelName:(NSString [weakSelf wrapperCallBack:result channelName:aChannelName error:aError - object:nil]; + object:list]; }]; }else { [EMClient.sharedClient getLoggedInDevicesFromServerWithUserId:username @@ -474,7 +474,7 @@ - (void)getLoggedInDevicesFromServer:(NSDictionary *)param channelName:(NSString [weakSelf wrapperCallBack:result channelName:aChannelName error:aError - object:nil]; + object:list]; }]; } From 4e1bce94d83f7327d02d39ee059915d3c7fdbf37 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Thu, 3 Aug 2023 18:03:28 +0800 Subject: [PATCH 45/49] change kick device api. --- lib/src/em_client.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/src/em_client.dart b/lib/src/em_client.dart index 5355c7a6..a46bb58a 100644 --- a/lib/src/em_client.dart +++ b/lib/src/em_client.dart @@ -754,7 +754,7 @@ class EMClient { /// /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 /// ~end - Future kickDevice({ + Future kickDevice({ required String userId, required String pwdOrToken, required String resource, @@ -771,7 +771,6 @@ class EMClient { await ClientChannel.invokeMethod(ChatMethodKeys.kickDevice, req); try { EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.kickDevice); } on EMError catch (e) { throw e; } From 07588b3cbf38b5650489ab0d31f21a0ebed63046 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Fri, 4 Aug 2023 11:04:15 +0800 Subject: [PATCH 46/49] upgrade android sdk to 411. --- android/build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index cf4a06f0..213dea09 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -48,6 +48,5 @@ tasks.withType(JavaCompile){ dependencies { api 'androidx.appcompat:appcompat:1.1.0' - implementation 'io.hyphenate:hyphenate-chat:4.1.0' - // implementation files('libs/hyphenatechat_4.1.0.jar') + implementation 'io.hyphenate:hyphenate-chat:4.1.1' } From 28c85ce4f0f4f04edf44f57cbb4c16c0fe5d835f Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Tue, 8 Aug 2023 18:04:26 +0800 Subject: [PATCH 47/49] fix ios delete remote message error. --- ios/Classes/EMChatManagerWrapper.m | 43 ++++++++++- lib/src/em_chat_manager.dart | 8 +-- lib/src/models/em_chat_enums.dart | 112 ++++++++++++++--------------- lib/src/models/em_message.dart | 2 +- 4 files changed, 102 insertions(+), 63 deletions(-) diff --git a/ios/Classes/EMChatManagerWrapper.m b/ios/Classes/EMChatManagerWrapper.m index 48440436..9bb1b9b2 100644 --- a/ios/Classes/EMChatManagerWrapper.m +++ b/ios/Classes/EMChatManagerWrapper.m @@ -983,10 +983,32 @@ - (void)removeMessagesFromServerWithMsgIds:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self) weakSelf = self; + NSArray *msgIds = param[@"msgIds"]; NSString *convId = param[@"convId"]; EMConversationType type = [EMConversation typeFromInt:[param[@"type"] intValue]]; + + if(!EMClient.sharedClient.isLoggedIn) { + EMError *e = [EMError errorWithDescription:@"Not login" code:EMErrorUserNotLogin]; + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:e + object:@(!e)]; + return; + } + + + if(convId == nil || convId.length == 0 || msgIds.count == 0 || type == EMConversationTypeChatRoom) { + EMError *e = [EMError errorWithDescription:@"Invalid parameter" code:EMErrorInvalidParam]; + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:e + object:@(!e)]; + return; + } + + EMConversation *conversation = [EMClient.sharedClient.chatManager getConversation:convId type:type createIfNotExist:YES]; - NSArray *msgIds = param[@"msgIds"]; + [conversation removeMessagesFromServerMessageIds:msgIds completion:^(EMError * _Nullable aError) { [weakSelf wrapperCallBack:result channelName:aChannelName @@ -1002,6 +1024,25 @@ - (void)removeMessagesFromServerWithTs:(NSDictionary *)param NSString *convId = param[@"convId"]; EMConversationType type = [EMConversation typeFromInt:[param[@"type"] intValue]]; long timestamp = [param[@"timestamp"] longValue]; + + if(!EMClient.sharedClient.isLoggedIn) { + EMError *e = [EMError errorWithDescription:@"Not login" code:EMErrorUserNotLogin]; + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:e + object:@(!e)]; + return; + } + + if(convId == nil || convId.length == 0 || type == EMConversationTypeChatRoom || timestamp <= 0) { + EMError *e = [EMError errorWithDescription:@"Invalid parameter" code:EMErrorInvalidParam]; + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:e + object:@(!e)]; + return; + } + EMConversation *conversation = [EMClient.sharedClient.chatManager getConversation:convId type:type createIfNotExist:YES]; [conversation removeMessagesFromServerWithTimeStamp:timestamp completion:^(EMError * _Nullable aError) { [weakSelf wrapperCallBack:result diff --git a/lib/src/em_chat_manager.dart b/lib/src/em_chat_manager.dart index 43173b4e..a0e251d3 100644 --- a/lib/src/em_chat_manager.dart +++ b/lib/src/em_chat_manager.dart @@ -1219,7 +1219,7 @@ class EMChatManager { /// /// Param [conversationType] The conversation type. See [EMConversationType]. /// - /// Param [isDeleteMessage] Whether to delete the chat history when deleting the conversation. + /// Param [isDeleteRemoteMessage] Whether to delete the server chat history when deleting the conversation. /// - `true`: (default) Yes. /// - `false`: No. /// @@ -1234,7 +1234,7 @@ class EMChatManager { /// /// Param [conversationType] 会话类型,详见 [EMConversationType]。 /// - /// Param [isDeleteMessage] 删除会话时是否同时删除历史消息记录。 + /// Param [isDeleteRemoteMessage] 删除会话时是否同时删除服务器历史消息记录。 /// /// - (默认)`true`:是; /// - `false`:否。 @@ -1244,7 +1244,7 @@ class EMChatManager { Future deleteRemoteConversation( String conversationId, { EMConversationType conversationType = EMConversationType.Chat, - bool isDeleteMessage = true, + bool isDeleteRemoteMessage = true, }) async { Map req = {}; req["conversationId"] = conversationId; @@ -1255,7 +1255,7 @@ class EMChatManager { } else { req["conversationType"] = 2; } - req["isDeleteRemoteMessage"] = isDeleteMessage; + req["isDeleteRemoteMessage"] = isDeleteRemoteMessage; Map data = await ChatChannel.invokeMethod( ChatMethodKeys.deleteRemoteConversation, req); diff --git a/lib/src/models/em_chat_enums.dart b/lib/src/models/em_chat_enums.dart index a53b5620..5f3b00ca 100644 --- a/lib/src/models/em_chat_enums.dart +++ b/lib/src/models/em_chat_enums.dart @@ -463,7 +463,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上删除了好友,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上删除好友。 /// ~end CONTACT_REMOVE, @@ -472,7 +472,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上同意了好友请求,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上接受好友请求。 /// ~end CONTACT_ACCEPT, @@ -481,7 +481,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上拒绝了好友请求,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上拒绝好友请求。 /// ~end CONTACT_DECLINE, @@ -490,7 +490,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上将其他用户加入了黑名单,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上将好友加入黑名单。 /// ~end CONTACT_BAN, @@ -499,7 +499,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上将其他用户移出了黑名单,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上将好友移出黑名单。 /// ~end CONTACT_ALLOW, @@ -508,7 +508,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上创建了群组,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上创建群组。 /// ~end GROUP_CREATE, @@ -517,7 +517,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上销毁了群组,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上解散群组。 /// ~end GROUP_DESTROY, @@ -526,7 +526,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上加入了群组,则设备 A2 会收到该事件。 + /// 当前用户在其他设备上加入群组。 /// ~end GROUP_JOIN, @@ -535,7 +535,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上退出群组,则设备 A2 会收到该事件。 + /// 当前用户在其他设备离开群组。 /// ~end GROUP_LEAVE, @@ -544,7 +544,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上申请加入群组,则设备 A2 会收到该事件。 + /// 当前用户在其他设备上申请加入群组。 /// ~end GROUP_APPLY, @@ -553,7 +553,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上收到了入群申请,则设备 A2 会收到该事件。 + /// 当前用户在其他设备接受入群申请。 /// ~end GROUP_APPLY_ACCEPT, @@ -562,7 +562,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上拒绝了入群申请,设备 A2 上会收到该事件。 + /// 当前用户在其他设备上拒绝入群申请。 /// ~end GROUP_APPLY_DECLINE, @@ -571,7 +571,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上邀请了其他用户进入群组,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上邀请用户入群。 /// ~end GROUP_INVITE, @@ -580,7 +580,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上同意了其他用户的群组邀请,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上接受了入群邀请。 /// ~end GROUP_INVITE_ACCEPT, @@ -589,7 +589,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上拒绝了其他用户的群组邀请,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上拒绝了入群邀请。 /// ~end GROUP_INVITE_DECLINE, @@ -598,7 +598,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上将其他用户踢出群组,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上将成员踢出群。 /// ~end GROUP_KICK, @@ -607,7 +607,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上被加入黑名单,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上将成员加入群组黑名单。 /// ~end GROUP_BAN, @@ -616,7 +616,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上将其他用户移出群组,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上将成员移除群组黑名单。 /// ~end GROUP_ALLOW, @@ -625,7 +625,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上屏蔽了某个群组的消息,设备 A2 上会收到该事件。 + /// 当前用户在其他设备上屏蔽群组。 /// ~end GROUP_BLOCK, @@ -634,7 +634,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上取消屏蔽了某个群组的消息,设备 A2 上会收到该事件。 + /// 当前用户在其他设备上取消群组屏蔽。 /// ~end GROUP_UNBLOCK, @@ -643,7 +643,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上更新了群主,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上转移群组所有权。 /// ~end GROUP_ASSIGN_OWNER, @@ -652,7 +652,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上添加了群组管理员,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上添加管理员。 /// ~end GROUP_ADD_ADMIN, @@ -661,7 +661,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上移除了群组管理员,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上移除管理员。 /// ~end GROUP_REMOVE_ADMIN, @@ -670,7 +670,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上禁言了群成员,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上禁言成员。 /// ~end GROUP_ADD_MUTE, @@ -679,7 +679,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上取消禁言了群成员,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上解除禁言。 /// ~end GROUP_REMOVE_MUTE, @@ -688,7 +688,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上将其他成员添加到群组白名单中,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备将其他用户加入到群组白名单。 /// ~end GROUP_ADD_USER_ALLOW_LIST, @@ -697,7 +697,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上将其他成员移除群组白名单,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备将其他用户移除群组白名单。 /// ~end GROUP_REMOVE_USER_ALLOW_LIST, @@ -706,7 +706,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上将所有其他群组成员添加到群组禁言列表,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备将全部群组成员禁言。 /// ~end GROUP_ALL_BAN, @@ -715,7 +715,7 @@ enum EMMultiDevicesEvent { /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上将所有其他群组成员移除群组禁言列表,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备将群组成员解除禁言。 /// ~end GROUP_REMOVE_ALL_BAN, @@ -738,93 +738,91 @@ enum EMMultiDevicesEvent { GROUP_ABLE, /// ~english - /// User A creates an event in the sub-area of device A1, and other devices logged in to this account will receive this event + /// The current user modified custom attributes of a group member on another device. + /// + /// ~chinese + /// 当前用户在其他设备上修改群组成员属性。 + /// ~end + GROUP_MEMBER_ATTRIBUTES_CHANGED, + + /// ~english + /// The current user created a message thread on another device. /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上创建了子区,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备创建子区。 /// ~end CHAT_THREAD_CREATE, /// ~english - /// User A destroys the event in the sub-area of device A1, and all other devices logged in to this account will receive this event + /// The current user destroyed a message thread on another device. /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上移除了子区,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备销毁子区。 /// ~end CHAT_THREAD_DESTROY, /// ~english - /// User A joins the event in the sub-area of device A1, and other devices logged in to this account will receive this event + /// The current user joined a message thread on another device. /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上加入了子区,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备加入子区。 /// ~end CHAT_THREAD_JOIN, /// ~english - /// User A leaves the event in the sub-area of device A1, and other devices logged in to this account will receive this event + /// The current user left a message thread on another device. /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上离开了子区,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备离开子区。 /// ~end CHAT_THREAD_LEAVE, /// ~english - /// User A updates the event in the sub-area of device A1, and other devices logged in to this account will receive this event + /// The current user updated message thread information on another device. /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上更新了子区信息,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备更新子区信息。 /// ~end CHAT_THREAD_UPDATE, /// ~english - /// User A is kicked in the sub-area of device A1, and all other devices that log in to this account will receive this event + /// The current user kicked a member out of a message thread on another device. /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 上将其他用户踢出子区,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上将成员踢出子区。 /// ~end CHAT_THREAD_KICK, /// ~english - /// If user A modifies a custom member attribute on device A1, - /// this event is triggered on another device that the user logs in with the same account. - /// ~end - /// - /// ~chinese - /// 若用户 A 在设备 A1 上修改群成员自定义属性,该事件会在登录该账号的其他设备触发。 - /// ~end - GROUP_MEMBER_ATTRIBUTES_CHANGED, - - /// ~english - /// If user A pins a conversation on device A1, this event is triggered on device A2 + /// The current user pinned a conversation on another device. /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 置顶会话,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上置顶会话。 /// ~end CONVERSATION_PINNED, /// ~english - /// If user A unpins a conversation on device A1, this event is triggered on device A2. + /// The current user unpinned a conversation on another device. /// ~end /// /// ~chinese - /// 用户 A 在设备 A1取消置顶会话,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上取消会话置顶。 /// ~end CONVERSATION_UNPINNED, /// ~english - /// If user A deletes a conversation on device A1, this event is triggered on device A2. + /// The current user removed a conversation from the server. /// ~end /// /// ~chinese - /// 用户 A 在设备 A1 删除会话,则设备 A2 上会收到该事件。 + /// 当前用户在其他设备上删除了服务端的会话。 /// ~end CONVERSATION_DELETE, } diff --git a/lib/src/models/em_message.dart b/lib/src/models/em_message.dart index 68a3df44..3263f140 100644 --- a/lib/src/models/em_message.dart +++ b/lib/src/models/em_message.dart @@ -797,7 +797,7 @@ class EMMessage { /// ~end EMMessage.createCustomSendMessage({ required String targetId, - required event, + required String event, Map? params, ChatType chatType = ChatType.Chat, }) : this.createSendMessage( From a0ddd6ce4a192b1a4c17e93b9e3e0e6ccd543f07 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Thu, 10 Aug 2023 14:39:10 +0800 Subject: [PATCH 48/49] update api referance. --- lib/src/em_chat_manager.dart | 89 +++---- lib/src/em_client.dart | 107 +++++---- lib/src/em_group_manager.dart | 26 +-- lib/src/em_push_manager.dart | 74 +++--- .../event_handler/manager_event_handler.dart | 219 +++++++++--------- lib/src/models/em_chat_enums.dart | 56 ++--- lib/src/models/em_message.dart | 32 +-- lib/src/models/em_options.dart | 16 +- lib/src/models/fetch_message_options.dart | 4 +- lib/src/models/reaction_operation.dart | 32 +-- 10 files changed, 328 insertions(+), 327 deletions(-) diff --git a/lib/src/em_chat_manager.dart b/lib/src/em_chat_manager.dart index a0e251d3..3c6ca593 100644 --- a/lib/src/em_chat_manager.dart +++ b/lib/src/em_chat_manager.dart @@ -181,7 +181,7 @@ class EMChatManager { } /// ~english - /// Resend a message. + /// Resends a message. /// /// Param [message] The message object to be resent: [EMMessage]. /// ~end @@ -478,7 +478,7 @@ class EMChatManager { /// ~end /// /// ~chinese - /// 根据threadId 获取 thread 会话。 + /// 根据thread ID 获取 thread 会话。 /// /// Param [threadId] Thread ID. /// @@ -746,7 +746,7 @@ class EMChatManager { @Deprecated('Use [fetchConversation] instead') /// ~english - /// fetch the conversations from the server. + /// Gets the list of conversations from the server. /// /// Param [pageNum] The current page number. /// @@ -758,11 +758,11 @@ class EMChatManager { /// ~end /// /// ~chinese - /// 获取服务器会话。 + /// 获取服务器会话列表。 /// - /// Param [pageNum] 获取的页码。 + /// Param [pageNum] 当前页码。 /// - /// Param [pageSize] 获取页中返回数量。 + /// Param [pageSize] 每页期望返回的会话数量。 /// /// **Return** 当前用户的会话列表。 /// @@ -799,7 +799,7 @@ class EMChatManager { /// The SDK retrieves the list of conversations in the reverse chronological order of their active time (the timestamp of the last message). /// If there is no message in the conversation, the SDK retrieves the list of conversations in the reverse chronological order of their creation time. /// - /// Param [cursor] The position from which to start getting data. the SDK retrieves conversations from the latest active one if no set. + /// Param [cursor] The position from which to start getting data. The SDK retrieves conversations from the latest active one if this parameter is not set. /// /// Param [pageSize] The number of conversations that you expect to get on each page. The value range is [1,50]. /// @@ -809,7 +809,7 @@ class EMChatManager { /// ~end /// /// ~chinese - /// 分页从服务器获取获取会话列表。 + /// 从服务器分页获取会话列表。 /// /// SDK 按照会话活跃时间(会话的最后一条消息的时间戳)倒序返回会话列表。 /// 若会话中没有消息,则 SDK 按照会话创建时间的倒序返回会话列表。 @@ -978,11 +978,11 @@ class EMChatManager { /// /// Param [pageSize] The number of messages per page. /// - /// Param [direction] The direction of the search to be fetched. See [EMSearchDirection]. + /// Param [direction] The message search direction. See [EMSearchDirection]. /// - /// Param [startMsgId] The ID of the message from which you start to get the historical messages. If `null` is passed, the SDK gets messages in reverse chronological order. + /// Param [startMsgId] The ID of the message from which you start to get the historical messages. If `null` is passed, the SDK gets messages in the reverse chronological order. /// - /// **Return** The obtained messages and the cursor for the next fetch action. + /// **Return** The obtained messages and the cursor for the next query. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -1032,7 +1032,7 @@ class EMChatManager { } /// ~english - /// [FetchMessageOptions] paging from the server to retrieve the history message for the specified session. + /// Gets historical messages of a conversation from the server according to [FetchMessageOptions]. /// /// Param [conversationId] The conversation ID, which is the user ID of the peer user for one-to-one chat, but the group ID for group chat. /// @@ -1097,7 +1097,7 @@ class EMChatManager { /// /// Param [maxCount] The maximum number of messages to retrieve each time. /// - /// Param [from] A username or group ID at which the retrieval is targeted. Usually, it is the conversation ID. + /// Param [from] A user ID or group ID at which the retrieval is targeted. Usually, it is the conversation ID. /// /// **Return** The list of messages. /// @@ -1152,7 +1152,6 @@ class EMChatManager { /// ~english /// Gets read receipts for group messages from the server with pagination. /// - /// See also: /// For how to send read receipts for group messages, see [sendConversationReadAck]. /// /// Param [msgId] The message ID. @@ -1219,7 +1218,7 @@ class EMChatManager { /// /// Param [conversationType] The conversation type. See [EMConversationType]. /// - /// Param [isDeleteRemoteMessage] Whether to delete the server chat history when deleting the conversation. + /// Param [isDeleteMessage] Whether to delete the chat history when deleting the conversation. /// - `true`: (default) Yes. /// - `false`: No. /// @@ -1234,7 +1233,7 @@ class EMChatManager { /// /// Param [conversationType] 会话类型,详见 [EMConversationType]。 /// - /// Param [isDeleteRemoteMessage] 删除会话时是否同时删除服务器历史消息记录。 + /// Param [isDeleteMessage] 删除会话时是否同时删除历史消息记录。 /// /// - (默认)`true`:是; /// - `false`:否。 @@ -1244,7 +1243,7 @@ class EMChatManager { Future deleteRemoteConversation( String conversationId, { EMConversationType conversationType = EMConversationType.Chat, - bool isDeleteRemoteMessage = true, + bool isDeleteMessage = true, }) async { Map req = {}; req["conversationId"] = conversationId; @@ -1255,7 +1254,7 @@ class EMChatManager { } else { req["conversationType"] = 2; } - req["isDeleteRemoteMessage"] = isDeleteRemoteMessage; + req["isDeleteRemoteMessage"] = isDeleteMessage; Map data = await ChatChannel.invokeMethod( ChatMethodKeys.deleteRemoteConversation, req); @@ -1330,11 +1329,11 @@ class EMChatManager { } /// ~english - /// Adds a reaction. + /// Adds a Reaction. /// /// Param [messageId] The message ID. /// - /// Param [reaction] The reaction content. + /// Param [reaction] The Reaction content. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -1363,11 +1362,11 @@ class EMChatManager { } /// ~english - /// Deletes a reaction. + /// Deletes a Reaction. /// /// Param [messageId] The message ID. /// - /// Param [reaction] The reaction content. + /// Param [reaction] The Reaction content. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -1402,7 +1401,7 @@ class EMChatManager { /// /// Param [chatType] The chat type. Only one-to-one chat [ChatType.Chat] and group chat [ChatType.GroupChat] are allowed. /// - /// Param [groupId] which is valid only when the chat type is group chat. + /// Param [groupId] The group ID. This parameter is valid only when the chat type is group chat. /// /// **Return** The Reaction list under the specified message ID([EMMessageReaction.userList] is the summary data, which only contains the information of the first three users). /// @@ -1454,11 +1453,11 @@ class EMChatManager { } /// ~english - /// Gets the reaction details. + /// Gets the Reaction details. /// /// Param [messageId] The message ID. /// - /// Param [reaction] The reaction content. + /// Param [reaction] The Reaction content. /// /// Param [cursor] The cursor position from which to get Reactions. /// @@ -1512,13 +1511,13 @@ class EMChatManager { } /// ~english - /// Translate a message. + /// Translates a text message. /// - /// Param [msg] The message object + /// Param [msg] The message object for translation. /// - /// Param [languages] The target languages to translate + /// Param [languages] The list of target language codes. /// - /// **Return** Translated Message + /// **Return** The translated message. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -1528,7 +1527,7 @@ class EMChatManager { /// /// Param [msg] 要翻译的文本消息。 /// - /// Param [languages] 目标语言。 + /// Param [languages] 目标语言代码列表。 /// /// **Return** 译文。 /// @@ -1552,9 +1551,9 @@ class EMChatManager { } /// ~english - /// Fetch all languages what the translate service support + /// Gets all languages supported by the translation service. /// - /// **Return** Supported languages + /// **Return** The supported languages. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -1586,7 +1585,7 @@ class EMChatManager { /// /// The SDK returns the pinned conversations in the reverse chronological order of their pinning. /// - /// Param [cursor] The position from which to start getting data. the SDK retrieves conversations from the latest pinned one if no set. + /// Param [cursor] The position from which to start getting data. If this parameter is not set, the SDK retrieves conversations from the latest pinned one. /// /// Param [pageSize] The number of conversations that you expect to get on each page. The value range is [1,50]. /// @@ -1674,9 +1673,11 @@ class EMChatManager { } /// ~english - /// Modifies a local message or a message at the server side. + /// Modifies a message. /// - /// You can call this method to only modify a text message in one-to-one chats or group chats, but not in chat rooms. + /// After this method is called to modify a message, both the local message and the message on the server are modified. + /// + /// This method can only modify a text message in one-to-one chats or group chats, but not in chat rooms. /// /// Param [messageId] The ID of the message to modify. /// @@ -1688,12 +1689,14 @@ class EMChatManager { /// ~end /// /// ~chinese - /// 修改本地以及服务端的消息内容。 + /// 修改消息内容。 /// - /// 只能调用该方法修改单聊和群聊中的文本消息,不能修改聊天室消息。 + /// 调用该方法修改消息内容后,本地和服务端的消息均会修改。 /// - /// Param [messageId] 消息实例id。 + /// 只能调用该方法修改单聊和群聊中的文本消息,不能修改聊天室消息。 /// + /// Param [messageId] 消息实例 ID。 + /// /// Param [msgBody] 文本消息体实例 [EMTextMessageBody]。 /// /// **Return** 修改后的消息实例。 @@ -1722,21 +1725,21 @@ class EMChatManager { } /// ~english - /// fetch combine message detail. + /// Gets the details of a combined message. /// - /// Param [message] The combine message. + /// Param [message] The combined message. /// - /// **Return** The combined message list. + /// **Return** The list of original messages included in the combined message. /// /// **Throws** A description of the exception. See [EMError]. /// ~end /// /// ~chinese - /// 获取合并消息详情。 + /// 获取合并消息的详情。 /// /// Param [message] 合并消息。 /// - /// **Return** 合并后的消息列表。 + /// **Return** 合并消息包含的原始消息列表。 /// /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 /// ~end diff --git a/lib/src/em_client.dart b/lib/src/em_client.dart index a46bb58a..744d5db2 100644 --- a/lib/src/em_client.dart +++ b/lib/src/em_client.dart @@ -45,31 +45,31 @@ class EMClient { String? _currentUserId; /// ~english - /// Obtain instance. + /// Gets the SDK instance. /// ~end /// /// ~chinese - /// 获取SDK实例 + /// 获取 SDK 实例。 /// ~end static EMClient get getInstance => _instance ??= EMClient._internal(); /// ~english - /// Set a custom event handle to receive data from iOS or Android devices. + /// Sets a custom event handler to receive data from iOS or Android devices. /// /// Param [customEventHandler] The custom event handler. /// ~end /// /// ~chinese - /// 设置一个自定义事件句柄来接收来自iOS或Android设备的数据。 + /// 设置一个自定义事件句柄来接收来自 iOS 或 Android 设备的数据。 /// ~end void Function(Map map)? customEventHandler; /// ~english - /// Gets the current logged-in userId. + /// Gets the current logged-in user ID. /// ~end /// /// ~chinese - /// 当前登录用户id + /// 当前登录用户 ID. /// ~end String? get currentUserId => _currentUserId; @@ -125,9 +125,9 @@ class EMClient { } /// ~english - /// Adds the connection event handler. After calling this method, you can handle for new room event when they arrive. + /// Adds the connection event handler. After calling this method, you can handle new connection events when they arrive. /// - /// Param [identifier] The custom handler identifier, is used to find the corresponding handler. + /// Param [identifier] The custom handler identifier, which is used to find the corresponding handler. /// /// Param [handler] The handler for connection event. See [EMConnectionEventHandler]. /// ~end @@ -147,7 +147,7 @@ class EMClient { } /// ~english - /// Remove the connection event handler. + /// Removes the connection event handler. /// /// Param [identifier] The custom handler identifier. /// ~end @@ -162,7 +162,7 @@ class EMClient { } /// ~english - /// Get the connection event handler. + /// Gets the connection event handler. /// /// Param [identifier] The custom handler identifier. /// @@ -181,7 +181,7 @@ class EMClient { } /// ~english - /// Clear all connection event handlers. + /// Clears all connection event handlers. /// ~end /// /// ~chinese @@ -192,9 +192,9 @@ class EMClient { } /// ~english - /// Adds the multi-device event handler. After calling this method, you can handle for new room event when they arrive. + /// Adds the multi-device event handler. After calling this method, you can handle for new multi-device events when they arrive. /// - /// Param [identifier] The custom handler identifier, is used to find the corresponding handler. + /// Param [identifier] The custom handler identifier, which is used to find the corresponding handler. /// /// Param [handler] The handler multi-device event. See [EMMultiDeviceEventHandler]. /// ~end @@ -214,7 +214,7 @@ class EMClient { } /// ~english - /// Remove the multi-device event handler. + /// Removes the multi-device event handler. /// /// Param [identifier] The custom handler identifier. /// ~end @@ -229,7 +229,7 @@ class EMClient { } /// ~english - /// Get the multi-device event handler. + /// Gets the multi-device event handler. /// /// Param [identifier] The custom handler identifier. /// @@ -248,7 +248,7 @@ class EMClient { } /// ~english - /// Clear all multi-device event handlers. + /// Clears all multi-device event handlers. /// ~end /// /// ~chinese @@ -259,16 +259,14 @@ class EMClient { } /// ~english - /// Start contact and group, chatroom callback. + /// Starts contact and group, chatroom callback. /// - /// Reference: - /// Call this method when you ui is ready, then will receive [EMChatRoomEventHandler], [EMContactEventHandler], [EMGroupEventHandler] event. + /// Call this method when you UI is ready, then will receive [EMChatRoomEventHandler], [EMContactEventHandler], [EMGroupEventHandler] event. /// ~end /// /// ~chinese /// /// 开始回调通知。 /// - /// Reference: /// 当UI准备好后调用,调用之后才能收到 [EMChatRoomEventHandler], [EMContactEventHandler], [EMGroupEventHandler] 监听。 /// ~end Future startCallback() async { @@ -283,9 +281,9 @@ class EMClient { /// ~english /// Checks whether the SDK is connected to the chat server. /// - /// **Return** the result whether the SDK is connected to the chat server. - /// `true`: means that the SDK is connected to the chat server. - /// `false`: means not. + /// **Return** Whether the SDK is connected to the chat server. + /// `true`: The SDK is connected to the chat server. + /// `false`: The SDK is not connected to the chat server. /// ~end /// /// ~chinese @@ -307,12 +305,11 @@ class EMClient { /// ~english /// Checks whether the user has logged in before and did not log out. /// - /// Reference: /// If you need to check whether the SDK is connected to the server, please use [isConnected]. /// - /// **Return** The result of whether the user has logged in before. - /// `true`: means that the user has logged in before, - /// `false`: means that the user has not login before or has called [logout] method. + /// **Return** Whether the user has logged in before. + /// `true`: The user has logged in before, + /// `false`: The user has not logged in before or has called the [logout] method. /// ~end /// /// ~chinese @@ -399,9 +396,9 @@ class EMClient { } /// ~english - /// Register a new user. + /// Registers a new user. /// - /// Param [userId] The userId. The maximum length is 64 characters. Ensure that you set this parameter. + /// Param [userId] The user Id. The maximum length is 64 characters. Ensure that you set this parameter. /// Supported characters include the 26 English letters (a-z), the ten numbers (0-9), the underscore (_), the hyphen (-), /// and the English period (.). This parameter is case insensitive, and upper-case letters are automatically changed to low-case ones. /// If you want to set this parameter as a regular expression, set it as ^[a-zA-Z0-9_-]+$. @@ -433,15 +430,15 @@ class EMClient { } /// ~english - /// An app user logs in to the chat server with a password or token. + /// Logs in to the chat server with a password or token. /// - /// Param [userId] The username. + /// Param [userId] The user ID. /// /// Param [pwdOrToken] The password or token. /// - /// Param [isPassword] Whether to log in with password or token. - /// `true`: (default) Log in with password. - /// `false`: Log in with token. + /// Param [isPassword] Whether to log in with a password or a token. + /// (Default) `true`: A password is used. + /// `false`: A token is used. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -477,11 +474,11 @@ class EMClient { } /// ~english - /// An app user logs in to the chat server by username and Agora token. This method supports automatic login. + /// Logs in to the chat server by user ID and Agora token. This method supports automatic login. /// - /// See also: Another method to login to chat server is to login with user ID and token, See [login]. + /// Another method to login to chat server is to login with user ID and token, See [login]. /// - /// Param [userId] The userId. + /// Param [userId] The user Id. /// /// Param [agoraToken] The Agora token. /// @@ -546,9 +543,9 @@ class EMClient { } /// ~english - /// An app user logs out. + /// Logs out. /// - /// Param [unbindDeviceToken] Whether to unbind the token when logout. + /// Param [unbindDeviceToken] Whether to unbind the token upon logout. /// /// `true` (default) Yes. /// `false` No. @@ -645,9 +642,9 @@ class EMClient { @Deprecated('Use [fetchLoggedInDevices] instead') /// ~english - /// Gets all the information about the logged in devices under the specified account. + /// Gets the list of currently logged-in devices of a specified account. /// - /// Param [userId] The username you want to get the device information. + /// Param [userId] The user ID. /// /// Param [password] The password. /// @@ -685,13 +682,13 @@ class EMClient { } /// ~english - /// Gets all the information about the logged in devices under the specified account. + /// Gets the list of currently logged-in devices of a specified account. /// - /// Param [userId] The username you want to get the device information. + /// Param [userId] The user ID. /// /// Param [pwdOrToken] The password or token. /// - /// Param [isPwd] Whether it is a password, the default is true. + /// Param [isPwd] Whether a password or token is used: (Default)`true`: A password is used; `false`: A token is used. /// /// **Return** The list of the logged-in devices. /// @@ -701,11 +698,11 @@ class EMClient { /// ~chinese /// 获取指定账号下登录的在线设备列表。 /// - /// Param [userId] 用户 ID。 + /// Param [userId] 用户 ID。 /// - /// Param [pwdOrToken] 密码 或者 token。 + /// Param [pwdOrToken] 密码或者 token。 /// - /// Param [isPwd] 是否是密码,默认为 true。 + /// Param [isPwd] 是否使用密码或 token:(默认)`true`:使用密码;`false`:使用 token。 /// /// **Return** 获取到到设备列表。 /// @@ -734,9 +731,9 @@ class EMClient { /// ~english /// Forces the specified account to log out from the specified device. /// - /// Param [userId] The account you want to force logout. + /// Param [userId] The account you want to force to log out. /// - /// Param [pwdOrToken] The account's password or token. + /// Param [pwdOrToken] The password or token. /// /// Param [resource] The device ID. For how to fetch the device ID, See [EMDeviceInfo.resource]. /// @@ -744,7 +741,7 @@ class EMClient { /// ~end /// /// ~chinese - /// 在指定账号下,根据设备 ID,将指定设备下线,设备 ID:[EMDeviceInfo.resource]。 + /// 将指定账号登录的指定设备踢下线。 /// /// Param [userId] 用户 ID。 /// @@ -777,25 +774,25 @@ class EMClient { } /// ~english - /// Kicks out all the devices logged in under the specified account. + /// Forces the specified account to log out from all devices. /// - /// Param [userId] The account you want to log out from all the devices. + /// Param [userId] The account you want to force to log out from all the devices. /// /// Param [pwdOrToken] The password or token. /// - /// Param [isPwd] Whether it is a password, the default is true. + /// Param [isPwd] Whether a password or token is used: (Default)`true`: A password is used; `false`: A token is used. /// /// **Throws** A description of the exception. See [EMError]. /// ~end /// /// ~chinese - /// 将指定用户 ID 下的所有设备都踢下线。 + /// 将指定账号登录的所有设备都踢下线。 /// /// Param [userId] 用户 ID。 /// /// Param [pwdOrToken] 密码 或 token。 /// - /// Param [isPwd] 是否是密码,默认为 true。 + /// Param [isPwd] 是否使用密码或 token:(默认)`true`:使用密码;`false`:使用 token。 /// /// **Throws** 如果有异常会在这里抛出,包含错误码和错误描述,详见 [EMError]。 /// diff --git a/lib/src/em_group_manager.dart b/lib/src/em_group_manager.dart index 7d244c0d..56135b29 100644 --- a/lib/src/em_group_manager.dart +++ b/lib/src/em_group_manager.dart @@ -1845,10 +1845,10 @@ class EMGroupManager { /// /// Param [groupId] The group ID. /// - /// Param [userId] The user ID of the group member for whom the custom attributes are set, The default is the current user. + /// Param [userId] The user ID of the group member for whom the custom attributes are set. The default value is the current user ID. /// - /// Param [attributes] The map of custom attributes in key-value format. In a key-value pair, - /// if the value is set to an empty string, the custom attribute will be deleted. + /// Param [attributes] The map of custom attributes in key-value format. + /// In a key-value pair, if the value is set to an empty string, the custom attribute will be deleted. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -1890,9 +1890,9 @@ class EMGroupManager { /// /// Param [groupId] The group ID. /// - /// Param [keys] The custom attributes corresponding key. + /// Param [keys] The keys of custom attributes to remove. /// - /// Param [userId] The user ID of the group member for whom the custom attributes are remove, The default is the current user. + /// Param [userId] The user ID of the group member for whom the custom attributes are removed. The default value is the current user ID. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -1902,9 +1902,9 @@ class EMGroupManager { /// /// Param [groupId] 群组 ID。 /// - /// Param [keys] 要删除群成员自定义属性对应的key。 + /// Param [keys] 要删除群成员自定义属性对应的 key。 /// - /// Param [userId] 要设置自定义属性的群成员的用户 ID,默认为当前用户。 + /// Param [userId] 要设置自定义属性的群成员的用户 ID,默认为当前用户 ID。 /// /// /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 @@ -1935,9 +1935,9 @@ class EMGroupManager { /// /// Param [groupId] The group ID. /// - /// Param [userId] The user ID of the group member whose all custom attributes are retrieved. The default is the current user. + /// Param [userId] The user ID of the group member whose all custom attributes are retrieved. The default value is the current user ID. /// - /// **Return** The user attributes. + /// **Return** The user attributes of the group member. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -1947,7 +1947,7 @@ class EMGroupManager { /// /// Param [groupId] 群组 ID。 /// - /// Param [userId] 要获取的自定义属性的群成员的用户 ID, 默认为当前用户。 + /// Param [userId] 要获取的自定义属性的群成员的用户 ID, 默认为当前用户 ID。 /// /// **Return** 需要查询的用户属性。 /// @@ -1981,7 +1981,7 @@ class EMGroupManager { /// /// Param [groupId] The group ID. /// - /// Param [userIds] The array of user IDs of group members whose custom attributes are retrieved.(limitation is ten.More than callback error. ) + /// Param [userIds] The array of user IDs of group members whose custom attributes are retrieved. You can pass in a maximum of 10 user IDs. /// /// Param [keys] The array of keys of custom attributes to be retrieved. /// @@ -1992,11 +1992,11 @@ class EMGroupManager { /// ~end /// /// ~chinese - /// 根据指定的属性 key 获取多个群成员的自定义属性 + /// 根据指定的属性 key 获取多个群成员的自定义属性。 /// /// Param [groupId] 群组 ID。 /// - /// Param [userIds] 要获取自定义属性的群成员的用户 ID 数组。(最多10个,多则报错) + /// Param [userIds] 要获取自定义属性的群成员的用户 ID 数组。最多可传 10 个用户 ID。 /// /// Param [keys] 要获取自定义属性的 key 的数组。 /// diff --git a/lib/src/em_push_manager.dart b/lib/src/em_push_manager.dart index 6308c996..2ef5b718 100644 --- a/lib/src/em_push_manager.dart +++ b/lib/src/em_push_manager.dart @@ -62,7 +62,7 @@ class EMPushManager { } /// ~english - /// Updates the push message style. The default value is [DisplayStyle.Simple]. + /// Updates the push message display style. The default value is [DisplayStyle.Simple]. /// /// Param [displayStyle] The push message display style. /// @@ -170,26 +170,26 @@ class EMPushManager { } /// ~english - /// Set offline push notification type for the special conversation. + /// Sets the push notifications for a conversation. /// - /// Param [conversationId] The conversation id. + /// Param [conversationId] The conversation ID. /// /// Param [type] The conversation type. /// - /// Param [param] Push DND parameters offline. + /// Param [param] The offline push parameters. /// /// **Throws** A description of the exception. See [EMError]. /// /// ~end /// /// ~chinese - /// 设置特殊对话的离线推送通知类型。 + /// 设置指定会话的离线推送设置。 /// /// Param [conversationId] 会话 ID. /// /// Param [type] 会话类型. /// - /// Param [param] 推送免打扰参数. + /// Param [param] 离线推送参数. /// /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 /// ~end @@ -213,10 +213,11 @@ class EMPushManager { } /// ~english - /// Remove the setting of offline push notification type for the special conversation. - /// After clearing, the session follows the Settings of the current logged-in user [EMPushManager.setSilentModeForAll]. + /// Removes the offline push notification settings for a conversation. /// - /// Param [conversationId] The conversation id. + /// After the setting is deleted, the conversation follows the setting of [EMPushManager.setSilentModeForAll] of the current logged-in user. + /// + /// Param [conversationId] The conversation ID. /// /// Param [type] The conversation type. /// @@ -224,7 +225,8 @@ class EMPushManager { /// ~end /// /// ~chinese - /// 删除特殊会话的离线推送通知类型设置。 + /// 删除指定会话的离线推送通知设置。 + /// /// 清除后,会话遵循当前登录用户的设置 [EMPushManager.setSilentModeForAll]。 /// /// Param [conversationId] 会话 ID。 @@ -250,25 +252,25 @@ class EMPushManager { } /// ~english - /// Gets the DND setting of the special conversation. + /// Gets the offline push settings of a conversation. /// - /// Param [conversationId] The conversation id. + /// Param [conversationId] The conversation ID. /// /// Param [type] The conversation type. /// - /// **Return** The conversation silent mode. + /// **Return** The offline push settings of the conversation. /// /// **Throws** A description of the exception. See [EMError]. /// ~end /// /// ~chinese - /// 获取会话的免打扰设置。 + /// 获取指定会话的离线推送设置。 /// /// Param [conversationId] 会话 ID。 /// /// Param [type] 会话类型。 /// - /// **Return** 会话的免打扰设置。 + /// **Return** 会话的离线推送设置。 /// /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 /// ~end @@ -291,17 +293,17 @@ class EMPushManager { } /// ~english - /// Set the DND normal settings for the current login user. + /// Sets the offline push settings at the app level for the current login user. /// - /// Param [param] Push DND parameters offline. + /// Param [param] The offline push parameters. /// /// **Throws** A description of the exception. See [EMError]. /// ~end /// /// ~chinese - /// 设置当前登录用户的免打扰设置。 + /// 设置当前登录用户的 app 级别的推送设置。 /// - /// Param [param] 推送免打扰设置参数。 + /// Param [param] 离线推送参数。 /// /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 /// ~end @@ -322,17 +324,17 @@ class EMPushManager { } /// ~english - /// Gets the DND normal settings of the current login user. + /// Gets the offline push settings at the app level for the current login user. /// - /// **Return** The normal silent mode. + /// **Return** The offline push settings settings. /// /// **Throws** A description of the exception. See [EMError]. /// ~end /// /// ~chinese - /// 获取当前登录用户的免打扰设置。 + /// 获取当前登录用户的 app 级别的推送通知设置。 /// - /// **Return** 免打扰设置。 + /// **Return** 推送通知设置。 /// /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 /// ~end @@ -350,21 +352,21 @@ class EMPushManager { } /// ~english - /// Obtain the DND Settings of specified conversations in batches. + /// Gets the offline push settings of specified conversations. /// /// Param [conversations] The conversation list. /// - /// **Return** key is conversation id and the value is silent mode. + /// **Return** The key is the conversation ID and the value is offline push settings. /// /// **Throws** A description of the exception. See [EMError]. /// ~end /// /// ~chinese - /// 批量获取指定会话的免打扰设置。 + /// 批量获取指定会话的推送通知设置。 /// /// Param [conversations] 会话列表。 /// - /// **Return** 键为会话id,值为免打扰设置。 + /// **Return** 键为会话 ID,值为离线推送设置。 /// /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 /// ~end @@ -397,9 +399,9 @@ class EMPushManager { } /// ~english - /// Set user push translation language. + /// Sets the preferred language for push notifications. /// - /// Param [languageCode] language code. + /// Param [languageCode] The language code. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -425,9 +427,9 @@ class EMPushManager { } /// ~english - /// Gets the push translation language set by the user. + /// Gets the preferred language for push notifications. /// - /// **Return** has set language code. + /// **Return** The language code. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -453,9 +455,9 @@ class EMPushManager { } /// ~english - /// Set the push template for offline push. + /// Sets the template for offline push notifications. /// - /// Param [pushTemplateName] push template name. + /// Param [pushTemplateName] The push template name. /// /// **Throws** A description of the exception. See [EMError]. /// ~end @@ -463,7 +465,7 @@ class EMPushManager { /// ~chinese /// 设置离线推送模板。 /// - /// Param [pushTemplateName] 推送模版名称。 + /// Param [pushTemplateName] 推送模板名称。 /// /// **Throws** 如果有异常会在此抛出,包括错误码和错误信息,详见 [EMError]。 /// ~end @@ -480,7 +482,7 @@ class EMPushManager { } /// ~english - /// Gets the offline push template for Settings. + /// Gets the template for offline push notifications. /// /// **Return** The push template name. /// @@ -488,7 +490,7 @@ class EMPushManager { /// ~end /// /// ~chinese - /// 获取推送模版名称。 + /// 获取推送模板名称。 /// /// **Return** 推送模板名称。 /// diff --git a/lib/src/event_handler/manager_event_handler.dart b/lib/src/event_handler/manager_event_handler.dart index 3436b43e..7d0fe25f 100644 --- a/lib/src/event_handler/manager_event_handler.dart +++ b/lib/src/event_handler/manager_event_handler.dart @@ -151,29 +151,29 @@ class EMConnectionEventHandler { /// ~english /// The chat connection listener callback. /// - /// Param [onConnected] The SDK connects to the chat server successfully callback. + /// Param [onConnected] The SDK connects to the chat server successfully. /// - /// Param [onDisconnected] The SDK disconnect from the chat server callback. + /// Param [onDisconnected] The SDK disconnect from the chat server. /// - /// Param [onUserDidLoginFromOtherDevice] Current user account is logged in to another device callback. + /// Param [onUserDidLoginFromOtherDevice] The current user account is logged in to another device. /// - /// Param [onUserDidRemoveFromServer] Current chat user is removed from the server callback. + /// Param [onUserDidRemoveFromServer] The current chat user is removed from the server. /// - /// Param [onUserDidForbidByServer] Current chat user is forbid from the server callback. + /// Param [onUserDidForbidByServer] The current chat user is banned by the server. /// - /// Param [onUserDidChangePassword] Current chat user is changed password callback. + /// Param [onUserDidChangePassword] The current chat user is changed password. /// - /// Param [onUserDidLoginTooManyDevice] Current chat user logged to many devices callback. + /// Param [onUserDidLoginTooManyDevice] The current chat user logged in to many devices. /// - /// Param [onUserKickedByOtherDevice] Current chat user kicked by other device callback. + /// Param [onUserKickedByOtherDevice] The current chat user is kicked by another device. /// - /// Param [onUserAuthenticationFailed] Current chat user authentication failed callback. + /// Param [onUserAuthenticationFailed] The authentication for the chat user failed. /// - /// Param [onTokenWillExpire] The token is about to expire callback. + /// Param [onTokenWillExpire] The token is about to expire. /// - /// Param [onTokenDidExpire] The token has expired callback. + /// Param [onTokenDidExpire] The token has expired. /// - /// Param [onAppActiveNumberReachLimit] The number of daily active users (DAU) or monthly active users (MAU) for the app has reached the upper limit callback. + /// Param [onAppActiveNumberReachLimit] The number of daily active users (DAU) or monthly active users (MAU) for the app has reached the upper limit. /// /// ~end /// @@ -222,14 +222,14 @@ class EMConnectionEventHandler { /// ~english /// The multi-device event handler. -/// Listens for callback for the current user's actions on other devices, including contact changes and group changes. +/// Listens for callback for the current user's actions on other devices, including contact changes, group changes, and thread changes. /// -/// Adds multi-device event handler: +/// Adds a multi-device event handler: /// ```dart /// EMClient.getInstance.addMultiDeviceEventHandler((UNIQUE_HANDLER_ID, EMMultiDeviceEventHandler()); /// ``` /// -/// Remove a multi-device event handler: +/// Removes a multi-device event handler: /// ```dart /// EMClient.getInstance.removeMultiDeviceEventHandler(UNIQUE_HANDLER_ID); /// ``` @@ -237,7 +237,7 @@ class EMConnectionEventHandler { /// /// ~chinese /// 多设备事件监听 -/// 监听当前用户在其他设备上的操作的回调,包括联系人更改和组,thread等更改。 +/// 监听当前用户在其他设备上的操作的回调,包括联系人更改、群组和 thread 等更改。 /// /// 添加监听: /// ```dart @@ -281,7 +281,7 @@ class EMMultiDeviceEventHandler { /// ~end /// /// ~chinese - /// 多设备Thread 事件。 + /// 多设备 Thread 事件。 /// ~end final void Function( EMMultiDevicesEvent event, @@ -290,7 +290,7 @@ class EMMultiDeviceEventHandler { )? onChatThreadEvent; /// ~english - /// Callback to other devices after conversation deleted message from server after enabling multiple devices. + /// Callback received by other devices after historical messages in a conversation are removed from the server in a multi-device login scenario. /// ~end /// /// ~chinese @@ -302,7 +302,7 @@ class EMMultiDeviceEventHandler { )? onRemoteMessagesRemoved; /// ~english - /// The multi-device event callback for the operation of a single conversation. + /// The multi-device event callback for the operation of a conversation. /// ~end /// /// ~chinese @@ -323,9 +323,9 @@ class EMMultiDeviceEventHandler { /// /// Param [onChatThreadEvent] The multi-device event of thread. /// - /// Param [onRemoteMessagesRemoved] The multi-device event of roam messages removed. + /// Param [onRemoteMessagesRemoved] The multi-device event of historical messages removed from the server. /// - /// Param [onConversationEvent] The multi-device event callback for the operation of a single conversation. + /// Param [onConversationEvent] The multi-device event callback for the operation of a conversation. /// /// ~end /// @@ -356,7 +356,7 @@ class EMMultiDeviceEventHandler { /// The chat event handler. /// /// This handler is used to check whether messages are received. If messages are sent successfully, a delivery receipt will be returned (delivery receipt needs to be enabled: [EMOptions.requireDeliveryAck]. -/// If the peer reads the received message, a read receipt will be returned (read receipt needs to be enabled: [EMOptions.requireAck]). +/// If the peer user reads the received message, a read receipt will be returned (read receipt needs to be enabled: [EMOptions.requireAck]). /// This API should be implemented in the app to listen for message status changes. /// /// Adds chat event handler: @@ -364,7 +364,7 @@ class EMMultiDeviceEventHandler { /// EMClient.getInstance.chatManager.addEventHandler(UNIQUE_HANDLER_ID, EMChatEventHandler()); /// ``` /// -/// Remove a chat event handler: +/// Removes a chat event handler: /// ```dart /// EMClient.getInstance.chatManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` @@ -387,7 +387,7 @@ class EMMultiDeviceEventHandler { /// ~end class EMChatEventHandler { /// ~english - /// Occurs when a message is received callback. + /// Occurs when a message is received. /// /// This callback is triggered to notify the user when a message such as texts or an image, video, voice, location, or file is received. /// ~end @@ -469,7 +469,7 @@ class EMChatEventHandler { /// Occurs when a conversation read receipt is received. /// /// Occurs in the following scenarios: - /// (1) The message is read by the receiver (The conversation receipt is sent). + /// (1) The message is read by the recipient (The conversation receipt is sent). /// Upon receiving this event, the SDK sets the [EMMessage.hasReadAck] property of the message in the conversation to `true` in the local database. /// (2) In the multi-device login scenario, when one device sends a Conversation receipt, /// the server will set the number of unread messages to 0, and the callback occurs on the other devices. @@ -513,27 +513,27 @@ class EMChatEventHandler { /// ~english /// The chat event handler. /// - /// Param [onMessagesReceived] Message is received callback. + /// Param [onMessagesReceived] Occurs when a message is received. /// - /// Param [onCmdMessagesReceived] Command message is received callback. + /// Param [onCmdMessagesReceived] Occurs when a command message is received. /// - /// Param [onMessagesRead] Read receipt is received for a message callback. + /// Param [onMessagesRead] Occurs when a read receipt is received for a one-to-one message. /// - /// Param [onGroupMessageRead] Read receipt is received for a group message callback. + /// Param [onGroupMessageRead] Occurs when a read receipt is received for a group message. /// - /// Param [onReadAckForGroupMessageUpdated] Group message read status is received callback. + /// Param [onReadAckForGroupMessageUpdated] Occurs when the group message read status is received. /// - /// Param [onMessagesDelivered] Delivery receipt is received callback. + /// Param [onMessagesDelivered] Occurs when a delivery receipt is received. /// - /// Param [onMessagesRecalled] Received message is recalled callback. + /// Param [onMessagesRecalled] Occurs when a received message is recalled. /// - /// Param [onConversationsUpdate] Conversation updated callback. + /// Param [onConversationsUpdate] Occurs when a conversation is updated. /// - /// Param [onConversationRead] Conversation read receipt is received callback. + /// Param [onConversationRead] Occurs when a conversation read receipt is received. /// - /// Param [onMessageReactionDidChange] Reaction data changes callback. + /// Param [onMessageReactionDidChange] Occurs when the Reaction data changes. /// - /// Param [onMessageContentChanged] Message content is modified callback. + /// Param [onMessageContentChanged] Occurs when the message content is modified. /// ~end /// /// ~chinese @@ -584,7 +584,7 @@ class EMChatEventHandler { /// EMClient.getInstance.chatRoomManager.addEventHandler(UNIQUE_HANDLER_ID, EMChatRoomEventHandler()); /// ``` /// -/// Remove a chat room event handler: +/// Removes a chat room event handler: /// ```dart /// EMClient.getInstance.chatRoomManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` @@ -598,14 +598,14 @@ class EMChatEventHandler { /// EMClient.getInstance.chatRoomManager.addEventHandler(UNIQUE_HANDLER_ID, EMChatRoomEventHandler()); /// ``` /// -/// Remove a chat room event handler: +/// Removes a chat room event handler: /// ```dart /// EMClient.getInstance.chatRoomManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` /// ~end class EMChatRoomEventHandler { /// ~english - /// Occurs when a member has been changed to an admin. + /// Occurs when a member is changed to be an admin. /// ~end /// /// ~chinese @@ -617,7 +617,7 @@ class EMChatRoomEventHandler { )? onAdminAddedFromChatRoom; /// ~english - /// Occurs when an admin is been removed. + /// Occurs when an admin is removed. /// ~end /// /// ~chinese @@ -641,7 +641,7 @@ class EMChatRoomEventHandler { )? onAllChatRoomMemberMuteStateChanged; /// ~english - /// Occurs when the chat room member(s) is added to the allowlist. + /// Occurs when the chat room member(s) is/are added to the allowlist. /// ~end /// /// ~chinese @@ -653,7 +653,7 @@ class EMChatRoomEventHandler { )? onAllowListAddedFromChatRoom; /// ~english - /// Occurs when the chat room member(s) is removed from the allowlist. + /// Occurs when the chat room member(s) is/are removed from the allowlist. /// ~end /// /// ~chinese @@ -689,7 +689,7 @@ class EMChatRoomEventHandler { )? onChatRoomDestroyed; /// ~english - /// Occurs when a member leaves the chatroom. + /// Occurs when a member leaves the chat room. /// ~end /// /// ~chinese @@ -702,7 +702,7 @@ class EMChatRoomEventHandler { )? onMemberExitedFromChatRoom; /// ~english - /// Occurs when a member join the chatroom. + /// Occurs when a user joins the chat room. /// ~end /// /// ~chinese @@ -712,7 +712,7 @@ class EMChatRoomEventHandler { onMemberJoinedFromChatRoom; /// ~english - /// Occurs when there are chat room member(s) muted (added to mute list), + /// Occurs when a chat room member(s) is/are added to mute list. /// ~end /// /// ~chinese @@ -725,7 +725,7 @@ class EMChatRoomEventHandler { )? onMuteListAddedFromChatRoom; /// ~english - /// Occurs when there are chat room member(s) unmuted (removed from mute list). + /// Occurs when the a chat room member(s) is/are removed from mute list. /// ~end /// /// ~chinese @@ -737,7 +737,7 @@ class EMChatRoomEventHandler { )? onMuteListRemovedFromChatRoom; /// ~english - /// Occurs when the chat room ownership has been transferred. + /// Occurs when the chat room ownership is transferred. /// ~end /// /// ~chinese @@ -750,7 +750,7 @@ class EMChatRoomEventHandler { )? onOwnerChangedFromChatRoom; /// ~english - /// Occurs when a you is dismissed from a chat room. + /// Occurs when a user is removed from a chat room. /// ~end /// /// ~chinese @@ -801,37 +801,37 @@ class EMChatRoomEventHandler { /// ~english /// The chat room manager listener callback. /// - /// Param [onAdminAddedFromChatRoom] A member has been changed to an admin callback. + /// Param [onAdminAddedFromChatRoom] A member is changed to be an admin. /// - /// Param [onAdminRemovedFromChatRoom] An admin is been removed callback callback. + /// Param [onAdminRemovedFromChatRoom] An admin is been removed. /// - /// Param [onAllChatRoomMemberMuteStateChanged] All members in the chat room are muted or unmuted callback. + /// Param [onAllChatRoomMemberMuteStateChanged] All members in the chat room are muted or unmuted. /// - /// Param [onAllowListAddedFromChatRoom] The chat room member(s) is added to the allowlist callback. + /// Param [onAllowListAddedFromChatRoom] The chat room member(s) is/are added to the allowlist. /// - /// Param [onAllowListRemovedFromChatRoom] The chat room member(s) is removed from the allowlist callback. + /// Param [onAllowListRemovedFromChatRoom] The chat room member(s) is/are removed from the allowlist. /// - /// Param [onAnnouncementChangedFromChatRoom] The announcement changed callback. + /// Param [onAnnouncementChangedFromChatRoom] The announcement is changed. /// - /// Param [onChatRoomDestroyed] The chat room is destroyed callback. + /// Param [onChatRoomDestroyed] The chat room is destroyed. /// - /// Param [onMemberExitedFromChatRoom] A member leaves the chatroom callback. + /// Param [onMemberExitedFromChatRoom] A member leaves the chat room. /// - /// Param [onMemberJoinedFromChatRoom] A member join the chatroom callback. + /// Param [onMemberJoinedFromChatRoom] A user joins the chat room. /// - /// Param [onMuteListAddedFromChatRoom] The chat room member(s) muted (added to mute list) callback. + /// Param [onMuteListAddedFromChatRoom] The chat room member(s) is/are added to mute list. /// - /// Param [onMuteListRemovedFromChatRoom] The chat room member(s) unmuted (removed from mute list) callback. + /// Param [onMuteListRemovedFromChatRoom] The chat room member(s) is/are removed from mute list. /// - /// Param [onOwnerChangedFromChatRoom] The chat room ownership has been transferred callback. + /// Param [onOwnerChangedFromChatRoom] The chat room ownership is transferred. /// - /// Param [onRemovedFromChatRoom] The chat room member(s) is removed from the allowlist callback. + /// Param [onRemovedFromChatRoom] The chat room member(s) is/are removed from the allowlist. /// - /// Param [onSpecificationChanged] The chat room specification changed callback. + /// Param [onSpecificationChanged] The chat room specification changed. /// - /// Param [onAttributesUpdated] The chat room attributes updated callback. + /// Param [onAttributesUpdated] The chat room attribute(s) is/are updated. /// - /// Param [onAttributesRemoved] The chat room attributes removed callback. + /// Param [onAttributesRemoved] The chat room attribute(s) is/are removed. /// ~end /// /// ~chinese @@ -890,14 +890,14 @@ class EMChatRoomEventHandler { } /// ~english -/// The message thread event handler. which handle for message thread events such as creating or leaving a message thread. +/// The message thread event handler, which handles message thread events such as creating or leaving a message thread. /// /// Adds a message thread event handler: /// ```dart /// EMClient.getInstance.chatThreadManager.addEventHandler(UNIQUE_HANDLER_ID, EMChatThreadEventHandler()); /// ``` /// -/// Remove a chat event handler: +/// Removes a chat event handler: /// ```dart /// EMClient.getInstance.chatThreadManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` @@ -972,19 +972,19 @@ class EMChatThreadEventHandler { )? onUserKickOutOfChatThread; /// ~english - /// The message thread listener callback + /// The message thread listener callback. /// - /// Param [onChatThreadCreate] A message thread is created callback. + /// Param [onChatThreadCreate] A message thread is created. All members in the group to which the thread belongs receive this callback. /// - /// Param [onChatThreadDestroy] A message thread is destroyed callback. + /// Param [onChatThreadDestroy] A message thread is destroyed. All members in the group to which the destroyed thread belongs receive this callback. /// - /// Param [onChatThreadUpdate] A message thread is updated callback. + /// Param [onChatThreadUpdate] A message thread is updated. All members in the group to which the updated thread belongs receive this callback. /// - /// Param [onUserKickOutOfChatThread] Current user is removed from the message thread by the group owner or a group admin to which the message thread belongs callback. + /// Param [onUserKickOutOfChatThread] The current user is removed from the message thread by the group owner or a group admin to which the message thread belongs. The current user removed from the thread receives the callback. /// ~end /// /// ~chinese - /// Thread 事件监听 + /// Thread 事件监听。 /// /// Param [onChatThreadCreate] 子区创建回调。 /// @@ -1005,15 +1005,14 @@ class EMChatThreadEventHandler { /// ~english /// The contact event handler. /// -/// Occurs when the contact changes, including requests to add friends, notifications to delete friends, -/// requests to accept friends, and requests to reject friends. +/// Occurs when the contact changes, including adding or deleting contacts and accept or rejecting friend requests. /// /// Adds a contact event handler: /// ```dart /// EMClient.getInstance.contactManager.addEventHandler(UNIQUE_HANDLER_ID, EMContactEventHandler()); /// ``` /// -/// Remove a contact event handler: +/// Removes a contact event handler: /// ```dart /// EMClient.getInstance.contactManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` @@ -1092,15 +1091,15 @@ class EMContactEventHandler { /// ~english /// The contact updates listener callback. /// - /// Param [onContactAdded] Current user is added as a contact by another user callback. + /// Param [onContactAdded] Current user is added as a contact by another user. /// - /// Param [onContactDeleted] Current user is removed from the contact list by another user callback. + /// Param [onContactDeleted] Current user is removed from the contact list by another user. /// - /// Param [onContactInvited] Current user receives a friend request callback. + /// Param [onContactInvited] Current user receives a friend request. /// - /// Param [onFriendRequestAccepted] A friend request is approved callback. + /// Param [onFriendRequestAccepted] A friend request is approved. /// - /// Param [onFriendRequestDeclined] A friend request is declined callback. + /// Param [onFriendRequestDeclined] A friend request is declined. /// ~end /// /// ~chinese @@ -1128,14 +1127,14 @@ class EMContactEventHandler { /// ~english /// The group event handler. /// -/// Occurs when the following group events happens: requesting to join a group, approving or declining a group request, and kicking a user out of a group. +/// Occurs when the following group events happens: joining a group, approving or declining a group request, and kicking a user out of a group. /// /// Adds a group event handler: /// ```dart /// EMClient.getInstance.groupManager.addEventHandler(UNIQUE_HANDLER_ID, EMGroupEventHandler()); /// ``` /// -/// Remove a group event handler: +/// Removes a group event handler: /// ```dart /// EMClient.getInstance.groupManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` @@ -1309,7 +1308,7 @@ class EMGroupEventHandler { )? onMemberExitedFromGroup; /// ~english - /// Occurs when a member joins a group. + /// Occurs when a user joins a group. /// ~end /// /// ~chinese @@ -1497,55 +1496,55 @@ class EMGroupEventHandler { /// ~english /// The group manager listener callback. /// - /// Param [onAdminAddedFromGroup] A member is set as an admin callback. + /// Param [onAdminAddedFromGroup] A member is set as an admin. /// - /// Param [onAdminRemovedFromGroup] A member's admin privileges are removed callback. + /// Param [onAdminRemovedFromGroup] A member's admin privileges are removed. /// - /// Param [onAllGroupMemberMuteStateChanged] All group members are muted or unmuted callback. + /// Param [onAllGroupMemberMuteStateChanged] All group members are muted or unmuted. /// - /// Param [onAllowListAddedFromGroup] One or more group members are muted callback. + /// Param [onAllowListAddedFromGroup] One or more group members are muted. /// - /// Param [onAllowListRemovedFromGroup] One or more group members are unmuted callback. + /// Param [onAllowListRemovedFromGroup] One or more group members are unmuted. /// - /// Param [onAnnouncementChangedFromGroup] The announcement is updated callback. + /// Param [onAnnouncementChangedFromGroup] The announcement is updated. /// - /// Param [onAutoAcceptInvitationFromGroup] The group invitation is accepted automatically callback. + /// Param [onAutoAcceptInvitationFromGroup] The group invitation is accepted automatically. /// - /// Param [onGroupDestroyed] A group is destroyed callback. + /// Param [onGroupDestroyed] A group is destroyed. /// - /// Param [onInvitationAcceptedFromGroup] A group invitation is accepted callback. + /// Param [onInvitationAcceptedFromGroup] A group invitation is accepted. /// - /// Param [onInvitationDeclinedFromGroup] A group invitation is declined callback. + /// Param [onInvitationDeclinedFromGroup] A group invitation is declined. /// - /// Param [onInvitationReceivedFromGroup] The user receives a group invitation callback. + /// Param [onInvitationReceivedFromGroup] The user receives a group invitation. /// - /// Param [onMemberExitedFromGroup] A member proactively leaves the group callback. + /// Param [onMemberExitedFromGroup] A member proactively leaves the group. /// - /// Param [onMemberJoinedFromGroup] A member joins a group callback. + /// Param [onMemberJoinedFromGroup] A user joins a group. /// - /// Param [onMuteListAddedFromGroup] One or more group members are muted callback. + /// Param [onMuteListAddedFromGroup] One or more group members are muted. /// - /// Param [onMuteListRemovedFromGroup] One or more group members are unmuted callback. + /// Param [onMuteListRemovedFromGroup] One or more group members are unmuted. /// - /// Param [onOwnerChangedFromGroup] The group ownership is transferred callback. + /// Param [onOwnerChangedFromGroup] The group ownership is transferred. /// - /// Param [onRequestToJoinAcceptedFromGroup] A group request is accepted callback. + /// Param [onRequestToJoinAcceptedFromGroup] A group request is accepted. /// - /// Param [onRequestToJoinDeclinedFromGroup] A group request is declined callback. + /// Param [onRequestToJoinDeclinedFromGroup] A group request is declined. /// - /// Param [onRequestToJoinReceivedFromGroup] The group owner or administrator receives a group request from a user callback. + /// Param [onRequestToJoinReceivedFromGroup] The group owner or administrator receives a group request from a user. /// - /// Param [onSharedFileAddedFromGroup] A shared file is added to a group callback. + /// Param [onSharedFileAddedFromGroup] A shared file is added to a group. /// - /// Param [onSharedFileDeletedFromGroup] A shared file is removed from a group callback. + /// Param [onSharedFileDeletedFromGroup] A shared file is removed from a group. /// - /// Param [onUserRemovedFromGroup] Current user is removed from the group by the group admin callback. + /// Param [onUserRemovedFromGroup] Current user is removed from the group by the group admin. /// - /// Param [onSpecificationDidUpdate] Occurs when the group detail information is updated. + /// Param [onSpecificationDidUpdate] The group detail information is updated. /// - /// Param [onDisableChanged] Occurs when the group is enabled or disabled. + /// Param [onDisableChanged] Te group is enabled or disabled. /// - /// Param [onAttributesChangedOfGroupMember] Occurs when a custom attribute(s) of a group member is/are changed. + /// Param [onAttributesChangedOfGroupMember] A custom attribute(s) of a group member is/are changed. /// ~end /// /// ~chinese @@ -1640,7 +1639,7 @@ class EMGroupEventHandler { /// EMClient.getInstance.presenceManager.addEventHandler(UNIQUE_HANDLER_ID, EMPresenceEventHandler()); /// ``` /// -/// Remove a presence event handler: +/// Removes a presence event handler: /// ```dart /// EMClient.getInstance.presenceManager.removeEventHandler(UNIQUE_HANDLER_ID); /// ``` @@ -1672,7 +1671,7 @@ class EMPresenceEventHandler { /// ~english /// The presence manager listener callback. /// - /// Param [onPresenceStatusChanged] The presence state of a subscribed user changes callback. + /// Param [onPresenceStatusChanged] The presence state of a subscribed user changes. /// ~end /// /// ~chinese diff --git a/lib/src/models/em_chat_enums.dart b/lib/src/models/em_chat_enums.dart index 5f3b00ca..726af5cb 100644 --- a/lib/src/models/em_chat_enums.dart +++ b/lib/src/models/em_chat_enums.dart @@ -1,5 +1,5 @@ /// ~english -/// The enumeration of group types. +/// The group types. /// ~end /// /// ~chinese @@ -80,7 +80,7 @@ enum EMConversationType { } /// ~english -/// The enumeration of chat types. +/// The chat types. /// /// There are three chat types: one-to-one chat, group chat, and chat room. /// ~end @@ -118,7 +118,7 @@ enum ChatType { } /// ~english -/// The enumeration of the message directions. +/// The message directions. /// /// Whether the message is sent or received. /// ~end @@ -149,7 +149,7 @@ enum MessageDirection { } /// ~english -/// The enumeration of the message sending/reception status. +/// The message sending/reception status. /// ~end /// /// ~chinese @@ -239,7 +239,7 @@ enum DownloadStatus { } /// ~english -/// The enumeration of message types. +/// The message types. /// ~end /// /// ~chinese @@ -329,7 +329,7 @@ enum MessageType { } /// ~english -/// The enumeration of group permission types. +/// The group roles. /// ~end /// /// ~chinese @@ -346,7 +346,7 @@ enum EMGroupPermissionType { None, /// ~english - /// The group member. + /// The regular group member. /// ~end /// /// ~chinese @@ -374,7 +374,7 @@ enum EMGroupPermissionType { } /// ~english -/// The enumeration of chat room role types. +/// The chat room roles. /// ~end /// /// ~chinese @@ -391,7 +391,7 @@ enum EMChatRoomPermissionType { None, /// ~english - /// The chat room member. + /// The regular chat room member. /// ~end /// /// ~chinese @@ -419,7 +419,7 @@ enum EMChatRoomPermissionType { } /// ~english -/// The enumeration of message search directions. +/// The message search directions. /// ~end /// /// ~chinese @@ -828,7 +828,7 @@ enum EMMultiDevicesEvent { } /// ~english -/// The message thread event types. +/// The message thread events. /// ~end /// /// ~chinese @@ -882,7 +882,7 @@ enum EMChatThreadOperation { } /// ~english -/// The push styles. +/// The push display styles. /// ~end /// /// ~chinese @@ -890,7 +890,7 @@ enum EMChatThreadOperation { /// ~end enum DisplayStyle { /// ~english - /// The push message presentation style: SimpleBanner represents the presentation of a simple message. + /// A simple message is shown in the notification bar, for example, "You've got a new message.". /// ~end /// /// ~chinese @@ -899,7 +899,7 @@ enum DisplayStyle { Simple, /// ~english - /// The push message presentation style: MessageSummary represents the presentation of message content. + /// The message content is shown in the notification bar. /// ~end /// /// ~chinese @@ -909,15 +909,15 @@ enum DisplayStyle { } /// ~english -/// Offline push DND parameter type Enumeration class. +/// The offline push settings. /// ~end /// /// ~chinese -/// 离线推送免打扰参数类型枚举类。 +/// 离线推送参数类型枚举类。 /// ~end enum ChatSilentModeParamType { /// ~english - /// Offline push notification type. + /// The push notification mode. /// ~end /// /// ~chinese @@ -926,7 +926,7 @@ enum ChatSilentModeParamType { REMIND_TYPE, /// ~english - /// Offline push DND duration. + /// The DND duration. /// ~end /// /// ~chinese @@ -935,7 +935,7 @@ enum ChatSilentModeParamType { SILENT_MODE_DURATION, /// ~english - /// Offline push DND period. + /// The DND time frame. /// ~end /// /// ~chinese @@ -945,7 +945,7 @@ enum ChatSilentModeParamType { } /// ~english -/// Offline push notification type enumeration class. +/// The push notification modes. /// ~end /// /// ~chinese @@ -953,29 +953,29 @@ enum ChatSilentModeParamType { /// ~end enum ChatPushRemindType { /// ~english - /// Collect all offline push. + /// Receives push notifications for all offline messages. /// ~end /// /// ~chinese - /// 所有离线推送。 + /// 接收所有离线消息的推送通知。 /// ~end ALL, /// ~english - /// Only receive @me offline push. + /// Only receives push notifications for mentioned messages. /// ~end /// /// ~chinese - /// 只有@我的离线推送 + /// 仅接收提及某些用户的消息的推送通知。 /// ~end MENTION_ONLY, /// ~english - /// Offline push is not collected. + /// Do not receive push notifications for offline messages. /// ~end /// /// ~chinese - /// 不接收离线推送。 + /// 不接收离线消息的推送通知。 /// ~end NONE, } @@ -1017,11 +1017,11 @@ enum ChatRoomMessagePriority { } /// ~english -/// Operation type of reaction. +/// Reaction operations. /// ~end /// /// ~chinese -/// reaction 操作种类。 +/// Reaction 操作类型。 /// ~end enum ReactionOperate { /// ~english diff --git a/lib/src/models/em_message.dart b/lib/src/models/em_message.dart index 3263f140..52b1aa73 100644 --- a/lib/src/models/em_message.dart +++ b/lib/src/models/em_message.dart @@ -797,7 +797,7 @@ class EMMessage { /// ~end EMMessage.createCustomSendMessage({ required String targetId, - required String event, + required event, Map? params, ChatType chatType = ChatType.Chat, }) : this.createSendMessage( @@ -806,22 +806,22 @@ class EMMessage { body: EMCustomMessageBody(event: event, params: params)); /// ~english - /// Creates a combine message for sending. + /// Creates a combined message for sending. /// - /// Param [targetId] The ID of the message recipient. - /// - For a one-to-one chat, it is the username of the peer user. + /// Param [targetId] The message recipient. The field setting is determined by the conversation type: + /// - For a one-to-one chat, it is the user ID of the peer user. /// - For a group chat, it is the group ID. /// - For a chat room, it is the chat room ID. /// - /// Param [title] The message title. + /// Param [title] The title of the combined message. /// - /// Param [summary] The message summary. + /// Param [summary] The summary of the combined message. /// - /// Param [compatibleText] The compatible text. + /// Param [compatibleText] The compatible text of the combined message. /// - /// Param [msgIds] The list of combined messages. + /// Param [msgIds] The list of original messages included in the combined message. /// - /// Param [chatType] The chat type, default is single chat, if it is group chat or chat room, see [ChatType]. + /// Param [chatType] The chat type, which is one-to-one chat by default. For group chat or chat room, see [ChatType]. /// /// **Return** The message instance. /// ~end @@ -829,20 +829,20 @@ class EMMessage { /// ~chinese /// 创建一条待发送的合并消息。 /// - /// Param [targetId] 消息接收方,可以是: - /// - 用户:用户 ID; + /// Param [targetId] 消息接收方。该字段的设置取决于会话类型: + /// - 单聊:对方用户 ID; /// - 群组:群组 ID; /// - 聊天室:聊天室 ID。 /// - /// Param [title] 消息标题。 + /// Param [title] 合并消息的标题。 /// - /// Param [summary] 消息概要。 + /// Param [summary] 合并消息的概要。 /// - /// Param [compatibleText] 兼容文本。 + /// Param [compatibleText] 合并消息的兼容信息。 /// - /// Param [msgIds] 合并的消息列表。 + /// Param [msgIds] 合并消息的消息 ID 列表。 /// - /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考[ChatType]。 + /// Param [chatType] 聊天类型, 默认为单聊,如果是群聊或者聊天室,可以参考 [ChatType]。 /// /// **Return** 消息体实例。 /// ~end diff --git a/lib/src/models/em_options.dart b/lib/src/models/em_options.dart index 03870f1b..88fc3c32 100644 --- a/lib/src/models/em_options.dart +++ b/lib/src/models/em_options.dart @@ -286,20 +286,20 @@ class EMOptions { final bool enableEmptyConversation; /// ~english - /// Custom device name + /// Custom device name. /// ~end /// /// ~chinese - /// 自定义设备名称 + /// 自定义设备名称。 /// ~end final String? deviceName; /// ~english - /// Custom system type + /// Custom system type. /// ~end /// /// ~chinese - /// 自定义系统类型 + /// 自定义系统类型。 /// ~end final int? osType; @@ -308,7 +308,7 @@ class EMOptions { /// ~english /// Enable OPPO PUSH on OPPO devices. /// - /// Param [appKey] The app id for OPPO PUSH. + /// Param [appKey] The app ID for OPPO PUSH. /// /// Param [secret] The app secret for OPPO PUSH. /// ~end @@ -318,7 +318,7 @@ class EMOptions { /// /// Param [appId] Oppo 推送的 App ID。 /// - /// Param [appKey] Oppo 推送的 app key。 + /// Param [appKey] Oppo 推送的 App Key。 /// ~end void enableOppoPush(String appKey, String secret) { _pushConfig.enableOppoPush = true; @@ -355,8 +355,8 @@ class EMOptions { /// /// ~chinese /// 开启魅族推送. - /// Param [appId] 魅族AppId. - /// Param [appKey] 魅族Appkey. + /// Param [appId] 魅族 App ID. + /// Param [appKey] 魅族 App Key. /// ~end void enableMeiZuPush(String appId, String appKey) { _pushConfig.mzAppId = appId; diff --git a/lib/src/models/fetch_message_options.dart b/lib/src/models/fetch_message_options.dart index a7776edf..e1ea2005 100644 --- a/lib/src/models/fetch_message_options.dart +++ b/lib/src/models/fetch_message_options.dart @@ -128,13 +128,13 @@ class FetchMessageOptions { /// ~english /// Whether to save the retrieved messages to the database: /// - `true`: save to database; - /// - `false`(Default):no save to database. + /// - (Default) `false`:Do not save to database. /// ~end /// /// ~chinese /// 获取的消息是否保存到数据库: /// - `true`:保存到数据库; - /// - `false`(默认):不保存到数据库。 + /// - (默认)`false`:不保存到数据库。 /// ~end final bool needSave; diff --git a/lib/src/models/reaction_operation.dart b/lib/src/models/reaction_operation.dart index 9b9d1d72..5411b71b 100644 --- a/lib/src/models/reaction_operation.dart +++ b/lib/src/models/reaction_operation.dart @@ -1,31 +1,31 @@ import 'em_chat_enums.dart'; /// ~english -/// Reaction Operation +/// Reaction operation. /// ~end /// /// ~chinese -/// Reaction 操作 +/// Reaction 操作。 /// ~end class ReactionOperation { /// ~english - /// Reaction Operation + /// Reaction operation. /// - /// Param [userId] Operator userId. + /// Param [userId] The user ID of the operator. /// - /// Param [reaction] Changed reaction. + /// Param [reaction] Changed Reaction. /// - /// Param [operate] Operate type. + /// Param [operate] The Reaction operation type. /// ~end /// /// ~chinese - /// Reaction 操作 + /// Reaction 操作。 /// - /// Param [userId] 操作者。 + /// Param [userId] 操作者的用户 ID。 /// - /// Param [reaction] 发生变化的 reaction。 + /// Param [reaction] 发生变化的 Reaction。 /// - /// Param [operate] 具体操作类型。 + /// Param [operate] 具体 Reaction 操作类型。 /// ~end const ReactionOperation._private( this.userId, @@ -34,29 +34,29 @@ class ReactionOperation { ); /// ~english - /// Operator userId. + /// The user ID of the operator. /// ~end /// /// ~chinese - /// 操作者。 + /// 操作者的用户 ID。 /// ~end final String userId; /// ~english - /// Changed reaction. + /// Changed Reaction. /// ~end /// /// ~chinese - /// 发生变化的 reaction。 + /// 发生变化的 Reaction。 /// ~end final String reaction; /// ~english - /// Operate type. + /// The Reaction operation type. /// ~end /// /// ~chinese - /// 具体操作类型。 + /// Reaction 操作类型。 /// ~end final ReactionOperate operate; From 2c14ff32f65fb65471dbea5e92b22140f1f68eb9 Mon Sep 17 00:00:00 2001 From: dujiepeng <347302029@qq.com> Date: Thu, 10 Aug 2023 15:56:01 +0800 Subject: [PATCH 49/49] update --- example/lib/main.dart | 6 ++++++ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 4294b144..cdf5ef9b 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -232,6 +232,12 @@ class _MyHomePageState extends State { // 当前回调中不会有 CMD 类型消息,CMD 类型消息通过 [EMChatManagerEventHandle.onCmdMessagesReceived] 回调接收 } break; + case MessageType.COMBINE: + { + _addLogToConsole( + "receive combine message, from: ${msg.from}", + ); + } } } }, diff --git a/pubspec.yaml b/pubspec.yaml index be0d216c..dd746a6b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ version: 4.1.0 homepage: https://www.easemob.com/product/im environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.12.0 <4.0.0' flutter: ">=2.0.0" dependencies: