diff --git a/CHANGELOG.md b/CHANGELOG.md index eba048cb..b9f21e47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,23 @@ ## NEXT +## 3.9.0 + +- 增加单人推送免打扰接口; + +- 增加api referance; + +- 增加renewToken api; + +- 修改消息callback方式; + +- iOS移除自动绑定deviceToken,如需使用,需要在iOS端单独增加; + +- android移除多余权限; + +- 修改已知bug; + ## 3.8.9 + - 增加单聊消息免打扰; - 去除不必要的信息收集; - 修复安卓某些场景下数据库损坏导致崩溃; @@ -14,12 +31,30 @@ - 默认使用https; - 优化登录速度; +## 3.8.3+9 + +- 将设置推送相关操作从EMPushConfigs中移到EMPushManager中; + +## 3.8.3+8 + +- 修复ios使用token登录失败; +- 修改Login方法和Logout方法返回值; + ## 3.8.3+6 - 修改EMImPushConfig为EMPushConfigs; - 删除EMOptions中的EMPushConfig.设置推送证书时直接调用EMOptions即可; - EMGroup中移除ShareFiles,如果需要获取共享文件,请调用Api: - `EMClient.getInstance.groupManager.getGroupFileListFromServer(groupId)` + `EMClient.getInstance.groupManager.getGroupFileListFromServer(groupId)` +- 将isConnected和isLoginBefore、Token改为从原生获取; +- 修复安卓设置群组免打扰失效的问题; +- 修复获取公开群crash的问题; +- 修改throw error的逻辑; +- 修改构造文本消息时的方法,需要传入参数名; +- 修改部分原生方法逻辑; +- 调整项目目录结构; +- 将`onConversationRead`回调方法参数改为必选; +- ## 3.8.3+5 diff --git a/README.md b/README.md index 9edbfd73..9c97827d 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,7 @@ 源码地址: [Github](https://github.com/easemob/im_flutter_sdk) 任何问题可以通过 [Github Issues](https://github.com/easemob/im_flutter_sdk/issues) 提问 -Demo中使用的音视频是针对声网音视频封装的[EaseCallKit](https://github.com/easemob/ease_call_kit),如果问题,可以通过 [EaseCallKit Issues](https://github.com/easemob/ease_call_kit/issues) 提问 -[常见问题](https://github.com/easemob/im_flutter_sdk/blob/stable/docs/flutter_QA.md) - -**QQ群: 535134817** ## 前期准备 @@ -29,7 +25,7 @@ Demo中使用的音视频是针对声网音视频封装的[EaseCallKit](https:// ```dart dependencies: - im_flutter_sdk: ^3.8.3+5 + im_flutter_sdk: ^3.9.0 ``` 2. 执行`flutter pub get`; @@ -49,7 +45,7 @@ dependencies: im_flutter_sdk: git: url: https://github.com/easemob/im_flutter_sdk.git - ref: dev_3.9.0 + ref: flutter2_stable ``` 2. 执行`flutter pub get`; @@ -74,16 +70,7 @@ import 'package:im_flutter_sdk/im_flutter_sdk.dart' #### 初始化 ```dart -EMOptions options = EMOptions(appKey: 'easemob-demo#chatdemoui'); -EMPushConfig config = EMPushConfig(); -// 配置推送信息 -config - ..enableAPNs("chatdemoui_dev") - ..enableHWPush() - ..enableFCM('') - ..enableMeiZuPush('', '') - ..enableMiPush('', ''); -options.pushConfig = config; +var options = EMOptions(appKey: "easemob-demo#easeim"); await EMClient.getInstance.init(options); ``` @@ -96,7 +83,7 @@ await EMClient.getInstance.init(options); try { await EMClient.getInstance.createAccount(username, password); } on EMError catch (e) { - print('操作失败,原因是: $e'); + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -108,24 +95,23 @@ try { try { await EMClient.getInstance.login(username, password); } on EMError catch (e) { - print('操作失败,原因是: $e'); + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 获取当前登录环信id ```dart -EMClient.getInstance.currentUsername; +String? currentUsername = await EMClient.getInstance.getCurrentUsername(); ``` #### 退出 ```dart try { - // true: 是否解除deviceToken绑定。 await EMClient.getInstance.logout(true); } on EMError catch (e) { - print('操作失败,原因是: $e'); + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -135,33 +121,32 @@ try { #### 监听服务器连接状态 ```dart -class _MyAppState extends State implements EMConnectionListener{ - +class _PageState extends State implements EMConnectionListener { @override void initState() { super.initState(); - // 添加连接监听 EMClient.getInstance.addConnectionListener(this); } - ... - @override - void onConnected() { - // 网络已连接 + Widget build(BuildContext context) { + return Container(); } + @override + void onConnected() {} @override - void onDisconnected(int errorCode) { - // 连接失败,原因是[errorCode] - } + void onDisconnected(int? errorCode) {} - ... + @override + void onTokenDidExpire() {} + + @override + void onTokenWillExpire() {} @override void dispose() { - // 移除连接监听 EMClient.getInstance.removeConnectionListener(this); super.dispose(); } @@ -171,25 +156,17 @@ class _MyAppState extends State implements EMConnectionListener{ #### 获取当前连接状态 ```dart -EMClient.getInstance.connected; +bool isConnected = await EMClient.getInstance.isConnected(); ``` -#### 获取flutter sdk版本号 -```dart -EMClient.getInstance.flutterSDKVersion; -``` ### EMChatManager #### 获取会话列表 ```dart -try { - List conList = await EMClient.getInstance.chatManager.loadAllConversations(); -} on EMError catch (e) { - print('操作失败,原因是: $e'); -} +List conversations = await EMClient.getInstance.chatManager.loadAllConversations(); ``` > 会话列表是存在本地的一种消息管理对象,如果您会话中没有消息,则表示会话不存在。 @@ -197,12 +174,7 @@ try { #### 获取会话 ```dart -try { - // emId: 会话对应环信id, 如果是群组或者聊天室,则为群组id或者聊天室id - EMConversation conv = await EMClient.getInstance.chatManager.getConversation(emId); -} on EMError catch (e) { - print('操作失败,原因是: $e'); -} +EMConversation? conversation = await EMClient.getInstance.chatManager.getConversation(conversationId); ``` > 获取会话,如果会话目前不存在会创建。 @@ -210,69 +182,47 @@ try { #### 获取会话中的消息 ```dart -try { - List msgs = con.loadMessages(); -} on EMError catch (e) { - print('操作失败,原因是: $e'); -} +List? messages = await conversation.loadMessages(); ``` #### 获取会话中未读消息数 ```dart -con.unreadCount; +int unreadCount = await conversation.unreadCount(); ``` #### 设置单条消息为已读 ```dart -try { - con.markMessageAsRead(msg.msgId); -} on EMError catch (e) { - print('操作失败,原因是: $e'); -} +await conversation.markMessageAsRead(messageId); ``` #### 设置所有消息为已读 ```dart -try { - con.markAllMessagesAsRead(); -} on EMError catch (e) { - print('操作失败,原因是: $e'); -} +await conversation.markAllMessagesAsRead(); ``` #### 发送消息已读状态 ```dart try { - await EMClient.getInstance.chatManager.sendMessageReadAck(msg); + await EMClient.getInstance.chatManager.sendMessageReadAck(message); } on EMError catch (e) { - print('操作失败,原因是: $e'); + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 删除会话中的消息 ```dart -try{ - // 删除会话中所有消息 - await conv.deleteAllMessages(); -} on EMError catch (e) { - print('操作失败,原因是: $e'); -} +await conversation.deleteAllMessages(); ``` #### 插入消息 ```dart -try{ - // 向会话中插入一条消息 - await conv.insertMessage(msg); -} on EMError catch (e) { - print('操作失败,原因是: $e'); -} +await conversation.insertMessage(message); ``` > SDK在您发送和接收消息(_cmd类型消息除外_)后会自动将消息插入数据库中,并不需要您自己将消息插入数据库,但如果您需要自己插入一条消息时可以调用该api。 @@ -280,32 +230,19 @@ try{ #### 更新消息 ```dart -try{ - await conv.updateMessage(msg); -} on EMError catch (e) { - print('操作失败,原因是: $e'); -} +await conversation.updateMessage(message); ``` #### 删除消息 ```dart -try{ - // 删除会话中某一条消息 - await conv.deleteMessage(msg.msgId); -} on EMError catch (e) { - print('操作失败,原因是: $e'); -} +await conversation.deleteMessage(messageId); ``` #### 删除会话 ```dart -try { - await EMClient.getInstance.chatManager.deleteConversation(conversation.id); -} on EMError catch (e) { - print('操作失败,原因是: $e'); -} +await EMClient.getInstance.chatManager.deleteConversation(conversationId); ``` ​ @@ -341,84 +278,40 @@ EMMessage msg = EMMessage.createCustomSendMessage(username: '接收方id', event #### 发送消息 ```dart -try{ - await EMClient.getInstance.chatManager.sendMessage(msg); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatManager.sendMessage(message); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 监听消息发送状态 ```dart -class ChatItemState extends State implements EMMessageStatusListener { - - EMMessage msg; - ... - - void initState() { - super.initState(); - // 添加监听 - msg.setMessageListener(this); - } - - ... - - // 消息进度 - @override - void onProgress(int progress) { - } - - // 消息发送失败 - @override - void onError(EMError error) { - } - - // 消息发送成功 - @override - void onSuccess() { - } - - // 消息已读 - @override - void onReadAck() { - } - - // 消息已送达 - @override - void onDeliveryAck() { - } - - // 消息状态发生改变 - @override - void onStatusChanged() { - } - - dispose(){ - msg.setMessageListener(null); - super.dispose(); - } - -} +message.setMessageStatusCallBack(MessageStatusCallBack( + onError: (error) => {}, + onProgress: (progress) => {}, + onSuccess: () => {}, +)); ``` #### 重发消息 ```dart -try{ +try { await EMClient.getInstance.chatManager.resendMessage(message); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 撤回消息 ```dart -try{ - await EMClient.getInstance.chatManager.recallMessage(msg.msgId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatManager.recallMessage(messageId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -427,86 +320,69 @@ try{ #### 收消息监听 ```dart -class _ChatPageState extends State implements EMChatManagerListener { - +class _PageState extends State implements EMChatManagerListener { @override void initState() { super.initState(); - // 添加收消息监听 - EMClient.getInstance.chatManager.addListener(this); + EMClient.getInstance.chatManager.addChatManagerListener(this); } - - // 收到cmd消息回调 @override - onCmdMessagesReceived(List messages) { + Widget build(BuildContext context) { + return Container(); } - // 会话列表数量变更 @override - onConversationsUpdate() { + void dispose() { + EMClient.getInstance.chatManager.removeChatManagerListener(this); + super.dispose(); } - // 消息已送达回调 @override - onMessagesDelivered(List messages) { - } + void onCmdMessagesReceived(List messages) {} - // 消息已读回调 @override - onMessagesRead(List messages) { - } + void onConversationRead(String from, String to) {} - // 消息被撤回回调 @override - onMessagesRecalled(List messages) { - } + void onConversationsUpdate() {} - // 会话已读回执 @override - onConversationRead(String from, String to) { - } + void onGroupMessageRead(List groupMessageAcks) {} - // 收消息回调 @override - onMessagesReceived(List messages) { - } + void onMessagesDelivered(List messages) {} - // 群消息已读回执 @override - void onGroupMessageRead(List groupMessageAcks) { - } + void onMessagesRead(List messages) {} @override - void dispose() { - // 移除收消息监听 - EMClient.getInstance.chatManager.removeListener(this); - super.dispose(); - } + void onMessagesRecalled(List messages) {} + + @override + void onMessagesReceived(List messages) {} } ``` -#### 会话列表漫游 +#### 从服务器拉取会话列表 ```dart try { - List conversations = - await EMClient.getInstance.chatManager.getConversationsFromServer(); + List? conversations = await EMClient.getInstance.chatManager.getConversationsFromServer(); } on EMError catch (e) { - debugPrint("error: ${e.code}"); + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` > 会话列表漫游为增值服务,需要单独开通。 -#### 消息漫游 +#### 从服务器拉取消息 ```dart try { - EMCursorResult result = await EMClient.getInstance.chatManager - .fetchHistoryMessages(conversationId); + EMCursorResult result = await EMClient.getInstance.chatManager.fetchHistoryMessages(conversationId); } on EMError catch (e) { - debugPrint("error: ${e.code}"); + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -517,10 +393,11 @@ try { #### 从服务器获取通讯录中的用户列表 ```dart -try{ - List contactsList = await EMClient.getInstance.contactManager.getAllContactsFromServer(); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + List contacts = + await EMClient.getInstance.contactManager.getAllContactsFromServer(); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -529,10 +406,10 @@ try{ #### 发送添加申请 ```dart -try{ - await EMClient.getInstance.contactManager.addContact(friendEmId, '您好,我想添加您为好友'); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.contactManager.addContact(userId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -541,30 +418,30 @@ try{ #### 删除通讯录中的成员 ```dart -try{ - await EMClient.getInstance.contactManager.deleteContact(friendEmId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.contactManager.deleteContact(userId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 从服务器获取黑名单 ```dart -try{ - List blockList = await EMClient.getInstance.contactManager.getBlockListFromServer(); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + ListblockList = await EMClient.getInstance.contactManager.getBlockListFromServer(); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 添加用户到黑名单中 ```dart -try{ - await EMClient.getInstance.contactManager.addUserToBlockList(emId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.contactManager.addUserToBlockList(userId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -573,56 +450,57 @@ try{ #### 将用户从黑名单中删除 ```dart -try{ - await EMClient.getInstance.contactManager.removeUserFromBlockList(emId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.contactManager.removeUserFromBlockList(userId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 通讯录监听 ```dart -class _ContactPageState extends State implements EMContactEventListener { - +class _PageState extends State implements EMContactManagerListener { @override void initState() { super.initState(); - // 添加通讯录监听 EMClient.getInstance.contactManager.addContactListener(this); } + @override + Widget build(BuildContext context) { + return Container(); + } - // [userName]添加您为好友 @override - onContactAdded(String userName) { + void dispose() { + EMClient.getInstance.contactManager.removeContactListener(this); + super.dispose(); } - // [userName]将您从好友中删除 @override - onContactDeleted(String userName) { + void onContactAdded(String userName) { + } - // 收到[userName]的好友申请,原因是[reason] @override - onContactInvited(String userName, String reason) { + void onContactDeleted(String? userName) { + } - // 发出的好友申请被[userName]同意 @override - onFriendRequestAccepted(String userName) { + void onContactInvited(String userName, String? reason) { + } - // 发出的好友申请被[userName]拒绝 @override - onFriendRequestDeclined(String userName) { + void onFriendRequestAccepted(String userName) { + } @override - void dispose() { - // 移除通讯录监听 - EMClient.getInstance.contactManager.removeContactListener(this); - super.dispose(); + void onFriendRequestDeclined(String userName) { + } } ``` @@ -630,20 +508,20 @@ class _ContactPageState extends State implements EMContactEventList #### 同意添加申请 ```dart -try{ - await EMClient.getInstance.contactManager.acceptInvitation(emId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.contactManager.acceptInvitation(userId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 拒绝添加申请 ```dart -try{ - await EMClient.getInstance.contactManager.declineInvitation(emId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.contactManager.declineInvitation(userId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -652,40 +530,41 @@ try{ #### 从服务器获取已加入群组列表 ```dart -try{ - List groupsList = await EMClient.getInstance.groupManager.getJoinedGroupsFromServer(); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + List groups = await EMClient.getInstance.groupManager.fetchJoinedGroupsFromServer(); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 从缓存中获取已加入群组列表 ```dart -try{ - List groupsList = await EMClient.getInstance.groupManager.getJoinedGroups(); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + List groups = await EMClient.getInstance.groupManager.getJoinedGroups(); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 从服务器获取公开群组列表 ```dart -try{ - List groupsList = await EMClient.getInstance.groupManager.getPublicGroupsFromServer(); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + EMCursorResult groups = await EMClient.getInstance.groupManager.fetchPublicGroupsFromServer(); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 创建群组 ```dart -try{ - EMGroup group = await EMClient.getInstance.groupManager.createGroup('群组名称', settings: EMGroupOptions()); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + EMGroup group = await EMClient.getInstance.groupManager + .createGroup(options: EMGroupOptions(), groupName: groupName); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -698,30 +577,30 @@ try{ #### 获取群组详情 ```dart -try{ - EMGroup group = await EMClient.getInstance.groupManager.getGroupSpecificationFromServer(group.groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + EMGroup group = await EMClient.getInstance.groupManager.fetchGroupInfoFromServer(groupId) +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 获取群成员列表 ```dart -try{ - EMCursorResult result = await EMClient.getInstance.groupManager.getGroupMemberListFromServer(group.groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + EMCursorResult result = await EMClient.getInstance.groupManager.fetchMemberListFromServer(groupId) +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 加入公开群组 ```dart -try{ - await EMClient.getInstance.groupManager.joinPublicGroup(groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.joinPublicGroup(groupId) +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -730,10 +609,10 @@ try{ #### 申请加入公开群 ```dart -try{ +try { await EMClient.getInstance.groupManager.requestToJoinPublicGroup(groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -742,10 +621,10 @@ try{ #### 邀请用户入群 ```dart -try{ - await EMClient.getInstance.groupManager.inviterUser(groupId, inviteMembers); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.inviterUser(groupId, members); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -755,10 +634,10 @@ try{ > 被邀请方会收到邀请通知,同意后进群。邀请通知并不会以推送的形式发出,如果用户不在线,等上线后会收到,用户同意后入群。 ```dart -try{ - EMClient.getInstance.groupManager.addMembers(groupId, members); -} on EMError catch(e){ - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.addMembers(groupId, members); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -769,10 +648,10 @@ try{ #### 从群组中移除用户 ```dart -try{ +try { await EMClient.getInstance.groupManager.removeMembers(groupId, members); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -781,10 +660,10 @@ try{ #### 添加管理员 ```dart -try{ +try { await EMClient.getInstance.groupManager.addAdmin(groupId, memberId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -793,10 +672,10 @@ try{ #### 移除管理员 ```dart -try{ +try { await EMClient.getInstance.groupManager.removeAdmin(groupId, memberId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -805,20 +684,20 @@ try{ #### 退出群组 ```dart -try{ +try { await EMClient.getInstance.groupManager.leaveGroup(groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 解散群组 ```dart -try{ +try { await EMClient.getInstance.groupManager.destroyGroup(groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -827,10 +706,10 @@ try{ #### 转移群组 ```dart -try{ - await EMClient.getInstance.groupManager.changeGroupOwner(groupId, newOwner); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.changeOwner(groupId, newOwnerId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -839,20 +718,20 @@ try{ #### 获取群组黑名单列表 ```dart -try{ - List blockList = await EMClient.getInstance.groupManager.getGroupBlocklistFromServer(group.groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + List? blockList = await EMClient.getInstance.groupManager.fetchBlockListFromServer(groupId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 将群成员添加到群黑名单 ```dart -try{ - await EMClient.getInstance.groupManager.blockMembers(group.groupId, blockList); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.blockMembers(groupId, members); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -861,10 +740,10 @@ try{ #### 将用户从黑名单移除 ```dart -try{ - await EMClient.getInstance.groupManager.unblockMembers(group.groupId, unBlockList); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.unblockMembers(groupId, members); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -873,20 +752,21 @@ try{ #### 获取群禁言列表 ```dart -try{ - List mutesList = await EMClient.getInstance.groupManager.getGroupMuteListFromServer(group.groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + List? list = await EMClient.getInstance.groupManager + .fetchMuteListFromServer(groupId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 对成员禁言 ```dart -try{ - await EMClient.getInstance.groupManager.muteMembers(group.groupId, mutesList); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.muteMembers(groupId, members); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -895,10 +775,10 @@ try{ #### 对成员解除禁言 ```dart -try{ - await EMClient.getInstance.groupManager.unMuteMembers(group.groupId, unMutesList); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.unMuteMembers(groupId, members); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -907,10 +787,10 @@ try{ #### 对所有成员禁言 ```dart -try{ - await EMClient.getInstance.groupManager.muteAllMembers(group.groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.muteAllMembers(groupId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -919,10 +799,10 @@ try{ #### 对所有成员解除禁言 ```dart -try{ - await EMClient.getInstance.groupManager.unMuteAllMembers(group.groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.unMuteAllMembers(groupId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -931,20 +811,20 @@ try{ #### 获取白名单列表 ```dart -try{ - List whiteList = await EMClient.getInstance.groupManager.getGroupWhiteListFromServer(group.groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + List? list = await EMClient.getInstance.groupManager.fetchWhiteListFromServer(groupId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 将用户添加到白名单中 ```dart -try{ - await EMClient.getInstance.groupManager.addWhiteList(group.groupId, whiteList); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.addWhiteList(groupId, members); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -953,10 +833,10 @@ try{ #### 将用户从白名单中移除 ```dart -try{ - await EMClient.getInstance.groupManager.removeWhiteList(group.groupId, whiteList); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.removeWhiteList(groupId, members); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -965,20 +845,20 @@ try{ #### 判断自己是否在白名单中 ```dart -try{ - bool inWhiteList = await EMClient.getInstance.groupManager.isMemberInWhiteListFromServer(group.groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + bool inWhiteList = await EMClient.getInstance.groupManager.isMemberInWhiteListFromServer(groupId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 不接收群消息 ```dart -try{ - await EMClient.getInstance.groupManager.blockGroup(group.groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.blockGroup(groupId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -987,20 +867,21 @@ try{ #### 恢复接收群消息 ```dart -try{ - await EMClient.getInstance.groupManager.unblockGroup(group.groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.unblockGroup(groupId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 消息免打扰 ```dart -try{ - await EMClient.getInstance.groupManager.ignoreGroupPush(group.groupId, true); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.pushManager.updatePushServiceForGroup( + groupIds: groupIds, enablePush: false); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1009,10 +890,10 @@ try{ #### 更新群名称 ```dart -try{ - await EMClient.getInstance.groupManager.changeGroupName(group.groupId, newName); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.changeGroupName(groupId, newName); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1021,10 +902,10 @@ try{ #### 更新群描述 ```dart -try{ - await EMClient.getInstance.groupManager.changeGroupDescription(group.groupId, newDescription); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.changeGroupDescription(groupId, newDesc); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1033,20 +914,20 @@ try{ #### 获取群组公告 ```dart -try{ - String announcement = await EMClient.getInstance.groupManager.getGroupAnnouncementFromServer(group.groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + String? announcement =await EMClient.getInstance.groupManager.fetchAnnouncementFromServer(groupId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 更新群公告 ```dart -try{ - await EMClient.getInstance.groupManager.updateGroupAnnouncement(group.groupId, announcement); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.updateGroupAnnouncement(groupId, newAnnouncement); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1055,40 +936,40 @@ try{ #### 获取群共享文件列表 ```dart -try{ - List filesList = await EMClient.getInstance.groupManager.getGroupFileListFromServer(group.groupId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + List fileList =await EMClient.getInstance.groupManager.fetchGroupFileListFromServer(groupId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 上传群共享文件 ```dart -try{ - await EMClient.getInstance.groupManager.uploadGroupSharedFile(group.groupId, filePath); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.uploadGroupSharedFile(groupId, filePath); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 下载群共享文件 ```dart -try{ - await EMClient.getInstance.groupManager.uploadGroupSharedFile(group.groupId, groupSharedFile.fileId, savePath: path); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.downloadGroupSharedFile(groupId, filePath, savePath); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 删除群共享文件 ```dart -try{ - await EMClient.getInstance.groupManager.removeGroupSharedFile(group.groupId, groupSharedFile.fileId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.removeGroupSharedFile(groupId, fileId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1097,111 +978,110 @@ try{ #### 群回调监听 ```dart -class _GroupPageState extends State implements EMGroupEventListener { - +class _PageState extends State implements EMGroupEventListener { @override void initState() { super.initState(); - // 添加群组监听 EMClient.getInstance.groupManager.addGroupChangeListener(this); } - ... - - // id是[groupId], 名称是[groupName]的群邀请被[inviter]拒绝,理由是[reason] - void onInvitationReceived(String groupId, String groupName, String inviter, String reason) { + @override + Widget build(BuildContext context) { + return Container(); } - // 收到用户[applicant]申请加入id是[groupId], 名称是[groupName]的群,原因是[reason] - void onRequestToJoinReceived(String groupId, String groupName, String applicant, String reason) { + @override + void dispose() { + EMClient.getInstance.groupManager.removeGroupChangeListener(this); + super.dispose(); } - // 入群申请被同意 - void onRequestToJoinAccepted(String groupId, String groupName, String accepter) { - } + @override + void onAdminAddedFromGroup(String groupId, String admin) {} - // 入群申请被拒绝 - void onRequestToJoinDeclined(String groupId, String groupName, String decliner, String reason) { - } + @override + void onAdminRemovedFromGroup(String groupId, String admin) {} - // 入群邀请被同意 - void onInvitationAccepted(String groupId, String invitee, String reason) { - } + @override + void onAllGroupMemberMuteStateChanged(String groupId, bool isAllMuted) {} - // 入群邀请被拒绝 - void onInvitationDeclined(String groupId, String invitee, String reason) { - } + @override + void onAnnouncementChangedFromGroup(String groupId, String announcement) {} - // 被移出群组 - void onUserRemoved(String groupId, String groupName) { - } + @override + void onAutoAcceptInvitationFromGroup( + String groupId, String inviter, String? inviteMessage) {} - // 群组解散 - void onGroupDestroyed(String groupId, String groupName) { - } + @override + void onGroupDestroyed(String groupId, String? groupName) {} - // 自动同意加群 - void onAutoAcceptInvitationFromGroup(String groupId, String inviter, String inviteMessage) { - } + @override + void onInvitationAcceptedFromGroup( + String groupId, String invitee, String? reason) {} - // 群禁言列表增加 - void onMuteListAdded(String groupId, List mutes, int muteExpire) { - } + @override + void onInvitationDeclinedFromGroup( + String groupId, String invitee, String? reason) {} - // 群禁言列表减少 - void onMuteListRemoved(String groupId, List mutes) { - } + @override + void onInvitationReceivedFromGroup( + String groupId, String? groupName, String inviter, String? reason) {} - // 群管理增加 - void onAdminAdded(String groupId, String administrator) { - } + @override + void onMemberExitedFromGroup(String groupId, String member) {} - // 群管理被移除 - void onAdminRemoved(String groupId, String administrator) { - } + @override + void onMemberJoinedFromGroup(String groupId, String member) {} - // 群所有者变更 - void onOwnerChanged(String groupId, String newOwner, String oldOwner) { - } + @override + void onMuteListAddedFromGroup( + String groupId, List mutes, int? muteExpire) {} - // 有用户加入群 - void onMemberJoined(String groupId, String member) { - } + @override + void onMuteListRemovedFromGroup(String groupId, List mutes) {} - // 有用户离开群 - void onMemberExited(String groupId, String member) { - } + @override + void onOwnerChangedFromGroup( + String groupId, String newOwner, String oldOwner) {} - // 群公告变更 - void onAnnouncementChanged(String groupId, String announcement) { - } + @override + void onRequestToJoinAcceptedFromGroup( + String groupId, String? groupName, String accepter) {} - // 群共享文件增加 - void onSharedFileAdded(String groupId, EMGroupSharedFile sharedFile) { - } + @override + void onRequestToJoinDeclinedFromGroup( + String groupId, String? groupName, String decliner, String? reason) {} - // 群共享文件被删除 - void onSharedFileDeleted(String groupId, String fileId) { - } + @override + void onRequestToJoinReceivedFromGroup( + String groupId, String? groupName, String applicant, String? reason) {} - ... + @override + void onSharedFileAddedFromGroup( + String groupId, EMGroupSharedFile sharedFile) {} @override - void dispose() { - // 移除群组监听 - EMClient.getInstance.groupManager.removeGroupChangeListener(this); - super.dispose(); - } + void onSharedFileDeletedFromGroup(String groupId, String fileId) {} + + @override + void onUserRemovedFromGroup(String groupId, String? groupName) {} + + @override + void onWhiteListAddedFromGroup(String groupId, List members) {} + + @override + void onWhiteListRemovedFromGroup(String groupId, List members) {} } + ``` #### 同意加群申请 ```dart -try{ - await EMClient.getInstance.groupManager.acceptJoinApplication(group.groupId, username); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.acceptJoinApplication(groupId, userId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1210,10 +1090,10 @@ try{ #### 拒绝加群申请 ```dart -try{ - await EMClient.getInstance.groupManager.declineJoinApplication(group.groupId, username); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.declineJoinApplication(groupId, userId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1222,20 +1102,20 @@ try{ #### 同意加群邀请 ```dart -try{ - await EMClient.getInstance.groupManager.declineJoinApplication(group.groupId, inviter); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.acceptInvitation(groupId, userId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 拒绝加群邀请 ```dart -try{ - await EMClient.getInstance.groupManager.declineInvitationFromGroup(group.groupId, inviter); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.groupManager.declineInvitation(groupId, userId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1244,30 +1124,20 @@ try{ #### 从服务器获取聊天室列表 ```dart -try{ - EMPageResult result = await EMClient.getInstance.roomManager.fetchPublicChatRoomsFromServer(); -} on EMError catch(e) { - print('操作失败,原因是: $e'); -} -``` - -#### 获取本地缓存聊天室列表 - -```dart -try{ - List list = await EMClient.getInstance.roomManager.getAllChatRooms(); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + EMPageResult result = await EMClient.getInstance.chatRoomManager.fetchPublicChatRoomsFromServer(); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 创建聊天室 ```dart -try{ - EMChatRoom room = await EMClient.getInstance.roomManager.createChatRoom('聊天室名称'); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + EMChatRoom room = await EMClient.getInstance.chatRoomManager.createChatRoom(subject); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1276,30 +1146,30 @@ try{ #### 加入聊天室 ```dart -try{ - await EMClient.getInstance.roomManager.joinChatRoom(roomId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.joinChatRoom(roomId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 离开聊天室 ```dart -try{ - await EMClient.getInstance.roomManager.leaveChatRoom(roomId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.leaveChatRoom(roomId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 销毁聊天室 ```dart -try{ - await EMClient.getInstance.roomManager.destroyChatRoom(roomId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.destroyChatRoom(roomId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1308,10 +1178,10 @@ try{ #### 转移聊天室 ```dart -try{ - await EMClient.getInstance.roomManager.changeOwner(roomId, newOwner); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.changeOwner(roomId, newOwnerId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1320,20 +1190,20 @@ try{ #### 获取聊天室详情 ```dart -try{ - await EMClient.getInstance.roomManager.fetchChatRoomInfoFromServer(roomId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + EMChatRoom room =await EMClient.getInstance.chatRoomManager.fetchChatRoomInfoFromServer(roomId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 获取聊天室成员 ```dart -try{ - EMCursorResult result = await EMClient.getInstance.roomManager.fetchChatRoomMembers(roomId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + EMCursorResult result = await EMClient.getInstance.chatRoomManager.fetchChatRoomMembers(roomId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1352,10 +1222,10 @@ try{ #### 添加管理员 ```dart -try{ - await EMClient.getInstance.roomManager.addChatRoomAdmin(roomId, memberId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.addChatRoomAdmin(roomId, memberId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1364,10 +1234,10 @@ try{ #### 移除管理员 ```dart -try{ - await EMClient.getInstance.roomManager.removeChatRoomAdmin(roomId, adminId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.removeChatRoomAdmin(roomId, AdminId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1376,20 +1246,20 @@ try{ #### 获取禁言列表 ```dart -try{ - List mutesList = await EMClient.getInstance.roomManager.fetchChatRoomMuteList(roomId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + List? list =await EMClient.getInstance.chatRoomManager.fetchChatRoomMuteList(roomId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 设置禁言 ```dart -try{ - await EMClient.getInstance.roomManager.muteChatRoomMembers(roomId, membersList); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.muteChatRoomMembers(roomId, memberIds); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1398,10 +1268,10 @@ try{ #### 解除禁言 ```dart -try{ - await EMClient.getInstance.roomManager.unMuteChatRoomMembers(roomId, membersList); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.unMuteChatRoomMembers(roomId, memberIds); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1410,20 +1280,20 @@ try{ #### 获取黑名单列表 ```dart -try{ - List blockList = await EMClient.getInstance.roomManager.fetchChatRoomBlockList(roomId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + List? list = await EMClient.getInstance.chatRoomManager.fetchChatRoomBlockList(roomId); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 添加黑名单 ```dart -try{ - List blockList = await EMClient.getInstance.roomManager.blockChatRoomMembers(roomId, membersList); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.blockChatRoomMembers(roomId, memberIds); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1432,10 +1302,10 @@ try{ #### 移除黑名单 ```dart -try{ - List blockList = await EMClient.getInstance.roomManager.unBlockChatRoomMembers(roomId, membersList); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.unBlockChatRoomMembers(roomId, memberIds); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1444,10 +1314,10 @@ try{ #### 修改聊天室标题 ```dart -try{ - await EMClient.getInstance.roomManager.changeChatRoomSubject(roomId, subject); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.changeChatRoomSubject(roomId, newSubject); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1468,20 +1338,20 @@ try{ #### 获取聊天室公告 ```dart -try{ - String announcement = await EMClient.getInstance.roomManager.fetchChatRoomAnnouncement(roomId); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.changeChatRoomDescription(omId, newDesc); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 修改聊天室公告 ```dart -try{ - await EMClient.getInstance.roomManager.updateChatRoomAnnouncement(roomId, announcement); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.chatRoomManager.updateChatRoomAnnouncement(chatRoomId, newAnnouncement); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1490,62 +1360,68 @@ try{ #### 添加聊天室监听 ```dart -class _RoomPageState extends State implements EMChatRoomEventListener { - +class _PageState extends State implements EMChatRoomEventListener { @override void initState() { super.initState(); - // 添加聊天室监听 - EMClient.getInstance.roomManager.addChatRoomChangeListener(this); + EMClient.getInstance.chatRoomManager.addChatRoomChangeListener(this); } - /// id是[roomId],名称是[roomName]的聊天室被销毁 - void onChatRoomDestroyed(String roomId, String roomName) { + @override + Widget build(BuildContext context) { + return Container(); } - /// 有用户[participant]加入id是[roomId]的聊天室 - void onMemberJoined(String roomId, String participant) { + @override + void dispose() { + EMClient.getInstance.chatRoomManager.removeChatRoomListener(this); + super.dispose(); } - /// 有用户[participant]离开id是[roomId],名字是[roomName]的聊天室 - void onMemberExited(String roomId, String roomName, String participant) { - } + @override + void onAdminAddedFromChatRoom(String roomId, String admin) {} - /// 用用户[participant]被id是[roomId],名称[roomName]的聊天室删除,删除原因是[reason] - void onRemovedFromChatRoom(int reason, String roomId, String roomName, String participant) { - } + @override + void onAdminRemovedFromChatRoom(String roomId, String admin) {} - /// id是[roomId]的聊天室禁言列表[mutes]有增加 - void onMuteListAdded(String roomId, List mutes, String expireTime) { - } + @override + void onAllChatRoomMemberMuteStateChanged(String roomId, bool isAllMuted) {} - /// id是[roomId]的聊天室禁言列表[mutes]有减少 - void onMuteListRemoved(String roomId, List mutes) { - } + @override + void onAnnouncementChangedFromChatRoom(String roomId, String announcement) {} - /// id是[roomId]的聊天室增加id是[admin]管理员 - void onAdminAdded(String roomId, String admin) { - } + @override + void onChatRoomDestroyed(String roomId, String? roomName) {} - /// id是[roomId]的聊天室移除id是[admin]管理员 - void onAdminRemoved(String roomId, String admin) { - } + @override + void onMemberExitedFromChatRoom( + String roomId, String? roomName, String participant) {} - /// id是[roomId]的聊天室所有者由[oldOwner]变更为[newOwner] - void onOwnerChanged(String roomId, String newOwner, String oldOwner) { - } + @override + void onMemberJoinedFromChatRoom(String roomId, String participant) {} - /// id是[roomId]的聊天室公告变为[announcement] - void onAnnouncementChanged(String roomId, String announcement) { - } + @override + void onMuteListAddedFromChatRoom( + String roomId, List mutes, String? expireTime) {} - @override - void dispose() { - // 移除聊天室监听 - EMClient.getInstance.roomManager.removeChatRoomListener(this); - super.dispose(); - } + @override + void onMuteListRemovedFromChatRoom(String roomId, List mutes) {} + + @override + void onOwnerChangedFromChatRoom( + String roomId, String newOwner, String oldOwner) {} + + @override + void onRemovedFromChatRoom( + String roomId, String? roomName, String? participant) {} + + @override + void onWhiteListAddedFromChatRoom(String roomId, List members) {} + + @override + void onWhiteListRemovedFromChatRoom(String roomId, List members) {} } + ``` ### 推送 @@ -1553,10 +1429,10 @@ class _RoomPageState extends State implements EMChatRoomEventListener #### 设置推送昵称 ```dart -try{ - await EMClient.getInstance.pushManager.updatePushNickname(pushName); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.pushManager.updatePushNickname(pushDisplayName); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1565,44 +1441,40 @@ try{ #### 从服务器获取推送配置 ```dart -try{ - EMImPushConfig pushManager = await EMClient.getInstance.pushManager.getImPushConfigFromServer(); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + EMPushConfigs configs = await EMClient.getInstance.pushManager.fetchPushConfigsFromServer(); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 从本地缓存获取推送配置 ```dart -try{ - EMImPushConfig pushConfig = await EMClient.getInstance.pushManager.getImPushConfig(); -} on EMError catch(e) { - print('操作失败,原因是: $e'); -} +EMPushConfigs? configs = await EMClient.getInstance.pushManager.getPushConfigsFromCache(); ``` #### 设置推送显示样式 ```dart -try{ - await pushConfig.setPushStyle(EMImPushStyle.Simple); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.pushManager.updatePushDisplayStyle(DisplayStyle.Simple); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` -> `EMImPushStyle`是收推送时样式,目前有两种样式: +> `DisplayStyle`是收推送时样式,目前有两种样式: > `Simple`显示“您有一条新消息”; > `Summary`显示推送详情; #### 设置消息免打扰 ```dart -try{ - await pushConfig.setNoDisturb(true, 10, 22); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.pushManager.disableOfflinePush(start: 10, end: 22); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` @@ -1611,64 +1483,73 @@ try{ #### 关闭消息免打扰 ```dart -try{ - await pushConfig.setNoDisturb(false); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.pushManager.enableOfflinePush(); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 设置群组免打扰 ```dart -try{ - await pushConfig.setGroupToDisturb(groupId, true); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +try { + await EMClient.getInstance.pushManager.updatePushServiceForGroup(groupIds: groupIds, enablePush: false); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` #### 获取免打扰群组列表 ```dart -try{ - List groupIdsList = await pushConfig.noDisturbGroupsFromServer(); -} on EMError catch(e) { - print('操作失败,原因是: $e'); +List list = await EMClient.getInstance.pushManager.getNoPushGroupsFromCache(); +``` + +#### 设置用户免打扰 + +```dart +try { + await EMClient.getInstance.pushManager.updatePushServiceFroUsers(userIds: userIds, enablePush: false); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); } ``` +#### 获取免打扰用户列表 + +```dart +List list = await EMClient.getInstance.pushManager.getNoPushUsersFromCache(); +``` + + + + + ### EMUserInfoManager #### 更新自己的用户属性 ```dart - try { - EMUserInfo info = EMUserInfo(EMClient.getInstance.currentUsername); - info.copyWith( - sign: "修改签名", - nickName: "用户属性昵称", - mail: "xxx@easemob.com", - ); - await EMClient.getInstance.userInfoManager.updateOwnUserInfo(info); - } on EMError catch (e) { - print('操作失败,原因是: $e'); - } +String? currentUser = await EMClient.getInstance.getCurrentUsername(); +if (currentUser == null) { + return; +} +try { + EMUserInfo userInfo = EMUserInfo(currentUser); + userInfo = userInfo.copyWith(nickName: nickname, avatarUrl: avatarUrl); + await EMClient.getInstance.userInfoManager.updateOwnUserInfo(userInfo); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); +} ``` #### 获取多用户的用户属性 ```dart - try { - String userId = EMClient.getInstance.currentUsername; - List userIds =[]; - userIds.add(userId); - userIds.add('xxx'); - - Map userInfoMap = await EMClient.getInstance.userInfoManager - .fetchUserInfoByIdWithExpireTime(userIds, expireTime: 3600); - - } on EMError catch (e) { - print('操作失败,原因是: $e'); - } +try { + Map map = await EMClient.getInstance.userInfoManager.fetchUserInfoById(userIds); +} on EMError catch (e) { + debugPrint("error code: ${e.code}, desc: ${e.description}"); +} ``` diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 4ed69573..0d003bbe 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,18 +1,12 @@ - - - - - - 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 3a52ab81..809f1d45 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 @@ -560,13 +560,6 @@ public void onMessageRecalled(List messages) { post(() -> channel.invokeMethod(EMSDKMethod.onMessagesRecalled, msgList)); } - @Override - public void onMessageChanged(EMMessage message, Object change) { - Map data = new HashMap<>(); - data.put("message", EMMessageHelper.toJson(message)); - post(() -> channel.invokeMethod(EMSDKMethod.onMessageStatusChanged, data)); - } - @Override public void onGroupMessageRead(List var1) { ArrayList> msgList = new ArrayList<>(); 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 e45d0cfe..d8ffa869 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 @@ -145,10 +145,15 @@ public void onError(int code, String desc) { private void fetchChatRoomInfoFromServer(JSONObject param, String channelName, MethodChannel.Result result) throws JSONException { String roomId = param.getString("roomId"); - + boolean fetchMembers = param.getBoolean("fetchMembers"); asyncRunnable(() -> { + EMChatRoom room = null; try { - EMChatRoom room = EMClient.getInstance().chatroomManager().fetchChatRoomFromServer(roomId); + if (fetchMembers) { + room = EMClient.getInstance().chatroomManager().fetchChatRoomFromServer(roomId, true); + }else { + room = EMClient.getInstance().chatroomManager().fetchChatRoomFromServer(roomId); + } onSuccess(result, channelName, EMChatRoomHelper.toJson(room)); } catch (HyphenateException e) { onError(result, e); @@ -247,13 +252,17 @@ private void changeChatRoomDescription(JSONObject param, String channelName, Met private void fetchChatRoomMembers(JSONObject param, String channelName, MethodChannel.Result result) throws JSONException { String roomId = param.getString("roomId"); - String cursor = param.getString("cursor"); + String cursor = null; + if(param.has("cursor")) { + cursor = param.getString("cursor"); + } int pageSize = param.getInt("pageSize"); + String finalCursor = cursor; asyncRunnable(() -> { try { EMCursorResult cursorResult = EMClient.getInstance().chatroomManager() - .fetchChatRoomMembers(roomId, cursor, pageSize); + .fetchChatRoomMembers(roomId, finalCursor, pageSize); onSuccess(result, channelName, EMCursorResultHelper.toJson(cursorResult)); } catch (HyphenateException e) { onError(result, e); @@ -356,7 +365,7 @@ private void fetchChatRoomMuteList(JSONObject param, String channelName, MethodC asyncRunnable(() -> { try { Map map = EMClient.getInstance().chatroomManager().fetchChatRoomMuteList(roomId, pageNum, pageSize); - onSuccess(result, channelName, map); + onSuccess(result, channelName, map.keySet().toArray()); } catch (HyphenateException e) { onError(result, e); } 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 e70abf73..d0ed296a 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 @@ -71,10 +71,6 @@ else if (EMSDKMethod.changeAppKey.equals(call.method)) { changeAppKey(param, call.method, result); } - else if (EMSDKMethod.updateCurrentUserNick.equals(call.method)) - { - updateCurrentUserNick(param, call.method, result); - } else if (EMSDKMethod.uploadLog.equals(call.method)) { uploadLog(param, call.method, result); @@ -114,6 +110,9 @@ else if (EMSDKMethod.getToken.equals(call.method)) else if (EMSDKMethod.isConnected.equals(call.method)) { isConnected(param, call.method, result); } + else if (EMSDKMethod.renewToken.equals(call.method)){ + renewToken(param, call.method, result); + } else { super.onMethodCall(call, result); } @@ -215,19 +214,6 @@ private void isConnected(JSONObject param, String channelName, Result result) th onSuccess(result, channelName, EMClient.getInstance().isConnected()); } - private void updateCurrentUserNick(JSONObject param, String channelName, Result result) throws JSONException { - String nickName = param.getString("nickname"); - asyncRunnable(()->{ - try { - boolean status = EMClient.getInstance().pushManager().updatePushNickname(nickName); - onSuccess(result, channelName, status); - } catch (HyphenateException e) { - onError(result, e); - } - }); - } - - private void uploadLog(JSONObject param, String channelName, Result result) throws JSONException { EMClient.getInstance().uploadLog(new EMWrapperCallBack(result, channelName, true)); } @@ -278,6 +264,21 @@ private void onMultiDeviceEvent(JSONObject param, String channelName, Result res } + private void init(JSONObject param, String channelName, Result result) throws JSONException { + EMOptions options = EMOptionsHelper.fromJson(param, this.context); + EMClient.getInstance().init(this.context, options); + EMClient.getInstance().setDebugMode(param.getBoolean("debugModel")); + bindingManagers(); + addEMListener(); + 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); + } + private void getLoggedInDevicesFromServer(JSONObject param, String channelName, Result result) throws JSONException { String username = param.getString("username"); String password = param.getString("password"); @@ -304,14 +305,7 @@ private void bindingManagers() { new EMPushManagerWrapper(binging, "chat_push_manager"); new EMUserInfoManagerWrapper(binging, "chat_userInfo_manager"); } - private void init(JSONObject param, String channelName, Result result) throws JSONException { - EMOptions options = EMOptionsHelper.fromJson(param, this.context); - EMClient.getInstance().init(this.context, options); - EMClient.getInstance().setDebugMode(param.getBoolean("debugModel")); - bindingManagers(); - addEMListener(); - onSuccess(result, channelName, null); - } + private void addEMListener() { EMClient.getInstance().addMultiDeviceListener(new EMMultiDeviceListener() { 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 87f03645..2bf1a8fc 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 @@ -44,9 +44,6 @@ else if (EMSDKMethod.markMessageAsRead.equals(call.method)) { else if (EMSDKMethod.syncConversationExt.equals(call.method)){ syncConversationExt(param, call.method, result); } - else if (EMSDKMethod.syncConversationName.equals(call.method)){ - syncConversationName(param, call.method, result); - } else if (EMSDKMethod.removeMessage.equals(call.method)) { removeMessage(param, call.method, result); @@ -84,7 +81,6 @@ else if (EMSDKMethod.loadMsgWithMsgType.equals(call.method)) { else if (EMSDKMethod.loadMsgWithTime.equals(call.method)) { loadMsgWithTime(param, call.method, result); } - else { super.onMethodCall(call, result); @@ -121,22 +117,6 @@ private void markMessageAsRead(JSONObject params, String channelName, Result res }); } - private void syncConversationName(JSONObject params, String channelName, Result result) throws JSONException { - EMConversation conversation = conversationWithParam(params); - String conName = params.getString("con_name"); - String extField = conversation.getExtField(); - JSONObject jsonObject = new JSONObject(); - if(!extField.isEmpty()){ - jsonObject = new JSONObject(extField); - } - jsonObject.put("con_name", conName); - String jsonStr = jsonObject.toString(); - conversation.setExtField(jsonStr); - asyncRunnable(()->{ - onSuccess(result, channelName, true); - }); - } - private void syncConversationExt(JSONObject params, String channelName, Result result) throws JSONException { EMConversation conversation = conversationWithParam(params); JSONObject ext = params.getJSONObject("ext"); @@ -311,7 +291,6 @@ private void loadMsgWithTime(JSONObject params, String channelName, Result resul }); } - private EMConversation conversationWithParam(JSONObject params ) throws JSONException { String con_id = params.getString("con_id"); EMConversation.EMConversationType type = EMConversationHelper.typeFromInt(params.getInt("type")); 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 add90788..c5c4ac04 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 @@ -152,6 +152,7 @@ private void getGroupWithId(JSONObject param, String channelName, Result result) } 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) { @@ -170,8 +171,14 @@ private void getGroupsWithoutPushNotification(JSONObject param, String channelNa private void getJoinedGroupsFromServer(JSONObject param, String channelName, Result result) throws JSONException { - int pageSize = param.getInt("pageSize"); - int pageNum = param.getInt("pageNum"); + int pageSize = 0; + if (param.has("pageSize")){ + pageSize = param.getInt("pageSize"); + } + int pageNum = 0; + if (param.has("pageNum")){ + pageNum = param.getInt("pageNum"); + } EMValueWrapperCallBack> callBack = new EMValueWrapperCallBack>(result, channelName) { @@ -189,9 +196,14 @@ public void onSuccess(List object) { } private void getPublicGroupsFromServer(JSONObject param, String channelName, Result result) throws JSONException { - int pageSize = param.getInt("pageSize"); - String cursor = param.getString("cursor"); - + int pageSize = 0; + if (param.has("pageSize")){ + pageSize = param.getInt("pageSize"); + } + String cursor = null; + if (param.has("cursor")){ + cursor = param.getString("cursor"); + } EMValueWrapperCallBack> callBack = new EMValueWrapperCallBack>( result, channelName) { @Override @@ -204,14 +216,34 @@ public void onSuccess(EMCursorResult object) { } private void createGroup(JSONObject param, String channelName, Result result) throws JSONException { - String groupName = param.getString("groupName"); - String desc = param.getString("desc"); - JSONArray inviteMembers = param.getJSONArray("inviteMembers"); - String[] members = new String[inviteMembers.length()]; - for (int i = 0; i < inviteMembers.length(); i++) { - members[i] = inviteMembers.getString(i); - } - String inviteReason = param.getString("inviteReason"); + String groupName = null; + + if (param.has("groupName")){ + groupName = param.getString("groupName"); + } + + String desc = null; + if(param.has("desc")){ + desc = param.getString("desc"); + } + + String[] members = null; + if(param.has("inviteMembers")){ + JSONArray inviteMembers = param.getJSONArray("inviteMembers"); + members = new String[inviteMembers.length()]; + for (int i = 0; i < inviteMembers.length(); i++) { + members[i] = inviteMembers.getString(i); + } + } + if (members == null) { + members = new String[0]; + } + String inviteReason = null; + + if (param.has("inviteReason")){ + inviteReason = param.getString("inviteReason"); + } + EMGroupOptions options = EMGroupOptionsHelper.fromJson(param.getJSONObject("options")); EMValueWrapperCallBack callBack = new EMValueWrapperCallBack(result, channelName) { @@ -242,7 +274,10 @@ public void onSuccess(EMGroup object) { private void getGroupMemberListFromServer(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String cursor = param.getString("cursor"); + String cursor = null; + if(param.has("cursor")){ + cursor = param.getString("cursor"); + } int pageSize = param.getInt("pageSize"); EMValueWrapperCallBack> callBack = new EMValueWrapperCallBack>( @@ -259,8 +294,14 @@ public void onSuccess(EMCursorResult object) { private void getGroupBlockListFromServer(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - int pageNum = param.getInt("pageNum"); - int pageSize = param.getInt("pageSize"); + int pageSize = 0; + if (param.has("pageSize")){ + pageSize = param.getInt("pageSize"); + } + int pageNum = 0; + if (param.has("pageNum")){ + pageNum = param.getInt("pageNum"); + } EMClient.getInstance().groupManager().asyncGetBlockedUsers(groupId, pageNum, pageSize, new EMValueWrapperCallBack>(result, channelName)); @@ -268,8 +309,15 @@ private void getGroupBlockListFromServer(JSONObject param, String channelName, R private void getGroupMuteListFromServer(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - int pageNum = param.getInt("pageNum"); - int pageSize = param.getInt("pageSize"); + int pageSize = 0; + if (param.has("pageSize")){ + pageSize = param.getInt("pageSize"); + } + int pageNum = 0; + if (param.has("pageNum")){ + pageNum = param.getInt("pageNum"); + } + EMValueWrapperCallBack> callBack = new EMValueWrapperCallBack>(result, channelName) { @@ -297,8 +345,14 @@ private void isMemberInWhiteListFromServer(JSONObject param, String channelName, private void getGroupFileListFromServer(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - int pageNum = param.getInt("pageNum"); - int pageSize = param.getInt("pageSize"); + int pageNum = 0; + if (param.has("pageNum")){ + pageNum = param.getInt("pageNum"); + } + int pageSize = 0; + if (param.has("pageSize")) { + pageSize = param.getInt("pageSize"); + } EMValueWrapperCallBack> callBack = new EMValueWrapperCallBack>( result, channelName) { @@ -328,37 +382,60 @@ private void inviterUser(JSONObject param, String channelName, Result result) th if (param.has("reason")) { reason = param.getString("reason"); } - JSONArray array = param.getJSONArray("members"); - String[] members = new String[array.length()]; - for (int i = 0; i < array.length(); i++) { - members[i] = array.getString(i); + String[] members = null; + if (param.has("members")){ + JSONArray array = param.getJSONArray("members"); + members = new String[array.length()]; + for (int i = 0; i < array.length(); i++) { + members[i] = array.getString(i); + } + } + if (members == null) { + members = new String[0]; } - EMClient.getInstance().groupManager().asyncInviteUser(groupId, members, reason, new EMWrapperCallBack(result, channelName, true)); } private void addMembers(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - JSONArray array = param.getJSONArray("members"); - String[] members = new String[array.length()]; - for (int i = 0; i < array.length(); i++) { - members[i] = array.getString(i); + String[] members = null; + if (param.has("members")){ + JSONArray array = param.getJSONArray("members"); + members = new String[array.length()]; + for (int i = 0; i < array.length(); i++) { + members[i] = array.getString(i); + } + } + if (members == null) { + members = new String[0]; } - - EMClient.getInstance().groupManager().asyncAddUsersToGroup(groupId, members, - new EMWrapperCallBack(result, channelName, true)); + String welcome = null; + if (param.has("welcome")){ + welcome = param.getString("welcome"); + } + String finalWelcome = welcome; + String[] finalMembers = members; + asyncRunnable(() -> { + try { + EMClient.getInstance().groupManager().addUsersToGroup(groupId, finalMembers, finalWelcome); + onSuccess(result, channelName, true); + } catch (HyphenateException e) { + onError(result, e); + } + }); } private void removeMembers(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - JSONArray array = param.getJSONArray("members"); - List members = new ArrayList<>(); - for (int i = 0; i < array.length(); i++) { - members.add(array.getString(i)); + if (param.has("members")){ + JSONArray array = param.getJSONArray("members"); + for (int i = 0; i < array.length(); i++) { + members.add(array.getString(i)); + } } EMClient.getInstance().groupManager().asyncRemoveUsersFromGroup(groupId, members, @@ -367,10 +444,12 @@ private void removeMembers(JSONObject param, String channelName, Result result) private void blockMembers(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - JSONArray array = param.getJSONArray("members"); List members = new ArrayList<>(); - for (int i = 0; i < array.length(); i++) { - members.add(array.getString(i)); + if (param.has("members")){ + JSONArray array = param.getJSONArray("members"); + for (int i = 0; i < array.length(); i++) { + members.add(array.getString(i)); + } } EMClient.getInstance().groupManager().asyncBlockUsers(groupId, members, @@ -379,10 +458,12 @@ private void blockMembers(JSONObject param, String channelName, Result result) t private void unblockMembers(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - JSONArray array = param.getJSONArray("members"); List members = new ArrayList<>(); - for (int i = 0; i < array.length(); i++) { - members.add(array.getString(i)); + if (param.has("members")){ + JSONArray array = param.getJSONArray("members"); + for (int i = 0; i < array.length(); i++) { + members.add(array.getString(i)); + } } EMClient.getInstance().groupManager().asyncUnblockUsers(groupId, members, @@ -391,7 +472,11 @@ private void unblockMembers(JSONObject param, String channelName, Result result) private void updateGroupSubject(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String name = param.getString("name"); + + String name = ""; + if (param.has("name")){ + name = param.getString("name"); + } EMWrapperCallBack callBack = new EMWrapperCallBack(result, channelName, null) { @Override @@ -408,7 +493,10 @@ public void onSuccess() { private void updateDescription(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String desc = param.getString("desc"); + String desc = ""; + if (param.has("desc")){ + desc = param.getString("desc"); + } EMWrapperCallBack callBack = new EMWrapperCallBack(result, channelName, null) { @Override @@ -508,13 +596,18 @@ public void onSuccess(EMGroup object) { private void muteMembers(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - int duration = param.getInt("duration"); - JSONArray array = param.getJSONArray("members"); + + int duration = 0; + if (param.has("duration")){ + duration = param.getInt("duration"); + } List members = new ArrayList<>(); - for (int i = 0; i < array.length(); i++) { - members.add(array.getString(i)); + if (param.has("members")){ + JSONArray array = param.getJSONArray("members"); + for (int i = 0; i < array.length(); i++) { + members.add(array.getString(i)); + } } - EMValueWrapperCallBack callBack = new EMValueWrapperCallBack(result, channelName) { @Override public void onSuccess(EMGroup object) { @@ -527,12 +620,13 @@ public void onSuccess(EMGroup object) { private void unMuteMembers(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - JSONArray array = param.getJSONArray("members"); List members = new ArrayList<>(); - for (int i = 0; i < array.length(); i++) { - members.add(array.getString(i)); + if (param.has("members")){ + JSONArray array = param.getJSONArray("members"); + for (int i = 0; i < array.length(); i++) { + members.add(array.getString(i)); + } } - EMValueWrapperCallBack callBack = new EMValueWrapperCallBack(result, channelName) { @Override public void onSuccess(EMGroup object) { @@ -571,31 +665,36 @@ public void onSuccess(EMGroup object) { private void addWhiteList(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - JSONArray array = param.getJSONArray("members"); List members = new ArrayList<>(); - for (int i = 0; i < array.length(); i++) { - members.add(array.getString(i)); + if (param.has("members")){ + JSONArray array = param.getJSONArray("members"); + for (int i = 0; i < array.length(); i++) { + members.add(array.getString(i)); + } } - EMClient.getInstance().groupManager().addToGroupWhiteList(groupId, members, new EMWrapperCallBack(result, channelName, true)); } private void removeWhiteList(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - JSONArray array = param.getJSONArray("members"); List members = new ArrayList<>(); - for (int i = 0; i < array.length(); i++) { - members.add(array.getString(i)); + if (param.has("members")){ + JSONArray array = param.getJSONArray("members"); + for (int i = 0; i < array.length(); i++) { + members.add(array.getString(i)); + } } - EMClient.getInstance().groupManager().removeFromGroupWhiteList(groupId, members, new EMWrapperCallBack(result, channelName, true)); } private void uploadGroupSharedFile(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String filePath = param.getString("filePath"); + String filePath = null; + if (param.has("filePath")){ + filePath = param.getString("filePath"); + } EMClient.getInstance().groupManager().asyncUploadGroupSharedFile(groupId, filePath, new EMWrapperCallBack(result, channelName, true)); @@ -603,8 +702,14 @@ private void uploadGroupSharedFile(JSONObject param, String channelName, Result private void downloadGroupSharedFile(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String fileId = param.getString("fileId"); - String savePath = param.getString("savePath"); + String fileId = null; + if (param.has("fileId")) { + fileId = param.getString("fileId"); + } + String savePath = null; + if (param.has("savePath")) { + savePath = param.getString("savePath"); + } EMClient.getInstance().groupManager().asyncDownloadGroupSharedFile(groupId, fileId, savePath, new EMWrapperCallBack(result, channelName, true)); @@ -612,15 +717,20 @@ private void downloadGroupSharedFile(JSONObject param, String channelName, Resul private void removeGroupSharedFile(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String fileId = param.getString("fileId"); + String fileId = null; + if (param.has("fileId")) { + fileId = param.getString("fileId"); + } EMClient.getInstance().groupManager().asyncDeleteGroupSharedFile(groupId, fileId, new EMWrapperCallBack(result, channelName, true)); } private void updateGroupAnnouncement(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String announcement = param.getString("announcement"); - + String announcement = null; + if (param.has("announcement")) { + announcement = param.getString("announcement"); + } EMWrapperCallBack callBack = new EMWrapperCallBack(result, channelName, null) { @Override public void onSuccess() { @@ -635,11 +745,15 @@ public void onSuccess() { private void updateGroupExt(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String ext = param.getString("ext"); + String ext = null; + if (param.has("ext")) { + ext = param.getString("ext"); + } + String finalExt = ext; asyncRunnable(() -> { try { - EMGroup group = EMClient.getInstance().groupManager().updateGroupExtension(groupId, ext); + EMGroup group = EMClient.getInstance().groupManager().updateGroupExtension(groupId, finalExt); onSuccess(result, channelName, EMGroupHelper.toJson(group)); } catch (HyphenateException e) { onError(result, e); @@ -648,23 +762,29 @@ private void updateGroupExt(JSONObject param, String channelName, Result result) } private void joinPublicGroup(JSONObject param, String channelName, Result result) throws JSONException { - String groupId = param.getString("groupId"); - EMWrapperCallBack callBack = new EMWrapperCallBack(result, channelName, null) { - @Override - public void onSuccess() { - EMGroup group = EMClient.getInstance().groupManager().getGroup(groupId); - super.object = EMGroupHelper.toJson(group); - super.onSuccess(); + String groupId = param.getString("groupId"); + asyncRunnable(()->{ + try{ + EMGroup group = EMClient.getInstance().groupManager().getGroupFromServer(groupId); + if (group.isMemberOnly()){ + throw new HyphenateException(603,"User has no permission for this operation"); + } + EMClient.getInstance().groupManager().joinGroup(groupId); + EMGroup joinedGroup = EMClient.getInstance().groupManager().getGroup(groupId); + onSuccess(result, channelName, EMGroupHelper.toJson(joinedGroup)); + }catch (HyphenateException e){ + onError(result, e); } - }; - - EMClient.getInstance().groupManager().asyncJoinGroup(groupId, callBack); + }); } private void requestToJoinPublicGroup(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - + String reason = null; + if (param.has("reason")){ + reason = param.getString("reason"); + } EMWrapperCallBack callBack = new EMWrapperCallBack(result, channelName, null) { @Override public void onSuccess() { @@ -674,12 +794,16 @@ public void onSuccess() { } }; - EMClient.getInstance().groupManager().asyncJoinGroup(groupId, callBack); + EMClient.getInstance().groupManager().asyncApplyJoinToGroup(groupId, reason, callBack); } private void acceptJoinApplication(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String username = param.getString("username"); + + String username = null; + if (param.has("username")){ + username = param.getString("username"); + } EMWrapperCallBack callBack = new EMWrapperCallBack(result, channelName, null) { @Override @@ -695,8 +819,14 @@ public void onSuccess() { private void declineJoinApplication(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String username = param.getString("username"); - String reason = param.getString("reason"); + String username = null; + if (param.has("username")){ + username = param.getString("username"); + } + String reason = null; + if (param.has("reason")){ + reason = param.getString("reason"); + } EMWrapperCallBack callBack = new EMWrapperCallBack(result, channelName, null) { @Override @@ -712,8 +842,11 @@ public void onSuccess() { private void acceptInvitationFromGroup(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String inviter = param.getString("inviter"); + String inviter = null; + if (param.has("inviter")){ + inviter = param.getString("inviter"); + } EMValueWrapperCallBack callBack = new EMValueWrapperCallBack(result, channelName) { @Override public void onSuccess(EMGroup object) { @@ -726,8 +859,14 @@ public void onSuccess(EMGroup object) { private void declineInvitationFromGroup(JSONObject param, String channelName, Result result) throws JSONException { String groupId = param.getString("groupId"); - String username = param.getString("username"); - String reason = param.getString("reason"); + String username = null; + if (param.has("username")){ + username = param.getString("username"); + } + String reason = null; + if (param.has("reason")){ + reason = param.getString("reason"); + } EMWrapperCallBack callBack = new EMWrapperCallBack(result, channelName, null) { @Override 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 c8c89a8a..2a7e78a8 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 @@ -57,12 +57,9 @@ static EMOptions fromJson(JSONObject json, Context context) throws JSONException options.setDeleteMessagesAsExitGroup(json.getBoolean("deleteMessagesAsExitGroup")); options.setDeleteMessagesAsExitChatRoom(json.getBoolean("deleteMessagesAsExitChatRoom")); options.setAutoDownloadThumbnail(json.getBoolean("isAutoDownload")); - // options.setAutoLogin(json.getBoolean("")); isChatRoomOwnerLeaveAllowed - // options.setAutoLogin(json.getBoolean("")); debugModel - // options.setAutoLogin(json.getBoolean("")); serverTransfer + options.allowChatroomOwnerLeave(json.getBoolean("isChatRoomOwnerLeaveAllowed")); + options.setAutoTransferMessageAttachments(json.getBoolean("serverTransfer")); options.setUsingHttpsOnly(json.getBoolean("usingHttpsOnly")); - // options.setAutoLogin(json.getBoolean("")); EMPushConfig - // options.setAutoLogin(json.getBoolean("")); enableDNSConfig options.enableDNSConfig(json.getBoolean("enableDNSConfig")); if (!json.getBoolean("enableDNSConfig")) { options.setImPort(json.getInt("imPort")); @@ -99,6 +96,7 @@ static EMOptions fromJson(JSONObject json, Context context) throws JSONException } + /* static Map toJson(EMOptions options) { Map data = new HashMap<>(); data.put("appKey", options.getAppKey()); @@ -125,6 +123,7 @@ static Map toJson(EMOptions options) { return data; } + */ } class EMGroupHelper { @@ -140,11 +139,6 @@ static Map toJson(EMGroup group) { data.put("adminList", group.getAdminList()); data.put("blockList", group.getBlackList()); data.put("muteList", group.getMuteList()); - - if (group.getGroupId() != null && EMClient.getInstance().pushManager().getNoPushGroups() != null) { - data.put("noticeEnable", - !EMClient.getInstance().pushManager().getNoPushGroups().contains(group.getGroupId())); - } data.put("messageBlocked", group.isMsgBlocked()); data.put("isAllMemberMuted", group.isAllMemberMuted()); data.put("permissionType", intTypeFromGroupPermissionType(group.getGroupPermissionType())); @@ -222,7 +216,9 @@ static EMGroupOptions fromJson(JSONObject json) throws JSONException { EMGroupOptions options = new EMGroupOptions(); options.maxUsers = json.getInt("maxCount"); options.inviteNeedConfirm = json.getBoolean("inviteNeedConfirm"); - options.extField = json.getString("ext"); + if (json.has("ext")){ + options.extField = json.getString("ext"); + } options.style = styleFromInt(json.getInt("style")); return options; } @@ -413,11 +409,11 @@ static EMMessage fromJson(JSONObject json) throws JSONException { } } - if (!json.isNull("to")) { + if (json.has("to")) { message.setTo(json.getString("to")); } - if (!json.isNull("from")) { + if (json.has("from")) { message.setFrom(json.getString("from")); } @@ -432,11 +428,17 @@ static EMMessage fromJson(JSONObject json) throws JSONException { } message.setLocalTime(json.getLong("localTime")); - message.setMsgTime(json.getLong("serverTime")); + if (json.has("serverTime")){ + message.setMsgTime(json.getLong("serverTime")); + } + message.setStatus(statusFromInt(json.getInt("status"))); message.setChatType(chatTypeFromInt(json.getInt("chatType"))); - message.setMsgId(json.getString("msgId")); - if (null != json.getJSONObject("attributes")) { + if (json.has("msgId")){ + message.setMsgId(json.getString("msgId")); + } + + if(json.has("attributes")){ JSONObject data = json.getJSONObject("attributes"); Iterator iterator = data.keys(); while (iterator.hasNext()) { @@ -587,6 +589,7 @@ class EMGroupAckHelper { static MaptoJson(EMGroupReadAck ack) { Map data = new HashMap<>(); data.put("msg_id", ack.getMsgId()); + data.put("ack_id", ack.getAckId()); data.put("from", ack.getFrom()); data.put("count", ack.getCount()); data.put("timestamp", ack.getTimestamp()); @@ -616,9 +619,18 @@ static Map textBodyToJson(EMTextMessageBody body) { static EMLocationMessageBody localBodyFromJson(JSONObject json) throws JSONException { double latitude = json.getDouble("latitude"); double longitude = json.getDouble("longitude"); - String address = json.getString("address"); + String address = null; + String buildingName = null; + if (json.has("address")){ + address = json.getString("address"); + } + + if (json.has("buildingName")){ + buildingName = json.getString("buildingName"); + } + + EMLocationMessageBody body = new EMLocationMessageBody(address, latitude, longitude, buildingName); - EMLocationMessageBody body = new EMLocationMessageBody(address, latitude, longitude); return body; } @@ -626,6 +638,7 @@ static Map localBodyToJson(EMLocationMessageBody body) { Map data = new HashMap<>(); data.put("latitude", body.getLatitude()); data.put("longitude", body.getLongitude()); + data.put("buildingName", body.getBuildingName()); data.put("address", body.getAddress()); data.put("type", "loc"); return data; @@ -679,11 +692,20 @@ static EMFileMessageBody fileBodyFromJson(JSONObject json) throws JSONException File file = new File(localPath); EMNormalFileMessageBody body = new EMNormalFileMessageBody(file); - body.setFileName(json.getString("displayName")); - body.setRemoteUrl(json.getString("remotePath")); - body.setSecret(json.getString("secret")); + if (json.has("displayName")){ + body.setFileName(json.getString("displayName")); + } + if (json.has("remotePath")){ + body.setRemoteUrl(json.getString("remotePath")); + } + if (json.has("secret")){ + body.setSecret(json.getString("secret")); + } body.setDownloadStatus(downloadStatusFromInt(json.getInt("fileStatus"))); - body.setFileLength(json.getInt("fileSize")); + if (json.has("fileSize")){ + body.setFileLength(json.getInt("fileSize")); + } + return body; } @@ -694,7 +716,6 @@ static Map fileBodyToJson(EMNormalFileMessageBody body) { data.put("displayName", body.getFileName()); data.put("remotePath", body.getRemoteUrl()); data.put("secret", body.getSecret()); - data.put("fileSize", body.getFileSize()); data.put("fileStatus", downloadStatusToInt(body.downloadStatus())); data.put("type", "file"); return data; @@ -705,20 +726,39 @@ static EMImageMessageBody imageBodyFromJson(JSONObject json) throws JSONExceptio File file = new File(localPath); EMImageMessageBody body = new EMImageMessageBody(file); - body.setFileName(json.getString("displayName")); - body.setRemoteUrl(json.getString("remotePath")); - body.setSecret(json.getString("secret")); - body.setDownloadStatus(downloadStatusFromInt(json.getInt("fileStatus"))); - if (json.getString("thumbnailLocalPath") != null) { + if (json.has("displayName")){ + body.setFileName(json.getString("displayName")); + } + if (json.has("remotePath")){ + body.setRemoteUrl(json.getString("remotePath")); + } + if (json.has("secret")){ + body.setSecret(json.getString("secret")); + } + if (json.has("thumbnailLocalPath")) { body.setThumbnailLocalPath(json.getString("thumbnailLocalPath")); } - body.setThumbnailUrl(json.getString("thumbnailRemotePath")); - body.setThumbnailSecret(json.getString("thumbnailSecret")); - body.setFileLength(json.getInt("fileSize")); - int width = json.getInt("height"); - int height = json.getInt("width"); - body.setThumbnailSize(width, height); - body.setSendOriginalImage(json.getBoolean("sendOriginalImage")); + if (json.has("thumbnailRemotePath")){ + body.setThumbnailUrl(json.getString("thumbnailRemotePath")); + } + if (json.has("thumbnailSecret")){ + body.setThumbnailSecret(json.getString("thumbnailSecret")); + } + if (json.has("fileSize")){ + body.setFileLength(json.getInt("fileSize")); + } + if (json.has("width") && json.has("height")){ + int width = json.getInt("width"); + int height = json.getInt("height"); + body.setThumbnailSize(width, height); + } + if (json.has("sendOriginalImage")){ + body.setSendOriginalImage(json.getBoolean("sendOriginalImage")); + } + + if (json.has("fileStatus")){ + body.setDownloadStatus(downloadStatusFromInt(json.getInt("fileStatus"))); + } return body; } @@ -743,23 +783,42 @@ static Map imageBodyToJson(EMImageMessageBody body) { static EMVideoMessageBody videoBodyFromJson(JSONObject json) throws JSONException { String localPath = json.getString("localPath"); - String thumbnailLocalPath = json.getString("thumbnailLocalPath"); int duration = json.getInt("duration"); - int fileSize = json.getInt("fileSize"); - EMVideoMessageBody body = new EMVideoMessageBody(localPath, thumbnailLocalPath, duration, fileSize); - body.setThumbnailUrl(json.getString("thumbnailRemotePath")); + EMVideoMessageBody body = new EMVideoMessageBody(localPath, null, duration, 0); + + if (json.has("thumbnailRemotePath")){ + body.setThumbnailUrl(json.getString("thumbnailRemotePath")); + } if (json.getString("thumbnailLocalPath") != null) { body.setLocalThumb(json.getString("thumbnailLocalPath")); } - body.setThumbnailSecret(json.getString("thumbnailSecret")); - body.setFileName(json.getString("displayName")); - int width = json.getInt("height"); - int height = json.getInt("width"); - body.setThumbnailSize(width, height); - body.setRemoteUrl(json.getString("remotePath")); - body.setDownloadStatus(downloadStatusFromInt(json.getInt("fileStatus"))); - body.setSecret(json.getString("secret")); - body.setFileLength(json.getInt("fileSize")); + if (json.has("thumbnailSecret")){ + body.setThumbnailSecret(json.getString("thumbnailSecret")); + } + if (json.has("displayName")){ + body.setFileName(json.getString("displayName")); + } + if (json.has("remotePath")){ + body.setRemoteUrl(json.getString("remotePath")); + } + if (json.has("secret")){ + body.setSecret(json.getString("secret")); + } + if (json.has("fileSize")){ + body.setVideoFileLength(json.getInt("fileSize")); + } + + if(json.has("fileStatus")){ + body.setDownloadStatus(downloadStatusFromInt(json.getInt("fileStatus"))); + } + + if (json.has("width") && json.has("height")){ + int width = json.getInt("width"); + int height = json.getInt("height"); + body.setThumbnailSize(width, height); + } + + return body; } @@ -768,7 +827,6 @@ static Map videoBodyToJson(EMVideoMessageBody body) { data.put("localPath", body.getLocalUrl()); data.put("thumbnailLocalPath", body.getLocalThumbUri()); data.put("duration", body.getDuration()); - data.put("fileSize", body.getVideoFileLength()); data.put("thumbnailRemotePath", body.getThumbnailUrl()); data.put("thumbnailSecret", body.getThumbnailSecret()); data.put("displayName", body.getFileName()); @@ -789,10 +847,19 @@ static EMVoiceMessageBody voiceBodyFromJson(JSONObject json) throws JSONExceptio int duration = json.getInt("duration"); EMVoiceMessageBody body = new EMVoiceMessageBody(file, duration); body.setDownloadStatus(downloadStatusFromInt(json.getInt("fileStatus"))); - body.setFileName(json.getString("displayName")); - body.setFileLength(json.getLong("fileSize")); - body.setSecret(json.getString("secret")); - body.setFileLength(json.getInt("fileSize")); + if (json.has("displayName")){ + body.setFileName(json.getString("displayName")); + } + if (json.has("secret")){ + body.setSecret(json.getString("secret")); + } + if (json.has("remotePath")){ + body.setRemoteUrl(json.getString("remotePath")); + } + if (json.has("fileSize")){ + body.setFileLength(json.getLong("fileSize")); + } + return body; } @@ -1039,19 +1106,34 @@ static Map toJson(HyphenateException e) { class EMUserInfoHelper { static EMUserInfo fromJson(JSONObject obj) throws JSONException { EMUserInfo userInfo = new EMUserInfo(); + if (obj.has("userId")){ + userInfo.setUserId(obj.getString("userId")); + } + if (obj.has("nickName")){ + userInfo.setNickname(obj.getString("nickName")); + } - userInfo.setUserId(obj.getString("userId")); - userInfo.setNickName(obj.optString("nickName")); if (obj.has("gender")){ userInfo.setGender(obj.getInt("gender")); } - - userInfo.setEmail(obj.optString("mail")); - userInfo.setPhoneNumber(obj.optString("phone")); - userInfo.setSignature(obj.optString("sign")); - userInfo.setAvatarUrl(obj.optString("avatarUrl")); - userInfo.setExt(obj.optString("ext")); - userInfo.setBirth(obj.optString("birth")); + if (obj.has("mail")){ + userInfo.setEmail(obj.optString("mail")); + } + if (obj.has("phone")){ + userInfo.setPhoneNumber(obj.optString("phone")); + } + if (obj.has("sign")){ + userInfo.setSignature(obj.optString("sign")); + } + if (obj.has("avatarUrl")){ + userInfo.setAvatarUrl(obj.optString("avatarUrl")); + } + if (obj.has("ext")){ + userInfo.setExt(obj.getString("ext")); + } + if (obj.has("birth")){ + userInfo.setBirth(obj.getString("birth")); + } return userInfo; } 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 016462f2..771b1738 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 @@ -41,29 +41,32 @@ else if(EMSDKMethod.getImPushConfigFromServer.equals(call.method)){ else if(EMSDKMethod.updatePushNickname.equals(call.method)){ updatePushNickname(param, call.method, result); } - else if(EMSDKMethod.imPushNoDisturb.equals(call.method)){ - imPushNoDisturb(param, call.method, result); - } else if(EMSDKMethod.updateImPushStyle.equals(call.method)){ updateImPushStyle(param, call.method, result); } else if(EMSDKMethod.updateGroupPushService.equals(call.method)){ updateGroupPushService(param, call.method, result); } - else if(EMSDKMethod.getNoDisturbGroups.equals(call.method)){ - getNoDisturbGroups(param, call.method, result); - } else if(EMSDKMethod.updateHMSPushToken.equals(call.method)){ updateHMSPushToken(param, call.method, result); } else if(EMSDKMethod.updateFCMPushToken.equals(call.method)){ updateFCMPushToken(param, call.method, result); } - else if(EMSDKMethod.setNoDisturbUsers.equals(call.method)) { - setNoDisturbUsers(param, EMSDKMethod.setNoDisturbUsers, result); + else if (EMSDKMethod.enableOfflinePush.equals(call.method)) { + enableOfflinePush(param, call.method, result); + } + else if (EMSDKMethod.disableOfflinePush.equals(call.method)){ + disableOfflinePush(param, call.method, result); } - else if(EMSDKMethod.getNoDisturbUsersFromServer.equals(call.method)) { - getNoDisturbUsersFromServer(param, EMSDKMethod.getNoDisturbUsersFromServer, result); + else if (EMSDKMethod.getNoPushGroups.equals(call.method)) { + getNoPushGroups(param, call.method, result); + } + else if (EMSDKMethod.updateUserPushService.equals(call.method)) { + updateUserPushService(param, call.method, result); + } + else if (EMSDKMethod.getNoPushUsers.equals(call.method)) { + getNoPushUsers(param, call.method, result); } else { super.onMethodCall(call, result); @@ -102,86 +105,88 @@ private void updatePushNickname(JSONObject params, String channelName, Result r }); } - private void imPushNoDisturb(JSONObject params, String channelName, Result result) throws JSONException { - boolean noDisturb = params.getBoolean("noDisturb"); - int startTime = params.getInt("startTime"); - int endTime = params.getInt("endTime"); + + private void enableOfflinePush(JSONObject params, String channelName, Result result) throws JSONException + { asyncRunnable(()-> { try { - if (noDisturb) { - EMClient.getInstance().pushManager().disableOfflinePush(startTime, endTime); - }else{ - EMClient.getInstance().pushManager().enableOfflinePush(); - } - } catch (HyphenateException e) { - + EMClient.getInstance().pushManager().enableOfflinePush(); + onSuccess(result, channelName, null); + } catch(HyphenateException e) { + onError(result, e); } }); } - private void updateImPushStyle(JSONObject params, String channelName, Result result) throws JSONException { - DisplayStyle style = params.getInt("pushStyle") == 0 ? DisplayStyle.SimpleBanner : DisplayStyle.MessageSummary; - EMClient.getInstance().pushManager().asyncUpdatePushDisplayStyle(style, new EMWrapperCallBack(result, channelName, true)); - } - - private void updateGroupPushService(JSONObject params, String channelName, Result result) throws JSONException { - String groupId = params.getString("group_id"); - boolean enablePush = params.getBoolean("noDisturb"); - List groupList = new ArrayList<>(); - groupList.add(groupId); + private void disableOfflinePush(JSONObject params, String channelName, Result result) throws JSONException + { + int startTime = params.getInt("start"); + int endTime = params.getInt("end"); asyncRunnable(()-> { try { - EMClient.getInstance().pushManager().updatePushServiceForGroup(groupList, !enablePush); - EMGroup group = EMClient.getInstance().groupManager().getGroup(groupId); - onSuccess(result, channelName, EMGroupHelper.toJson(group)); + EMClient.getInstance().pushManager().disableOfflinePush(startTime, endTime); + onSuccess(result, channelName, null); } catch(HyphenateException e) { onError(result, e); } }); } - private void getNoDisturbGroups(JSONObject params, String channelName, Result result) throws JSONException { + private void getNoPushGroups(JSONObject params, String channelName, Result result) throws JSONException { + asyncRunnable(()-> { + List groups = EMClient.getInstance().pushManager().getNoPushGroups(); + onSuccess(result, channelName, groups); + }); + } + private void getNoPushUsers(JSONObject params, String channelName, Result result) throws JSONException { asyncRunnable(()->{ - try{ - EMClient.getInstance().pushManager().getPushConfigsFromServer(); - List groupIds = EMClient.getInstance().pushManager().getNoPushGroups(); - onSuccess(result, channelName, groupIds); - } catch (HyphenateException e) { - onError(result, e); - } + List list = EMClient.getInstance().pushManager().getNoPushUsers(); + onSuccess(result, channelName, list); }); } - private void setNoDisturbUsers(JSONObject params, String channelName, Result result) throws JSONException { - JSONArray jsonMembers = params.getJSONArray("members"); - Boolean disable = params.getBoolean("disable"); - List members = new ArrayList<>(); - for (int i = 0; i < jsonMembers.length(); i++) { - String memberId = jsonMembers.getString(i); - members.add(memberId); + private void updateImPushStyle(JSONObject params, String channelName, Result result) throws JSONException { + DisplayStyle style = params.getInt("pushStyle") == 0 ? DisplayStyle.SimpleBanner : DisplayStyle.MessageSummary; + EMClient.getInstance().pushManager().asyncUpdatePushDisplayStyle(style, new EMWrapperCallBack(result, channelName, true)); + } + + private void updateGroupPushService(JSONObject params, String channelName, Result result) throws JSONException { + JSONArray groupIds = params.getJSONArray("group_ids"); + boolean noPush = params.getBoolean("noPush"); + + List groupList = new ArrayList<>(); + for (int i = 0; i < groupIds.length(); i++) { + String groupId = groupIds.getString(i); + groupList.add(groupId); } - asyncRunnable(()->{ - try{ - EMClient.getInstance().pushManager().updatePushServiceForUsers(members, disable); + asyncRunnable(()-> { + try { + EMClient.getInstance().pushManager().updatePushServiceForGroup(groupList, noPush); onSuccess(result, channelName, null); - } catch (HyphenateException e) { + } catch(HyphenateException e) { onError(result, e); } }); } - private void getNoDisturbUsersFromServer(JSONObject params, String channelName, Result result) throws JSONException { - asyncRunnable(()->{ - try{ - EMClient.getInstance().pushManager().getPushConfigsFromServer(); - List userIds = EMClient.getInstance().pushManager().getNoPushUsers(); - onSuccess(result, channelName, userIds); - } catch (HyphenateException e) { + private void updateUserPushService(JSONObject params, String channelName, Result result) throws JSONException { + JSONArray groupIds = params.getJSONArray("user_ids"); + boolean noPush = params.getBoolean("noPush"); + + List userList = new ArrayList<>(); + for (int i = 0; i < groupIds.length(); i++) { + String userId = groupIds.getString(i); + userList.add(userId); + } + asyncRunnable(()-> { + try { + EMClient.getInstance().pushManager().updatePushServiceForUsers(userList, noPush); + onSuccess(result, channelName, null); + } catch(HyphenateException e) { onError(result, e); } }); - } private void updateHMSPushToken(JSONObject params, String channelName, Result result) throws JSONException { 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 611128b3..e6c52867 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 @@ -6,9 +6,10 @@ public class EMSDKMethod { static final String createAccount = "createAccount"; static final String login = "login"; static final String loginWithAgoraToken = "loginWithAgoraToken"; + static final String renewToken = "renewToken"; static final String logout = "logout"; static final String changeAppKey = "changeAppKey"; - static final String updateCurrentUserNick = "updateCurrentUserNick"; + static final String uploadLog = "uploadLog"; static final String compressLogs = "compressLogs"; static final String kickDevice = "kickDevice"; @@ -83,14 +84,12 @@ public class EMSDKMethod { static final String onMessageSuccess = "onMessageSuccess"; static final String onMessageReadAck = "onMessageReadAck"; static final String onMessageDeliveryAck = "onMessageDeliveryAck"; - static final String onMessageStatusChanged = "onMessageStatusChanged"; /// EMConversation static final String getUnreadMsgCount = "getUnreadMsgCount"; static final String markAllMessagesAsRead = "markAllMessagesAsRead"; static final String markMessageAsRead = "markMessageAsRead"; static final String syncConversationExt = "syncConversationExt"; - static final String syncConversationName = "syncConversationName"; static final String removeMessage = "removeMessage"; static final String getLatestMessage = "getLatestMessage"; static final String getLatestMessageFromOthers = "getLatestMessageFromOthers"; @@ -141,7 +140,7 @@ public class EMSDKMethod { static final String isMemberInChatRoomWhiteListFromServer = "isMemberInChatRoomWhiteListFromServer"; static final String muteAllChatRoomMembers = "muteAllChatRoomMembers"; - static final String unMuteAllChatRoomMembers = "umMuteAllChatRoomMembers"; + static final String unMuteAllChatRoomMembers = "unMuteAllChatRoomMembers"; // EMChatRoomManagerListener @@ -160,7 +159,7 @@ public class EMSDKMethod { static final String getGroupMuteListFromServer = "getGroupMuteListFromServer"; static final String getGroupWhiteListFromServer = "getGroupWhiteListFromServer"; static final String isMemberInWhiteListFromServer = "isMemberInWhiteListFromServer"; - static final String getGroupFileListFromServer = "getGroupFileList"; + static final String getGroupFileListFromServer = "getGroupFileListFromServer"; static final String getGroupAnnouncementFromServer = "getGroupAnnouncementFromServer"; static final String addMembers = "addMembers"; static final String inviterUser = "inviterUser"; @@ -201,17 +200,20 @@ public class EMSDKMethod { /// EMPushManager static final String getImPushConfig = "getImPushConfig"; static final String getImPushConfigFromServer = "getImPushConfigFromServer"; + static final String enableOfflinePush = "enableOfflinePush"; + static final String disableOfflinePush = "disableOfflinePush"; + static final String updateImPushStyle = "updateImPushStyle"; static final String updatePushNickname = "updatePushNickname"; + + static final String updateGroupPushService = "updateGroupPushService"; + static final String getNoPushGroups = "getNoPushGroups"; + static final String updateUserPushService = "updateUserPushService"; + static final String getNoPushUsers = "getNoPushUsers"; + + static final String updateHMSPushToken = "updateHMSPushToken"; static final String updateFCMPushToken = "updateFCMPushToken"; - /// ImPushConfig - static final String imPushNoDisturb = "imPushNoDisturb"; - static final String updateImPushStyle = "updateImPushStyle"; - static final String updateGroupPushService = "updateGroupPushService"; - static final String getNoDisturbGroups = "getNoDisturbGroups"; - static final String setNoDisturbUsers = "setNoDisturbUsers"; - static final String getNoDisturbUsersFromServer = "getNoDisturbUsersFromServer"; /// EMUserInfoManager diff --git a/android/src/main/java/com/easemob/im_flutter_sdk/EMUserInfoManagerWrapper.java b/android/src/main/java/com/easemob/im_flutter_sdk/EMUserInfoManagerWrapper.java index f2b24db4..16320582 100644 --- a/android/src/main/java/com/easemob/im_flutter_sdk/EMUserInfoManagerWrapper.java +++ b/android/src/main/java/com/easemob/im_flutter_sdk/EMUserInfoManagerWrapper.java @@ -85,7 +85,6 @@ private void updateOwnUserInfoWithType(JSONObject params, String channelName, Re EMValueWrapperCallBack callBack = new EMValueWrapperCallBack(result, channelName){ @Override public void onSuccess(final String object) { - EMLog.e("updateOwnUserInfoWithType", "object: "+object); if(object != null && object.length() > 0) { JSONObject obj = null; diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 2fc41a4b..2abcaace 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -26,7 +26,8 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 29 + + compileSdkVersion 31 sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -40,7 +41,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.easeim_flutter_demo" minSdkVersion 19 - targetSdkVersion 29 + targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName multiDexEnabled true diff --git a/example/android/app/proguard-rules.pro b/example/android/app/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/example/android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 2c05e78c..beafc5d7 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -6,7 +6,7 @@ additional functionality it is fine to subclass or reimplement FlutterApplication and put your custom class here. --> { void _updateInputBarType() { _showSendBtn = widget.textController?.text.length != 0; - setState(() {}); + if (mounted) { + setState(() {}); + } } } diff --git a/example/lib/pages/chat/chat_items/chat_image_bubble.dart b/example/lib/pages/chat/chat_items/chat_image_bubble.dart index e04312d3..60b90f93 100644 --- a/example/lib/pages/chat/chat_items/chat_image_bubble.dart +++ b/example/lib/pages/chat/chat_items/chat_image_bubble.dart @@ -22,8 +22,8 @@ class ChatImageBubble extends StatelessWidget { Widget image; // 作为接收方,是有图片size的,需要先根据size缩放 - double width = body.width!; - double height = body.height!; + double width = body.width ?? 100; + double height = body.height ?? 100; if (height > width) { width = maxSize / height * width; @@ -32,7 +32,7 @@ class ChatImageBubble extends StatelessWidget { height = maxSize / width * height; width = maxSize; } - File localPath = File(body.localPath!); + File localPath = File(body.localPath); if (isSend && localPath.existsSync()) { image = Image.file( localPath, diff --git a/example/lib/pages/chat/chat_items/chat_item.dart b/example/lib/pages/chat/chat_items/chat_item.dart index 71ffe9af..da7e677f 100644 --- a/example/lib/pages/chat/chat_items/chat_item.dart +++ b/example/lib/pages/chat/chat_items/chat_item.dart @@ -41,15 +41,29 @@ class ChatItem extends StatefulWidget { State createState() => ChatItemState(); } -class ChatItemState extends State implements EMMessageStatusListener { +class ChatItemState extends State { void initState() { super.initState(); - widget.msg.setMessageListener(this); + widget.msg.setMessageStatusCallBack(MessageStatusCallBack(onSuccess: () { + if (mounted) { + setState(() {}); + } + }, onError: (error) { + if (mounted) { + setState(() {}); + } + }, onReadAck: () { + if (mounted) { + setState(() {}); + } + }, onProgress: (progress) { + debugPrint("progress --- $progress"); + })); } @override Widget build(context) { - bool isRecv = widget.msg.direction == EMMessageDirection.RECEIVE; + bool isRecv = widget.msg.direction == MessageDirection.RECEIVE; return Builder( builder: (_) { _info() { @@ -74,7 +88,7 @@ class ChatItemState extends State implements EMMessageStatusListener { } Widget ret; - if (isRecv && widget.msg.chatType != EMMessageChatType.Chat) { + if (isRecv && widget.msg.chatType != ChatType.Chat) { ret = Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -190,7 +204,7 @@ class ChatItemState extends State implements EMMessageStatusListener { } else { return Builder( builder: (_) { - if (widget.msg.status == EMMessageStatus.PROGRESS) { + if (widget.msg.status == MessageStatus.PROGRESS) { return Padding( padding: EdgeInsets.all(sWidth(10)), child: SizedBox( @@ -201,8 +215,8 @@ class ChatItemState extends State implements EMMessageStatusListener { ), ), ); - } else if (widget.msg.status == EMMessageStatus.FAIL || - widget.msg.status == EMMessageStatus.CREATE) { + } else if (widget.msg.status == MessageStatus.FAIL || + widget.msg.status == MessageStatus.CREATE) { return IconButton( padding: EdgeInsets.zero, icon: Icon( @@ -225,51 +239,22 @@ class ChatItemState extends State implements EMMessageStatusListener { return Container(); } - @override - void onDeliveryAck() {} - - @override - void onError(EMError error) { - setState(() {}); - print('发送失败'); - } - - @override - void onProgress(int progress) { - print('progress --- $progress'); - } - - @override - void onReadAck() { - setState(() {}); - print('收到已读回调'); - } - - @override - void onStatusChanged() {} - - @override - void onSuccess() { - setState(() {}); - print('发送成功'); - } - _messageBubble() { - EMMessageBody body = widget.msg.body!; - bool isSend = widget.msg.direction != EMMessageDirection.RECEIVE; + EMMessageBody body = widget.msg.body; + bool isSend = widget.msg.direction != MessageDirection.RECEIVE; return Builder(builder: (_) { Widget bubble; - switch (widget.msg.body!.type!) { - case EMMessageBodyType.TXT: + switch (widget.msg.body.type) { + case MessageType.TXT: bubble = ChatTextBubble(body as EMTextMessageBody); break; - case EMMessageBodyType.LOCATION: + case MessageType.LOCATION: bubble = ChatLocationBubble(body as EMLocationMessageBody); break; - case EMMessageBodyType.IMAGE: + case MessageType.IMAGE: bubble = ChatImageBubble(body as EMImageMessageBody, isSend); break; - case EMMessageBodyType.VOICE: + case MessageType.VOICE: bubble = Builder(builder: (context) { return Selector( selector: (_, ChatVoicePlayer player) { @@ -283,14 +268,14 @@ class ChatItemState extends State implements EMMessageStatusListener { ); }); break; - case EMMessageBodyType.VIDEO: + case MessageType.VIDEO: bubble = ChatVideoBubble(body as EMVideoMessageBody); break; - case EMMessageBodyType.FILE: + case MessageType.FILE: bubble = ChatFileBubble(body as EMFileMessageBody); break; - case EMMessageBodyType.CMD: - case EMMessageBodyType.CUSTOM: + case MessageType.CMD: + case MessageType.CUSTOM: bubble = Container(); } return Container( diff --git a/example/lib/pages/chat/chat_items/chat_text_bubble.dart b/example/lib/pages/chat/chat_items/chat_text_bubble.dart index 60d12c8e..fa472e28 100644 --- a/example/lib/pages/chat/chat_items/chat_text_bubble.dart +++ b/example/lib/pages/chat/chat_items/chat_text_bubble.dart @@ -42,7 +42,7 @@ class ChatTextBubble extends StatelessWidget { bottom: sHeight(9), ), child: ExpressionText( - body.content!, + body.content, TextStyle( color: Color.fromRGBO(51, 51, 51, 1), fontSize: sFontSize(17), diff --git a/example/lib/pages/chat/chat_items/chat_voice_bubble.dart b/example/lib/pages/chat/chat_items/chat_voice_bubble.dart index 832461f7..89c74108 100644 --- a/example/lib/pages/chat/chat_items/chat_voice_bubble.dart +++ b/example/lib/pages/chat/chat_items/chat_voice_bubble.dart @@ -48,7 +48,7 @@ class ChatVoiceBubbleState extends State controller.stop(); controller.reverse(from: 0); } - double width = minSize * widget.body.duration! / 15; + double width = minSize * widget.body.duration / 15; if (width < minSize) width = minSize; if (width > maxSize) width = maxSize; return Container( diff --git a/example/lib/pages/chat/chat_page.dart b/example/lib/pages/chat/chat_page.dart index 08e18853..09a61c00 100644 --- a/example/lib/pages/chat/chat_page.dart +++ b/example/lib/pages/chat/chat_page.dart @@ -71,7 +71,7 @@ class _ChatPageState extends State _moreView = ChatMoreView(items); // 添加环信回调监听 - EMClient.getInstance.chatManager.addListener(this); + EMClient.getInstance.chatManager.addChatManagerListener(this); EMClient.getInstance.chatRoomManager.addChatRoomChangeListener(this); // 设置所有消息已读 widget.conversation.markAllMessagesAsRead(); @@ -95,13 +95,13 @@ class _ChatPageState extends State .joinChatRoom(widget.conversation.id); _loadMessages(); } on EMError catch (e) { - print("加入房间失败 -- " + e.toString()); + debugPrint("加入房间失败 -- " + e.toString()); } } void dispose() { // 移除环信回调监听 - EMClient.getInstance.chatManager.removeListener(this); + EMClient.getInstance.chatManager.removeChatManagerListener(this); _scrollController.dispose(); _inputBarEditingController.dispose(); if (widget.conversation.type == EMConversationType.ChatRoom) { @@ -130,7 +130,9 @@ class _ChatPageState extends State if (_keyboardVisible) { _inputBarType = ChatInputBarType.normal; SystemChannels.textInput.invokeMethod('TextInput.hide'); - setState(() {}); + if (mounted) { + setState(() {}); + } } }, child: SafeArea( @@ -236,8 +238,8 @@ class _ChatPageState extends State /// 发送消息已读回执 _makeMessageAsRead(EMMessage msg) async { - if (msg.chatType == EMMessageChatType.Chat && - msg.direction == EMMessageDirection.RECEIVE) { + if (msg.chatType == ChatType.Chat && + msg.direction == MessageDirection.RECEIVE) { if (msg.hasReadAck == false) { try { await EMClient.getInstance.chatManager.sendMessageReadAck(msg); @@ -245,7 +247,7 @@ class _ChatPageState extends State } if (msg.hasRead == false) { try { - await widget.conversation.markMessageAsRead(msg.msgId!); + await widget.conversation.markMessageAsRead(msg.msgId); } on EMError {} } } @@ -261,7 +263,9 @@ class _ChatPageState extends State onFaceTap: (expression) { _inputBarEditingController.text = _inputBarEditingController.text + '[${expression.name}]'; - setState(() {}); + if (mounted) { + setState(() {}); + } }, onDeleteTap: () { if (_inputBarEditingController.text.length > 0) { @@ -279,11 +283,13 @@ class _ChatPageState extends State /// 下拉加载更多消息 _loadMessages({int count = 20, bool moveBottom = true}) async { try { - List msgs = await widget.conversation.loadMessages( - startMsgId: _msgList.length > 0 ? _msgList.first.msgId! : '', + List? msgs = await widget.conversation.loadMessages( + startMsgId: _msgList.length > 0 ? _msgList.first.msgId : '', loadCount: count, ); - _msgList.insertAll(0, msgs); + if (msgs != null) { + _msgList.insertAll(0, msgs); + } } on EMError { } finally { if (moveBottom) { @@ -296,7 +302,9 @@ class _ChatPageState extends State /// 刷新View并滑动到最底部 _setStateAndMoreToListViewEnd() { - setState(() {}); + if (mounted) { + setState(() {}); + } Future.delayed(Duration(milliseconds: 100), () { _scrollController.jumpTo(_scrollController.position.maxScrollExtent); }); @@ -304,21 +312,21 @@ class _ChatPageState extends State /// 点击bubble _messageBubbleOnTap(EMMessage msg) async { - switch (msg.body!.type!) { - case EMMessageBodyType.TXT: + switch (msg.body.type) { + case MessageType.TXT: break; - case EMMessageBodyType.IMAGE: + case MessageType.IMAGE: { EMImageMessageBody body = msg.body as EMImageMessageBody; Image img; - if (body.fileStatus != EMDownloadStatus.SUCCESS) { + if (body.fileStatus != DownloadStatus.SUCCESS) { img = Image.network( body.remotePath!, fit: BoxFit.cover, ); } else { img = Image.file( - File(body.localPath!), + File(body.localPath), fit: BoxFit.cover, ); } @@ -331,7 +339,7 @@ class _ChatPageState extends State ); } break; - case EMMessageBodyType.VOICE: + case MessageType.VOICE: { if (_voicePlayer.currentMsgId == msg.msgId) { _voicePlayer.stopPlay(); @@ -340,15 +348,15 @@ class _ChatPageState extends State } } break; - case EMMessageBodyType.VIDEO: + case MessageType.VIDEO: break; - case EMMessageBodyType.LOCATION: + case MessageType.LOCATION: break; - case EMMessageBodyType.FILE: + case MessageType.FILE: break; - case EMMessageBodyType.CMD: + case MessageType.CMD: break; - case EMMessageBodyType.CUSTOM: + case MessageType.CUSTOM: break; } } @@ -372,7 +380,7 @@ class _ChatPageState extends State } /// 发送图片消息 - _sendImageMessage(String imagePath, [String fileName = '']) { + _sendImageMessage(String imagePath, {String? fileName}) { Image.file( File(imagePath), fit: BoxFit.contain, @@ -385,7 +393,7 @@ class _ChatPageState extends State filePath: imagePath, displayName: fileName, ); - EMImageMessageBody body = msg.body! as EMImageMessageBody; + EMImageMessageBody body = msg.body as EMImageMessageBody; body.height = info.image.height.toDouble(); body.width = info.image.width.toDouble(); msg.body = body; @@ -396,16 +404,16 @@ class _ChatPageState extends State /// 发消息方法 _sendMessage(EMMessage msg) async { _chatType() { - EMMessageChatType type = EMMessageChatType.Chat; + ChatType type = ChatType.Chat; switch (widget.conversation.type) { case EMConversationType.Chat: - type = EMMessageChatType.Chat; + type = ChatType.Chat; break; case EMConversationType.ChatRoom: - type = EMMessageChatType.ChatRoom; + type = ChatType.ChatRoom; break; case EMConversationType.GroupChat: - type = EMMessageChatType.GroupChat; + type = ChatType.GroupChat; break; default: } diff --git a/example/lib/pages/chatroom/chat_room_list_page.dart b/example/lib/pages/chatroom/chat_room_list_page.dart index 0748e40c..28f1949d 100644 --- a/example/lib/pages/chatroom/chat_room_list_page.dart +++ b/example/lib/pages/chatroom/chat_room_list_page.dart @@ -43,7 +43,9 @@ class ChatRoomsListPagesState extends State { _searchName = text; if (_searchName.length == 0) { _searchedRoom = null; - setState(() {}); + if (mounted) { + setState(() {}); + } } }, style: TextStyle( @@ -120,7 +122,7 @@ class ChatRoomsListPagesState extends State { child: ListTile( onTap: () => _chatToRoom(room), title: Text( - room.name, + room.name ?? room.roomId, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( @@ -162,11 +164,14 @@ class ChatRoomsListPagesState extends State { _isEnd = false; } } - setState(() {}); + SmartDialog.showToast('获取成功'); isMore ? _refreshController.loadComplete() : _refreshController.refreshCompleted(); + if (mounted) { + setState(() {}); + } } on EMError catch (e) { SmartDialog.showToast('获取失败$e'); isMore @@ -185,10 +190,10 @@ class ChatRoomsListPagesState extends State { SmartDialog.showToast('会话创建失败'); return; } - con.name = room.name; + Navigator.of(context).pushNamed( '/chat', - arguments: [con.name, con], + arguments: [con.id, con], ).then((value) => EMClient.getInstance.chatRoomManager.leaveChatRoom(room.roomId)); } @@ -203,7 +208,9 @@ class ChatRoomsListPagesState extends State { SmartDialog.showToast('搜索失败: $e'); } finally { SmartDialog.dismiss(); - setState(() {}); + if (mounted) { + setState(() {}); + } } } } diff --git a/example/lib/pages/contacts/contact_friends_request_page.dart b/example/lib/pages/contacts/contact_friends_request_page.dart index ed0d4eb3..ee97c4f1 100644 --- a/example/lib/pages/contacts/contact_friends_request_page.dart +++ b/example/lib/pages/contacts/contact_friends_request_page.dart @@ -19,7 +19,9 @@ class ContactFriendsRequestPageState extends State { String? currentUser = EMClient.getInstance.currentUsername; if (currentUser != null) { SharePreferenceManager.load(currentUser, callback: () { - setState(() {}); + if (mounted) { + setState(() {}); + } }); } } @@ -39,7 +41,9 @@ class ContactFriendsRequestPageState extends State { TextButton( onPressed: () { SharePreferenceManager.removeAllRequest(); - setState(() {}); + if (mounted) { + setState(() {}); + } }, child: Text( '清空', @@ -104,7 +108,9 @@ class ContactFriendsRequestPageState extends State { reqestId, true, ); - setState(() {}); + if (mounted) { + setState(() {}); + } }, ), TextButton( @@ -121,7 +127,9 @@ class ContactFriendsRequestPageState extends State { reqestId, false, ); - setState(() {}); + if (mounted) { + setState(() {}); + } }, ), ], diff --git a/example/lib/pages/contacts/contact_select_page.dart b/example/lib/pages/contacts/contact_select_page.dart index c12b4c59..624226d9 100644 --- a/example/lib/pages/contacts/contact_select_page.dart +++ b/example/lib/pages/contacts/contact_select_page.dart @@ -193,8 +193,8 @@ class ContactSelectPageState extends State { Future> _fetchUsersInfo(List list) async { List ret = []; - Map map = await EMClient.getInstance.userInfoManager - .fetchUserInfoByIdWithExpireTime(list); + Map map = + await EMClient.getInstance.userInfoManager.fetchUserInfoById(list); List emIds = map.keys.toList(); List noInfoIds = list.toList(); noInfoIds.removeWhere((element) { diff --git a/example/lib/pages/contacts/contacts_page.dart b/example/lib/pages/contacts/contacts_page.dart index fd95c197..d9ed62c8 100644 --- a/example/lib/pages/contacts/contacts_page.dart +++ b/example/lib/pages/contacts/contacts_page.dart @@ -17,7 +17,7 @@ class ContactsPage extends StatefulWidget { } class ContactsPageState extends State - implements EMContactEventListener { + implements EMContactManagerListener { List _contactList = []; List _topList = [ ContactModel.custom('新的好友'), @@ -35,7 +35,9 @@ class ContactsPageState extends State String? currentUser = EMClient.getInstance.currentUsername; if (currentUser != null) { SharePreferenceManager.load(currentUser, callback: () { - setState(() {}); + if (mounted) { + setState(() {}); + } }); } } @@ -247,13 +249,16 @@ class ContactsPageState extends State _contactList.addAll(list); } } on EMError { + _contactList.clear(); SmartDialog.showToast('获取失败'); _loadLocalContacts(count); } finally { SuspensionUtil.sortListBySuspensionTag(_contactList); SuspensionUtil.setShowSuspensionStatus(_contactList); _contactList.insertAll(0, _topList); - setState(() {}); + if (mounted) { + setState(() {}); + } } } @@ -274,7 +279,9 @@ class ContactsPageState extends State SuspensionUtil.sortListBySuspensionTag(_contactList); SuspensionUtil.setShowSuspensionStatus(_contactList); _contactList.insertAll(0, _topList); - setState(() {}); + if (mounted) { + setState(() {}); + } Future.delayed(Duration(seconds: 3)).then((value) { _fetchContactsFromServer(count); }); @@ -284,8 +291,8 @@ class ContactsPageState extends State Future> _fetchUserInfo(List emIds) async { List ret = []; - Map map = await EMClient.getInstance.userInfoManager - .fetchUserInfoByIdWithExpireTime(emIds); + Map map = + await EMClient.getInstance.userInfoManager.fetchUserInfoById(emIds); List hasInfoIds = map.keys.toList(); for (var hasInfoId in hasInfoIds) { @@ -320,7 +327,9 @@ class ContactsPageState extends State void onContactInvited(String? userName, String? reason) { SharePreferenceManager.addRequest(userName!); _friendRequestCount = SharePreferenceManager.loadUnreadCount(); - setState(() {}); + if (mounted) { + setState(() {}); + } } @override diff --git a/example/lib/pages/conversations/conversation_item.dart b/example/lib/pages/conversations/conversation_item.dart index 17d6523b..901e0cf9 100644 --- a/example/lib/pages/conversations/conversation_item.dart +++ b/example/lib/pages/conversations/conversation_item.dart @@ -54,8 +54,11 @@ class _ConversationItemState extends State { Positioned( top: sHeight(10), right: sWidth(5), - child: unreadCountWidget( - _unreadCount(), + child: FutureBuilder( + future: _unreadCount(), + builder: (context, snapshot) { + return unreadCountWidget(snapshot.data ?? 0); + }, ), ), ], @@ -86,13 +89,18 @@ class _ConversationItemState extends State { Container( margin: EdgeInsets.only( left: sWidth(5), right: sWidth(12)), - child: Text( - _latestMessageTime(), - maxLines: 1, - style: TextStyle( - color: Color.fromRGBO(153, 153, 153, 1), - fontSize: sFontSize(12), - ), + child: FutureBuilder( + future: _latestMessageTime(), + builder: (context, snapshot) { + return Text( + snapshot.data ?? "", + maxLines: 1, + style: TextStyle( + color: Color.fromRGBO(153, 153, 153, 1), + fontSize: sFontSize(12), + ), + ); + }, ), ), ], @@ -102,16 +110,20 @@ class _ConversationItemState extends State { Expanded( flex: 1, child: Container( - padding: EdgeInsets.only(right: sWidth(10)), - child: ExpressionText( - _showInfo(), - TextStyle( - color: Color.fromRGBO(153, 153, 153, 1), - fontSize: sFontSize(14), - ), - maxLine: 1, - ), - ), + padding: EdgeInsets.only(right: sWidth(10)), + child: FutureBuilder( + future: _showInfo(), + builder: (context, snapshot) { + return ExpressionText( + snapshot.data ?? "", + TextStyle( + color: Color.fromRGBO(153, 153, 153, 1), + fontSize: sFontSize(14), + ), + maxLine: 1, + ); + }, + )), ), ], ), @@ -123,31 +135,31 @@ class _ConversationItemState extends State { } /// 消息详情 - String _showInfo() { + Future _showInfo() async { String showInfo = ''; - EMMessage? _latestMessage = this.widget.conversation.latestMessage; + EMMessage? _latestMessage = await this.widget.conversation.latestMessage(); if (_latestMessage == null) { return showInfo; } - switch (_latestMessage.body!.type) { - case EMMessageBodyType.TXT: + switch (_latestMessage.body.type) { + case MessageType.TXT: var body = _latestMessage.body as EMTextMessageBody; - showInfo = body.content!; + showInfo = body.content; break; - case EMMessageBodyType.IMAGE: + case MessageType.IMAGE: showInfo = '[图片]'; break; - case EMMessageBodyType.VIDEO: + case MessageType.VIDEO: showInfo = '[视频]'; break; - case EMMessageBodyType.FILE: + case MessageType.FILE: showInfo = '[文件]'; break; - case EMMessageBodyType.VOICE: + case MessageType.VOICE: showInfo = '[语音]'; break; - case EMMessageBodyType.LOCATION: + case MessageType.LOCATION: showInfo = '[位置]'; break; default: @@ -158,19 +170,17 @@ class _ConversationItemState extends State { /// 显示的名称 String _showName() { - return this.widget.conversation.name; + return this.widget.conversation.id; } /// 未读数 - int _unreadCount() { - return this.widget.conversation.unreadCount; + Future _unreadCount() async { + return this.widget.conversation.unreadCount(); } /// 消息时间 - String _latestMessageTime() { - if (this.widget.conversation.latestMessage == null) { - return ''; - } - return timeStrByMs(this.widget.conversation.latestMessage?.serverTime ?? 0); + Future _latestMessageTime() async { + EMMessage? msg = await this.widget.conversation.latestMessage(); + return timeStrByMs(msg?.serverTime ?? 0); } } diff --git a/example/lib/pages/conversations/conversations_page.dart b/example/lib/pages/conversations/conversations_page.dart index 81629a92..07df450a 100644 --- a/example/lib/pages/conversations/conversations_page.dart +++ b/example/lib/pages/conversations/conversations_page.dart @@ -33,7 +33,7 @@ class ConversationPageState extends State void initState() { super.initState(); // 添加环信回调监听 - EMClient.getInstance.chatManager.addListener(this); + EMClient.getInstance.chatManager.addChatManagerListener(this); notifier = eventBus.on().listen((event) { if (event.eventKey == EventBusManager.updateConversationsList) { _reLoadAllConversations(); @@ -44,7 +44,7 @@ class ConversationPageState extends State void dispose() { _refreshController.dispose(); // 移除环信回调监听 - EMClient.getInstance.chatManager.removeListener(this); + EMClient.getInstance.chatManager.removeChatManagerListener(this); notifier.cancel(); super.dispose(); } @@ -155,20 +155,20 @@ class ConversationPageState extends State /// 更新会话列表 void _reLoadAllConversations() async { try { + int count = + await EMClient.getInstance.chatManager.getUnreadMessageCount(); List list = await EMClient.getInstance.chatManager.loadAllConversations(); _conversationsList.clear(); _conversationsList.addAll(list); _refreshController.refreshCompleted(); - int count = 0; - for (var conversation in _conversationsList) { - count += conversation.unreadCount; - } widget.updateCount(count); } on Error { _refreshController.refreshFailed(); } finally { - setState(() {}); + if (mounted) { + setState(() {}); + } } } @@ -193,7 +193,9 @@ class ConversationPageState extends State _conversationsList.removeAt(index); } on Error { } finally { - setState(() {}); + if (mounted) { + setState(() {}); + } } } @@ -202,7 +204,7 @@ class ConversationPageState extends State EMConversation con = _conversationsList[index]; Navigator.of(context).pushNamed( '/chat', - arguments: [con.name, con], + arguments: [con.id, con], ).then((value) { // 返回时刷新页面 _reLoadAllConversations(); diff --git a/example/lib/pages/group/group_info_page.dart b/example/lib/pages/group/group_info_page.dart index d69b2dc1..5ddcf148 100644 --- a/example/lib/pages/group/group_info_page.dart +++ b/example/lib/pages/group/group_info_page.dart @@ -26,7 +26,7 @@ class GroupInfoPageState extends State { Widget build(BuildContext context) { bool needApproval = false; if (_group != null) { - if (_group!.settings?.style == EMGroupStyle.PublicJoinNeedApproval) { + if (_group!.isMemberOnly == false) { needApproval = true; } else { needApproval = false; @@ -164,10 +164,10 @@ class GroupInfoPageState extends State { ); } - _joinPublicGroup() { + _joinPublicGroup() async { try { SmartDialog.showLoading(msg: '加入中...'); - EMClient.getInstance.groupManager.joinPublicGroup(_group!.groupId); + await EMClient.getInstance.groupManager.joinPublicGroup(_group!.groupId); SmartDialog.showToast('加入成功'); } on EMError catch (e) { SmartDialog.showToast('加入失败: $e'); @@ -180,7 +180,7 @@ class GroupInfoPageState extends State { try { SmartDialog.showLoading(msg: '申请中...'); if (_group != null) { - EMClient.getInstance.groupManager.requestToJoinPublicGroup( + await EMClient.getInstance.groupManager.requestToJoinPublicGroup( _group!.groupId, ); } @@ -195,12 +195,14 @@ class GroupInfoPageState extends State { _fetchGroupInfo() async { try { SmartDialog.showLoading(msg: '获取中...'); - _group = await EMClient.getInstance.groupManager - .getGroupSpecificationFromServer( + _group = await EMClient.getInstance.groupManager.fetchGroupInfoFromServer( widget.group.groupId, ); - setState(() {}); + SmartDialog.showToast('获取成功'); + if (mounted) { + setState(() {}); + } } on EMError catch (e) { SmartDialog.showToast('获取失败: $e'); } finally { diff --git a/example/lib/pages/group/joined_groups_page.dart b/example/lib/pages/group/joined_groups_page.dart index e1a9e232..b064e794 100644 --- a/example/lib/pages/group/joined_groups_page.dart +++ b/example/lib/pages/group/joined_groups_page.dart @@ -232,7 +232,7 @@ class JoinedGroupsPageState extends State { } _loadJoinedGroups([bool isMore = false]) async { - print('_loadJoinedGroups'); + debugPrint('_loadJoinedGroups'); try { if (!isMore) { _pageNumber = 0; @@ -255,7 +255,9 @@ class JoinedGroupsPageState extends State { _groupsList.clear(); } _groupsList.addAll(groups); - setState(() {}); + if (mounted) { + setState(() {}); + } SmartDialog.showToast('获取成功'); isMore ? _refreshController.loadComplete() @@ -278,10 +280,10 @@ class JoinedGroupsPageState extends State { SmartDialog.showToast('会话创建失败'); return; } - con.name = group.name!; + // con.name = group.name!; Navigator.of(context).pushNamed( '/chat', - arguments: [con.name, con], + arguments: [con.id, con], ).then((value) { eventBus.fire(EventBusManager.updateConversations()); }); @@ -291,7 +293,9 @@ class JoinedGroupsPageState extends State { _searchName = std; if (std.length == 0) { _searchedGroups.clear(); - setState(() {}); + if (mounted) { + setState(() {}); + } return; } _searchedGroups.clear(); @@ -305,6 +309,8 @@ class JoinedGroupsPageState extends State { continue; } } - setState(() {}); + if (mounted) { + setState(() {}); + } } } diff --git a/example/lib/pages/group/public_groups_page.dart b/example/lib/pages/group/public_groups_page.dart index 4621dd10..a1472377 100644 --- a/example/lib/pages/group/public_groups_page.dart +++ b/example/lib/pages/group/public_groups_page.dart @@ -43,7 +43,9 @@ class PublicGroupsPageState extends State { _searchName = text; if (_searchName.length == 0) { _searchedGroup = null; - setState(() {}); + if (mounted) { + setState(() {}); + } } }, style: TextStyle( @@ -143,17 +145,17 @@ class PublicGroupsPageState extends State { _loadMorePublicGroups() async { try { EMCursorResult cursor = - await EMClient.getInstance.groupManager.getPublicGroupsFromServer( + await EMClient.getInstance.groupManager.fetchPublicGroupsFromServer( pageSize: _pageSize, cursor: _cursor ?? "", ); _refreshController.loadComplete(); _cursor = cursor.cursor; - if (cursor.data != null) { - _groupsList.addAll(cursor.data!); - // 返回数据小于pageSize,说明是最后一页 - if (_pageSize > cursor.data!.length) { - _isEnd = true; + _groupsList.addAll(cursor.data); + // 返回数据小于pageSize,说明是最后一页 + if (_pageSize > cursor.data.length) { + _isEnd = true; + if (mounted) { setState(() {}); } } @@ -168,18 +170,20 @@ class PublicGroupsPageState extends State { _isEnd = false; EMCursorResult cursor = - await EMClient.getInstance.groupManager.getPublicGroupsFromServer( + await EMClient.getInstance.groupManager.fetchPublicGroupsFromServer( pageSize: _pageSize, ); _refreshController.refreshCompleted(); - if (_pageSize > cursor.data!.length) { + if (_pageSize > cursor.data.length) { _isEnd = true; } _cursor = cursor.cursor; _groupsList.clear(); - _groupsList.addAll(cursor.data!); - setState(() {}); + _groupsList.addAll(cursor.data); SmartDialog.showToast('获取成功'); + if (mounted) { + setState(() {}); + } } on EMError catch (e) { SmartDialog.showToast('获取失败$e'); _refreshController.refreshFailed(); @@ -197,13 +201,15 @@ class PublicGroupsPageState extends State { if (std.length == 0) return; try { SmartDialog.showLoading(msg: '搜索中...'); - _searchedGroup = await EMClient.getInstance.groupManager - .getGroupSpecificationFromServer(std); + _searchedGroup = + await EMClient.getInstance.groupManager.fetchGroupInfoFromServer(std); } on EMError catch (e) { SmartDialog.showToast('搜索失败: $e'); } finally { SmartDialog.dismiss(); - setState(() {}); + if (mounted) { + setState(() {}); + } } } } diff --git a/ios/Classes/EMChatManagerWrapper.m b/ios/Classes/EMChatManagerWrapper.m index 0490aa9e..79d9b219 100644 --- a/ios/Classes/EMChatManagerWrapper.m +++ b/ios/Classes/EMChatManagerWrapper.m @@ -41,91 +41,91 @@ - (instancetype)initWithChannelName:(NSString *)aChannelName - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - if ([EMMethodKeySendMessage isEqualToString:call.method]) { + if ([ChatSendMessage isEqualToString:call.method]) { [self sendMessage:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyResendMessage isEqualToString:call.method]) { + } else if ([ChatResendMessage isEqualToString:call.method]) { [self resendMessage:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyAckMessageRead isEqualToString:call.method]) { + } else if ([ChatAckMessageRead isEqualToString:call.method]) { [self ackMessageRead:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyAckGroupMessageRead isEqualToString:call.method]) { - [self ackMessageRead:call.arguments - channelName:call.method - result:result]; - } else if ([EMMethodKeyAckConversationRead isEqualToString:call.method]) { + } else if ([ChatAckGroupMessageRead isEqualToString:call.method]) { + [self ackGroupMessageRead:call.arguments + channelName:call.method + result:result]; + } else if ([ChatAckConversationRead isEqualToString:call.method]) { [self ackConversationRead:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyRecallMessage isEqualToString:call.method]) { + else if ([ChatRecallMessage isEqualToString:call.method]) { [self recallMessage:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetConversation isEqualToString:call.method]) { + } else if ([ChatGetConversation isEqualToString:call.method]) { [self getConversation:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetMessage isEqualToString:call.method]) { + } else if ([ChatGetMessage isEqualToString:call.method]) { [self getMessageWithMessageId:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyMarkAllChatMsgAsRead isEqualToString:call.method]) { + } else if ([ChatMarkAllChatMsgAsRead isEqualToString:call.method]) { [self markAllMessagesAsRead:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetUnreadMessageCount isEqualToString:call.method]) { + } else if ([ChatGetUnreadMessageCount isEqualToString:call.method]) { [self getUnreadMessageCount:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyUpdateChatMessage isEqualToString:call.method]) { + } else if ([ChatUpdateChatMessage isEqualToString:call.method]) { [self updateChatMessage:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyDownloadAttachment isEqualToString:call.method]) { + } else if ([ChatDownloadAttachment isEqualToString:call.method]) { [self downloadAttachment:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyDownloadThumbnail isEqualToString:call.method]) { + } else if ([ChatDownloadThumbnail isEqualToString:call.method]) { [self downloadThumbnail:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyImportMessages isEqualToString:call.method]) { + } else if ([ChatImportMessages isEqualToString:call.method]) { [self importMessages:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyLoadAllConversations isEqualToString:call.method]) { + } else if ([ChatLoadAllConversations isEqualToString:call.method]) { [self loadAllConversations:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetConversationsFromServer isEqualToString:call.method]) { + } else if ([ChatGetConversationsFromServer isEqualToString:call.method]) { [self getConversationsFromServer:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyDeleteConversation isEqualToString:call.method]) { + } else if ([ChatDeleteConversation isEqualToString:call.method]) { [self deleteConversation:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyFetchHistoryMessages isEqualToString:call.method]) { + } else if ([ChatFetchHistoryMessages isEqualToString:call.method]) { [self fetchHistoryMessages:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeySearchChatMsgFromDB isEqualToString:call.method]) { + } else if ([ChatSearchChatMsgFromDB isEqualToString:call.method]) { [self searchChatMsgFromDB:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyUpdateConversationsName isEqualToString:call.method]) { - [self updateConversationsName:call.arguments - channelName:call.method - result:result]; - } else if ([EMMethodKeyAsyncFetchGroupAcks isEqualToString:call.method]) { + } else if ([ChatAsyncFetchGroupAcks isEqualToString:call.method]) { [self fetchGroupReadAck:call.arguments channelName:call.method result:result]; + } else if ([ChatDeleteRemoteConversation isEqualToString:call.method]){ + [self deleteRemoteConversation:call.arguments + channelName:call.method + result:result]; } else { [super handleMethodCall:call result:result]; @@ -148,21 +148,21 @@ - (void)sendMessage:(NSDictionary *)param [EMClient.sharedClient.chatManager sendMessage:msg progress:^(int progress) { - [weakSelf.messageChannel invokeMethod:EMMethodKeyOnMessageProgressUpdate + [weakSelf.messageChannel invokeMethod:ChatOnMessageProgressUpdate arguments:@{ @"progress":@(progress), @"localTime":@(msg.localTime) }]; } completion:^(EMChatMessage *message, EMError *error) { if (error) { - [weakSelf.messageChannel invokeMethod:EMMethodKeyOnMessageError + [weakSelf.messageChannel invokeMethod:ChatOnMessageError arguments:@{ @"error":[error toJson], @"localTime":@(msg.localTime), @"message":[message toJson] }]; }else { - [weakSelf.messageChannel invokeMethod:EMMethodKeyOnMessageSuccess + [weakSelf.messageChannel invokeMethod:ChatOnMessageSuccess arguments:@{ @"message":[message toJson], @"localTime":@(msg.localTime) @@ -185,21 +185,21 @@ - (void)resendMessage:(NSDictionary *)param [EMClient.sharedClient.chatManager resendMessage:msg progress:^(int progress) { - [weakSelf.messageChannel invokeMethod:EMMethodKeyOnMessageProgressUpdate + [weakSelf.messageChannel invokeMethod:ChatOnMessageProgressUpdate arguments:@{ @"progress":@(progress), @"localTime":@(msg.localTime) }]; } completion:^(EMChatMessage *message, EMError *error) { if (error) { - [weakSelf.messageChannel invokeMethod:EMMethodKeyOnMessageError + [weakSelf.messageChannel invokeMethod:ChatOnMessageError arguments:@{ @"error":[error toJson], @"localTime":@(msg.localTime), @"message":[message toJson] }]; }else { - [weakSelf.messageChannel invokeMethod:EMMethodKeyOnMessageSuccess + [weakSelf.messageChannel invokeMethod:ChatOnMessageSuccess arguments:@{ @"message":[message toJson], @"localTime":@(msg.localTime) @@ -399,7 +399,7 @@ - (void)downloadAttachment:(NSDictionary *)param [EMClient.sharedClient.chatManager downloadMessageAttachment:needDownMSg progress:^(int progress) { - [weakSelf.messageChannel invokeMethod:EMMethodKeyOnMessageProgressUpdate + [weakSelf.messageChannel invokeMethod:ChatOnMessageProgressUpdate arguments:@{ @"progress":@(progress), @"localTime":@(msg.localTime) @@ -407,14 +407,14 @@ - (void)downloadAttachment:(NSDictionary *)param } completion:^(EMChatMessage *message, EMError *error) { if (error) { - [weakSelf.messageChannel invokeMethod:EMMethodKeyOnMessageError + [weakSelf.messageChannel invokeMethod:ChatOnMessageError arguments:@{ @"error":[error toJson], @"localTime":@(msg.localTime), @"message":[message toJson] }]; }else { - [weakSelf.messageChannel invokeMethod:EMMethodKeyOnMessageSuccess + [weakSelf.messageChannel invokeMethod:ChatOnMessageSuccess arguments:@{ @"message":[message toJson], @"localTime":@(msg.localTime) @@ -437,7 +437,7 @@ - (void)downloadThumbnail:(NSDictionary *)param [EMClient.sharedClient.chatManager downloadMessageThumbnail:needDownMSg progress:^(int progress) { - [weakSelf.messageChannel invokeMethod:EMMethodKeyOnMessageProgressUpdate + [weakSelf.messageChannel invokeMethod:ChatOnMessageProgressUpdate arguments:@{ @"progress":@(progress), @"localTime":@(msg.localTime) @@ -445,14 +445,14 @@ - (void)downloadThumbnail:(NSDictionary *)param } completion:^(EMChatMessage *message, EMError *error) { if (error) { - [weakSelf.messageChannel invokeMethod:EMMethodKeyOnMessageError + [weakSelf.messageChannel invokeMethod:ChatOnMessageError arguments:@{ @"error":[error toJson], @"localTime":@(msg.localTime), @"message":[message toJson] }]; }else { - [weakSelf.messageChannel invokeMethod:EMMethodKeyOnMessageSuccess + [weakSelf.messageChannel invokeMethod:ChatOnMessageSuccess arguments:@{ @"message":[message toJson], @"localTime":@(msg.localTime) @@ -566,7 +566,6 @@ - (void)fetchGroupReadAck:(NSDictionary *)param }]; } - - (void)searchChatMsgFromDB:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { @@ -595,33 +594,6 @@ - (void)searchChatMsgFromDB:(NSDictionary *)param }]; } -- (void)updateConversationsName:(NSDictionary *)param - channelName:(NSString *)aChannelName - result:(FlutterResult)result { - __weak typeof(self) weakSelf = self; - NSDictionary *namesMap = param[@"name_map"]; - - NSArray *conversationsList = EMClient.sharedClient.chatManager.getAllConversations; - for (EMConversation *con in conversationsList) { - if (namesMap[con.conversationId]) { - NSMutableDictionary *ext = [con.ext mutableCopy]; - if (!ext) { - ext = [NSMutableDictionary dictionary]; - } - NSString *current = ext[@"con_name"] ?: @""; - if (![current isEqualToString:namesMap[@"con_name"]]) { - ext[@"con_name"] = namesMap[@"con_name"]; - con.ext = ext; - } - } - - } - [weakSelf wrapperCallBack:result - channelName:aChannelName - error:nil - object:@(true)]; -} - - (void)deleteRemoteConversation:(NSDictionary *)param channelName:(NSString *)aChannelName @@ -657,13 +629,13 @@ - (void)deleteRemoteConversation:(NSDictionary *)param - (void)conversationListDidUpdate:(NSArray *)aConversationList { - [self.channel invokeMethod:EMMethodKeyOnConversationUpdate + [self.channel invokeMethod:ChatOnConversationUpdate arguments:nil]; } - (void)onConversationRead:(NSString *)from to:(NSString *)to { - [self.channel invokeMethod:EMMethodKeyOnConversationHasRead + [self.channel invokeMethod:ChatOnConversationHasRead arguments:@{@"from":from, @"to": to}]; } @@ -673,7 +645,7 @@ - (void)messagesDidReceive:(NSArray *)aMessages { [msgList addObject:[msg toJson]]; } - [self.channel invokeMethod:EMMethodKeyOnMessagesReceived + [self.channel invokeMethod:ChatOnMessagesReceived arguments:msgList]; } @@ -683,7 +655,7 @@ - (void)cmdMessagesDidReceive:(NSArray *)aCmdMessages { [cmdMsgList addObject:[msg toJson]]; } - [self.channel invokeMethod:EMMethodKeyOnCmdMessagesReceived + [self.channel invokeMethod:ChatOnCmdMessagesReceived arguments:cmdMsgList]; } @@ -692,11 +664,11 @@ - (void)messagesDidRead:(NSArray *)aMessages { for (EMChatMessage *msg in aMessages) { NSDictionary *json = [msg toJson]; [list addObject:json]; - [self.messageChannel invokeMethod:EMMethodKeyOnMessageReadAck + [self.messageChannel invokeMethod:ChatOnMessageReadAck arguments:json]; } - [self.channel invokeMethod:EMMethodKeyOnMessagesRead arguments:list]; + [self.channel invokeMethod:ChatOnMessagesRead arguments:list]; } - (void)messagesDidDeliver:(NSArray *)aMessages { @@ -704,11 +676,11 @@ - (void)messagesDidDeliver:(NSArray *)aMessages { for (EMChatMessage *msg in aMessages) { NSDictionary *json = [msg toJson]; [list addObject:json]; - [self.messageChannel invokeMethod:EMMethodKeyOnMessageDeliveryAck + [self.messageChannel invokeMethod:ChatOnMessageDeliveryAck arguments:@{@"message":json}]; } - [self.channel invokeMethod:EMMethodKeyOnMessagesDelivered + [self.channel invokeMethod:ChatOnMessagesDelivered arguments:list]; } @@ -718,21 +690,10 @@ - (void)messagesDidRecall:(NSArray *)aMessages { [list addObject:[msg toJson]]; } - [self.channel invokeMethod:EMMethodKeyOnMessagesRecalled + [self.channel invokeMethod:ChatOnMessagesRecalled arguments:list]; } -- (void)messageStatusDidChange:(EMChatMessage *)aMessage - error:(EMError *)aError { - [self.messageChannel invokeMethod:EMMethodKeyOnMessageStatusChanged - arguments:@{@"message":[aMessage toJson]}]; -} - -// TODO: 安卓未找到对应回调 -- (void)messageAttachmentStatusDidChange:(EMChatMessage *)aMessage - error:(EMError *)aError { - -} - (void)groupMessageDidRead:(EMChatMessage *)aMessage groupAcks:(NSArray *)aGroupAcks { NSMutableArray *list = [NSMutableArray array]; @@ -741,7 +702,7 @@ - (void)groupMessageDidRead:(EMChatMessage *)aMessage groupAcks:(NSArray *)aGrou [list addObject:json]; } - [self.channel invokeMethod:EMMethodKeyOnGroupMessageRead + [self.channel invokeMethod:ChatOnGroupMessageRead arguments:list]; } diff --git a/ios/Classes/EMChatMessage+Flutter.m b/ios/Classes/EMChatMessage+Flutter.m index 7ba347b0..4c90c01c 100644 --- a/ios/Classes/EMChatMessage+Flutter.m +++ b/ios/Classes/EMChatMessage+Flutter.m @@ -292,9 +292,11 @@ + (EMMessageBody *)fromJson:(NSDictionary *)aJson { double latitude = [aJson[@"latitude"] doubleValue]; double longitude = [aJson[@"longitude"] doubleValue]; NSString *address = aJson[@"address"]; + NSString *buildingName = aJson[@"buildingName"]; + EMLocationMessageBody *ret = [[EMLocationMessageBody alloc] initWithLatitude:latitude longitude:longitude - address:address]; + address:address buildingName:buildingName]; return ret; } @@ -303,6 +305,7 @@ - (NSDictionary *)toJson { ret[@"address"] = self.address; ret[@"latitude"] = @(self.latitude); ret[@"longitude"] = @(self.longitude); + ret[@"buildingName"] = self.buildingName; return ret; } diff --git a/ios/Classes/EMChatroomManagerWrapper.m b/ios/Classes/EMChatroomManagerWrapper.m index 85d6ad8d..d9f8768b 100644 --- a/ios/Classes/EMChatroomManagerWrapper.m +++ b/ios/Classes/EMChatroomManagerWrapper.m @@ -33,148 +33,148 @@ - (instancetype)initWithChannelName:(NSString *)aChannelName #pragma mark - FlutterPlugin - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - if ([EMMethodKeyJoinChatRoom isEqualToString:call.method]) + if ([ChatJoinChatRoom isEqualToString:call.method]) { [self joinChatroom:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyLeaveChatRoom isEqualToString:call.method]) { + else if ([ChatLeaveChatRoom isEqualToString:call.method]) { [self leaveChatroom:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetChatroomsFromServer isEqualToString:call.method]) { + else if ([ChatGetChatroomsFromServer isEqualToString:call.method]) { [self getChatroomsFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyCreateChatRoom isEqualToString:call.method]) { + else if ([ChatCreateChatRoom isEqualToString:call.method]) { [self createChatroom:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyDestroyChatRoom isEqualToString:call.method]) { + else if ([ChatDestroyChatRoom isEqualToString:call.method]) { [self destroyChatRoom:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyFetchChatRoomFromServer isEqualToString:call.method]) { + else if ([ChatFetchChatRoomFromServer isEqualToString:call.method]) { [self fetchChatroomInfoFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetChatRoom isEqualToString:call.method]) { + else if ([ChatGetChatRoom isEqualToString:call.method]) { [self getChatroom:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetAllChatRooms isEqualToString:call.method]) { + else if ([ChatGetAllChatRooms isEqualToString:call.method]) { [self getAllChatrooms:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetChatroomMemberListFromServer isEqualToString:call.method]) { + else if ([ChatGetChatroomMemberListFromServer isEqualToString:call.method]) { [self getChatroomMemberListFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyFetchChatroomBlockListFromServer isEqualToString:call.method]) { + else if ([ChatFetchChatroomBlockListFromServer isEqualToString:call.method]) { [self fetchChatroomBlockListFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetChatroomMuteListFromServer isEqualToString:call.method]) { + else if ([ChatGetChatroomMuteListFromServer isEqualToString:call.method]) { [self getChatroomMuteListFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyFetchChatroomAnnouncement isEqualToString:call.method]) { + else if ([ChatFetchChatroomAnnouncement isEqualToString:call.method]) { [self fetchChatroomAnnouncement:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyChatRoomUpdateSubject isEqualToString:call.method]) { + else if ([ChatChatRoomUpdateSubject isEqualToString:call.method]) { [self chatRoomUpdateSubject:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyChatRoomUpdateDescription isEqualToString:call.method]) { + else if ([ChatChatRoomUpdateDescription isEqualToString:call.method]) { [self chatRoomUpdateDescription:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyChatRoomRemoveMembers isEqualToString:call.method]) { + else if ([ChatChatRoomRemoveMembers isEqualToString:call.method]) { [self chatRoomRemoveMembers:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyChatRoomBlockMembers isEqualToString:call.method]) { + else if ([ChatChatRoomBlockMembers isEqualToString:call.method]) { [self chatRoomBlockMembers:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyChatRoomUnblockMembers isEqualToString:call.method]) { + else if ([ChatChatRoomUnblockMembers isEqualToString:call.method]) { [self chatRoomUnblockMembers:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyChangeChatRoomOwner isEqualToString:call.method]) { + else if ([ChatChangeChatRoomOwner isEqualToString:call.method]) { [self chatRoomChangeOwner:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyChatRoomAddAdmin isEqualToString:call.method]) { + else if ([ChatChatRoomAddAdmin isEqualToString:call.method]) { [self chatRoomAddAdmin:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyChatRoomRemoveAdmin isEqualToString:call.method]) { + else if ([ChatChatRoomRemoveAdmin isEqualToString:call.method]) { [self chatRoomRemoveAdmin:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyChatRoomMuteMembers isEqualToString:call.method]) { + else if ([ChatChatRoomMuteMembers isEqualToString:call.method]) { [self chatRoomMuteMembers:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyChatRoomUnmuteMembers isEqualToString:call.method]) { + else if ([ChatChatRoomUnmuteMembers isEqualToString:call.method]) { [self chatRoomUnmuteMembers:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyUpdateChatRoomAnnouncement isEqualToString:call.method]) { + else if ([ChatUpdateChatRoomAnnouncement isEqualToString:call.method]) { [self updateChatroomAnnouncement:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyAddMembersToChatRoomWhiteList isEqualToString:call.method]) { + else if ([ChatAddMembersToChatRoomWhiteList isEqualToString:call.method]) { [self addMembersToChatRoomWhiteList:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyRemoveMembersFromChatRoomWhiteList isEqualToString:call.method]) { + else if ([ChatRemoveMembersFromChatRoomWhiteList isEqualToString:call.method]) { [self removeMembersFromChatRoomWhiteList:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyFetchChatRoomWhiteListFromServer isEqualToString:call.method]) { + else if ([ChatFetchChatRoomWhiteListFromServer isEqualToString:call.method]) { [self fetchChatRoomWhiteListFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyIsMemberInChatRoomWhiteListFromServer isEqualToString:call.method]) { + else if ([ChatIsMemberInChatRoomWhiteListFromServer isEqualToString:call.method]) { [self isMemberInChatRoomWhiteListFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyMuteAllChatRoomMembers isEqualToString:call.method]) { + else if ([ChatMuteAllChatRoomMembers isEqualToString:call.method]) { [self muteAllChatRoomMembers:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyUnMuteAllChatRoomMembers isEqualToString:call.method]) { + else if ([ChatUnMuteAllChatRoomMembers isEqualToString:call.method]) { [self unMuteAllChatRoomMembers:call.arguments channelName:call.method result:result]; @@ -666,7 +666,7 @@ - (void)userDidJoinChatroom:(EMChatroom *)aChatroom @"roomId":aChatroom.chatroomId, @"participant":aUsername }; - [self.channel invokeMethod:EMMethodKeyChatroomChanged + [self.channel invokeMethod:ChatChatroomChanged arguments:map]; } @@ -679,7 +679,7 @@ - (void)userDidLeaveChatroom:(EMChatroom *)aChatroom @"roomName":aChatroom.subject, @"participant":aUsername }; - [self.channel invokeMethod:EMMethodKeyChatroomChanged + [self.channel invokeMethod:ChatChatroomChanged arguments:map]; } @@ -704,7 +704,7 @@ - (void)didDismissFromChatroom:(EMChatroom *)aChatroom }; } - [self.channel invokeMethod:EMMethodKeyChatroomChanged + [self.channel invokeMethod:ChatChatroomChanged arguments:map]; } @@ -715,9 +715,9 @@ - (void)chatroomMuteListDidUpdate:(EMChatroom *)aChatroom @"type":@"onMuteListAdded", @"roomId":aChatroom.chatroomId, @"mutes":aMutes, - @"expireTime":[NSString stringWithFormat:@"%ld", aMuteExpire] + @"expireTime":[NSString stringWithFormat:@"%ld", (long)aMuteExpire] }; - [self.channel invokeMethod:EMMethodKeyChatroomChanged + [self.channel invokeMethod:ChatChatroomChanged arguments:map]; } @@ -728,7 +728,7 @@ - (void)chatroomMuteListDidUpdate:(EMChatroom *)aChatroom @"roomId":aChatroom.chatroomId, @"mutes":aMutes }; - [self.channel invokeMethod:EMMethodKeyChatroomChanged + [self.channel invokeMethod:ChatChatroomChanged arguments:map]; } @@ -739,7 +739,7 @@ - (void)chatroomAdminListDidUpdate:(EMChatroom *)aChatroom @"roomId":aChatroom.chatroomId, @"admin":aAdmin }; - [self.channel invokeMethod:EMMethodKeyChatroomChanged + [self.channel invokeMethod:ChatChatroomChanged arguments:map]; } @@ -750,7 +750,7 @@ - (void)chatroomAdminListDidUpdate:(EMChatroom *)aChatroom @"roomId":aChatroom.chatroomId, @"admin":aAdmin }; - [self.channel invokeMethod:EMMethodKeyChatroomChanged + [self.channel invokeMethod:ChatChatroomChanged arguments:map]; } @@ -763,7 +763,7 @@ - (void)chatroomOwnerDidUpdate:(EMChatroom *)aChatroom @"newOwner":aNewOwner, @"oldOwner":aOldOwner }; - [self.channel invokeMethod:EMMethodKeyChatroomChanged + [self.channel invokeMethod:ChatChatroomChanged arguments:map]; } @@ -774,7 +774,7 @@ - (void)chatroomAnnouncementDidUpdate:(EMChatroom *)aChatroom @"roomId":aChatroom.chatroomId, @"announcement":aAnnouncement }; - [self.channel invokeMethod:EMMethodKeyChatroomChanged + [self.channel invokeMethod:ChatChatroomChanged arguments:map]; } @@ -785,7 +785,7 @@ - (void)chatroomWhiteListDidUpdate:(EMChatroom *)aChatroom @"roomId":aChatroom.chatroomId, @"whitelist":aMembers }; - [self.channel invokeMethod:EMMethodKeyChatroomChanged + [self.channel invokeMethod:ChatChatroomChanged arguments:map]; } @@ -797,7 +797,7 @@ - (void)chatroomWhiteListDidUpdate:(EMChatroom *)aChatroom @"roomId":aChatroom.chatroomId, @"whitelist":aMembers }; - [self.channel invokeMethod:EMMethodKeyChatroomChanged + [self.channel invokeMethod:ChatChatroomChanged arguments:map]; } @@ -809,7 +809,7 @@ - (void)chatroomAllMemberMuteChanged:(EMChatroom *)aChatroom @"roomId":aChatroom.chatroomId, @"isMuted":@(aMuted) }; - [self.channel invokeMethod:EMMethodKeyChatroomChanged + [self.channel invokeMethod:ChatChatroomChanged arguments:map]; } diff --git a/ios/Classes/EMClientWrapper.m b/ios/Classes/EMClientWrapper.m index 3217bf55..9fb00e79 100644 --- a/ios/Classes/EMClientWrapper.m +++ b/ios/Classes/EMClientWrapper.m @@ -33,7 +33,7 @@ - (void)sendDataToFlutter:(NSDictionary *)aData { if (aData == nil) { return; } - [self.channel invokeMethod:EMMethodKeySendDataToFlutter + [self.channel invokeMethod:ChatSendDataToFlutter arguments:aData]; } @@ -59,113 +59,104 @@ - (instancetype)initWithChannelName:(NSString *)aChannelName #pragma mark - FlutterPlugin - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - if ([EMMethodKeyInit isEqualToString:call.method]) + if ([ChatInit isEqualToString:call.method]) { [self initSDKWithDict:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyCreateAccount isEqualToString:call.method]) + else if ([ChatCreateAccount isEqualToString:call.method]) { [self createAccount:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyLogin isEqualToString:call.method]) + else if ([ChatLogin isEqualToString:call.method]) { [self login:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyLogout isEqualToString:call.method]) + else if ([ChatLogout isEqualToString:call.method]) { [self logout:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyChangeAppKey isEqualToString:call.method]) + else if ([ChatChangeAppKey isEqualToString:call.method]) { [self changeAppKey:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyUploadLog isEqualToString:call.method]) + else if ([ChatUploadLog isEqualToString:call.method]) { [self uploadLog:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyCompressLogs isEqualToString:call.method]) + else if ([ChatCompressLogs isEqualToString:call.method]) { [self compressLogs:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetLoggedInDevicesFromServer isEqualToString:call.method]) + else if ([ChatGetLoggedInDevicesFromServer isEqualToString:call.method]) { [self getLoggedInDevicesFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyKickDevice isEqualToString:call.method]) + else if ([ChatKickDevice isEqualToString:call.method]) { [self kickDevice:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyKickAllDevices isEqualToString:call.method]) + else if ([ChatKickAllDevices isEqualToString:call.method]) { [self kickAllDevices:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyIsLoggedInBefore isEqualToString:call.method]) + else if([ChatIsLoggedInBefore isEqualToString:call.method]) { [self isLoggedInBefore:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyGetCurrentUser isEqualToString:call.method]) + else if([ChatGetCurrentUser isEqualToString:call.method]) { [self getCurrentUser:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyGetToken isEqualToString:call.method]) + else if([ChatGetToken isEqualToString:call.method]) { [self getToken:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyLoginWithAgoraToken isEqualToString:call.method]) + else if ([ChatLoginWithAgoraToken isEqualToString:call.method]) { - [self loginWithAgoraToken:call.arguments result:result]; + [self loginWithAgoraToken:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyIsConnected isEqualToString:call.method]) + else if([ChatIsConnected isEqualToString:call.method]) { [self isConnected:call.arguments channelName:call.method result:result]; } + else if ([ChatRenewToken isEqualToString:call.method]){ + [self renewToken:call.arguments + channelName:call.method + result:result]; + } else { [super handleMethodCall:call result:result]; } } -- (void)getToken:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result{ - [self wrapperCallBack:result - channelName:aChannelName - error:nil - object:EMClient.sharedClient.accessUserToken]; -} - - -- (void)isConnected:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result{ - [self wrapperCallBack:result - channelName:aChannelName - error:nil - object:@(EMClient.sharedClient.isConnected)]; -} #pragma mark - Actions - (void)initSDKWithDict:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { @@ -173,22 +164,19 @@ - (void)initSDKWithDict:(NSDictionary *)param channelName:(NSString *)aChannelNa __weak typeof(self) weakSelf = self; EMOptions *options = [EMOptions fromJson:param]; - // options.enableConsoleLog = YES; + [EMClient.sharedClient initializeSDKWithOptions:options]; + + [EMClient.sharedClient removeDelegate:self]; + [EMClient.sharedClient removeMultiDevicesDelegate:self]; [EMClient.sharedClient addDelegate:self delegateQueue:nil]; [EMClient.sharedClient addMultiDevicesDelegate:self delegateQueue:nil]; [self registerManagers]; - // 如果有证书名,说明要使用Apns - if (options.apnsCertName.length > 0) { - [self _registerAPNs]; - } + [weakSelf wrapperCallBack:result - channelName:EMMethodKeyInit + channelName:ChatInit error:nil - object:@{ - @"currentUsername": EMClient.sharedClient.currentUsername ?: @"", - @"isLoginBefore": @(EMClient.sharedClient.isLoggedIn) - }]; + object:nil]; } @@ -229,9 +217,8 @@ - (void)login:(NSDictionary *)param channelName:(NSString *)aChannelName result: if (isPwd) { [EMClient.sharedClient loginWithUsername:username password:pwdOrToken - completion:^(NSString *aUsername, EMError *aError) - { - + completion:^(NSString *aUsername, EMError *aError){ + [weakSelf wrapperCallBack:result channelName:aChannelName error:aError @@ -344,7 +331,7 @@ - (void)isLoggedInBefore:(NSDictionary *)param channelName:(NSString *)aChannelN } -- (void)loginWithAgoraToken:(NSDictionary *)param result:(FlutterResult)result { +- (void)loginWithAgoraToken:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self) weakSelf = self; NSString *username = param[@"username"]; NSString *agoraToken = param[@"agoratoken"]; @@ -353,17 +340,37 @@ - (void)loginWithAgoraToken:(NSDictionary *)param result:(FlutterResult)result { completion:^(NSString *aUsername, EMError *aError) { [weakSelf wrapperCallBack:result - channelName:EMMethodKeyLoginWithAgoraToken + channelName:aChannelName error:aError - object:@{ - @"username": aUsername, - @"token": EMClient.sharedClient.accessUserToken - }]; + object:EMClient.sharedClient.currentUsername]; }]; } -- (void)onMultiDeviceEvent:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { + +- (void)getToken:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result{ + [self wrapperCallBack:result + channelName:aChannelName + error:nil + object:EMClient.sharedClient.accessUserToken]; +} + + +- (void)isConnected:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result{ + [self wrapperCallBack:result + channelName:aChannelName + error:nil + object:@(EMClient.sharedClient.isConnected)]; +} + +- (void)renewToken:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result{ + NSString *newAgoraToken = param[@"agora_token"]; + [EMClient.sharedClient renewToken:newAgoraToken]; + [self wrapperCallBack:result + channelName:aChannelName + error:nil + object:nil]; } + - (void)getLoggedInDevicesFromServer:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self)weakSelf = self; NSString *username = param[@"username"]; @@ -407,13 +414,13 @@ - (void)autoLoginDidCompleteWithError:(EMError *)aError { // 声网token即将过期 - (void)tokenWillExpire:(int)aErrorCode { - [self.channel invokeMethod:EMMethodKeyOnTokenWillExpire + [self.channel invokeMethod:ChatOnTokenWillExpire arguments:nil]; } // 声网token过期 - (void)tokenDidExpire:(int)aErrorCode { - [self.channel invokeMethod:EMMethodKeyOnTokenDidExpire + [self.channel invokeMethod:ChatOnTokenDidExpire arguments:nil]; } @@ -438,69 +445,33 @@ - (void)userAccountDidForcedToLogout:(EMError *)aError { - (void)multiDevicesContactEventDidReceive:(EMMultiDevicesEvent)aEvent username:(NSString *)aUsername ext:(NSString *)aExt { - + NSMutableDictionary *data = [NSMutableDictionary dictionary]; + data[@"event"] = @(aEvent); + data[@"target"] = aUsername; + data[@"ext"] = aExt; + [self.channel invokeMethod:ChatOnMultiDeviceEvent arguments:data]; } - (void)multiDevicesGroupEventDidReceive:(EMMultiDevicesEvent)aEvent groupId:(NSString *)aGroupId ext:(id)aExt { - + NSMutableDictionary *data = [NSMutableDictionary dictionary]; + data[@"event"] = @(aEvent); + data[@"target"] = aGroupId; + data[@"userNames"] = aExt; + [self.channel invokeMethod:ChatOnMultiDeviceEvent arguments:data]; } #pragma mark - Merge Android and iOS Method - (void)onConnected { - [self.channel invokeMethod:EMMethodKeyOnConnected + [self.channel invokeMethod:ChatOnConnected arguments:@{@"connected" : @(YES)}]; } - (void)onDisconnected:(int)errorCode { - [self.channel invokeMethod:EMMethodKeyOnDisconnected + [self.channel invokeMethod:ChatOnDisconnected arguments:@{@"errorCode" : @(errorCode)}]; } -#pragma mark - register APNs -- (void)_registerAPNs { - UIApplication *application = [UIApplication sharedApplication]; - application.applicationIconBadgeNumber = 0; - - if (NSClassFromString(@"UNUserNotificationCenter")) { - // [UNUserNotificationCenter currentNotificationCenter].delegate = self; - [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert completionHandler:^(BOOL granted, NSError *error) { - if (granted) { -#if !TARGET_IPHONE_SIMULATOR - dispatch_async(dispatch_get_main_queue(), ^{ - [application registerForRemoteNotifications]; - }); -#endif - } - }]; - return; - } - - if([application respondsToSelector:@selector(registerUserNotificationSettings:)]) { - UIUserNotificationType notificationTypes = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert; - UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:notificationTypes categories:nil]; - [application registerUserNotificationSettings:settings]; - } - -#if !TARGET_IPHONE_SIMULATOR - if ([application respondsToSelector:@selector(registerForRemoteNotifications)]) { - [application registerForRemoteNotifications]; - } -#endif -} - -#pragma mark - AppDelegate - -//- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { -// -// return YES; -//} -// -//- (void)applicationDidBecomeActive:(UIApplication *)application { -// -//} - - @end diff --git a/ios/Classes/EMContactManagerWrapper.m b/ios/Classes/EMContactManagerWrapper.m index 19d2e558..68498d15 100644 --- a/ios/Classes/EMContactManagerWrapper.m +++ b/ios/Classes/EMContactManagerWrapper.m @@ -27,47 +27,47 @@ - (instancetype)initWithChannelName:(NSString *)aChannelName - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - if ([EMMethodKeyAddContact isEqualToString:call.method]) { + if ([ChatAddContact isEqualToString:call.method]) { [self addContact:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyDeleteContact isEqualToString:call.method]) { + } else if ([ChatDeleteContact isEqualToString:call.method]) { [self deleteContact:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetAllContactsFromServer isEqualToString:call.method]) { + } else if ([ChatGetAllContactsFromServer isEqualToString:call.method]) { [self getAllContactsFromServer:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetAllContactsFromDB isEqualToString:call.method]) { + } else if ([ChatGetAllContactsFromDB isEqualToString:call.method]) { [self getAllContactsFromDB:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyAddUserToBlockList isEqualToString:call.method]) { + } else if ([ChatAddUserToBlockList isEqualToString:call.method]) { [self addUserToBlockList:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyRemoveUserFromBlockList isEqualToString:call.method]) { + } else if ([ChatRemoveUserFromBlockList isEqualToString:call.method]) { [self removeUserFromBlockList:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetBlockListFromServer isEqualToString:call.method]) { + } else if ([ChatGetBlockListFromServer isEqualToString:call.method]) { [self getBlockListFromServer:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetBlockListFromDB isEqualToString:call.method]){ + } else if ([ChatGetBlockListFromDB isEqualToString:call.method]){ [self getBlockListFromDB:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyAcceptInvitation isEqualToString:call.method]) { + } else if ([ChatAcceptInvitation isEqualToString:call.method]) { [self acceptInvitation:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyDeclineInvitation isEqualToString:call.method]) { + } else if ([ChatDeclineInvitation isEqualToString:call.method]) { [self declineInvitation:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetSelfIdsOnOtherPlatform isEqualToString:call.method]) { + } else if ([ChatGetSelfIdsOnOtherPlatform isEqualToString:call.method]) { [self getSelfIdsOnOtherPlatform:call.arguments channelName:call.method result:result]; @@ -218,7 +218,7 @@ - (void)friendshipDidAddByUser:(NSString *)aUsername { @"type":@"onContactAdded", @"username":aUsername }; - [self.channel invokeMethod:EMMethodKeyOnContactChanged + [self.channel invokeMethod:ChatOnContactChanged arguments:map]; } @@ -227,7 +227,7 @@ - (void)friendshipDidRemoveByUser:(NSString *)aUsername { @"type":@"onContactDeleted", @"username":aUsername }; - [self.channel invokeMethod:EMMethodKeyOnContactChanged + [self.channel invokeMethod:ChatOnContactChanged arguments:map]; } @@ -238,7 +238,7 @@ - (void)friendRequestDidReceiveFromUser:(NSString *)aUsername @"username":aUsername, @"reason":aMessage }; - [self.channel invokeMethod:EMMethodKeyOnContactChanged + [self.channel invokeMethod:ChatOnContactChanged arguments:map]; } @@ -247,7 +247,7 @@ - (void)friendRequestDidApproveByUser:(NSString *)aUsername { @"type":@"onFriendRequestAccepted", @"username":aUsername }; - [self.channel invokeMethod:EMMethodKeyOnContactChanged + [self.channel invokeMethod:ChatOnContactChanged arguments:map]; } @@ -256,7 +256,7 @@ - (void)friendRequestDidDeclineByUser:(NSString *)aUsername { @"type":@"onFriendRequestDeclined", @"username":aUsername }; - [self.channel invokeMethod:EMMethodKeyOnContactChanged + [self.channel invokeMethod:ChatOnContactChanged arguments:map]; } diff --git a/ios/Classes/EMConversation+Flutter.m b/ios/Classes/EMConversation+Flutter.m index 9ddc90db..1c205410 100644 --- a/ios/Classes/EMConversation+Flutter.m +++ b/ios/Classes/EMConversation+Flutter.m @@ -13,10 +13,7 @@ - (NSDictionary *)toJson { NSMutableDictionary *ret = [NSMutableDictionary dictionary]; ret[@"con_id"] = self.conversationId; ret[@"type"] = @([self.class typeToInt:self.type]); - ret[@"unreadCount"] = @(self.unreadMessagesCount); ret[@"ext"] = self.ext; - ret[@"latestMessage"] = [self.latestMessage toJson]; - ret[@"lastReceivedMessage"] = [self.lastReceivedMessage toJson]; return ret; } diff --git a/ios/Classes/EMConversationWrapper.m b/ios/Classes/EMConversationWrapper.m index d4f50a58..34e8cdca 100644 --- a/ios/Classes/EMConversationWrapper.m +++ b/ios/Classes/EMConversationWrapper.m @@ -29,71 +29,67 @@ - (instancetype)initWithChannelName:(NSString *)aChannelName - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - if ([EMMethodKeyLoadMsgWithId isEqualToString:call.method]) { + if ([ChatLoadMsgWithId isEqualToString:call.method]) { [self loadMsgWithId:call.arguments channelName:call.method result:result]; - } else if([EMMethodKeyLoadMsgWithStartId isEqualToString:call.method]){ + } else if([ChatLoadMsgWithStartId isEqualToString:call.method]){ [self loadMsgWithStartId:call.arguments channelName:call.method result:result]; - } else if([EMMethodKeyLoadMsgWithKeywords isEqualToString:call.method]){ + } else if([ChatLoadMsgWithKeywords isEqualToString:call.method]){ [self loadMsgWithKeywords:call.arguments channelName:call.method result:result]; - } else if([EMMethodKeyLoadMsgWithMsgType isEqualToString:call.method]){ + } else if([ChatLoadMsgWithMsgType isEqualToString:call.method]){ [self loadMsgWithMsgType:call.arguments channelName:call.method result:result]; - } else if([EMMethodKeyLoadMsgWithTime isEqualToString:call.method]){ + } else if([ChatLoadMsgWithTime isEqualToString:call.method]){ [self loadMsgWithTime:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetUnreadMsgCount isEqualToString:call.method]) { + } else if ([ChatGetUnreadMsgCount isEqualToString:call.method]) { [self getUnreadMsgCount:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyMarkAllMsgsAsRead isEqualToString:call.method]) { + } else if ([ChatMarkAllMsgsAsRead isEqualToString:call.method]) { [self markAllMessagesAsRead:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyMarkMsgAsRead isEqualToString:call.method]) { + } else if ([ChatMarkMsgAsRead isEqualToString:call.method]) { [self markMessageAsRead:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeySyncConversationExt isEqualToString:call.method]){ + } else if ([ChatSyncConversationExt isEqualToString:call.method]){ [self syncConversationExt:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeySyncConversationName isEqualToString:call.method]){ - [self syncConversationName:call.arguments - channelName:call.method - result:result]; - } else if ([EMMethodKeyRemoveMsg isEqualToString:call.method]) { + } else if ([ChatRemoveMsg isEqualToString:call.method]) { [self removeMessage:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetLatestMsg isEqualToString:call.method]) { + } else if ([ChatGetLatestMsg isEqualToString:call.method]) { [self getLatestMessage:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetLatestMsgFromOthers isEqualToString:call.method]) { + } else if ([ChatGetLatestMsgFromOthers isEqualToString:call.method]) { [self getLatestMessageFromOthers:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyClearAllMsg isEqualToString:call.method]) { + } else if ([ChatClearAllMsg isEqualToString:call.method]) { [self clearAllMessages:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyInsertMsg isEqualToString:call.method]) { + } else if ([ChatInsertMsg isEqualToString:call.method]) { [self insertMessage:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyAppendMsg isEqualToString:call.method]) { + } else if ([ChatAppendMsg isEqualToString:call.method]) { [self appendMessage:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyUpdateConversationMsg isEqualToString:call.method]) { + } else if ([ChatUpdateConversationMsg isEqualToString:call.method]) { [self updateConversationMessage:call.arguments channelName:call.method result:result]; @@ -183,28 +179,6 @@ - (void)markMessageAsRead:(NSDictionary *)param }]; } -- (void)syncConversationName:(NSDictionary *)param - channelName:(NSString *)aChannelName - result:(FlutterResult)result -{ - __weak typeof(self) weakSelf = self; - [self getConversationWithParam:param - completion:^(EMConversation *conversation) - { - NSString *name = param[@"con_name"]; - NSMutableDictionary *ext = [conversation.ext mutableCopy]; - if (!ext) { - ext = [NSMutableDictionary dictionary]; - } - ext[@"con_name"] = name; - conversation.ext = ext; - [weakSelf wrapperCallBack:result - channelName:aChannelName - error:nil - object:@(YES)]; - }]; -} - - (void)syncConversationExt:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result diff --git a/ios/Classes/EMGroup+Flutter.m b/ios/Classes/EMGroup+Flutter.m index b4b264c5..f39d521e 100644 --- a/ios/Classes/EMGroup+Flutter.m +++ b/ios/Classes/EMGroup+Flutter.m @@ -27,7 +27,7 @@ - (NSDictionary *)toJson { ret[@"isAllMemberMuted"] = @(self.isMuteAllMembers); ret[@"options"] = [self.setting toJson]; ret[@"permissionType"] = @([EMGroup premissionTypeToInt:self.permissionType]); - + return ret; } @@ -94,7 +94,7 @@ + (EMGroupPermissionType)premissionTypeFromInt:(int)type { @implementation EMGroupOptions (Flutter) - (NSDictionary *)toJson { NSMutableDictionary *ret = [NSMutableDictionary dictionary]; - ret[@"maxCount"] = @(self.maxUsersCount); + ret[@"maxCount"] = @(self.maxUsers); ret[@"ext"] = self.ext; ret[@"style"] = @([EMGroupOptions styleToInt:self.style]); ret[@"inviteNeedConfirm"] = @(self.IsInviteNeedConfirm); @@ -103,7 +103,7 @@ - (NSDictionary *)toJson { + (EMGroupOptions *)formJson:(NSDictionary *)dict { EMGroupOptions *options = [[EMGroupOptions alloc] init]; - options.maxUsersCount = [dict[@"maxCount"] intValue]; + options.maxUsers = [dict[@"maxCount"] intValue]; options.ext = dict[@"ext"]; options.IsInviteNeedConfirm = [dict[@"inviteNeedConfirm"] boolValue]; options.style = [EMGroupOptions styleFromInt:[dict[@"style"] intValue]]; diff --git a/ios/Classes/EMGroupManagerWrapper.m b/ios/Classes/EMGroupManagerWrapper.m index b649f46b..1a748ff3 100644 --- a/ios/Classes/EMGroupManagerWrapper.m +++ b/ios/Classes/EMGroupManagerWrapper.m @@ -33,275 +33,275 @@ - (instancetype)initWithChannelName:(NSString *)aChannelName - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - if([EMMethodKeyGetGroupWithId isEqualToString:call.method]) { + if([ChatGetGroupWithId isEqualToString:call.method]) { [self getGroupWithId:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetJoinedGroups isEqualToString:call.method]) + else if ([ChatGetJoinedGroups isEqualToString:call.method]) { [self getJoinedGroups:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetGroupsWithoutPushNotification isEqualToString:call.method]) + else if ([ChatGetGroupsWithoutPushNotification isEqualToString:call.method]) { [self getGroupsWithoutPushNotification:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetJoinedGroupsFromServer isEqualToString:call.method]) + else if ([ChatGetJoinedGroupsFromServer isEqualToString:call.method]) { [self getJoinedGroupsFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetPublicGroupsFromServer isEqualToString:call.method]) + else if ([ChatGetPublicGroupsFromServer isEqualToString:call.method]) { [self getPublicGroupsFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyCreateGroup isEqualToString:call.method]) + else if ([ChatCreateGroup isEqualToString:call.method]) { [self createGroup:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetGroupSpecificationFromServer isEqualToString:call.method]) + else if ([ChatGetGroupSpecificationFromServer isEqualToString:call.method]) { [self getGroupSpecificationFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetGroupMemberListFromServer isEqualToString:call.method]) + else if ([ChatGetGroupMemberListFromServer isEqualToString:call.method]) { [self getGroupMemberListFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetGroupBlockListFromServer isEqualToString:call.method]) + else if ([ChatGetGroupBlockListFromServer isEqualToString:call.method]) { [self getGroupBlockListFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetGroupMuteListFromServer isEqualToString:call.method]) + else if ([ChatGetGroupMuteListFromServer isEqualToString:call.method]) { [self getGroupMuteListFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetGroupWhiteListFromServer isEqualToString:call.method]) + else if ([ChatGetGroupWhiteListFromServer isEqualToString:call.method]) { [self getGroupWhiteListFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyIsMemberInWhiteListFromServer isEqualToString:call.method]) + else if ([ChatIsMemberInWhiteListFromServer isEqualToString:call.method]) { [self isMemberInWhiteListFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetGroupFileListFromServer isEqualToString:call.method]) + else if ([ChatGetGroupFileListFromServer isEqualToString:call.method]) { [self getGroupFileListFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyGetGroupAnnouncementFromServer isEqualToString:call.method]) + else if ([ChatGetGroupAnnouncementFromServer isEqualToString:call.method]) { [self getGroupAnnouncementFromServer:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyAddMembers isEqualToString:call.method]) + else if ([ChatAddMembers isEqualToString:call.method]) { [self addMembers:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyInviterUser isEqualToString:call.method]){ + else if ([ChatInviterUser isEqualToString:call.method]){ [self inviterUsers:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyRemoveMembers isEqualToString:call.method]) + else if ([ChatRemoveMembers isEqualToString:call.method]) { [self removeMembers:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyBlockMembers isEqualToString:call.method]) + else if ([ChatBlockMembers isEqualToString:call.method]) { [self blockMembers:call.arguments channelName:call.method result:result]; } - else if ([EMMethodKeyUnblockMembers isEqualToString:call.method]) + else if ([ChatUnblockMembers isEqualToString:call.method]) { [self unblockMembers:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyUpdateGroupSubject isEqualToString:call.method]) + else if([ChatUpdateGroupSubject isEqualToString:call.method]) { [self updateGroupSubject:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyUpdateDescription isEqualToString:call.method]) + else if([ChatUpdateDescription isEqualToString:call.method]) { [self updateDescription:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyLeaveGroup isEqualToString:call.method]) + else if([ChatLeaveGroup isEqualToString:call.method]) { [self leaveGroup:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyDestroyGroup isEqualToString:call.method]) + else if([ChatDestroyGroup isEqualToString:call.method]) { [self destroyGroup:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyBlockGroup isEqualToString:call.method]) + else if([ChatBlockGroup isEqualToString:call.method]) { [self blockGroup:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyUnblockGroup isEqualToString:call.method]) + else if([ChatUnblockGroup isEqualToString:call.method]) { [self unblockGroup:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyUpdateGroupOwner isEqualToString:call.method]) + else if([ChatUpdateGroupOwner isEqualToString:call.method]) { [self updateGroupOwner:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyAddAdmin isEqualToString:call.method]) + else if([ChatAddAdmin isEqualToString:call.method]) { [self addAdmin:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyRemoveAdmin isEqualToString:call.method]) + else if([ChatRemoveAdmin isEqualToString:call.method]) { [self removeAdmin:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyMuteMembers isEqualToString:call.method]) + else if([ChatMuteMembers isEqualToString:call.method]) { [self muteMembers:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyUnMuteMembers isEqualToString:call.method]) + else if([ChatUnMuteMembers isEqualToString:call.method]) { [self unMuteMembers:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyMuteAllMembers isEqualToString:call.method]) + else if([ChatMuteAllMembers isEqualToString:call.method]) { [self muteAllMembers:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyUnMuteAllMembers isEqualToString:call.method]) + else if([ChatUnMuteAllMembers isEqualToString:call.method]) { [self unMuteAllMembers:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyAddWhiteList isEqualToString:call.method]) + else if([ChatAddWhiteList isEqualToString:call.method]) { [self addWhiteList:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyRemoveWhiteList isEqualToString:call.method]) + else if([ChatRemoveWhiteList isEqualToString:call.method]) { [self removeWhiteList:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyUploadGroupSharedFile isEqualToString:call.method]) + else if([ChatUploadGroupSharedFile isEqualToString:call.method]) { [self uploadGroupSharedFile:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyDownloadGroupSharedFile isEqualToString:call.method]) + else if([ChatDownloadGroupSharedFile isEqualToString:call.method]) { [self downloadGroupSharedFile:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyRemoveGroupSharedFile isEqualToString:call.method]) + else if([ChatRemoveGroupSharedFile isEqualToString:call.method]) { [self removeGroupSharedFile:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyUpdateGroupAnnouncement isEqualToString:call.method]) + else if([ChatUpdateGroupAnnouncement isEqualToString:call.method]) { [self updateGroupAnnouncement:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyUpdateGroupExt isEqualToString:call.method]) + else if([ChatUpdateGroupExt isEqualToString:call.method]) { [self updateGroupExt:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyJoinPublicGroup isEqualToString:call.method]) + else if([ChatJoinPublicGroup isEqualToString:call.method]) { [self joinPublicGroup:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyRequestToJoinPublicGroup isEqualToString:call.method]) + else if([ChatRequestToJoinPublicGroup isEqualToString:call.method]) { [self requestToJoinPublicGroup:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyAcceptJoinApplication isEqualToString:call.method]) + else if([ChatAcceptJoinApplication isEqualToString:call.method]) { [self acceptJoinApplication:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyDeclineJoinApplication isEqualToString:call.method]) + else if([ChatDeclineJoinApplication isEqualToString:call.method]) { [self declineJoinApplication:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyAcceptInvitationFromGroup isEqualToString:call.method]) + else if([ChatAcceptInvitationFromGroup isEqualToString:call.method]) { [self acceptInvitationFromGroup:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyDeclineInvitationFromGroup isEqualToString:call.method]) + else if([ChatDeclineInvitationFromGroup isEqualToString:call.method]) { [self declineInvitationFromGroup:call.arguments channelName:call.method result:result]; } - else if([EMMethodKeyIgnoreGroupPush isEqualToString:call.method]) + else if([ChatIgnoreGroupPush isEqualToString:call.method]) { [self ignoreGroupPush:call.arguments channelName:call.method @@ -842,6 +842,7 @@ - (void)updateGroupExt:(NSDictionary *)param channelName:(NSString *)aChannelNam - (void)joinPublicGroup:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self) weakSelf = self; + [EMClient.sharedClient.groupManager joinPublicGroup:param[@"groupId"] completion:^(EMGroup *aGroup, EMError *aError) { @@ -945,7 +946,7 @@ - (void)groupInvitationDidReceive:(NSString *)aGroupId @"inviter":aInviter, @"message":aMessage }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -957,7 +958,7 @@ - (void)groupInvitationDidAccept:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"invitee":aInvitee }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -971,7 +972,7 @@ - (void)groupInvitationDidDecline:(EMGroup *)aGroup @"invitee":aInvitee, @"reason":aReason }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -984,7 +985,7 @@ - (void)didJoinGroup:(EMGroup *)aGroup @"message":aMessage, @"inviter":aInviter }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1001,7 +1002,7 @@ - (void)didLeaveGroup:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"groupName":aGroup.groupName }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1014,7 +1015,7 @@ - (void)joinGroupRequestDidReceive:(EMGroup *)aGroup @"applicant":aUsername, @"reason":aReason }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1025,7 +1026,7 @@ - (void)joinGroupRequestDidDecline:(NSString *)aGroupId @"groupId":aGroupId, @"reason":aReason }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1036,7 +1037,7 @@ - (void)joinGroupRequestDidApprove:(EMGroup *)aGroup { @"groupName":aGroup.groupName, @"accepter":aGroup.owner, }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1049,7 +1050,7 @@ - (void)groupMuteListDidUpdate:(EMGroup *)aGroup @"mutes":aMutedMembers, @"muteExpire":[NSNumber numberWithInteger:aMuteExpire] }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1060,7 +1061,7 @@ - (void)groupMuteListDidUpdate:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"mutes":aMutedMembers }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1071,7 +1072,7 @@ - (void)groupWhiteListDidUpdate:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"whitelist":aMembers }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1082,7 +1083,7 @@ - (void)groupWhiteListDidUpdate:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"whitelist":aMembers }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1093,7 +1094,7 @@ - (void)groupAllMemberMuteChanged:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"isMuted":@(aMuted) }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1104,7 +1105,7 @@ - (void)groupAdminListDidUpdate:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"administrator":aAdmin }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1115,7 +1116,7 @@ - (void)groupAdminListDidUpdate:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"administrator":aAdmin }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1128,7 +1129,7 @@ - (void)groupOwnerDidUpdate:(EMGroup *)aGroup @"newOwner":aNewOwner, @"oldOwner":aOldOwner }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1139,7 +1140,7 @@ - (void)userDidJoinGroup:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"member":aUsername }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1150,7 +1151,7 @@ - (void)userDidLeaveGroup:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"member":aUsername }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1161,7 +1162,7 @@ - (void)groupAnnouncementDidUpdate:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"announcement":aAnnouncement }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1172,7 +1173,7 @@ - (void)groupFileListDidUpdate:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"sharedFile":[aSharedFile toJson] }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } @@ -1183,7 +1184,7 @@ - (void)groupFileListDidUpdate:(EMGroup *)aGroup @"groupId":aGroup.groupId, @"fileId":aFileId }; - [self.channel invokeMethod:EMMethodKeyOnGroupChanged + [self.channel invokeMethod:ChatOnGroupChanged arguments:map]; } diff --git a/ios/Classes/EMOptions+Flutter.m b/ios/Classes/EMOptions+Flutter.m index 36695887..094c83dd 100644 --- a/ios/Classes/EMOptions+Flutter.m +++ b/ios/Classes/EMOptions+Flutter.m @@ -17,12 +17,12 @@ - (NSDictionary *)toJson { data[@"requireAck"] = @(self.enableRequireReadAck); data[@"requireDeliveryAck"] = @(self.enableDeliveryAck); data[@"sortMessageByServerTime"] = @(self.sortMessageByServerTime); - data[@"acceptInvitationAlways"] = @(self.isAutoAcceptFriendInvitation); - data[@"autoAcceptGroupInvitation"] = @(self.isAutoAcceptGroupInvitation); - data[@"deleteMessagesAsExitGroup"] = @(self.isDeleteMessagesWhenExitGroup); - data[@"deleteMessagesAsExitChatRoom"] = @(self.isDeleteMessagesWhenExitChatRoom); - data[@"isAutoDownload"] = @(self.isAutoDownloadThumbnail); - data[@"isChatRoomOwnerLeaveAllowed"] = @(self.isChatroomOwnerLeaveAllowed); + data[@"acceptInvitationAlways"] = @(self.autoAcceptFriendInvitation); + data[@"autoAcceptGroupInvitation"] = @(self.autoAcceptGroupInvitation); + data[@"deleteMessagesAsExitGroup"] = @(self.deleteMessagesOnLeaveGroup); + data[@"deleteMessagesAsExitChatRoom"] = @(self.deleteMessagesOnLeaveChatroom); + data[@"isAutoDownload"] = @(self.autoDownloadThumbnail); + data[@"isChatRoomOwnerLeaveAllowed"] = @(self.canChatroomOwnerLeave); data[@"serverTransfer"] = @(self.isAutoTransferMessageAttachments); data[@"usingHttpsOnly"] = @(self.usingHttpsOnly); data[@"pushConfig"] = @{@"pushConfig": @{@"apnsCertName": self.apnsCertName}}; @@ -41,12 +41,12 @@ + (EMOptions *)fromJson:(NSDictionary *)aJson { options.enableRequireReadAck = [aJson[@"requireAck"] boolValue]; options.enableDeliveryAck = [aJson[@"requireDeliveryAck"] boolValue]; options.sortMessageByServerTime = [aJson[@"sortMessageByServerTime"] boolValue]; - options.isAutoAcceptFriendInvitation = [aJson[@"acceptInvitationAlways"] boolValue]; - options.isAutoAcceptGroupInvitation = [aJson[@"autoAcceptGroupInvitation"] boolValue]; - options.isDeleteMessagesWhenExitGroup = [aJson[@"deleteMessagesAsExitGroup"] boolValue]; - options.isDeleteMessagesWhenExitChatRoom = [aJson[@"deleteMessagesAsExitChatRoom"] boolValue]; - options.isAutoDownloadThumbnail = [aJson[@"isAutoDownload"] boolValue]; - options.isChatroomOwnerLeaveAllowed = [aJson[@"isChatRoomOwnerLeaveAllowed"] boolValue]; + options.autoAcceptFriendInvitation = [aJson[@"acceptInvitationAlways"] boolValue]; + options.autoAcceptGroupInvitation = [aJson[@"autoAcceptGroupInvitation"] boolValue]; + options.deleteMessagesOnLeaveGroup = [aJson[@"deleteMessagesAsExitGroup"] boolValue]; + options.deleteMessagesOnLeaveChatroom = [aJson[@"deleteMessagesAsExitChatRoom"] boolValue]; + options.autoDownloadThumbnail = [aJson[@"isAutoDownload"] boolValue]; + options.canChatroomOwnerLeave = [aJson[@"isChatRoomOwnerLeaveAllowed"] boolValue]; options.isAutoTransferMessageAttachments = [aJson[@"serverTransfer"] boolValue]; options.usingHttpsOnly = [aJson[@"usingHttpsOnly"] boolValue]; options.apnsCertName = aJson[@"pushConfig"][@"apnsCertName"]; diff --git a/ios/Classes/EMPushManagerWrapper.m b/ios/Classes/EMPushManagerWrapper.m index 8f4811b0..83ba801c 100644 --- a/ios/Classes/EMPushManagerWrapper.m +++ b/ios/Classes/EMPushManagerWrapper.m @@ -24,46 +24,50 @@ - (instancetype)initWithChannelName:(NSString *)aChannelName - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - if ([EMMethodKeyGetImPushConfig isEqualToString:call.method]) { + if ([ChatGetImPushConfig isEqualToString:call.method]) { [self getImPushConfig:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyGetImPushConfigFromServer isEqualToString:call.method]) { + } else if ([ChatGetImPushConfigFromServer isEqualToString:call.method]) { [self getImPushConfigFromServer:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyUpdatePushNickname isEqualToString:call.method]) { + } else if ([ChatUpdatePushNickname isEqualToString:call.method]) { [self updatePushNickname:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyImPushNoDisturb isEqualToString:call.method]) { - [self setImPushNoDisturb:call.arguments - channelName:call.method - result:result]; - } else if ([EMMethodKeyUpdateImPushStyle isEqualToString:call.method]) { + } else if ([ChatUpdateImPushStyle isEqualToString:call.method]) { [self updateImPushStyle:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeyUpdateGroupPushService isEqualToString:call.method]) { + } else if ([ChatUpdateGroupPushService isEqualToString:call.method]) { [self updateGroupPushService:call.arguments - channelName:EMMethodKeyUpdateGroupPushService + channelName:call.method result:result]; - } else if ([EMMethodKeyGetNoDisturbGroups isEqualToString:call.method]) { - [self getNoDisturbGroups:call.arguments - channelName:call.method - result:result]; - } else if ([EMMethodKeyBindDeviceToken isEqualToString:call.method]) { + } else if ([ChatBindDeviceToken isEqualToString:call.method]) { [self bindDeviceToken:call.arguments channelName:call.method result:result]; - } else if ([EMMethodKeySetNoDisturbUsers isEqualToString:call.method]) { - [self setNoDisturbUsers:call.arguments - channelName:EMMethodKeySetNoDisturbUsers - result:result]; - } else if ([EMMethodKeyGetNoDisturbUsersFromServer isEqualToString:call.method]) { - [self getNoDisturbUsersFromServer:call.arguments - channelName:EMMethodKeyGetNoDisturbUsersFromServer - result:result]; + } else if ([ChatEnablePush isEqualToString:call.method]) { + [self enablePush:call.arguments + channelName:call.method + result:result]; + } else if ([ChatDisablePush isEqualToString:call.method]) { + [self disablePush:call.arguments + channelName:call.method + result:result]; + } else if ([ChatGetNoPushGroups isEqualToString:call.method]) { + [self getNoPushGroups:call.arguments + channelName:call.method + result:result]; + } else if ([ChatUpdateUserPushService isEqualToString:call.method]){ + [self updateUserPushService:call.arguments + channelName:call.method + result:result]; + } else if ([ChatGetNoPushUsers isEqualToString:call.method]){ + [self getNoPushUsers:call.arguments + channelName:call.method + result:result]; } else{ [super handleMethodCall:call result:result]; @@ -111,33 +115,6 @@ - (void)updatePushNickname:(NSDictionary *)param } -- (void)setImPushNoDisturb:(NSDictionary *)param - channelName:(NSString *)aChannelName - result:(FlutterResult)result { - __weak typeof(self) weakSelf = self; - - bool noDisturb = [param[@"noDisturb"] boolValue]; - int startTime = [param[@"startTime"] intValue]; - int endTime = [param[@"endTime"] intValue]; - - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - EMError *aError = nil; - if (noDisturb) { - aError = [EMClient.sharedClient.pushManager disableOfflinePushStart:startTime end:endTime]; - }else { - aError = [EMClient.sharedClient.pushManager enableOfflinePush]; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - [weakSelf wrapperCallBack:result - channelName:aChannelName - error:aError - object:@(!aError)]; - }); - }); - - -} - (void)updateImPushStyle:(NSDictionary *)param channelName:(NSString *)aChannelName @@ -161,92 +138,114 @@ - (void)updateGroupPushService:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self) weakSelf = self; - NSString *groupId = param[@"group_id"]; - bool enablePush = [param[@"enablePush"] boolValue]; + NSArray *groupIds = param[@"group_ids"]; + bool noPush = [param[@"noPush"] boolValue]; - [EMClient.sharedClient.pushManager updatePushServiceForGroups:@[groupId] - disablePush:!enablePush + [EMClient.sharedClient.pushManager updatePushServiceForGroups:groupIds + disablePush:noPush completion:^(EMError * _Nonnull aError) { - EMGroup *aGroup = [EMGroup groupWithId:groupId]; [weakSelf wrapperCallBack:result channelName:aChannelName error:aError - object:[aGroup toJson]]; + object:nil]; }]; } -- (void)getNoDisturbGroups:(NSDictionary *)param - channelName:(NSString *)aChannelName - result:(FlutterResult)result { + +- (void)bindDeviceToken:(NSDictionary *)param + channelName:(NSString *)aChannelName + result:(FlutterResult)result { __weak typeof(self) weakSelf = self; + NSString *deviceToken = param[@"token"]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - EMError *aError = nil; - [EMClient.sharedClient.pushManager getPushOptionsFromServerWithError:&aError]; - NSArray *list = [EMClient.sharedClient.pushManager noPushGroups]; + EMError *error = [EMClient.sharedClient bindDeviceToken:deviceToken]; dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf wrapperCallBack:result channelName:aChannelName - error:aError - object:list]; + error:error + object:nil]; }); }); } -- (void)setNoDisturbUsers:(NSDictionary *)param - channelName:(NSString *)aChannelName - result:(FlutterResult)result { + +- (void)enablePush:(NSDictionary *)param + channelName:(NSString *)aChannelName + result:(FlutterResult)result { __weak typeof(self) weakSelf = self; - NSArray *members = param[@"members"]; - BOOL disablePush = [param[@"disable"] boolValue]; - [EMClient.sharedClient.pushManager updatePushServiceForUsers:members - disablePush:disablePush - completion:^(EMError * _Nonnull aError) - { - [EMClient.sharedClient.pushManager updatePushServiceForUsers:members - disablePush:disablePush - completion:^(EMError * _Nonnull aError) - { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + EMError *error = [EMClient.sharedClient.pushManager enableOfflinePush]; + dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf wrapperCallBack:result channelName:aChannelName - error:aError + error:error object:nil]; - }]; - }]; + }); + }); } -- (void)getNoDisturbUsersFromServer:(NSDictionary *)param - channelName:(NSString *)aChannelName - result:(FlutterResult)result { +- (void)disablePush:(NSDictionary *)param + channelName:(NSString *)aChannelName + result:(FlutterResult)result { + int startTime = [param[@"start"] intValue]; + int endTime = [param[@"end"] intValue]; __weak typeof(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - EMError *aError = nil; - [EMClient.sharedClient.pushManager getPushOptionsFromServerWithError:&aError]; - NSArray *list = [EMClient.sharedClient.pushManager noPushUIds]; + EMError *error = [EMClient.sharedClient.pushManager disableOfflinePushStart:startTime end:endTime]; dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf wrapperCallBack:result channelName:aChannelName - error:aError - object:list]; + error:error + object:nil]; }); }); } -- (void)bindDeviceToken:(NSDictionary *)param +- (void)getNoPushGroups:(NSDictionary *)param channelName:(NSString *)aChannelName result:(FlutterResult)result { __weak typeof(self) weakSelf = self; - NSString *deviceToken = param[@"token"]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - EMError *error = [EMClient.sharedClient bindDeviceToken:deviceToken]; + NSArray* groups = [EMClient.sharedClient.pushManager noPushGroups]; dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf wrapperCallBack:result channelName:aChannelName - error:error - object:nil]; + error:nil + object:groups]; }); }); } +- (void)updateUserPushService:(NSDictionary *)param + channelName:(NSString *)aChannelName + result:(FlutterResult)result { + __weak typeof(self) weakSelf = self; + NSArray *userIds = param[@"user_ids"]; + bool noPush = [param[@"noPush"] boolValue]; + + [EMClient.sharedClient.pushManager updatePushServiceForUsers:userIds disablePush:noPush completion:^(EMError * _Nonnull aError) { + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:aError + object:nil]; + }]; +} + +- (void)getNoPushUsers:(NSDictionary *)param + channelName:(NSString *)aChannelName + result:(FlutterResult)result { + __weak typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSArray* userIds = [EMClient.sharedClient.pushManager noPushUIds]; + dispatch_async(dispatch_get_main_queue(), ^{ + [weakSelf wrapperCallBack:result + channelName:aChannelName + error:nil + object:userIds]; + }); + }); +} + @end diff --git a/ios/Classes/EMSDKMethod.h b/ios/Classes/EMSDKMethod.h index d9104f1a..700f1a12 100644 --- a/ios/Classes/EMSDKMethod.h +++ b/ios/Classes/EMSDKMethod.h @@ -2,231 +2,229 @@ // EMSDKMethod.h // // -// Created by 杜洁鹏 EMMethodKeyOn 2019/10/8. +// Created by 杜洁鹏 ChatOn 2019/10/8. // #import -static NSString *const EMMethodKeyDebugLog = @"debugLog"; -static NSString *const EMMethodKeyErrorLog = @"errorLog"; - - #pragma mark - EMClientWrapper -static NSString *const EMMethodKeyInit = @"init"; -static NSString *const EMMethodKeyCreateAccount = @"createAccount"; -static NSString *const EMMethodKeyLogin = @"login"; -static NSString *const EMMethodKeyLogout = @"logout"; -static NSString *const EMMethodKeyLoginWithAgoraToken = @"loginWithAgoraToken"; -static NSString *const EMMethodKeyChangeAppKey = @"changeAppKey"; -static NSString *const EMMethodKeyUploadLog = @"uploadLog"; -static NSString *const EMMethodKeyCompressLogs = @"compressLogs"; -static NSString *const EMMethodKeyKickDevice = @"kickDevice"; -static NSString *const EMMethodKeyKickAllDevices = @"kickAllDevices"; -static NSString *const EMMethodKeyGetLoggedInDevicesFromServer = @"getLoggedInDevicesFromServer"; - -static NSString *const EMMethodKeyGetToken = @"getToken"; -static NSString *const EMMethodKeyGetCurrentUser = @"getCurrentUser"; -static NSString *const EMMethodKeyIsLoggedInBefore = @"isLoggedInBefore"; -static NSString *const EMMethodKeyIsConnected = @"isConnected"; +static NSString *const ChatInit = @"init"; +static NSString *const ChatCreateAccount = @"createAccount"; +static NSString *const ChatLogin = @"login"; +static NSString *const ChatRenewToken = @"renewToken"; +static NSString *const ChatLoginWithAgoraToken = @"loginWithAgoraToken"; +static NSString *const ChatLogout = @"logout"; +static NSString *const ChatChangeAppKey = @"changeAppKey"; + +static NSString *const ChatUploadLog = @"uploadLog"; +static NSString *const ChatCompressLogs = @"compressLogs"; +static NSString *const ChatKickDevice = @"kickDevice"; +static NSString *const ChatKickAllDevices = @"kickAllDevices"; +static NSString *const ChatGetLoggedInDevicesFromServer = @"getLoggedInDevicesFromServer"; + +static NSString *const ChatGetToken = @"getToken"; +static NSString *const ChatGetCurrentUser = @"getCurrentUser"; +static NSString *const ChatIsLoggedInBefore = @"isLoggedInBefore"; +static NSString *const ChatIsConnected = @"isConnected"; #pragma mark - EMClientDelegate -static NSString *const EMMethodKeyOnConnected = @"onConnected"; -static NSString *const EMMethodKeyOnDisconnected = @"onDisconnected"; -static NSString *const EMMethodKeyOnMultiDeviceEvent = @"onMultiDeviceEvent"; +static NSString *const ChatOnConnected = @"onConnected"; +static NSString *const ChatOnDisconnected = @"onDisconnected"; +static NSString *const ChatOnMultiDeviceEvent = @"onMultiDeviceEvent"; -static NSString *const EMMethodKeySendDataToFlutter = @"onSendDataToFlutter"; +static NSString *const ChatSendDataToFlutter = @"onSendDataToFlutter"; -static NSString *const EMMethodKeyOnTokenWillExpire = @"onTokenWillExpire"; -static NSString *const EMMethodKeyOnTokenDidExpire = @"onTokenDidExpire"; +static NSString *const ChatOnTokenWillExpire = @"onTokenWillExpire"; +static NSString *const ChatOnTokenDidExpire = @"onTokenDidExpire"; #pragma mark - EMContactManagerWrapper -static NSString *const EMMethodKeyAddContact = @"addContact"; -static NSString *const EMMethodKeyDeleteContact = @"deleteContact"; -static NSString *const EMMethodKeyGetAllContactsFromServer = @"getAllContactsFromServer"; -static NSString *const EMMethodKeyGetAllContactsFromDB = @"getAllContactsFromDB"; -static NSString *const EMMethodKeyAddUserToBlockList = @"addUserToBlockList"; -static NSString *const EMMethodKeyRemoveUserFromBlockList = @"removeUserFromBlockList"; -static NSString *const EMMethodKeyGetBlockListFromServer = @"getBlockListFromServer"; -static NSString *const EMMethodKeyGetBlockListFromDB = @"getBlockListFromDB"; -static NSString *const EMMethodKeyAcceptInvitation = @"acceptInvitation"; -static NSString *const EMMethodKeyDeclineInvitation = @"declineInvitation"; -static NSString *const EMMethodKeyGetSelfIdsOnOtherPlatform = @"getSelfIdsOnOtherPlatform"; +static NSString *const ChatAddContact = @"addContact"; +static NSString *const ChatDeleteContact = @"deleteContact"; +static NSString *const ChatGetAllContactsFromServer = @"getAllContactsFromServer"; +static NSString *const ChatGetAllContactsFromDB = @"getAllContactsFromDB"; +static NSString *const ChatAddUserToBlockList = @"addUserToBlockList"; +static NSString *const ChatRemoveUserFromBlockList = @"removeUserFromBlockList"; +static NSString *const ChatGetBlockListFromServer = @"getBlockListFromServer"; +static NSString *const ChatGetBlockListFromDB = @"getBlockListFromDB"; +static NSString *const ChatAcceptInvitation = @"acceptInvitation"; +static NSString *const ChatDeclineInvitation = @"declineInvitation"; +static NSString *const ChatGetSelfIdsOnOtherPlatform = @"getSelfIdsOnOtherPlatform"; #pragma mark - EMContactDelegate -static NSString *const EMMethodKeyOnContactChanged = @"onContactChanged"; +static NSString *const ChatOnContactChanged = @"onContactChanged"; #pragma mark - EMChatManagerWrapper -static NSString *const EMMethodKeySendMessage = @"sendMessage"; -static NSString *const EMMethodKeyResendMessage = @"resendMessage"; -static NSString *const EMMethodKeyAckMessageRead = @"ackMessageRead"; -static NSString *const EMMethodKeyAckGroupMessageRead = @"ackGroupMessageRead"; -static NSString *const EMMethodKeyAckConversationRead = @"ackConversationRead"; -static NSString *const EMMethodKeyRecallMessage = @"recallMessage"; -static NSString *const EMMethodKeyGetConversation = @"getConversation"; -static NSString *const EMMethodKeyMarkAllChatMsgAsRead = @"markAllChatMsgAsRead"; -static NSString *const EMMethodKeyGetUnreadMessageCount = @"getUnreadMessageCount"; -static NSString *const EMMethodKeyUpdateChatMessage = @"updateChatMessage"; -static NSString *const EMMethodKeyDownloadAttachment = @"downloadAttachment"; -static NSString *const EMMethodKeyDownloadThumbnail = @"downloadThumbnail"; -static NSString *const EMMethodKeyImportMessages = @"importMessages"; -static NSString *const EMMethodKeyLoadAllConversations = @"loadAllConversations"; -static NSString *const EMMethodKeyGetConversationsFromServer = @"getConversationsFromServer"; - -static NSString *const EMMethodKeyDeleteConversation = @"deleteConversation"; -//static NSString * const EMMethodKeySetVoiceMessageListened = @"setVoiceMessageListened"; -//static NSString * const EMMethodKeyUpdateParticipant = @"updateParticipant"; -static NSString *const EMMethodKeyUpdateConversationsName = @"updateConversationsName"; -static NSString *const EMMethodKeyFetchHistoryMessages = @"fetchHistoryMessages"; -static NSString *const EMMethodKeySearchChatMsgFromDB = @"searchChatMsgFromDB"; -static NSString *const EMMethodKeyGetMessage = @"getMessage"; -static NSString *const EMMethodKeyAsyncFetchGroupAcks = @"asyncFetchGroupAcks"; +static NSString *const ChatSendMessage = @"sendMessage"; +static NSString *const ChatResendMessage = @"resendMessage"; +static NSString *const ChatAckMessageRead = @"ackMessageRead"; +static NSString *const ChatAckGroupMessageRead = @"ackGroupMessageRead"; +static NSString *const ChatAckConversationRead = @"ackConversationRead"; +static NSString *const ChatRecallMessage = @"recallMessage"; +static NSString *const ChatGetConversation = @"getConversation"; +static NSString *const ChatMarkAllChatMsgAsRead = @"markAllChatMsgAsRead"; +static NSString *const ChatGetUnreadMessageCount = @"getUnreadMessageCount"; +static NSString *const ChatUpdateChatMessage = @"updateChatMessage"; +static NSString *const ChatDownloadAttachment = @"downloadAttachment"; +static NSString *const ChatDownloadThumbnail = @"downloadThumbnail"; +static NSString *const ChatImportMessages = @"importMessages"; +static NSString *const ChatLoadAllConversations = @"loadAllConversations"; +static NSString *const ChatGetConversationsFromServer = @"getConversationsFromServer"; + +static NSString *const ChatDeleteConversation = @"deleteConversation"; +static NSString *const ChatFetchHistoryMessages = @"fetchHistoryMessages"; +static NSString *const ChatSearchChatMsgFromDB = @"searchChatMsgFromDB"; +static NSString *const ChatGetMessage = @"getMessage"; +static NSString *const ChatAsyncFetchGroupAcks = @"asyncFetchGroupAcks"; +static NSString *const ChatDeleteRemoteConversation = @"deleteRemoteConversation"; #pragma mark - EMChatManagerDelegate -static NSString *const EMMethodKeyOnMessagesReceived = @"onMessagesReceived"; -static NSString *const EMMethodKeyOnCmdMessagesReceived = @"onCmdMessagesReceived"; -static NSString *const EMMethodKeyOnMessagesRead = @"onMessagesRead"; -static NSString *const EMMethodKeyOnGroupMessageRead = @"onGroupMessageRead"; -static NSString *const EMMethodKeyOnMessagesDelivered = @"onMessagesDelivered"; -static NSString *const EMMethodKeyOnMessagesRecalled = @"onMessagesRecalled"; +static NSString *const ChatOnMessagesReceived = @"onMessagesReceived"; +static NSString *const ChatOnCmdMessagesReceived = @"onCmdMessagesReceived"; +static NSString *const ChatOnMessagesRead = @"onMessagesRead"; +static NSString *const ChatOnGroupMessageRead = @"onGroupMessageRead"; +static NSString *const ChatOnMessagesDelivered = @"onMessagesDelivered"; +static NSString *const ChatOnMessagesRecalled = @"onMessagesRecalled"; -static NSString *const EMMethodKeyOnConversationUpdate = @"onConversationUpdate"; -static NSString *const EMMethodKeyOnConversationHasRead = @"onConversationHasRead"; +static NSString *const ChatOnConversationUpdate = @"onConversationUpdate"; +static NSString *const ChatOnConversationHasRead = @"onConversationHasRead"; #pragma mark - EMMessageListener -static NSString *const EMMethodKeyOnMessageProgressUpdate = @"onMessageProgressUpdate"; -static NSString *const EMMethodKeyOnMessageSuccess = @"onMessageSuccess"; -static NSString *const EMMethodKeyOnMessageError = @"onMessageError"; -static NSString *const EMMethodKeyOnMessageReadAck = @"onMessageReadAck"; -static NSString *const EMMethodKeyOnMessageDeliveryAck = @"onMessageDeliveryAck"; -static NSString *const EMMethodKeyOnMessageStatusChanged = @"onMessageStatusChanged"; +static NSString *const ChatOnMessageProgressUpdate = @"onMessageProgressUpdate"; +static NSString *const ChatOnMessageSuccess = @"onMessageSuccess"; +static NSString *const ChatOnMessageError = @"onMessageError"; +static NSString *const ChatOnMessageReadAck = @"onMessageReadAck"; +static NSString *const ChatOnMessageDeliveryAck = @"onMessageDeliveryAck"; + #pragma mark - EMConversationWrapper -static NSString *const EMMethodKeyGetUnreadMsgCount = @"getUnreadMsgCount"; -static NSString *const EMMethodKeyMarkAllMsgsAsRead = @"markAllMessagesAsRead"; -static NSString *const EMMethodKeyMarkMsgAsRead = @"markMessageAsRead"; -static NSString *const EMMethodKeySyncConversationExt = @"syncConversationExt"; -static NSString *const EMMethodKeySyncConversationName = @"syncConversationName"; -static NSString *const EMMethodKeyRemoveMsg = @"removeMessage"; -static NSString *const EMMethodKeyGetLatestMsg = @"getLatestMessage"; -static NSString *const EMMethodKeyGetLatestMsgFromOthers = @"getLatestMessageFromOthers"; -static NSString *const EMMethodKeyClearAllMsg = @"clearAllMessages"; -static NSString *const EMMethodKeyInsertMsg = @"insertMessage"; -static NSString *const EMMethodKeyAppendMsg = @"appendMessage"; -static NSString *const EMMethodKeyUpdateConversationMsg = @"updateConversationMessage"; - -static NSString *const EMMethodKeyLoadMsgWithId = @"loadMsgWithId"; -static NSString *const EMMethodKeyLoadMsgWithStartId = @"loadMsgWithStartId"; -static NSString *const EMMethodKeyLoadMsgWithKeywords = @"loadMsgWithKeywords"; -static NSString *const EMMethodKeyLoadMsgWithMsgType = @"loadMsgWithMsgType"; -static NSString *const EMMethodKeyLoadMsgWithTime = @"loadMsgWithTime"; +static NSString *const ChatGetUnreadMsgCount = @"getUnreadMsgCount"; +static NSString *const ChatMarkAllMsgsAsRead = @"markAllMessagesAsRead"; +static NSString *const ChatMarkMsgAsRead = @"markMessageAsRead"; +static NSString *const ChatSyncConversationExt = @"syncConversationExt"; +static NSString *const ChatRemoveMsg = @"removeMessage"; +static NSString *const ChatGetLatestMsg = @"getLatestMessage"; +static NSString *const ChatGetLatestMsgFromOthers = @"getLatestMessageFromOthers"; +static NSString *const ChatClearAllMsg = @"clearAllMessages"; +static NSString *const ChatInsertMsg = @"insertMessage"; +static NSString *const ChatAppendMsg = @"appendMessage"; +static NSString *const ChatUpdateConversationMsg = @"updateConversationMessage"; + +static NSString *const ChatLoadMsgWithId = @"loadMsgWithId"; +static NSString *const ChatLoadMsgWithStartId = @"loadMsgWithStartId"; +static NSString *const ChatLoadMsgWithKeywords = @"loadMsgWithKeywords"; +static NSString *const ChatLoadMsgWithMsgType = @"loadMsgWithMsgType"; +static NSString *const ChatLoadMsgWithTime = @"loadMsgWithTime"; #pragma mark - EMChatroomManagerWrapper -static NSString *const EMMethodKeyJoinChatRoom = @"joinChatRoom"; -static NSString *const EMMethodKeyLeaveChatRoom = @"leaveChatRoom"; -static NSString *const EMMethodKeyGetChatroomsFromServer = @"fetchPublicChatRoomsFromServer"; -static NSString *const EMMethodKeyFetchChatRoomFromServer = @"fetchChatRoomInfoFromServer"; -static NSString *const EMMethodKeyGetChatRoom = @"getChatRoom"; -static NSString *const EMMethodKeyGetAllChatRooms = @"getAllChatRooms"; -static NSString *const EMMethodKeyCreateChatRoom = @"createChatRoom"; -static NSString *const EMMethodKeyDestroyChatRoom = @"destroyChatRoom"; -static NSString *const EMMethodKeyChatRoomUpdateSubject = @"changeChatRoomSubject"; -static NSString *const EMMethodKeyChatRoomUpdateDescription = @"changeChatRoomDescription"; -static NSString *const EMMethodKeyGetChatroomMemberListFromServer = @"fetchChatRoomMembers"; -static NSString *const EMMethodKeyChatRoomMuteMembers = @"muteChatRoomMembers"; -static NSString *const EMMethodKeyChatRoomUnmuteMembers = @"unMuteChatRoomMembers"; -static NSString *const EMMethodKeyChangeChatRoomOwner = @"changeChatRoomOwner"; -static NSString *const EMMethodKeyChatRoomAddAdmin = @"addChatRoomAdmin"; -static NSString *const EMMethodKeyChatRoomRemoveAdmin = @"removeChatRoomAdmin"; -static NSString *const EMMethodKeyGetChatroomMuteListFromServer = @"fetchChatRoomMuteList"; -static NSString *const EMMethodKeyChatRoomRemoveMembers = @"removeChatRoomMembers"; -static NSString *const EMMethodKeyChatRoomBlockMembers = @"blockChatRoomMembers"; -static NSString *const EMMethodKeyChatRoomUnblockMembers = @"unBlockChatRoomMembers"; -static NSString *const EMMethodKeyFetchChatroomBlockListFromServer = @"fetchChatRoomBlockList"; -static NSString *const EMMethodKeyUpdateChatRoomAnnouncement = @"updateChatRoomAnnouncement"; -static NSString *const EMMethodKeyFetchChatroomAnnouncement = @"fetchChatRoomAnnouncement"; - -static NSString *const EMMethodKeyAddMembersToChatRoomWhiteList = @"addMembersToChatRoomWhiteList"; -static NSString *const EMMethodKeyRemoveMembersFromChatRoomWhiteList = @"removeMembersFromChatRoomWhiteList"; -static NSString *const EMMethodKeyFetchChatRoomWhiteListFromServer = @"fetchChatRoomWhiteListFromServer"; -static NSString *const EMMethodKeyIsMemberInChatRoomWhiteListFromServer = @"isMemberInChatRoomWhiteListFromServer"; - -static NSString *const EMMethodKeyMuteAllChatRoomMembers = @"muteAllChatRoomMembers"; -static NSString *const EMMethodKeyUnMuteAllChatRoomMembers = @"umMuteAllChatRoomMembers"; - - -static NSString *const EMMethodKeyChatroomChanged = @"onChatRoomChanged"; +static NSString *const ChatJoinChatRoom = @"joinChatRoom"; +static NSString *const ChatLeaveChatRoom = @"leaveChatRoom"; +static NSString *const ChatGetChatroomsFromServer = @"fetchPublicChatRoomsFromServer"; +static NSString *const ChatFetchChatRoomFromServer = @"fetchChatRoomInfoFromServer"; +static NSString *const ChatGetChatRoom = @"getChatRoom"; +static NSString *const ChatGetAllChatRooms = @"getAllChatRooms"; +static NSString *const ChatCreateChatRoom = @"createChatRoom"; +static NSString *const ChatDestroyChatRoom = @"destroyChatRoom"; +static NSString *const ChatChatRoomUpdateSubject = @"changeChatRoomSubject"; +static NSString *const ChatChatRoomUpdateDescription = @"changeChatRoomDescription"; +static NSString *const ChatGetChatroomMemberListFromServer = @"fetchChatRoomMembers"; +static NSString *const ChatChatRoomMuteMembers = @"muteChatRoomMembers"; +static NSString *const ChatChatRoomUnmuteMembers = @"unMuteChatRoomMembers"; +static NSString *const ChatChangeChatRoomOwner = @"changeChatRoomOwner"; +static NSString *const ChatChatRoomAddAdmin = @"addChatRoomAdmin"; +static NSString *const ChatChatRoomRemoveAdmin = @"removeChatRoomAdmin"; +static NSString *const ChatGetChatroomMuteListFromServer = @"fetchChatRoomMuteList"; +static NSString *const ChatChatRoomRemoveMembers = @"removeChatRoomMembers"; +static NSString *const ChatChatRoomBlockMembers = @"blockChatRoomMembers"; +static NSString *const ChatChatRoomUnblockMembers = @"unBlockChatRoomMembers"; +static NSString *const ChatFetchChatroomBlockListFromServer = @"fetchChatRoomBlockList"; +static NSString *const ChatUpdateChatRoomAnnouncement = @"updateChatRoomAnnouncement"; +static NSString *const ChatFetchChatroomAnnouncement = @"fetchChatRoomAnnouncement"; + +static NSString *const ChatAddMembersToChatRoomWhiteList = @"addMembersToChatRoomWhiteList"; +static NSString *const ChatRemoveMembersFromChatRoomWhiteList = @"removeMembersFromChatRoomWhiteList"; +static NSString *const ChatFetchChatRoomWhiteListFromServer = @"fetchChatRoomWhiteListFromServer"; +static NSString *const ChatIsMemberInChatRoomWhiteListFromServer = @"isMemberInChatRoomWhiteListFromServer"; + +static NSString *const ChatMuteAllChatRoomMembers = @"muteAllChatRoomMembers"; +static NSString *const ChatUnMuteAllChatRoomMembers = @"unMuteAllChatRoomMembers"; + + +static NSString *const ChatChatroomChanged = @"onChatRoomChanged"; #pragma mark - EMGroupManagerWrapper -static NSString *const EMMethodKeyGetGroupWithId = @"getGroupWithId"; -static NSString *const EMMethodKeyGetJoinedGroups = @"getJoinedGroups"; -static NSString *const EMMethodKeyGetGroupsWithoutPushNotification = @"getGroupsWithoutPushNotification"; -static NSString *const EMMethodKeyGetJoinedGroupsFromServer = @"getJoinedGroupsFromServer"; -static NSString *const EMMethodKeyGetPublicGroupsFromServer = @"getPublicGroupsFromServer"; -static NSString *const EMMethodKeyCreateGroup = @"createGroup"; -static NSString *const EMMethodKeyGetGroupSpecificationFromServer = @"getGroupSpecificationFromServer"; -static NSString *const EMMethodKeyGetGroupMemberListFromServer = @"getGroupMemberListFromServer"; -static NSString *const EMMethodKeyGetGroupBlockListFromServer = @"getGroupBlockListFromServer"; -static NSString *const EMMethodKeyGetGroupMuteListFromServer = @"getGroupMuteListFromServer"; -static NSString *const EMMethodKeyGetGroupWhiteListFromServer = @"getGroupWhiteListFromServer"; -static NSString *const EMMethodKeyIsMemberInWhiteListFromServer = @"isMemberInWhiteListFromServer"; -static NSString *const EMMethodKeyGetGroupFileListFromServer = @"getGroupFileListFromServer"; -static NSString *const EMMethodKeyGetGroupAnnouncementFromServer = @"getGroupAnnouncementFromServer"; -static NSString *const EMMethodKeyAddMembers = @"addMembers"; -static NSString *const EMMethodKeyInviterUser = @"inviterUser"; -static NSString *const EMMethodKeyRemoveMembers = @"removeMembers"; -static NSString *const EMMethodKeyBlockMembers = @"blockMembers"; -static NSString *const EMMethodKeyUnblockMembers = @"unblockMembers"; -static NSString *const EMMethodKeyUpdateGroupSubject = @"updateGroupSubject"; -static NSString *const EMMethodKeyUpdateDescription = @"updateDescription"; -static NSString *const EMMethodKeyLeaveGroup = @"leaveGroup"; -static NSString *const EMMethodKeyDestroyGroup = @"destroyGroup"; -static NSString *const EMMethodKeyBlockGroup = @"blockGroup"; -static NSString *const EMMethodKeyUnblockGroup = @"unblockGroup"; -static NSString *const EMMethodKeyUpdateGroupOwner = @"updateGroupOwner"; -static NSString *const EMMethodKeyAddAdmin = @"addAdmin"; -static NSString *const EMMethodKeyRemoveAdmin = @"removeAdmin"; -static NSString *const EMMethodKeyMuteMembers = @"muteMembers"; -static NSString *const EMMethodKeyUnMuteMembers = @"unMuteMembers"; -static NSString *const EMMethodKeyMuteAllMembers = @"muteAllMembers"; -static NSString *const EMMethodKeyUnMuteAllMembers = @"unMuteAllMembers"; -static NSString *const EMMethodKeyAddWhiteList = @"addWhiteList"; -static NSString *const EMMethodKeyRemoveWhiteList = @"removeWhiteList"; -static NSString *const EMMethodKeyUploadGroupSharedFile = @"uploadGroupSharedFile"; -static NSString *const EMMethodKeyDownloadGroupSharedFile = @"downloadGroupSharedFile"; -static NSString *const EMMethodKeyRemoveGroupSharedFile = @"removeGroupSharedFile"; -static NSString *const EMMethodKeyUpdateGroupAnnouncement = @"updateGroupAnnouncement"; -static NSString *const EMMethodKeyUpdateGroupExt = @"updateGroupExt"; -static NSString *const EMMethodKeyJoinPublicGroup = @"joinPublicGroup"; -static NSString *const EMMethodKeyRequestToJoinPublicGroup = @"requestToJoinPublicGroup"; -static NSString *const EMMethodKeyAcceptJoinApplication = @"acceptJoinApplication"; -static NSString *const EMMethodKeyDeclineJoinApplication = @"declineJoinApplication"; -static NSString *const EMMethodKeyAcceptInvitationFromGroup = @"acceptInvitationFromGroup"; -static NSString *const EMMethodKeyDeclineInvitationFromGroup = @"declineInvitationFromGroup"; -static NSString *const EMMethodKeyIgnoreGroupPush = @"ignoreGroupPush"; - -static NSString *const EMMethodKeyOnGroupChanged = @"onGroupChanged"; +static NSString *const ChatGetGroupWithId = @"getGroupWithId"; +static NSString *const ChatGetJoinedGroups = @"getJoinedGroups"; +static NSString *const ChatGetGroupsWithoutPushNotification = @"getGroupsWithoutPushNotification"; +static NSString *const ChatGetJoinedGroupsFromServer = @"getJoinedGroupsFromServer"; +static NSString *const ChatGetPublicGroupsFromServer = @"getPublicGroupsFromServer"; +static NSString *const ChatCreateGroup = @"createGroup"; +static NSString *const ChatGetGroupSpecificationFromServer = @"getGroupSpecificationFromServer"; +static NSString *const ChatGetGroupMemberListFromServer = @"getGroupMemberListFromServer"; +static NSString *const ChatGetGroupBlockListFromServer = @"getGroupBlockListFromServer"; +static NSString *const ChatGetGroupMuteListFromServer = @"getGroupMuteListFromServer"; +static NSString *const ChatGetGroupWhiteListFromServer = @"getGroupWhiteListFromServer"; +static NSString *const ChatIsMemberInWhiteListFromServer = @"isMemberInWhiteListFromServer"; +static NSString *const ChatGetGroupFileListFromServer = @"getGroupFileListFromServer"; +static NSString *const ChatGetGroupAnnouncementFromServer = @"getGroupAnnouncementFromServer"; +static NSString *const ChatAddMembers = @"addMembers"; +static NSString *const ChatInviterUser = @"inviterUser"; +static NSString *const ChatRemoveMembers = @"removeMembers"; +static NSString *const ChatBlockMembers = @"blockMembers"; +static NSString *const ChatUnblockMembers = @"unblockMembers"; +static NSString *const ChatUpdateGroupSubject = @"updateGroupSubject"; +static NSString *const ChatUpdateDescription = @"updateDescription"; +static NSString *const ChatLeaveGroup = @"leaveGroup"; +static NSString *const ChatDestroyGroup = @"destroyGroup"; +static NSString *const ChatBlockGroup = @"blockGroup"; +static NSString *const ChatUnblockGroup = @"unblockGroup"; +static NSString *const ChatUpdateGroupOwner = @"updateGroupOwner"; +static NSString *const ChatAddAdmin = @"addAdmin"; +static NSString *const ChatRemoveAdmin = @"removeAdmin"; +static NSString *const ChatMuteMembers = @"muteMembers"; +static NSString *const ChatUnMuteMembers = @"unMuteMembers"; +static NSString *const ChatMuteAllMembers = @"muteAllMembers"; +static NSString *const ChatUnMuteAllMembers = @"unMuteAllMembers"; +static NSString *const ChatAddWhiteList = @"addWhiteList"; +static NSString *const ChatRemoveWhiteList = @"removeWhiteList"; +static NSString *const ChatUploadGroupSharedFile = @"uploadGroupSharedFile"; +static NSString *const ChatDownloadGroupSharedFile = @"downloadGroupSharedFile"; +static NSString *const ChatRemoveGroupSharedFile = @"removeGroupSharedFile"; +static NSString *const ChatUpdateGroupAnnouncement = @"updateGroupAnnouncement"; +static NSString *const ChatUpdateGroupExt = @"updateGroupExt"; +static NSString *const ChatJoinPublicGroup = @"joinPublicGroup"; +static NSString *const ChatRequestToJoinPublicGroup = @"requestToJoinPublicGroup"; +static NSString *const ChatAcceptJoinApplication = @"acceptJoinApplication"; +static NSString *const ChatDeclineJoinApplication = @"declineJoinApplication"; +static NSString *const ChatAcceptInvitationFromGroup = @"acceptInvitationFromGroup"; +static NSString *const ChatDeclineInvitationFromGroup = @"declineInvitationFromGroup"; +static NSString *const ChatIgnoreGroupPush = @"ignoreGroupPush"; + +static NSString *const ChatOnGroupChanged = @"onGroupChanged"; #pragma mark - EMPushManagerWrapper -static NSString *const EMMethodKeyGetImPushConfig = @"getImPushConfig"; -static NSString *const EMMethodKeyGetImPushConfigFromServer = @"getImPushConfigFromServer"; -static NSString *const EMMethodKeyUpdatePushNickname = @"updatePushNickname"; - -static NSString *const EMMethodKeyImPushNoDisturb = @"imPushNoDisturb"; -static NSString *const EMMethodKeyUpdateImPushStyle = @"updateImPushStyle"; -static NSString *const EMMethodKeyUpdateGroupPushService = @"updateGroupPushService"; -static NSString *const EMMethodKeyGetNoDisturbGroups = @"getNoDisturbGroups"; -static NSString *const EMMethodKeyBindDeviceToken = @"updateAPNsPushToken"; -static NSString *const EMMethodKeySetNoDisturbUsers = @"setNoDisturbUsers"; -static NSString *const EMMethodKeyGetNoDisturbUsersFromServer = @"getNoDisturbUsersFromServer"; +static NSString *const ChatGetImPushConfig = @"getImPushConfig"; +static NSString *const ChatGetImPushConfigFromServer = @"getImPushConfigFromServer"; +static NSString *const ChatEnablePush = @"enableOfflinePush"; +static NSString *const ChatDisablePush = @"disableOfflinePush"; +static NSString *const ChatUpdateImPushStyle = @"updateImPushStyle"; +static NSString *const ChatUpdatePushNickname = @"updatePushNickname"; + +static NSString *const ChatUpdateGroupPushService = @"updateGroupPushService"; +static NSString *const ChatGetNoPushGroups = @"getNoPushGroups"; +static NSString *const ChatUpdateUserPushService = @"updateUserPushService"; +static NSString *const ChatGetNoPushUsers = @"getNoPushUsers"; + + +static NSString *const ChatBindDeviceToken = @"updateAPNsPushToken"; #pragma mark - EMUserInfoManagerWrapper -static NSString *const EMMethodKeyUpdateOwnUserInfo = @"updateOwnUserInfo"; -static NSString *const EMMethodKeyUpdateOwnUserInfoWithType = @"updateOwnUserInfoWithType"; -static NSString *const EMMethodKeyFetchUserInfoById = @"fetchUserInfoById"; -static NSString *const EMMethodKeyFetchUserInfoByIdWithType = @"fetchUserInfoByIdWithType"; +static NSString *const ChatUpdateOwnUserInfo = @"updateOwnUserInfo"; +static NSString *const ChatUpdateOwnUserInfoWithType = @"updateOwnUserInfoWithType"; +static NSString *const ChatFetchUserInfoById = @"fetchUserInfoById"; +static NSString *const ChatFetchUserInfoByIdWithType = @"fetchUserInfoByIdWithType"; diff --git a/ios/Classes/EMUserInfo+Flutter.m b/ios/Classes/EMUserInfo+Flutter.m index 3e05bda7..682a0c10 100644 --- a/ios/Classes/EMUserInfo+Flutter.m +++ b/ios/Classes/EMUserInfo+Flutter.m @@ -12,7 +12,7 @@ @implementation EMUserInfo (Flutter) - (NSDictionary *)toJson { NSMutableDictionary *ret = [NSMutableDictionary dictionary]; ret[@"userId"] = self.userId; - ret[@"nickName"] = self.nickName; + ret[@"nickName"] = self.nickname; ret[@"avatarUrl"] = self.avatarUrl; ret[@"mail"] = self.mail; ret[@"phone"] = self.phone; @@ -28,7 +28,7 @@ - (NSDictionary *)toJson { + (EMUserInfo *)fromJson:(NSDictionary *)aJson { EMUserInfo *userInfo = EMUserInfo.new; userInfo.userId = aJson[@"userId"] ?: @""; - userInfo.nickName = aJson[@"nickName"] ?: @""; + userInfo.nickname = aJson[@"nickName"] ?: @""; userInfo.avatarUrl = aJson[@"avatarUrl"] ?: @""; userInfo.mail = aJson[@"mail"] ?: @""; userInfo.phone = aJson[@"phone"] ?: @""; diff --git a/ios/Classes/EMUserInfoManagerWrapper.m b/ios/Classes/EMUserInfoManagerWrapper.m index 00bebf22..ddd109f0 100644 --- a/ios/Classes/EMUserInfoManagerWrapper.m +++ b/ios/Classes/EMUserInfoManagerWrapper.m @@ -26,23 +26,23 @@ - (instancetype)initWithChannelName:(NSString *)aChannelName registrar:(NSObject #pragma mark - FlutterPlugin - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { - if ([call.method isEqualToString:EMMethodKeyUpdateOwnUserInfo]) { + if ([call.method isEqualToString:ChatUpdateOwnUserInfo]) { [self updateOwnUserInfo:call.arguments channelName:call.method result:result]; } - if ([call.method isEqualToString:EMMethodKeyUpdateOwnUserInfoWithType]) { + if ([call.method isEqualToString:ChatUpdateOwnUserInfoWithType]) { [self updateOwnUserInfoWithType:call.arguments channelName:call.method result:result]; } - if ([call.method isEqualToString:EMMethodKeyFetchUserInfoById]) { + if ([call.method isEqualToString:ChatFetchUserInfoById]) { [self fetchUserInfoById:call.arguments channelName:call.method result:result]; } - if ([call.method isEqualToString:EMMethodKeyFetchUserInfoByIdWithType]) { + if ([call.method isEqualToString:ChatFetchUserInfoByIdWithType]) { [self fetchUserInfoByIdWithType:call.arguments channelName:call.method result:result]; @@ -120,7 +120,7 @@ - (void)fetchUserInfoByIdWithType:(NSDictionary *)param channelName:(NSString *) [weakSelf wrapperCallBack:result - channelName:EMMethodKeyFetchUserInfoByIdWithType + channelName:ChatFetchUserInfoByIdWithType error:aError object:dic]; }]; diff --git a/ios/Classes/ImFlutterSdkPlugin.m b/ios/Classes/ImFlutterSdkPlugin.m index 58a61cf2..e23a2dbe 100644 --- a/ios/Classes/ImFlutterSdkPlugin.m +++ b/ios/Classes/ImFlutterSdkPlugin.m @@ -37,16 +37,5 @@ - (void)applicationWillEnterForeground:(UIApplication *)application [[EMClient sharedClient] applicationWillEnterForeground:application]; } -- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken -{ - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [[EMClient sharedClient] bindDeviceToken:deviceToken]; - }); -} - -- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { - NSLog(@"注册推送失败 --- %@", error); -} - @end diff --git a/lib/im_flutter_sdk.dart b/lib/im_flutter_sdk.dart index 285793c6..fc61269a 100644 --- a/lib/im_flutter_sdk.dart +++ b/lib/im_flutter_sdk.dart @@ -2,17 +2,16 @@ library im_flutter_sdk; export 'src/em_client.dart'; -export 'src/models/em_message.dart'; -export 'src/models/em_group_message_ack.dart'; -export 'src/tools/em_log.dart'; export 'src/em_listeners.dart'; + +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_message.dart'; + export 'src/models/em_options.dart'; export 'src/models/em_push_configs.dart'; export 'src/models/em_page_result.dart'; @@ -20,3 +19,25 @@ export 'src/models/em_userInfo.dart'; export 'src/models/em_group_shared_file.dart'; export 'src/models/em_group_options.dart'; export 'src/models/em_chat_enums.dart'; + +export 'src/models/em_message.dart' show EMMessage; +export 'src/models/em_message_body.dart' show EMMessageBody; +export 'src/models/em_text_message_body.dart' show EMTextMessageBody; +export 'src/models/em_image_message_body.dart' show EMImageMessageBody; +export 'src/models/em_voice_message_body.dart' show EMVoiceMessageBody; +export 'src/models/em_video_message_body.dart' show EMVideoMessageBody; +export 'src/models/em_file_message_body.dart' show EMFileMessageBody; +export 'src/models/em_cmd_message_body.dart' show EMCmdMessageBody; +export 'src/models/em_custom_message_body.dart' show EMCustomMessageBody; +export 'src/models/em_location_message_body.dart' show EMLocationMessageBody; + +@Deprecated("Switch to using MessageStatusCallBack instead.") +export 'src/em_status_listener.dart'; +export 'src/em_message_status_callback.dart'; + +export 'src/em_chat_manager.dart'; +export 'src/em_contact_manager.dart'; +export 'src/em_group_manager.dart'; +export 'src/em_chat_room_manager.dart'; +export 'src/em_push_manager.dart'; +export 'src/em_userInfo_manager.dart'; diff --git a/lib/src/chat_method_keys.dart b/lib/src/chat_method_keys.dart deleted file mode 100644 index 0d10a49f..00000000 --- a/lib/src/chat_method_keys.dart +++ /dev/null @@ -1,237 +0,0 @@ -class ChatMethodKeys { - /// EMClient methods - static const String init = 'init'; - static const String createAccount = 'createAccount'; - static const String login = 'login'; - static const String loginWithAgoraToken = 'loginWithAgoraToken'; - static const String logout = 'logout'; - static const String changeAppKey = 'changeAppKey'; - - static const String uploadLog = 'uploadLog'; - static const String compressLogs = 'compressLogs'; - static const String kickDevice = 'kickDevice'; - static const String kickAllDevices = 'kickAllDevices'; - static const String currentUser = 'currentUser'; - static const String getLoggedInDevicesFromServer = - 'getLoggedInDevicesFromServer'; - - static const String getToken = 'getToken'; - static const String getCurrentUser = 'getCurrentUser'; - static const String isLoggedInBefore = 'isLoggedInBefore'; - static const String isConnected = 'isConnected'; - - /// EMClient listener - static const String onMultiDeviceEvent = 'onMultiDeviceEvent'; - static const String onConnected = 'onConnected'; - static const String onDisconnected = 'onDisconnected'; - static const String onSendDataToFlutter = "onSendDataToFlutter"; - static const String onTokenWillExpire = 'onTokenWillExpire'; - static const String onTokenDidExpire = 'onTokenDidExpire'; - - /// EMContactManager methods - static const String addContact = 'addContact'; - static const String deleteContact = 'deleteContact'; - static const String getAllContactsFromServer = 'getAllContactsFromServer'; - static const String getAllContactsFromDB = 'getAllContactsFromDB'; - static const String addUserToBlockList = 'addUserToBlockList'; - static const String removeUserFromBlockList = 'removeUserFromBlockList'; - static const String getBlockListFromServer = 'getBlockListFromServer'; - static const String getBlockListFromDB = 'getBlockListFromDB'; - static const String acceptInvitation = 'acceptInvitation'; - static const String declineInvitation = 'declineInvitation'; - static const String getSelfIdsOnOtherPlatform = 'getSelfIdsOnOtherPlatform'; - - /// EMContactManager listener - static const String onContactChanged = 'onContactChanged'; - - /// EMChatManager methods - static const String sendMessage = 'sendMessage'; - static const String resendMessage = 'resendMessage'; - static const String ackMessageRead = 'ackMessageRead'; - static const String ackGroupMessageRead = 'ackGroupMessageRead'; - static const String ackConversationRead = 'ackConversationRead'; - static const String recallMessage = 'recallMessage'; - static const String getConversation = 'getConversation'; - static const String markAllChatMsgAsRead = 'markAllChatMsgAsRead'; - static const String getUnreadMessageCount = 'getUnreadMessageCount'; - static const String updateChatMessage = 'updateChatMessage'; - static const String downloadAttachment = 'downloadAttachment'; - static const String downloadThumbnail = 'downloadThumbnail'; - static const String importMessages = 'importMessages'; - static const String loadAllConversations = 'loadAllConversations'; - static const String getConversationsFromServer = 'getConversationsFromServer'; - static const String deleteConversation = 'deleteConversation'; - static const String updateConversationsName = 'updateConversationsName'; - static const String fetchHistoryMessages = 'fetchHistoryMessages'; - static const String searchChatMsgFromDB = 'searchChatMsgFromDB'; - static const String getMessage = 'getMessage'; - static const String asyncFetchGroupAcks = 'asyncFetchGroupAcks'; - static const String deleteRemoteConversation = "deleteRemoteConversation"; - - /// EMChatManager listener - static const String onMessagesReceived = 'onMessagesReceived'; - static const String onCmdMessagesReceived = 'onCmdMessagesReceived'; - static const String onMessagesRead = 'onMessagesRead'; - static const String onGroupMessageRead = 'onGroupMessageRead'; - static const String onMessagesDelivered = 'onMessagesDelivered'; - static const String onMessagesRecalled = 'onMessagesRecalled'; - static const String onMessageChanged = 'onMessageChanged'; - - static const String onConversationUpdate = 'onConversationUpdate'; - static const String onConversationHasRead = 'onConversationHasRead'; - - /// EMMessage listener - static const String onMessageProgressUpdate = 'onMessageProgressUpdate'; - static const String onMessageError = 'onMessageError'; - static const String onMessageSuccess = 'onMessageSuccess'; - static const String onMessageReadAck = 'onMessageReadAck'; - static const String onMessageDeliveryAck = 'onMessageDeliveryAck'; - static const String onMessageStatusChanged = 'onMessageStatusChanged'; - - /// EMConversation - static const String getUnreadMsgCount = 'getUnreadMsgCount'; - static const String markAllMessagesAsRead = 'markAllMessagesAsRead'; - static const String markMessageAsRead = 'markMessageAsRead'; - static const String syncConversationExt = 'syncConversationExt'; - static const String syncConversationName = 'syncConversationName'; - static const String removeMessage = 'removeMessage'; - static const String getLatestMessage = 'getLatestMessage'; - static const String getLatestMessageFromOthers = 'getLatestMessageFromOthers'; - static const String clearAllMessages = 'clearAllMessages'; - static const String insertMessage = 'insertMessage'; - static const String appendMessage = 'appendMessage'; - static const String updateConversationMessage = 'updateConversationMessage'; - - // 根据消息id获取消息 - static const String loadMsgWithId = 'loadMsgWithId'; - // 根据起始消息id获取消息 - static const String loadMsgWithStartId = 'loadMsgWithStartId'; - // 根据关键字获取消息 - static const String loadMsgWithKeywords = 'loadMsgWithKeywords'; - // 根据消息类型获取消息 - static const String loadMsgWithMsgType = 'loadMsgWithMsgType'; - // 通过时间获取消息 - static const String loadMsgWithTime = 'loadMsgWithTime'; - - /// EMChatRoomManager methods - static const String joinChatRoom = 'joinChatRoom'; - static const String leaveChatRoom = 'leaveChatRoom'; - static const String fetchPublicChatRoomsFromServer = - 'fetchPublicChatRoomsFromServer'; - static const String fetchChatRoomInfoFromServer = - 'fetchChatRoomInfoFromServer'; - static const String getChatRoom = 'getChatRoom'; - static const String getAllChatRooms = 'getAllChatRooms'; - static const String createChatRoom = 'createChatRoom'; - static const String destroyChatRoom = 'destroyChatRoom'; - static const String changeChatRoomSubject = 'changeChatRoomSubject'; - static const String changeChatRoomDescription = 'changeChatRoomDescription'; - static const String fetchChatRoomMembers = 'fetchChatRoomMembers'; - static const String muteChatRoomMembers = 'muteChatRoomMembers'; - static const String unMuteChatRoomMembers = 'unMuteChatRoomMembers'; - static const String changeChatRoomOwner = 'changeChatRoomOwner'; - static const String addChatRoomAdmin = 'addChatRoomAdmin'; - static const String removeChatRoomAdmin = 'removeChatRoomAdmin'; - static const String fetchChatRoomMuteList = 'fetchChatRoomMuteList'; - static const String removeChatRoomMembers = 'removeChatRoomMembers'; - static const String blockChatRoomMembers = 'blockChatRoomMembers'; - static const String unBlockChatRoomMembers = 'unBlockChatRoomMembers'; - static const String fetchChatRoomBlockList = 'fetchChatRoomBlockList'; - static const String updateChatRoomAnnouncement = 'updateChatRoomAnnouncement'; - static const String fetchChatRoomAnnouncement = 'fetchChatRoomAnnouncement'; - static const String addMembersToChatRoomWhiteList = - "addMembersToChatRoomWhiteList"; - static const String removeMembersFromChatRoomWhiteList = - "removeMembersFromChatRoomWhiteList"; - static const String fetchChatRoomWhiteListFromServer = - "fetchChatRoomWhiteListFromServer"; - static const String isMemberInChatRoomWhiteListFromServer = - "isMemberInChatRoomWhiteListFromServer"; - - static const String muteAllChatRoomMembers = "muteAllChatRoomMembers"; - static const String unMuteAllChatRoomMembers = "umMuteAllChatRoomMembers"; - - /// EMChatRoomManagerListener - static const String chatRoomChange = 'onChatRoomChanged'; - - /// EMGroupManager - static const String getGroupWithId = 'getGroupWithId'; - static const String getJoinedGroups = 'getJoinedGroups'; - static const String getGroupsWithoutPushNotification = - 'getGroupsWithoutPushNotification'; - static const String getJoinedGroupsFromServer = 'getJoinedGroupsFromServer'; - static const String getPublicGroupsFromServer = 'getPublicGroupsFromServer'; - static const String createGroup = 'createGroup'; - static const String getGroupSpecificationFromServer = - 'getGroupSpecificationFromServer'; - static const String getGroupMemberListFromServer = - 'getGroupMemberListFromServer'; - static const String getGroupBlockListFromServer = - 'getGroupBlockListFromServer'; - static const String getGroupMuteListFromServer = 'getGroupMuteListFromServer'; - static const String getGroupWhiteListFromServer = - 'getGroupWhiteListFromServer'; - static const String isMemberInWhiteListFromServer = - 'isMemberInWhiteListFromServer'; - static const String getGroupFileListFromServer = 'getGroupFileList'; - static const String getGroupAnnouncementFromServer = - 'getGroupAnnouncementFromServer'; - static const String addMembers = 'addMembers'; - static const String inviterUser = 'inviterUser'; - static const String removeMembers = 'removeMembers'; - static const String blockMembers = 'blockMembers'; - static const String unblockMembers = 'unblockMembers'; - static const String updateGroupSubject = 'updateGroupSubject'; - static const String updateDescription = 'updateDescription'; - static const String leaveGroup = 'leaveGroup'; - static const String destroyGroup = 'destroyGroup'; - static const String blockGroup = 'blockGroup'; - static const String unblockGroup = 'unblockGroup'; - static const String updateGroupOwner = 'updateGroupOwner'; - static const String addAdmin = 'addAdmin'; - static const String removeAdmin = 'removeAdmin'; - static const String muteMembers = 'muteMembers'; - static const String unMuteMembers = 'unMuteMembers'; - static const String muteAllMembers = 'muteAllMembers'; - static const String unMuteAllMembers = 'unMuteAllMembers'; - static const String addWhiteList = 'addWhiteList'; - static const String removeWhiteList = 'removeWhiteList'; - static const String uploadGroupSharedFile = 'uploadGroupSharedFile'; - static const String downloadGroupSharedFile = 'downloadGroupSharedFile'; - static const String removeGroupSharedFile = 'removeGroupSharedFile'; - static const String updateGroupAnnouncement = 'updateGroupAnnouncement'; - static const String updateGroupExt = 'updateGroupExt'; - static const String joinPublicGroup = 'joinPublicGroup'; - static const String requestToJoinPublicGroup = 'requestToJoinPublicGroup'; - static const String acceptJoinApplication = 'acceptJoinApplication'; - static const String declineJoinApplication = 'declineJoinApplication'; - static const String acceptInvitationFromGroup = 'acceptInvitationFromGroup'; - static const String declineInvitationFromGroup = 'declineInvitationFromGroup'; - static const String ignoreGroupPush = 'ignoreGroupPush'; - - /// EMGroupManagerListener - static const String onGroupChanged = 'onGroupChanged'; - - /// EMPushManager - static const String getImPushConfig = 'getImPushConfig'; - static const String getImPushConfigFromServer = 'getImPushConfigFromServer'; - static const String updatePushNickname = 'updatePushNickname'; - static const String updateHMSPushToken = 'updateHMSPushToken'; - static const String updateFCMPushToken = 'updateFCMPushToken'; - static const String updateAPNsPushToken = 'updateAPNsPushToken'; - - /// ImPushConfig - static const String imPushNoDisturb = 'imPushNoDisturb'; - static const String updateImPushStyle = 'updateImPushStyle'; - static const String updateGroupPushService = 'updateGroupPushService'; - static const String getNoDisturbGroups = 'getNoDisturbGroups'; - static const String setNoDisturbUsers = 'setNoDisturbUsers'; - static const String getNoDisturbUsersFromServer = - 'getNoDisturbUsersFromServer'; - - /// EMUserInfoManager methods - static const String updateOwnUserInfo = 'updateOwnUserInfo'; - static const String updateOwnUserInfoWithType = 'updateOwnUserInfoWithType'; - static const String fetchUserInfoById = 'fetchUserInfoById'; - static const String fetchUserInfoByIdWithType = 'fetchUserInfoByIdWithType'; -} diff --git a/lib/src/em_chat_manager.dart b/lib/src/em_chat_manager.dart index 5e28091e..c1af025e 100644 --- a/lib/src/em_chat_manager.dart +++ b/lib/src/em_chat_manager.dart @@ -1,17 +1,30 @@ import "dart:async"; import 'package:flutter/services.dart'; +import 'internal/em_transform_tools.dart'; import 'tools/em_extension.dart'; import '../im_flutter_sdk.dart'; -import 'chat_method_keys.dart'; - -class EMChatManager implements EMMessageStatusListener { +import 'internal/chat_method_keys.dart'; + +/// +/// 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: +/// +/// ```dart +/// EMMessage msg = EMMessage.createTxtSendMessage( +/// username: toChatUsername, content: content); +/// await EMClient.getInstance.chatManager.sendMessage(msg); +/// ``` +/// +class EMChatManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel('$_channelPrefix/chat_manager', JSONMethodCodec()); final List _messageListeners = []; + /// @nodoc EMChatManager() { _channel.setMethodCallHandler((MethodCall call) async { if (call.method == ChatMethodKeys.onMessagesReceived) { @@ -35,12 +48,21 @@ class EMChatManager implements EMMessageStatusListener { }); } - /// 发送消息 [message]. + /// + /// Sends a message. + /// + /// **Note** + /// For attachment messages such as voice, image, or video messages, the SDK automatically uploads the attachment. + /// You can set whether to upload the attachment to the chat sever using {@link EMOptions#serverTransfer(boolean)}. + /// + /// To listen for the status of sending messages, call {@link EMMessage#setMessageStatusListener(EMMessageStatusListener)}. + /// + /// Param [message] The message object to be sent: {@link EMMessage}. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future sendMessage(EMMessage message) async { - if (message.listener == null) { - message.listener = this; - } - message.status = EMMessageStatus.PROGRESS; + message.status = MessageStatus.PROGRESS; Map result = await _channel.invokeMethod( ChatMethodKeys.sendMessage, message.toJson()); try { @@ -55,12 +77,10 @@ class EMChatManager implements EMMessageStatusListener { } } - /// 重发消息 [message]. + /// Resends a message. + /// Param [message] The message object to be resent: {@link EMMessage}. Future resendMessage(EMMessage message) async { - if (message.listener == null) { - message.listener = this; - } - message.status = EMMessageStatus.PROGRESS; + message.status = MessageStatus.PROGRESS; Map result = await _channel.invokeMethod( ChatMethodKeys.resendMessage, message.toJson()); try { @@ -75,7 +95,23 @@ class EMChatManager implements EMMessageStatusListener { } } - /// 发送消息已读 [message]. + /// + /// Sends the read receipt to the server. + /// + /// This method applies to one-to-one chats only. + /// + /// **Warning** + /// This method only takes effect if you set {@link EMOptions#requireAck(bool)} as `true`. + /// + /// **Note** + /// To send the group message read receipt, call {@link #sendGroupMessageReadAck(String, String, String)}. + /// + /// We recommend that you call {@link #sendConversationReadAck(String)} when entering a chat page, and call this method to reduce the number of method calls. + /// + /// Param [message] The message body: {@link EMMessage}. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future sendMessageReadAck(EMMessage message) async { Map req = {"to": message.from, "msg_id": message.msgId}; Map result = @@ -88,6 +124,24 @@ class EMChatManager implements EMMessageStatusListener { } } + /// + /// Sends the group message receipt to the server. + /// + /// You can call the method only after setting the following method: {@link EMOptions#requireAck(bool)} and {@link EMMessage#needGroupAck(bool)}. + /// + /// **Note** + /// - This method takes effect only after you set {@link EMOptions#requireAck} and {@link EMMessage#needGroupAck} as `true`. + /// - This method applies to group messages only. To send a one-to-one chat message receipt, call `sendMessageReadAck`; to send a conversation receipt, call `sendConversationReadAck`. + /// + /// + /// Param [msgId] The message ID. + /// + /// Param [groupId] The group ID. + /// + /// Param [content] The extension information, which is a custom keyword that specifies a custom action or command. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future sendGroupMessageReadAck( String msgId, String groupId, { @@ -110,7 +164,18 @@ class EMChatManager implements EMMessageStatusListener { } } - /// 发送会话已读 [conversationId]为会话Id + /// + /// 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 {@link EMChatManagerListener#onConversationRead(String, String)} callback. + /// + /// **Note** + /// This method applies to one-to-one chat conversations only. To send a group message read receipt, call `sendGroupMessageReadAck`. + /// + /// Param [conversationId] The conversation ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future sendConversationReadAck(String conversationId) async { Map req = {"con_id": conversationId}; Map result = @@ -123,32 +188,63 @@ class EMChatManager implements EMMessageStatusListener { } } - /// 撤回发送的消息(增值服务), 默认时效为2分钟,超过2分钟无法撤回. - Future recallMessage(String messageId) async { + /// + /// Recalls the sent message. + /// + /// Param [messageId] The message ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future recallMessage(String messageId) async { Map req = {"msg_id": messageId}; Map result = await _channel.invokeMethod(ChatMethodKeys.recallMessage, req); try { EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.recallMessage); } on EMError catch (e) { throw e; } } - /// 通过[messageId]从db获取消息. - Future loadMessage(String messageId) async { + /// + /// Loads a message from the local database by message ID. + /// + /// Param [messageId] The message ID. + /// + /// **Return** The message object specified by the message ID. Returns null if the message does not exist. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future loadMessage(String messageId) async { Map req = {"msg_id": messageId}; Map result = await _channel.invokeMethod(ChatMethodKeys.getMessage, req); try { EMError.hasErrorFromResult(result); - return EMMessage.fromJson(result[ChatMethodKeys.getMessage]); + if (result.containsKey(ChatMethodKeys.getMessage)) { + return EMMessage.fromJson(result[ChatMethodKeys.getMessage]); + } else { + return null; + } } on EMError catch (e) { throw e; } } - /// 通过会话[conversationId], 会话类型[type]获取会话. + /// + /// Gets the conversation by conversation ID and conversation type. + /// + /// Param [conversationId] The conversation ID. + /// + /// Param [type] The conversation type: {@link EMConversationType}. + /// + /// Param [createIfNeed] Whether to create a conversation is the specified conversation is not found: + /// - `true`: Yes. + /// - `false`: No. + /// + /// **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 {@link EMError}. + /// Future getConversation( String conversationId, [ EMConversationType type = EMConversationType.Chat, @@ -156,7 +252,7 @@ class EMChatManager implements EMMessageStatusListener { ]) async { Map req = { "con_id": conversationId, - "type": EMConversation.typeToInt(type), + "type": conversationTypeToInt(type), "createIfNeed": createIfNeed }; Map result = @@ -173,45 +269,74 @@ class EMChatManager implements EMMessageStatusListener { } } - /// 将所有对话标记为已读. - Future markAllConversationsAsRead() async { + /// Marks all messages as read. + /// + /// This method is for the local conversations only. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future markAllConversationsAsRead() async { Map result = await _channel.invokeMethod(ChatMethodKeys.markAllChatMsgAsRead); try { EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.markAllChatMsgAsRead); } on EMError catch (e) { throw e; } } - /// 获取未读消息的计数. - Future getUnreadMessageCount() async { + /// + /// Gets the count of the unread messages. + /// + /// **Return** The count of the unread messages. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future getUnreadMessageCount() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getUnreadMessageCount); try { + int ret = 0; EMError.hasErrorFromResult(result); - return result[ChatMethodKeys.getUnreadMessageCount] as int?; + if (result.containsKey(ChatMethodKeys.getUnreadMessageCount)) { + ret = result[ChatMethodKeys.getUnreadMessageCount] as int; + } + return ret; } on EMError catch (e) { throw e; } } - /// 更新消息[message]. - Future updateMessage(EMMessage message) async { + /// + /// Updates the local message. + /// + /// The message will be updated both in the cache and local database. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future updateMessage(EMMessage message) async { Map req = {"message": message.toJson()}; Map result = await _channel.invokeMethod(ChatMethodKeys.updateChatMessage, req); try { EMError.hasErrorFromResult(result); - return EMMessage.fromJson(result[ChatMethodKeys.updateChatMessage]); } on EMError catch (e) { throw e; } } - /// 导入消息 [messages]. - Future importMessages(List messages) async { + /// + /// Imports messages to the local database. + /// + /// Before importing, ensure that the sender or receiver of the message is the current user. + /// + /// For each method call, we recommends to import less than 1,000 messages. + /// + /// Param [messages] The message list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future importMessages(List messages) async { List list = []; messages.forEach((element) { list.add(element.toJson()); @@ -221,37 +346,56 @@ class EMChatManager implements EMMessageStatusListener { await _channel.invokeMethod(ChatMethodKeys.importMessages, req); try { EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.importMessages); } on EMError catch (e) { throw e; } } - /// 下载附件 [message]. - Future downloadAttachment(EMMessage message) async { + /// + /// Downloads the attachment files from the server. + /// + /// You can call the method again if the attachment download fails. + /// + /// Param [message] The message with the attachment that is to be downloaded. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future downloadAttachment(EMMessage message) async { Map result = await _channel.invokeMethod( ChatMethodKeys.downloadAttachment, {"message": message.toJson()}); try { EMError.hasErrorFromResult(result); - return EMMessage.fromJson(result[ChatMethodKeys.downloadAttachment]); } on EMError catch (e) { throw e; } } - /// 下载缩略图 [message]. - Future downloadThumbnail(EMMessage message) async { + /// + /// 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 {@link EMError}. + /// + Future downloadThumbnail(EMMessage message) async { Map result = await _channel.invokeMethod( ChatMethodKeys.downloadThumbnail, {"message": message.toJson()}); try { EMError.hasErrorFromResult(result); - return EMMessage.fromJson(result[ChatMethodKeys.downloadThumbnail]); } on EMError catch (e) { throw e; } } - /// 获取所有会话 + /// + /// 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. + /// + /// **Return** All the conversations from the cache or local database. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> loadAllConversations() async { Map result = await _channel.invokeMethod(ChatMethodKeys.loadAllConversations); @@ -267,7 +411,15 @@ class EMChatManager implements EMMessageStatusListener { } } - /// 从服务器获取会话 + /// + /// 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 convesation contains the latest historical message). If you want to adjust the number of conversations or time limit, please contact our business manager. + /// + /// **Return** The conversation list of the current user. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> getConversationsFromServer() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getConversationsFromServer); @@ -283,16 +435,23 @@ class EMChatManager implements EMMessageStatusListener { } } - // 批量更新一组会话显示名称`Map`,`key`会话id, `value`对应名称,既conversation.name属性。 - // Future updateConversationsName(Map nameMap) async { - // Map req = {"name_map": nameMap}; - // Map result = - // await _channel.invokeMethod(ChatMethodKeys.updateConversationsName, req); - // EMError.hasErrorFromResult(result); - // return result.boolValue(ChatMethodKeys.updateConversationsName); - // } - - /// 删除会话, 如果[deleteMessages]设置为true,则同时删除消息。 + /// + /// 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. + /// + /// Param [conversationId] The conversation ID. + /// + /// Param [deleteMessages] Whether to delete the historical messages when deleting the conversation. + /// - `true`: (default) Yes. + /// - `false`: No. + /// + /// **Return** Whether the conversation is successfully deleted. + /// - `true`: Yes; + /// - `false`: No. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future deleteConversation( String conversationId, [ bool deleteMessages = true, @@ -308,20 +467,44 @@ class EMChatManager implements EMMessageStatusListener { } } - /// 添加消息监听 [listener] - void addListener(EMChatManagerListener listener) { + /// + /// Adds the message listener. After calling this method, you can listen for new messages when they arrive. + /// + /// Param [listener] The message listener that listens for new messages. See {@link EMChatManagerListener}. + /// + void addChatManagerListener(EMChatManagerListener listener) { _messageListeners.add(listener); } - /// 移除消息监听[listener] - void removeListener(EMChatManagerListener listener) { + /// + /// Removes the message listener. + /// + /// After adding a chat manager listener, you can remove this listener if you do not want to listen for it. + /// + /// Param [listener] The message listener to be removed. See {@link EMChatManagerListener}. + /// + void removeChatManagerListener(EMChatManagerListener listener) { if (_messageListeners.contains(listener)) { _messageListeners.remove(listener); } } - /// 在会话[conversationId]中提取历史消息,按[type]筛选。 - /// 结果按每页[pageSize]分页,从[startMsgId]开始。 + /// + /// Gets historical messages of the conversation from the server with pagination. + /// + /// + /// Param [conversationId] The conversation ID. + /// + /// Param [type] The conversation type. See {@link EMConversationType}. + /// + /// Param [pageSize] The number of messages per page. + /// + /// 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. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> fetchHistoryMessages( String conversationId, { EMConversationType type = EMConversationType.Chat, @@ -330,7 +513,7 @@ class EMChatManager implements EMMessageStatusListener { }) async { Map req = Map(); req['con_id'] = conversationId; - req['type'] = EMConversation.typeToInt(type); + req['type'] = conversationTypeToInt(type); req['pageSize'] = pageSize; req['startMsgId'] = startMsgId; Map result = @@ -347,20 +530,37 @@ class EMChatManager implements EMMessageStatusListener { } } - /// 搜索包含[keywords]的消息,消息类型为[type],起始时间[timeStamp],条数[maxCount], 消息发送方[from],方向[direction]。 + /// + /// Retrieves messages from the database according to the parameters. + /// + /// **Note** + /// Pay attention to the memory usage when the maxCount is large. Currently, a maximum of 400 historical messages can be retrieved each time. + /// + /// Param [keywords] The keywords in message. + /// + /// Param [timeStamp] The Unix timestamp for search, in milliseconds. + /// + /// 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. + /// + /// **Return** The list of messages. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> searchMsgFromDB( String keywords, { int timeStamp = -1, int maxCount = 20, String from = '', - EMMessageSearchDirection direction = EMMessageSearchDirection.Up, + EMSearchDirection direction = EMSearchDirection.Up, }) async { Map req = Map(); req['keywords'] = keywords; req['timeStamp'] = timeStamp; req['maxCount'] = maxCount; req['from'] = from; - req['direction'] = direction == EMMessageSearchDirection.Up ? "up" : "down"; + req['direction'] = direction == EMSearchDirection.Up ? "up" : "down"; Map result = await _channel.invokeMethod(ChatMethodKeys.searchChatMsgFromDB, req); @@ -376,11 +576,23 @@ class EMChatManager implements EMMessageStatusListener { } } - /// 从服务器获取群组已读回执。 - /// [msgId], 需要获取的群消息id。 - /// [startAckId], 起始的ackId, 用于分页。 - /// [pageSize], 返回的数量。 - Future> asyncFetchGroupAcks( + /// + /// Gets read receipts for group messages from the server with pagination. + /// + /// See also: + /// For how to send read receipts for group messages, see {@link {@link #sendConversationReadAck(String)}. + /// + /// Param [msgId] The message ID. + /// + /// Param [startAckId] The starting read receipt ID for query. If you set it as null, the SDK retrieves the read receipts in the in reverse chronological order. + /// + /// Param [pageSize] The number of read receipts per page. + /// + /// **Return** The list of obtained read receipts and the cursor for next query. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future> fetchGroupAcks( String msgId, { String? startAckId, int pageSize = 0, @@ -410,8 +622,21 @@ class EMChatManager implements EMMessageStatusListener { } } - /// 删除远程会话列表 - Future asyncDeleteRemoteConversation( + /// + /// Deletes the specified conversation and the related historical messages from the server. + /// + /// Param [conversationId] The conversation ID. + /// + /// Param [conversationType] The conversation type. See {@link EMConversationType}. + /// + /// Param [isDeleteMessage] Whether to delete the chat history when deleting the conversation. + /// - `true`: (default) Yes. + /// - `false`: No. + /// + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future deleteRemoteConversation( String conversationId, { EMConversationType conversationType = EMConversationType.Chat, bool isDeleteMessage = true, @@ -433,7 +658,6 @@ class EMChatManager implements EMMessageStatusListener { EMError.hasErrorFromResult(data); } - /// @nodoc Future _onMessagesReceived(List messages) async { List messageList = []; for (var message in messages) { @@ -444,7 +668,6 @@ class EMChatManager implements EMMessageStatusListener { } } - /// @nodoc Future _onCmdMessagesReceived(List messages) async { List list = []; for (var message in messages) { @@ -455,7 +678,6 @@ class EMChatManager implements EMMessageStatusListener { } } - /// @nodoc Future _onMessagesRead(List messages) async { List list = []; for (var message in messages) { @@ -466,7 +688,6 @@ class EMChatManager implements EMMessageStatusListener { } } - /// @nodoc Future _onGroupMessageRead(List messages) async { List list = []; for (var message in messages) { @@ -477,7 +698,6 @@ class EMChatManager implements EMMessageStatusListener { } } - /// @nodoc Future _onMessagesDelivered(List messages) async { List list = []; for (var message in messages) { @@ -511,22 +731,4 @@ class EMChatManager implements EMMessageStatusListener { listener.onConversationRead(from, to); } } - - @override - void onDeliveryAck() {} - - @override - void onError(EMError error) {} - - @override - void onProgress(int progress) {} - - @override - void onReadAck() {} - - @override - void onStatusChanged() {} - - @override - void onSuccess() {} } diff --git a/lib/src/em_chat_room_manager.dart b/lib/src/em_chat_room_manager.dart index 649234b0..0249c3f8 100644 --- a/lib/src/em_chat_room_manager.dart +++ b/lib/src/em_chat_room_manager.dart @@ -1,15 +1,27 @@ import "dart:async"; import 'package:flutter/services.dart'; +import 'internal/em_event_keys.dart'; import 'tools/em_extension.dart'; -import 'chat_method_keys.dart'; +import 'internal/chat_method_keys.dart'; import '../im_flutter_sdk.dart'; +/// +/// 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()); +/// } +/// ``` class EMChatRoomManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( '$_channelPrefix/chat_room_manager', JSONMethodCodec()); + /// @nodoc EMChatRoomManager() { _channel.setMethodCallHandler((MethodCall call) async { Map? argMap = call.arguments; @@ -22,19 +34,30 @@ class EMChatRoomManager { final List _chatRoomEventListeners = []; - /// 添加聊天室监听器 + /// + /// Registers a chat room event listener. + /// After registering the chat room event listener, you can listen for events in {@link EMChatRoomEventListener}, 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 events, call {@link #removeChatRoomListener(EMChatRoomEventListener)}. + /// + /// Param [listener] A chat room listener. See {@link EMChatRoomEventListener}. + /// void addChatRoomChangeListener(EMChatRoomEventListener listener) { _chatRoomEventListeners.add(listener); } - /// 移除聊天室监听器 + /// + /// Removes a chat room event listener. + /// This method removes the chat room event listener registered with {@link #addChatRoomChangeListener(EMChatRoomEventListener)}. + /// + /// Param [listener] The chat room event listener to be removed. + /// void removeChatRoomListener(EMChatRoomEventListener listener) { if (_chatRoomEventListeners.contains(listener)) { _chatRoomEventListeners.remove(listener); } } - /// @nodoc Future _chatRoomChange(Map event) async { String? type = event['type']; for (EMChatRoomEventListener listener in _chatRoomEventListeners) { @@ -112,7 +135,15 @@ class EMChatRoomManager { } } - /// 加入聊天室[roomId]. + /// + /// Joins the chat room. + /// + /// To exit the chat room, call {@link #leaveChatRoom(String)}. + /// + /// Param [roomId] The ID of the chat room to join. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future joinChatRoom(String roomId) async { Map result = await _channel .invokeMethod(ChatMethodKeys.joinChatRoom, {"roomId": roomId}); @@ -123,7 +154,13 @@ class EMChatRoomManager { } } - /// 离开聊天室[roomId]. + /// + /// Leaves the chat room. + /// + /// Param [roomId] The ID of the chat room to leave. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future leaveChatRoom(String roomId) async { Map result = await _channel .invokeMethod(ChatMethodKeys.leaveChatRoom, {"roomId": roomId}); @@ -134,7 +171,17 @@ class EMChatRoomManager { } } - /// 翻页从服务器获取聊天室 [pageNum] and [pageSize] + /// + /// Gets chat room data from the server with pagination. + /// + /// Param [pageNum] The page number, starting from 1. + /// + /// Param [pageSize] The number of records per page. + /// + /// **Return** Chat room data. See {@link EMPageResult}. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> fetchPublicChatRoomsFromServer({ int pageNum = 1, int pageSize = 200, @@ -154,7 +201,16 @@ class EMChatRoomManager { } } - /// 获取聊天室详情[roomId]. + /// + /// Gets the details of the chat room from the server. + /// By default, the details do not include the chat room member list. + /// + /// Param [roomId] The chat room ID. + /// + /// **Return** The chat room instance. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future fetchChatRoomInfoFromServer(String roomId) async { Map result = await _channel.invokeMethod( ChatMethodKeys.fetchChatRoomInfoFromServer, {"roomId": roomId}); @@ -167,20 +223,36 @@ class EMChatRoomManager { } } - /// 从本地获取聊天室 [roomId]. - Future getChatRoomWithId(String roomId) async { + /// + /// Gets the chat room in the cache. + /// + /// Param [roomId] The chat room ID. + /// + /// **Return** The chat room instance. Returns null if the chat room is not found in the cache. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future getChatRoomWithId(String roomId) async { Map result = await _channel .invokeMethod(ChatMethodKeys.getChatRoom, {"roomId": roomId}); try { EMError.hasErrorFromResult(result); - return EMChatRoom.fromJson( - result[ChatMethodKeys.fetchChatRoomInfoFromServer]); + if (result.containsKey(ChatMethodKeys.fetchChatRoomInfoFromServer)) { + return EMChatRoom.fromJson( + result[ChatMethodKeys.fetchChatRoomInfoFromServer]); + } else { + return null; + } } on EMError catch (e) { throw e; } } - /// 获取所有聊天室 + /// + /// Gets the list of chat rooms in the cache. + /// + /// **Return** The list of chat rooms maintained by EMChatRoomManager. + @Deprecated("") Future> getAllChatRooms() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getAllChatRooms); try { @@ -194,6 +266,23 @@ class EMChatRoomManager { } } + /// + /// Creates a chat room. + /// + /// Param [subject] The chat room subject. + /// + /// Param [desc] The chat room description. + /// + /// Param [welcomeMsg] A welcome message that invites users to join the chat room. + /// + /// Param [maxUserCount] The maximum number of members allowed to join the chat room. + /// + /// Param [members] The list of members invited to join the chat room. + /// + /// **Return** The chat room instance. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future createChatRoom( String subject, { String? desc, @@ -217,7 +306,15 @@ class EMChatRoomManager { } } - /// @nodoc 销毁聊天室,需要owner权限 [roomId] + /// + /// Destroys a chat room. + /// + /// Only the chat room owner can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future destroyChatRoom( String roomId, ) async { @@ -231,7 +328,17 @@ class EMChatRoomManager { } } - /// @nodoc 修改聊天室标题,需要owner权限[roomId] [subject] + /// + /// Changes the chat room subject. + /// + /// Only the chat room owner can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [subject] The new subject of the chat room. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future changeChatRoomSubject( String roomId, String subject, @@ -246,7 +353,17 @@ class EMChatRoomManager { } } - /// @nodoc 修改聊天室描述信息,需要owner权限 [roomId] .[description] + /// + /// Modifies the chat room description. + /// + /// Only the chat room owner can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [description] The new description of the chat room. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future changeChatRoomDescription( String roomId, String description, @@ -261,18 +378,31 @@ class EMChatRoomManager { } } - /// @nodoc 获取聊天室成员列表,[roomId] [cursor] [pageSize] - Future> fetchChatRoomMembers( + /// + /// Gets the chat room member list. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [cursor] The cursor position from which to start getting data. + /// + /// Param [pageSize] The number of members per page. + /// + /// **Return** The list of chat room members. See {@link EMCursorResult}. If `EMCursorResult.cursor` is an empty string (""), all data is fetched. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future> fetchChatRoomMembers( String roomId, { String cursor = '', int pageSize = 200, }) async { - Map req = {"roomId": roomId, "cursor": cursor, "pageSize": pageSize}; + Map req = {"roomId": roomId, "pageSize": pageSize}; + req.setValueWithOutNull("cursor", cursor); Map result = await _channel.invokeMethod(ChatMethodKeys.fetchChatRoomMembers, req); try { EMError.hasErrorFromResult(result); - return EMCursorResult.fromJson( + return EMCursorResult.fromJson( result[ChatMethodKeys.fetchChatRoomMembers], dataItemCallback: (obj) => obj); } on EMError catch (e) { @@ -280,11 +410,22 @@ class EMChatRoomManager { } } - /// @nodoc 禁止聊天室成员发言,需要聊天室拥有者或者管理员权限 - /// [roomId] 聊天室ID [duration] 禁言的时间,单位是毫秒 [muteMembers] 禁言的用户列表 + /// + /// Mutes the specified members in a chat room. + /// + /// Only the chat room owner or admin can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [muteMembers] The list of members to be muted. + /// + /// Param [duration] The mute duration in milliseconds. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future muteChatRoomMembers( String roomId, - List muteMembers, { + List muteMembers, { int duration = -1, }) async { Map req = { @@ -301,10 +442,20 @@ class EMChatRoomManager { } } - /// @nodoc 取消禁言,需要聊天室拥有者或者管理员权限 [roomId].[muteMembers] + /// + /// Unmutes the specified members in a chat room. + /// + /// Only the chat room owner or admin can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [unMuteMembers] The list of members to be unmuted. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future unMuteChatRoomMembers( String roomId, - List unMuteMembers, + List unMuteMembers, ) async { Map req = {"roomId": roomId, "unMuteMembers": unMuteMembers}; Map result = @@ -316,8 +467,17 @@ class EMChatRoomManager { } } - /// @nodoc 转移聊天室的所有权,需要聊天室拥有者权限 [roomId] .[newOwner] - /// @nodoc 如果转移成功,请调用[onSuccess],如果出现错误,请调用[onError]。 + /// + /// Transfers the chat room ownership. + /// + /// Only the chat room owner can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [newOwner] The ID of the new chat room owner. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future changeOwner( String roomId, String newOwner, @@ -332,8 +492,17 @@ class EMChatRoomManager { } } - /// 为聊天室添加管理员,需要拥有者权限 [roomId].[admin] - /// 如果添加成功,请调用[onSuccess],如果出现错误,请调用[onError]。 + /// + /// Adds a chat room admin. + /// + /// Only the chat room owner can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [admin] The ID of the chat room admin to be added. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future addChatRoomAdmin( String roomId, String admin, @@ -348,8 +517,15 @@ class EMChatRoomManager { } } - /// 删除聊天室管理员,需要拥有着权限[roomId].[admin] - /// 如果删除成功,请调用[onSuccess],如果出现错误,请调用[onError]。 + /// + /// Removes privileges of a chat room admin. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [admin] The ID of admin whose privileges are to be removed. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future removeChatRoomAdmin( String roomId, String admin, @@ -364,7 +540,21 @@ class EMChatRoomManager { } } - /// @nodoc 获取聊天室的禁言列表,需要拥有者或者管理员权限 [roomId].[pageNum].[pageSize] + /// + /// 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. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [pageNum] The page number, starting from 1. + /// + /// Param [pageSize] The number of muted members per page. + /// + /// **Return** The muted member list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future?> fetchChatRoomMuteList( String roomId, { int pageNum = 1, @@ -381,10 +571,20 @@ class EMChatRoomManager { } } - /// @nodoc 删除聊天室成员,需要拥有者或者管理员权限[roomId].[members]. + /// + /// Removes the specified members from a chat room. + /// + /// Only the chat room owner or admin can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [members] The list of the members to be removed. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future removeChatRoomMembers( String roomId, - List members, + List members, ) async { Map req = {"roomId": roomId, "members": members}; Map result = @@ -396,7 +596,21 @@ class EMChatRoomManager { } } - /// @nodoc 添加成员到黑名单,禁止成员继续加入聊天室,需要拥有者或者管理员权限[roomId].[members]. + /// + /// Adds the specified members to the block list of the chat room. + /// + /// Only the chat room owner or admin can call this method. + /// + /// **Note** + /// - Chat room members added to the block list are removed from the chat room by the server, and cannot re-join the chat room. + /// - The removed members receive the {@link EMChatRoomEventListener#onRemovedFromChatRoom(String, String?, String)} callback. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [members] The list of members to be added to block list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future blockChatRoomMembers( String roomId, List members, @@ -411,7 +625,17 @@ class EMChatRoomManager { } } - /// @nodoc 将成员从黑名单种移除,需要拥有者或者管理员权限[roomId].[members]. + /// + /// Removes the specified members from the block list of the chat room. + /// + /// Only the chat room owner or admin can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [members] The list of members to be removed from the block list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future unBlockChatRoomMembers( String roomId, List members, @@ -426,7 +650,21 @@ class EMChatRoomManager { } } - /// @nodoc 获取群组黑名单列表,分页显示,需要拥有者或者管理员权限 [roomId].[pageNum].[pageSize] + /// + /// Gets the chat room block list with pagination. + /// + /// Only the chat room owner or admin can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [pageNum] The page number, starting from 1. + /// + /// Param [pageSize] The number of users on the block list per page. + /// + /// **Return** The list of the blocked chat room members. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future?> fetchChatRoomBlockList( String roomId, [ int pageNum = 1, @@ -443,7 +681,17 @@ class EMChatRoomManager { } } - /// 更新聊天室公告[roomId].[announcement] + /// + /// Updates the chat room announcement. + /// + /// Only the chat room owner or admin can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [announcement] The announcement content. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future updateChatRoomAnnouncement( String roomId, String announcement, @@ -458,7 +706,15 @@ class EMChatRoomManager { } } - /// 从服务器获取聊天室公告内容[roomId] + /// + /// Gets the chat room announcement from the server. + /// + /// Param [roomId] The chat room ID. + /// + /// **Return** The chat room announcement. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future fetchChatRoomAnnouncement( String roomId, ) async { @@ -473,8 +729,18 @@ class EMChatRoomManager { } } - /// 从服务器获取聊天室白名单列表 [roomId]: 聊天室id - Future> fetchChatRoomWhiteListFromServer(String roomId) async { + /// + /// Gets the allow list from the server. + /// + /// Only the chat room owner or admin can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// **Return** The chat room allow list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future?> fetchChatRoomWhiteListFromServer(String roomId) async { Map req = {"roomId": roomId}; Map result = await _channel.invokeMethod( ChatMethodKeys.fetchChatRoomWhiteListFromServer, req); @@ -486,7 +752,16 @@ class EMChatRoomManager { return contacts; } - /// 判断当前登录账号是否在聊天室白名单中 [roomId]: 聊天室id + /// + /// Checks whether the member is on the allow list. + /// + /// Param [roomId] The chat room ID. + /// + /// **Return** Whether the member is on the allow list. + /// - `true`: Yes; + /// - `false`: No. + /// **Throws** A description of the exception. See {@link EMError}. + /// Future isMemberInChatRoomWhiteList(String roomId) async { Map req = {"roomId": roomId}; Map result = await _channel.invokeMethod( @@ -496,9 +771,21 @@ class EMChatRoomManager { .boolValue(ChatMethodKeys.isMemberInChatRoomWhiteListFromServer); } - /// 向聊天室白名单中添加用户[roomId]: 聊天室id, [members]: 需要添加到聊天室的用户id。 + /// + /// Adds members to the allowlist. + /// + /// Only the chat room owner or admin can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [members] The list of members to be added to the allow list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future addMembersToChatRoomWhiteList( - String roomId, List members) async { + String roomId, + List members, + ) async { Map req = { "roomId": roomId, "members": members, @@ -511,7 +798,17 @@ class EMChatRoomManager { EMError.hasErrorFromResult(result); } - /// 从聊天室中移除白名单成员,[roomId]: 聊天室id, [members]: 需要移除的用户列表。 + /// + /// Removes members from the allow list. + /// + /// Only the chat room owner or admin can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// Param [members] The list of members to be removed from the allow list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future removeMembersFromChatRoomWhiteList( String roomId, List members, @@ -527,27 +824,41 @@ class EMChatRoomManager { EMError.hasErrorFromResult(result); } - Future muteAllChatRoomMembers(String roomId) async { + /// + /// Mutes all members. + /// + /// Only the chat room owner or admin can call this method. + /// + /// This method does not work for the chat room owner, admin, and members added to the allow list. + /// + /// Param [roomId] The chat room ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future muteAllChatRoomMembers(String roomId) async { Map req = {"roomId": roomId}; Map result = await _channel.invokeMethod( ChatMethodKeys.muteAllChatRoomMembers, req, ); EMError.hasErrorFromResult(result); - return result.boolValue( - ChatMethodKeys.muteAllChatRoomMembers, - ); } - Future unMuteAllChatRoomMembers(String roomId) async { + /// + /// Unmutes all members. + /// + /// Only the chat room owner or admin can call this method. + /// + /// Param [roomId] The chat room ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future unMuteAllChatRoomMembers(String roomId) async { Map req = {"roomId": roomId}; Map result = await _channel.invokeMethod( ChatMethodKeys.unMuteAllChatRoomMembers, req, ); EMError.hasErrorFromResult(result); - return result.boolValue( - ChatMethodKeys.unMuteAllChatRoomMembers, - ); } } diff --git a/lib/src/em_client.dart b/lib/src/em_client.dart index f3866424..4145b578 100644 --- a/lib/src/em_client.dart +++ b/lib/src/em_client.dart @@ -1,16 +1,16 @@ import 'dart:async'; import 'package:flutter/services.dart'; -import 'em_chat_manager.dart'; -import 'em_contact_manager.dart'; -import 'em_group_manager.dart'; -import 'em_push_manager.dart'; -import 'em_userInfo_manager.dart'; + +import 'internal/em_transform_tools.dart'; import 'tools/em_extension.dart'; import '../im_flutter_sdk.dart'; -import 'chat_method_keys.dart'; -import 'em_chat_room_manager.dart'; +import 'internal/chat_method_keys.dart'; +import 'tools/em_log.dart'; +/// +/// 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. +/// class EMClient { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = @@ -28,18 +28,17 @@ class EMClient { EMOptions? _options; - /// 获取配置信息[EMOptions]. + /// Gets the configurations. EMOptions? get options => _options; String? _currentUsername; - /// 获取当前登录的环信id + /// Gets the current logged-in username. String? get currentUsername => _currentUsername; static EMClient get getInstance => _instance = _instance ?? EMClient._internal(); - /// @nodoc private constructor EMClient._internal() { _addNativeMethodCallHandler(); } @@ -101,7 +100,7 @@ class EMClient { } } - /// 获取已登录账号的环信Token + /// Gets the token of the current logged-in user. Future getAccessToken() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getToken); try { @@ -112,7 +111,11 @@ class EMClient { } } - /// 初始化SDK 指定[options]. + /// + /// Initializes the SDK. + /// + /// Param [options] The configurations: {@link EMOptions}. Ensure that you set this parameter. + /// Future init(EMOptions options) async { _options = options; EMLog.v('init: $options'); @@ -120,23 +123,42 @@ class EMClient { _currentUsername = await getCurrentUsername(); } - /// 注册环信id,[username],[password], - /// 需要在环信后台的console中设置为开放注册才能通过sdk注册,否则只能使用rest api注册。 - /// 返回注册成功的环信id - Future createAccount(String username, String password) async { + /// + /// Register a new user. + /// + /// Param [username] The username. 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_-]+$. + /// + /// Param [password] The password. The maximum length is 64 characters. Ensure that you set this parameter. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future createAccount(String username, String password) async { EMLog.v('create account: $username : $password'); Map req = {'username': username, 'password': password}; Map result = await _channel.invokeMethod(ChatMethodKeys.createAccount, req); try { EMError.hasErrorFromResult(result); - return result[ChatMethodKeys.createAccount]; } on EMError catch (e) { throw e; } } - /// 使用用户名(环信id)和密码(或token)登录,[username], [pwdOrToken] - /// 返回登录成功的id(环信id) + /// + /// An app user logs in to the chat server with a password or token. + /// + /// Param [username] The username. + /// + /// 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. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future login(String username, String pwdOrToken, [bool isPassword = true]) async { EMLog.v('login: $username : $pwdOrToken, isPassword: $isPassword'); @@ -148,12 +170,23 @@ class EMClient { Map result = await _channel.invokeMethod(ChatMethodKeys.login, req); try { EMError.hasErrorFromResult(result); - _currentUsername = result[ChatMethodKeys.login]; + _currentUsername = username; } on EMError catch (e) { throw e; } } + /// + /// 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 {@link #login(String, String, bool)}. + /// + /// Param [username] The username. + /// + /// Param [agoraToken] The Agora token. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future loginWithAgoraToken(String username, String agoraToken) async { Map req = { "username": username, @@ -164,15 +197,43 @@ class EMClient { await _channel.invokeMethod(ChatMethodKeys.loginWithAgoraToken, req); try { EMError.hasErrorFromResult(result); - _currentUsername = result[ChatMethodKeys.loginWithAgoraToken]; + _currentUsername = username; } on EMError catch (e) { throw e; } } - /// 退出登录,是否解除deviceToken绑定[unbindDeviceToken] - /// 返回退出是否成功 - Future logout([ + /// + /// 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. + /// + /// Param [agoraToken] The new Agora token. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future renewAgoraToken(String agoraToken) async { + Map req = {"agora_token": agoraToken}; + + Map result = await _channel.invokeMethod(ChatMethodKeys.renewToken, req); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } + } + + /// + /// An app user logs out. + /// + /// Param [unbindDeviceToken] Whether to unbind the token when logout. + /// + /// `true` (default) Yes. + /// `false` No. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future logout([ bool unbindDeviceToken = true, ]) async { EMLog.v('logout unbindDeviceToken: $unbindDeviceToken'); @@ -181,13 +242,22 @@ class EMClient { try { EMError.hasErrorFromResult(result); _clearAllInfo(); - return result.boolValue(ChatMethodKeys.logout); } on EMError catch (e) { throw e; } } - /// 修改appKey [newAppKey]. + /// + /// Updates the App Key, which is the unique identifier to access Agora Chat. + /// + /// You can retrieve the new App Key from Agora Console. + /// + /// As this key controls all access to Agora Chat for your app, you can only update the key when the current user is logged out. + /// + /// Param [newAppKey] The App Key. Ensure that you set this parameter. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future changeAppKey({required String newAppKey}) async { EMLog.v('changeAppKey: $newAppKey'); Map req = {'appKey': newAppKey}; @@ -200,15 +270,15 @@ class EMClient { } } - // /// @nodoc 上传日志到环信, 不对外暴露 - // Future _uploadLog() async { - // Map result = await _channel.invokeMethod(ChatMethodKeys.uploadLog); - // EMError.hasErrorFromResult(result); - // return true; - // } - - /// 压缩环信日志 - /// 返回日志路径 + /// + /// Compresses the debug log into a gzip archive. + /// + /// Best practice is to delete this debug archive as soon as it is no longer used. + /// + /// **Return** The path of the compressed gzip file. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future compressLogs() async { EMLog.v('compressLogs:'); Map result = await _channel.invokeMethod(ChatMethodKeys.compressLogs); @@ -220,8 +290,17 @@ class EMClient { } } - /// 获取账号名下登陆的在线设备列表 - /// 当前登录账号和密码 [username]/[password]. + /// + /// Gets all the information about the logged in devices under the specified account. + /// + /// Param [username] The username you want to get the device information. + /// + /// Param [password] The password. + /// + /// **Return** TThe list of the logged-in devices. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> getLoggedInDevicesFromServer( {required String username, required String password}) async { EMLog.v('getLoggedInDevicesFromServer: $username, "******"'); @@ -240,8 +319,17 @@ class EMClient { } } - /// 根据设备ID,将该设备下线, - /// 账号和密码 [username]/[password] 设备ID[resource]. + /// + /// Forces the specified account to log out from the specified device. + /// + /// Param [username] The account you want to force logout. + /// + /// Param [password] The account's password. + /// + /// Param [resource] The device ID. For how to fetch the device ID, ee {@link EMDeviceInfo#resource}. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future kickDevice( {required String username, required String password, @@ -261,9 +349,16 @@ class EMClient { } } - /// 将该账号下的所有设备都踢下线 - /// 账号和密码 [username]/[password]. - Future kickAllDevices( + /// + /// Kicks out all the devices logged in under the specified account. + /// + /// Param [username] The account you want to log out from all the devices. + /// + /// Param [password] The password. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future kickAllDevices( {required String username, required String password}) async { EMLog.v('kickAllDevices: $username, "******"'); Map req = {'username': username, 'password': password}; @@ -271,7 +366,6 @@ class EMClient { await _channel.invokeMethod(ChatMethodKeys.kickAllDevices, req); try { EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.kickAllDevices); } on EMError catch (e) { throw e; } @@ -279,36 +373,60 @@ class EMClient { /* Listeners*/ - /// @nodoc 添加多设备监听的接口 [listener]. + /// + /// Adds the multi-device listener. + /// + /// Param [listener] The listener to be added: {EMMultiDeviceListener}. + /// void addMultiDeviceListener(EMMultiDeviceListener listener) { _multiDeviceListeners.add(listener); } - /// @nodoc 移除多设备监听的接口[listener]. + /// + /// Removes the multi-device listener. + /// + /// Param [listener] The listener to be removed: {EMMultiDeviceListener}. + /// void removeMultiDeviceListener(EMMultiDeviceListener listener) { if (_multiDeviceListeners.contains(listener)) { _multiDeviceListeners.remove(listener); } } - /// 添加链接状态监听的接口[listener]. + /// + /// Adds the connection listener of chat server. + /// + /// Param [listener] The chat server connection listener to be added. + /// void addConnectionListener(EMConnectionListener listener) { _connectionListeners.add(listener); } - /// 移除链接状态监听的接口[listener]. + /// + /// Removes the chat server connection listener. + /// + /// Param [listener] The chat server connection listener to be removed. + /// void removeConnectionListener(EMConnectionListener listener) { if (_connectionListeners.contains(listener)) { _connectionListeners.remove(listener); } } - /// 添加从原生到flutter的监听 + /// + /// Adds a custom listener to receive data from iOS or Android devices. + /// + /// Param [listener] The custom native listener to be added. + /// void addCustomListener(EMCustomListener listener) { _customListeners.add(listener); } - /// 移除从原生到flutter的监听 + /// + /// Removes the custom listener. + /// + /// Param [listener] The custom native listener. + /// void removeCustomListener(EMCustomListener listener) { if (_customListeners.contains(listener)) { _customListeners.remove(listener); @@ -332,11 +450,17 @@ class EMClient { var event = map['event']; for (var listener in _multiDeviceListeners) { if (event >= 10) { - listener.onGroupEvent(convertIntToEMContactGroupEvent(event), - map['target'], map['userNames']); + listener.onGroupEvent( + convertIntToEMContactGroupEvent(event)!, + map['target'], + map['userNames'], + ); } else { listener.onContactEvent( - convertIntToEMContactGroupEvent(event), map['target'], map['ext']); + convertIntToEMContactGroupEvent(event)!, + map['target'], + map['ext'], + ); } } } @@ -359,87 +483,60 @@ class EMClient { } } + /// + /// Gets the `EMChatManager` class. Make sure to call it after EMClient has been initialized. + /// + /// **Return** The `EMChatManager` class. + /// EMChatManager get chatManager { return _chatManager; } + /// + /// Gets the `EMContactManager` class. Make sure to call it after the EMClient has been initialized. + /// + /// **Return** The `EMContactManager` class. + /// EMContactManager get contactManager { return _contactManager; } + /// + /// Gets the `ChatRoomManager` class. Make sure to call it after the EMClient has been initialized. + /// + /// **Return** The `EMChatRoomManager` class. + /// EMChatRoomManager get chatRoomManager { return _chatRoomManager; } + /// + /// Gets the `EMGroupManager` class. Make sure to call it after the EMClient has been initialized. + /// + /// **Return** The `EMGroupManager` class. + /// EMGroupManager get groupManager { return _groupManager; } + /// + /// Gets the `EMPushManager` class. Make sure to call it after the EMClient has been initialized. + /// + /// **Return** The `EMPushManager` class. + /// EMPushManager get pushManager { return _pushManager; } + /// + /// Gets the `EMUserInfoManager` class. Make sure to call it after the EMClient has been initialized. + /// + /// **Return** The `EMUserInfoManager` class. + /// EMUserInfoManager get userInfoManager { return _userInfoManager; } - EMContactGroupEvent? convertIntToEMContactGroupEvent(int? i) { - switch (i) { - case 2: - return EMContactGroupEvent.CONTACT_REMOVE; - case 3: - return EMContactGroupEvent.CONTACT_ACCEPT; - case 4: - return EMContactGroupEvent.CONTACT_DECLINE; - case 5: - return EMContactGroupEvent.CONTACT_BAN; - case 6: - return EMContactGroupEvent.CONTACT_ALLOW; - case 10: - return EMContactGroupEvent.GROUP_CREATE; - case 11: - return EMContactGroupEvent.GROUP_DESTROY; - case 12: - return EMContactGroupEvent.GROUP_JOIN; - case 13: - return EMContactGroupEvent.GROUP_LEAVE; - case 14: - return EMContactGroupEvent.GROUP_APPLY; - case 15: - return EMContactGroupEvent.GROUP_APPLY_ACCEPT; - case 16: - return EMContactGroupEvent.GROUP_APPLY_DECLINE; - case 17: - return EMContactGroupEvent.GROUP_INVITE; - case 18: - return EMContactGroupEvent.GROUP_INVITE_ACCEPT; - case 19: - return EMContactGroupEvent.GROUP_INVITE_DECLINE; - case 20: - return EMContactGroupEvent.GROUP_KICK; - case 21: - return EMContactGroupEvent.GROUP_BAN; - case 22: - return EMContactGroupEvent.GROUP_ALLOW; - case 23: - return EMContactGroupEvent.GROUP_BLOCK; - case 24: - return EMContactGroupEvent.GROUP_UNBLOCK; - case 25: - return EMContactGroupEvent.GROUP_ASSIGN_OWNER; - case 26: - return EMContactGroupEvent.GROUP_ADD_ADMIN; - case 27: - return EMContactGroupEvent.GROUP_REMOVE_ADMIN; - case 28: - return EMContactGroupEvent.GROUP_ADD_MUTE; - case 29: - return EMContactGroupEvent.GROUP_REMOVE_MUTE; - default: - return null; - } - } - void _clearAllInfo() { _currentUsername = null; _userInfoManager.clearUserInfoCache(); diff --git a/lib/src/em_contact_manager.dart b/lib/src/em_contact_manager.dart index ddd4e30d..4e9f9e23 100644 --- a/lib/src/em_contact_manager.dart +++ b/lib/src/em_contact_manager.dart @@ -2,9 +2,14 @@ import 'dart:async'; import 'package:flutter/services.dart'; -import '../im_flutter_sdk.dart'; -import 'chat_method_keys.dart'; +import 'em_listeners.dart'; +import 'internal/chat_method_keys.dart'; +import 'internal/em_event_keys.dart'; +import 'models/em_error.dart'; +/// +/// The contact manager class, which manages chat contacts such as adding, deleting, retrieving, and modifying contacts. +/// class EMContactManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( @@ -21,14 +26,13 @@ class EMContactManager { }); } - final List _contactChangeEventListeners = []; + final List _contactManagerListeners = []; - /// @nodoc Future _onContactChanged(Map event) async { var type = event['type']; - String? username = event['username']; + String username = event['username']; String? reason = event['reason']; - for (var listener in _contactChangeEventListeners) { + for (var listener in _contactManagerListeners) { switch (type) { case EMContactChangeEvent.CONTACT_ADD: listener.onContactAdded(username); @@ -50,8 +54,16 @@ class EMContactManager { } } - /// 添加联系人[username] with [reason]. - Future addContact( + /// + /// Adds a new contact. + /// + /// Param [username] The user to be added. + /// + /// Param [reason] (optional) The invitation message. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future addContact( String username, [ String reason = '', ]) async { @@ -59,15 +71,23 @@ class EMContactManager { Map result = await _channel.invokeMethod(ChatMethodKeys.addContact, req); try { EMError.hasErrorFromResult(result); - return result[ChatMethodKeys.addContact]; } on EMError catch (e) { throw e; } } - /// 删除联系人 [username] - /// [keepConversation] true 保留会话和消息 false 不保留, 默认为false - Future deleteContact( + /// + /// Deletes a contact and all the related conversations. + /// + /// Param [username] The contact to be deleted. + /// + /// Param [keepConversation] Whether to retain conversations of the deleted contact. + /// - `true`: Yes. + /// - `false`: (default) No. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future deleteContact( String username, [ bool keepConversation = false, ]) async { @@ -75,13 +95,18 @@ class EMContactManager { Map result = await _channel.invokeMethod(ChatMethodKeys.deleteContact, req); try { EMError.hasErrorFromResult(result); - return result[ChatMethodKeys.deleteContact]; } on EMError catch (e) { throw e; } } - /// 从服务器获取所有的好友 + /// + /// Gets all the contacts from the server. + /// + /// **Return** The list of contacts. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> getAllContactsFromServer() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getAllContactsFromServer); @@ -89,7 +114,6 @@ class EMContactManager { EMError.hasErrorFromResult(result); List contacts = []; result[ChatMethodKeys.getAllContactsFromServer]?.forEach((element) { - // 此处做了一个适配,目前native 返回的都是String, 为了避免以后出现进一步扩展,flutter直接返回contact对象 contacts.add(element); }); return contacts; @@ -98,7 +122,13 @@ class EMContactManager { } } - /// 从本地获取所有的好友 + /// + /// Gets the contact list from the local database. + /// + /// **Return** The contact list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> getAllContactsFromDB() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getAllContactsFromDB); @@ -106,7 +136,6 @@ class EMContactManager { EMError.hasErrorFromResult(result); List contacts = []; result[ChatMethodKeys.getAllContactsFromDB]?.forEach((element) { - // 此处做了一个适配,目前native 返回的都是String, 为了避免以后出现进一步扩展,flutter直接返回contact对象 contacts.add(element); }); @@ -116,35 +145,54 @@ class EMContactManager { } } - /// 把指定用户加入到黑名单中 [username] . - Future addUserToBlockList( + /// + /// 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 {@link EMError}. + /// + Future addUserToBlockList( String username, ) async { Map req = {'username': username}; - Map result = - await _channel.invokeMethod(ChatMethodKeys.addUserToBlockList, req); + Map result = await _channel.invokeMethod( + ChatMethodKeys.addUserToBlockList, + req, + ); try { EMError.hasErrorFromResult(result); - return result[ChatMethodKeys.addUserToBlockList]; } on EMError catch (e) { throw e; } } - /// 把用户从黑名单中移除 [username]. - Future removeUserFromBlockList(String username) async { + /// + /// 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 {@link EMError}. + /// + Future removeUserFromBlockList(String username) async { Map req = {'username': username}; Map result = await _channel.invokeMethod( ChatMethodKeys.removeUserFromBlockList, req); try { EMError.hasErrorFromResult(result); - return result[ChatMethodKeys.removeUserFromBlockList]; } on EMError catch (e) { throw e; } } - /// 从服务器获取黑名单列表 + /// + /// Gets the block list from the server. + /// + /// **Return** The block list obtained from the server. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> getBlockListFromServer() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getBlockListFromServer); @@ -152,7 +200,6 @@ class EMContactManager { EMError.hasErrorFromResult(result); List blockList = []; result[ChatMethodKeys.getBlockListFromServer]?.forEach((element) { - // 此处做了一个适配,目前native 返回的都是String, 为了避免以后出现进一步扩展,flutter直接返回contact对象 blockList.add(element); }); return blockList; @@ -161,7 +208,13 @@ class EMContactManager { } } - /// 从本地数据库中获取黑名单列表 + /// + /// Gets the block list from the local database. + /// + /// **Return** The block list obtained from the local database. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> getBlockListFromDB() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getBlockListFromDB); try { @@ -176,33 +229,49 @@ class EMContactManager { } } - /// 接受加好友的邀请[username]. - Future acceptInvitation(String username) async { + /// + /// Accepts a friend invitation。 + /// + /// Param [username] The user who sends the friend invitation. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future acceptInvitation(String username) async { Map req = {'username': username}; Map result = await _channel.invokeMethod(ChatMethodKeys.acceptInvitation, req); try { EMError.hasErrorFromResult(result); - return result[ChatMethodKeys.acceptInvitation]; } on EMError catch (e) { throw e; } } - /// 拒绝加好友的邀请 [username]. - Future declineInvitation(String username) async { + /// + /// Declines a friend invitation. + /// + /// Param [username] The user who sends the friend invitation. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future declineInvitation(String username) async { Map req = {'username': username}; Map result = await _channel.invokeMethod(ChatMethodKeys.declineInvitation, req); try { EMError.hasErrorFromResult(result); - return result[ChatMethodKeys.declineInvitation]; } on EMError catch (e) { throw e; } } - /// 从服务器获取登录用户在其他设备上登录的ID + /// + /// 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 {@link EMError}. + /// Future?> getSelfIdsOnOtherPlatform() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getSelfIdsOnOtherPlatform); @@ -216,23 +285,23 @@ class EMContactManager { } } - /// 设置好友监听器 [contactListener] - void addContactListener(EMContactEventListener contactListener) { - _contactChangeEventListeners.add(contactListener); + /// + /// Registers a new contact listener. + /// + /// Param [contactListener] The contact listener to be registered: {@link EMContactEventListener}. + /// + void addContactListener(EMContactManagerListener contactListener) { + _contactManagerListeners.add(contactListener); } - /// 移除好友监听器 [contactListener] - void removeContactListener(EMContactEventListener contactListener) { - if (_contactChangeEventListeners.contains(contactListener)) { - _contactChangeEventListeners.remove(contactListener); + /// + /// Removes the contact listener. + /// + /// Param [contactListener] The contact listener to be removed. + /// + void removeContactListener(EMContactManagerListener contactListener) { + if (_contactManagerListeners.contains(contactListener)) { + _contactManagerListeners.remove(contactListener); } } } - -class EMContactChangeEvent { - static const String CONTACT_ADD = 'onContactAdded'; - static const String CONTACT_DELETE = 'onContactDeleted'; - static const String INVITED = 'onContactInvited'; - static const String INVITATION_ACCEPTED = 'onFriendRequestAccepted'; - static const String INVITATION_DECLINED = 'onFriendRequestDeclined'; -} diff --git a/lib/src/em_group_manager.dart b/lib/src/em_group_manager.dart index b47c6ecd..a25cfd79 100644 --- a/lib/src/em_group_manager.dart +++ b/lib/src/em_group_manager.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/services.dart'; import 'em_listeners.dart'; +import 'internal/em_event_keys.dart'; import 'models/em_cursor_result.dart'; import 'models/em_error.dart'; import 'models/em_group.dart'; @@ -9,13 +10,17 @@ import 'models/em_group_options.dart'; import 'models/em_group_shared_file.dart'; import 'tools/em_extension.dart'; -import 'chat_method_keys.dart'; +import 'internal/chat_method_keys.dart'; +/// +/// The group manager class, which manages group creation and deletion, user joining and exiting the group, etc. +/// class EMGroupManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( '$_channelPrefix/chat_group_manager', JSONMethodCodec()); + /// @nodoc EMGroupManager() { _channel.setMethodCallHandler((MethodCall call) async { Map? argMap = call.arguments; @@ -29,16 +34,38 @@ class EMGroupManager { final _groupChangeListeners = []; - /// 根据群组id获取群实例 - Future getGroupWithId(String groupId) async { + /// + /// Gets the group instance from the cache by group ID. + /// + /// Param [groupId] The group ID. + /// + /// **Return** The group instance. Returns null if the group does not exist. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future getGroupWithId(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.getGroupWithId, req); - EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.getGroupWithId]); + try { + EMError.hasErrorFromResult(result); + if (result.containsKey(ChatMethodKeys.getGroupWithId)) { + return EMGroup.fromJson(result[ChatMethodKeys.getGroupWithId]); + } else { + return null; + } + } on EMError catch (e) { + throw e; + } } - /// 从本地缓存中获取已加入的群组列表 + /// + /// Gets all groups of the current user from the cache. + /// + /// **Return** The group list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> getJoinedGroups() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getJoinedGroups); EMError.hasErrorFromResult(result); @@ -48,7 +75,7 @@ class EMGroupManager { return list; } - /// 获取免打扰的群组列表id + @Deprecated("Switch to using EMPushConfig#noDisturbGroupsFromServer instead.") Future?> getGroupsWithoutNotice() async { Map result = await _channel .invokeMethod(ChatMethodKeys.getGroupsWithoutPushNotification); @@ -58,8 +85,16 @@ class EMGroupManager { return list; } - /// 从服务器获取已加入的群组列表 - Future> getJoinedGroupsFromServer({ + /// + /// 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 {@link #fetchGroupInfoFromServer(String groupId)}. + /// + /// **Return** The list of groups that the current user joins. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future> fetchJoinedGroupsFromServer({ int pageSize = 200, int pageNum = 1, }) async { @@ -73,12 +108,24 @@ class EMGroupManager { return list; } - /// 从服务器获取公开群组列表 - Future> getPublicGroupsFromServer({ + /// + /// Gets public groups from the server with pagination. + /// + /// Param [pageSize] The number of public groups per page. + /// + /// Param [cursor] The cursor position from which to start to get data next time. Sets the parameter as null for the first time. + /// + /// **Return** The result of {@link EMCursorResult}, including the cursor for getting data next time and the group list. + /// If `EMCursorResult.cursor` is an empty string (""), all data is fetched. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future> fetchPublicGroupsFromServer({ int pageSize = 200, - String cursor = '', + String? cursor, }) async { - Map req = {'pageSize': pageSize, 'cursor': cursor}; + Map req = {'pageSize': pageSize}; + req.setValueWithOutNull("cursor", cursor); Map result = await _channel.invokeMethod( ChatMethodKeys.getPublicGroupsFromServer, req); try { @@ -93,19 +140,46 @@ class EMGroupManager { } } - /// 创建群组 - Future createGroup(String groupName, - {required EMGroupOptions settings, - String desc = '', - List? inviteMembers, - String inviteReason = ''}) async { - Map req = { - 'groupName': groupName, - 'desc': desc, - 'inviteMembers': inviteMembers ?? [], - 'inviteReason': inviteReason, - 'options': settings.toJson() - }; + /// + /// 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. + /// You can set {@link com.EMMultiDeviceListener} to listen for the event. If an event occurs, the callback function + /// {@link EMMultiDeviceListener#onGroupEvent(int, String, List)} is triggered, where the first parameter is the event which is + /// {@link EMContactGroupEvent#GROUP_CREATE} for a group creation event. + /// + /// Param [groupName] The group name. + /// + /// Param [desc] The group description. + /// + /// Param [inviteMembers] The group member array. The group owner ID is optional. + /// + /// Param [inviteReason] The group joining invitation. + /// + /// Param [options] The options for creating a group. See {@link EMGroupOptions}. + /// The options are as follows: + /// - The maximum number of group members. The default value is 200. + /// - The group style. See {@link EMGroupManager.EMGroupStyle}. The default value is {@link EMGroupStyle#PrivateOnlyOwnerInvite}. + /// - Whether to ask for permission when inviting a user to join the group. The default value is `false`, indicating that invitees are automatically added to the group without their permission. + /// - The group detail extensions. + /// + /// **Return** The created group instance. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future createGroup({ + String? groupName, + String? desc, + List? inviteMembers, + String? inviteReason, + required EMGroupOptions options, + }) async { + Map req = {'options': options.toJson()}; + req.setValueWithOutNull("groupName", groupName); + req.setValueWithOutNull("desc", desc); + req.setValueWithOutNull("inviteMembers", inviteMembers); + req.setValueWithOutNull("inviteReason", inviteReason); + Map result = await _channel.invokeMethod(ChatMethodKeys.createGroup, req); try { EMError.hasErrorFromResult(result); @@ -115,8 +189,18 @@ class EMGroupManager { } } - /// 获取群组详情 - Future getGroupSpecificationFromServer(String groupId) async { + /// + /// Gets the group information from the server. + /// + /// This method does not get member information. If member information is required, call {@link #fetchMemberListFromServer(String, int?, String?)}. + /// + /// Param [groupId] The group ID. + /// + /// **Return** The group instance. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future fetchGroupInfoFromServer(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod( ChatMethodKeys.getGroupSpecificationFromServer, req); @@ -129,17 +213,36 @@ class EMGroupManager { } } - /// 获取群组成员列表 - Future> getGroupMemberListFromServer( + /// + /// Gets the member list of the group with pagination. + /// + /// For example: + /// ```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] The group ID. + /// + /// Param [pageSize] The number of group members per page. + /// + /// Param [cursor] The cursor position from which to start to get data next time. Sets the parameter as null for the first time. + /// + /// **Return** The result of {@link EMCursorResult}, including the cursor for getting data next time and the group member list. + /// If `EMCursorResult.cursor` is an empty string (""), all data is fetched. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future> fetchMemberListFromServer( String groupId, { int pageSize = 200, - String cursor = '', + String? cursor, }) async { Map req = { 'groupId': groupId, - 'cursor': cursor, 'pageSize': pageSize, }; + req.setValueWithOutNull("cursor", cursor); Map result = await _channel.invokeMethod( ChatMethodKeys.getGroupMemberListFromServer, req, @@ -154,8 +257,22 @@ class EMGroupManager { } } - /// 获取黑名单列表 - Future?> getGroupBlockListFromServer( + /// + /// Gets the group block list from server with pagination. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [pageSize] The number of groups per page. + /// + /// Param [pageNum] The page number, starting from 1. + /// + /// **Return** The group block list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future?> fetchBlockListFromServer( String groupId, { int pageSize = 200, int pageNum = 1, @@ -171,8 +288,22 @@ class EMGroupManager { } } - /// 获取禁言列表 - Future?> getGroupMuteListFromServer( + /// + /// Gets the mute list of the group from the server. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [pageSize] The number of muted members per page. + /// + /// Param [pageNum] The page number, starting from 1. + /// + /// **Return** The group mute list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future?> fetchMuteListFromServer( String groupId, { int pageSize = 200, int pageNum = 1, @@ -188,8 +319,18 @@ class EMGroupManager { } } - /// 获取白名单列表 - Future?> getGroupWhiteListFromServer(String groupId) async { + /// + /// Gets the allow list of the group from the server. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// **Return** The allow list of the group. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future?> fetchWhiteListFromServer(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod( ChatMethodKeys.getGroupWhiteListFromServer, req); @@ -201,7 +342,15 @@ class EMGroupManager { } } - /// 判断自己是否在白名单中 + /// + /// Gets whether the member is on the allow list of the group. + /// + /// Param [groupId] The group ID. + /// + /// **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 {@link EMError}. + /// Future isMemberInWhiteListFromServer(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod( @@ -214,8 +363,20 @@ class EMGroupManager { } } - /// 获取群共享文件列表 - Future> getGroupFileListFromServer( + /// + /// Gets the shared files of the group from the server. + /// + /// Param [groupId] The group ID. + /// + /// Param [pageSize] The number of shared files per page. + /// + /// Param [pageNum] The page number, starting from 1. + /// + /// **Return** The shared files. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future> fetchGroupFileListFromServer( String groupId, { int pageSize = 200, int pageNum = 1, @@ -235,8 +396,18 @@ class EMGroupManager { } } - /// 从服务器获取群公告 - Future getGroupAnnouncementFromServer(String groupId) async { + /// + /// Gets the group announcement from the server. + /// + /// Group members can call this method. + /// + /// Param [groupId] The group ID. + /// + /// **Return** The group announcement. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future fetchAnnouncementFromServer(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod( ChatMethodKeys.getGroupAnnouncementFromServer, req); @@ -248,13 +419,26 @@ class EMGroupManager { } } - /// 邀请用户加入私有群,用于公开群: PublicJoinNeedApproval / PublicOpenJoin + /// + /// Adds users to the group. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [members] The array of new members to add. + /// + /// Param [welcome] The welcome message. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future addMembers( String groupId, List members, [ - String welcome = '', + String? welcome, ]) async { - Map req = {'welcome': welcome, 'groupId': groupId, 'members': members}; + Map req = {'groupId': groupId, 'members': members}; + req.setValueWithOutNull("welcome", welcome); Map result = await _channel.invokeMethod(ChatMethodKeys.addMembers, req); try { EMError.hasErrorFromResult(result); @@ -263,7 +447,21 @@ class EMGroupManager { } } - /// 邀请用户加入私有群,用于私有群: PrivateOnlyOwnerInvite / PrivateMemberCanInvite + /// + /// Invites users to join the group. + /// + /// This method works only for groups with the style of `PrivateOnlyOwnerInvite`, `PrivateMemberCanInvite`, or `PublicJoinNeedApproval`. + /// For a group with the PrivateOnlyOwnerInvite style, only the group owner can invite users to join the group; + /// For a group with the PrivateMemberCanInvite style, each group member can invite users to join the group. + /// + /// Param [groupId] The group ID. + /// + /// Param [members] The array of new members to invite. + /// + /// Param [reason] The invitation reason. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future inviterUser( String groupId, List members, [ @@ -289,7 +487,17 @@ class EMGroupManager { } } - /// 从群组中移除用户 + /// + /// Removes a member from the group. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [members] The username of the member to be removed. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future removeMembers( String groupId, List members, @@ -303,7 +511,19 @@ class EMGroupManager { } } - /// 将用户加入到群组黑名单中 + /// + /// 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. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [members] The list of users to be added to the block list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future blockMembers( String groupId, List members, @@ -317,7 +537,17 @@ class EMGroupManager { } } - /// 将用户从黑名单中移除 + /// + /// Removes users from the group block list. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [members] The users to be removed from the group block list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future unblockMembers( String groupId, List members, @@ -332,8 +562,18 @@ class EMGroupManager { } } - /// 更新群组名称 - Future changeGroupName( + /// + /// Changes the group name. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [name] The new group name. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future changeGroupName( String groupId, String name, ) async { @@ -342,14 +582,23 @@ class EMGroupManager { await _channel.invokeMethod(ChatMethodKeys.updateGroupSubject, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.updateGroupSubject]); } on EMError catch (e) { throw e; } } - /// 更新群描述 - Future changeGroupDescription( + /// + /// Changes the group description. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [desc] The new group description. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future changeGroupDescription( String groupId, String desc, ) async { @@ -358,13 +607,18 @@ class EMGroupManager { await _channel.invokeMethod(ChatMethodKeys.updateDescription, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.updateDescription]); } on EMError catch (e) { throw e; } } - /// 退出群组 + /// + /// Leaves a group. + /// + /// Param [groupId] The group ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future leaveGroup(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.leaveGroup, req); @@ -375,7 +629,15 @@ class EMGroupManager { } } - /// 解散群组 + /// + /// Destroys the group instance. + /// + /// Only the group owner can call this method. + /// + /// Param [groupId] The group ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future destroyGroup(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.destroyGroup, req); @@ -386,7 +648,15 @@ class EMGroupManager { } } - /// 不接收群消息 + /// + /// Blocks group messages. + /// + /// The user that blocks group messages is still a group member, but can't receive group messages. + /// + /// Param [groupId] The group ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future blockGroup(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.blockGroup, req); @@ -397,7 +667,13 @@ class EMGroupManager { } } - /// 恢复接收群消息 + /// + /// Unblocks group messages. + /// + /// Param [groupId] The group ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future unblockGroup(String groupId) async { Map req = {'groupId': groupId}; Map result = await _channel.invokeMethod(ChatMethodKeys.unblockGroup, req); @@ -408,8 +684,20 @@ class EMGroupManager { } } - /// 将群转给其他人,需要群主调用 - Future changeGroupOwner( + /// + /// Transfers the group ownership. + /// + /// Only the group owner can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [newOwner] The new owner ID. + /// + /// **Return** The updated group instance. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future changeOwner( String groupId, String newOwner, ) async { @@ -418,14 +706,25 @@ class EMGroupManager { await _channel.invokeMethod(ChatMethodKeys.updateGroupOwner, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.updateGroupOwner]); } on EMError catch (e) { throw e; } } - /// 添加管理员 - Future addAdmin( + /// + /// Adds a group admin. + /// + /// Only the group owner can call this method and group admins cannot. + /// + /// Param [groupId] The group ID. + /// + /// Param [memberId] The username of the admin to add. + /// + /// **Return** The updated group instance. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future addAdmin( String groupId, String memberId, ) async { @@ -433,14 +732,25 @@ class EMGroupManager { Map result = await _channel.invokeMethod(ChatMethodKeys.addAdmin, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.addAdmin]); } on EMError catch (e) { throw e; } } - /// 移除管理员 - Future removeAdmin( + /// + /// Removes a group admin. + /// + /// Only the group owner can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [adminId] The username of the admin to remove. + /// + /// **Return** The updated group instance. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future removeAdmin( String groupId, String adminId, ) async { @@ -448,14 +758,25 @@ class EMGroupManager { Map result = await _channel.invokeMethod(ChatMethodKeys.removeAdmin, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.removeAdmin]); } on EMError catch (e) { throw e; } } - /// 对群成员禁言,白名单中的用户不会被限制 - Future muteMembers( + /// + /// Mutes group members. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [members] The list of members to be muted. + /// + /// Param [duration] The mute duration in milliseconds. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future muteMembers( String groupId, List members, { int duration = -1, @@ -464,14 +785,23 @@ class EMGroupManager { Map result = await _channel.invokeMethod(ChatMethodKeys.muteMembers, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.muteMembers]); } on EMError catch (e) { throw e; } } - /// 对群成员取消禁言 - Future unMuteMembers( + /// + /// Unmutes group members. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [members] The list of members to be muted. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future unMuteMembers( String groupId, List members, ) async { @@ -479,13 +809,20 @@ class EMGroupManager { Map result = await _channel.invokeMethod(ChatMethodKeys.unMuteMembers, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.unMuteMembers]); } on EMError catch (e) { throw e; } } - /// 对所有群成员禁言,白名单中的用户不会被限制 + /// + /// Mutes all members. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future muteAllMembers(String groupId) async { Map req = {'groupId': groupId}; Map result = @@ -497,7 +834,15 @@ class EMGroupManager { } } - /// 取消对所有群成员禁言 + /// + /// Unmutes all members. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future unMuteAllMembers(String groupId) async { Map req = {'groupId': groupId}; Map result = @@ -509,8 +854,18 @@ class EMGroupManager { } } - /// 将用户添加到白名单 - Future addWhiteList( + /// + /// Adds members to the allow list of the group. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [members] The members to be added to the allow list of the group. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future addWhiteList( String groupId, List members, ) async { @@ -518,14 +873,23 @@ class EMGroupManager { Map result = await _channel.invokeMethod(ChatMethodKeys.addWhiteList, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.addWhiteList]); } on EMError catch (e) { throw e; } } - /// 将用户移出白名单 - Future removeWhiteList( + /// + /// Removes members from the allow list of the group. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [members] The members to be removed from the allow list of the group. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future removeWhiteList( String groupId, List members, ) async { @@ -534,14 +898,23 @@ class EMGroupManager { await _channel.invokeMethod(ChatMethodKeys.removeWhiteList, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.removeWhiteList]); } on EMError catch (e) { throw e; } } - /// 上传群共享文件 - Future uploadGroupSharedFile( + /// + /// Uploads the shared file to the group. + /// + /// When a shared file is uploaded, the upload progress callback will be triggered. + /// + /// Param [groupId] The group ID. + /// + /// Param [filePath] The local path of the shared file. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future uploadGroupSharedFile( String groupId, String filePath, ) async { @@ -550,14 +923,25 @@ class EMGroupManager { await _channel.invokeMethod(ChatMethodKeys.uploadGroupSharedFile, req); try { EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.uploadGroupSharedFile); } on EMError catch (e) { throw e; } } - /// 下载群共享文件 - Future downloadGroupSharedFile( + /// + /// Downloads the shared file of the group. + /// + /// Note: The callback is only used for progress callback. + /// + /// Param [groupId] The group ID. + /// + /// Param [fileId] The ID of the shared file. + /// + /// Param [savePath] The local path of the shared file. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future downloadGroupSharedFile( String groupId, String fileId, String savePath, @@ -567,14 +951,23 @@ class EMGroupManager { ChatMethodKeys.downloadGroupSharedFile, req); try { EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.downloadGroupSharedFile); } on EMError catch (e) { throw e; } } - /// 删除群共享文件 - Future removeGroupSharedFile( + /// + /// 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. + /// + /// Param [groupId] The group ID. + /// + /// Param [fileId] The ID of the shared file. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future removeGroupSharedFile( String groupId, String fileId, ) async { @@ -583,14 +976,23 @@ class EMGroupManager { await _channel.invokeMethod(ChatMethodKeys.removeGroupSharedFile, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.removeGroupSharedFile]); } on EMError catch (e) { throw e; } } - /// 更新群公告 - Future updateGroupAnnouncement( + /// + /// Updates the group announcement. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [announcement] The group announcement. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future updateGroupAnnouncement( String groupId, String announcement, ) async { @@ -599,30 +1001,47 @@ class EMGroupManager { ChatMethodKeys.updateGroupAnnouncement, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.updateGroupAnnouncement]); } on EMError catch (e) { throw e; } } - /// 更新群扩展 - Future updateGroupExt( + /// + /// Updates the group extension field. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [extension] The group extension field. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future updateGroupExtension( String groupId, - String ext, + String extension, ) async { - Map req = {'groupId': groupId, 'ext': ext}; + Map req = {'groupId': groupId, 'ext': extension}; Map result = await _channel.invokeMethod(ChatMethodKeys.updateGroupExt, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.updateGroupExt]); } on EMError catch (e) { throw e; } } - /// 加入公开群,用于加入不需要群主/管理员同意的公开群: EMGroupStyle.PublicOpenJoin - Future joinPublicGroup( + /// + /// Joins a public group. + /// + /// For a group that requires no authentication,users can join it freely without obtaining permissions from the group owner. + /// For a group that requires authentication, users need to wait for the group owner to agree before joining the group. For details, see {@link EMGroupStyle}. + /// + /// Param [groupId] The group ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future joinPublicGroup( String groupId, ) async { Map req = {'groupId': groupId}; @@ -630,31 +1049,49 @@ class EMGroupManager { await _channel.invokeMethod(ChatMethodKeys.joinPublicGroup, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.joinPublicGroup]); } on EMError catch (e) { throw e; } } - /// 申请加入公开群,用于加入需要群主/管理员同意的公开群: EMGroupStyle.PublicJoinNeedApproval - Future requestToJoinPublicGroup( + /// + /// Requests to join a group. + /// + /// This method works only for public groups requiring authentication, i.e., groups with the style of {@link EMGroupStyle#PublicJoinNeedApproval}. + /// + /// Param [groupId] The group ID. + /// + /// Param [reason] The reason for requesting to join the group. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future requestToJoinPublicGroup( String groupId, [ - String reason = '', + String? reason, ]) async { - Map req = {'groupId': groupId, 'reason': reason}; + Map req = {'groupId': groupId}; + req.setValueWithOutNull('reason', reason); Map result = await _channel.invokeMethod( ChatMethodKeys.requestToJoinPublicGroup, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.requestToJoinPublicGroup]); } on EMError catch (e) { throw e; } } - /// 同意公开群组申请,当群类型是EMGroupStyle.PublicJoinNeedApproval, - /// 有人申请进群时,管理员和群主会收到申请,用该方法同意申请 - Future acceptJoinApplication( + /// + /// Approves a group request. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [username] The username of the user who sends a request to join the group. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future acceptJoinApplication( String groupId, String username, ) async { @@ -663,33 +1100,53 @@ class EMGroupManager { await _channel.invokeMethod(ChatMethodKeys.acceptJoinApplication, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.acceptJoinApplication]); } on EMError catch (e) { throw e; } } - /// 拒绝公开群组申请,当群类型是EMGroupStyle.PublicJoinNeedApproval, - /// 有人申请进群时,管理员和群主会收到申请,用该方法拒绝申请 - Future declineJoinApplication( + /// + /// Declines a group request. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [username] The username of the user who sends a request to join the group. + /// + /// Param [reason] The reason of declining. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future declineJoinApplication( String groupId, String username, [ - String reason = '', + String? reason, ]) async { - Map req = {'groupId': groupId, 'username': username, 'reason': reason}; + Map req = {'groupId': groupId, 'username': username}; + req.setValueWithOutNull('reason', reason); + Map result = await _channel.invokeMethod(ChatMethodKeys.declineJoinApplication, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.declineJoinApplication]); } on EMError catch (e) { throw e; } } - /// 同意群邀请,当群组是PrivateOnlyOwnerInvite / PrivateMemberCanInvite时, - /// 有人添加您入群时您会收到群邀请,用该方法同意群邀请 - Future acceptInvitationFromGroup( + /// + /// Accepts a group invitation. + /// + /// Param [groupId] The group ID. + /// + /// Param [inviter] The user who initiates the invitation. + /// + /// **Return** The group instance which the user has accepted the invitation to join. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future acceptInvitation( String groupId, String inviter, ) async { @@ -704,53 +1161,330 @@ class EMGroupManager { } } - /// 拒绝群邀请,当群组是PrivateOnlyOwnerInvite / PrivateMemberCanInvite时, - /// 有人添加您入群时您会收到群邀请,用该方法拒绝群邀请 - Future declineInvitationFromGroup( + /// + /// Declines a group invitation. + /// + /// Param [groupId] The group ID. + /// + /// Param [inviter] The username of the inviter. + /// + /// Param [reason] The reason of declining. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future declineInvitation( String groupId, String inviter, [ - String reason = '', + String? reason, ]) async { - Map req = {'groupId': groupId, 'inviter': inviter, 'reason': reason}; + Map req = {'groupId': groupId, 'inviter': inviter}; + req.setValueWithOutNull('reason', reason); Map result = await _channel.invokeMethod( ChatMethodKeys.declineInvitationFromGroup, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.acceptInvitationFromGroup]); } on EMError catch (e) { throw e; } } - /// 设置群组免打扰,设置后,当您不在线时您不会收到群推送 - Future ignoreGroupPush( - String groupId, [ - bool enable = true, - ]) async { - Map req = {'groupId': groupId, 'enable': enable}; - Map result = - await _channel.invokeMethod(ChatMethodKeys.ignoreGroupPush, req); + /// + /// Registers a group event listener. + /// + /// The registered listener needs to be used together with {@link #removeGroupChangeListener(EMGroupEventListener)}. + /// + /// Param [listener] The group event listener to be registered. + /// + void addGroupChangeListener(EMGroupEventListener listener) { + _groupChangeListeners.add(listener); + } + + /// + /// Removes a group event listener. + /// + /// This method removes a group event listener registered with {@link #addGroupChangeListener(EMGroupEventListener)}. + /// + /// Param [listener] The group event listener to be removed. + /// + void removeGroupChangeListener(EMGroupEventListener listener) { + if (_groupChangeListeners.contains(listener)) { + _groupChangeListeners.remove(listener); + } + } + + /// + /// Gets the group information from the server. + /// + /// This method does not get member information. If member information is required, call {@link #fetchMemberListFromServer(String, int?, String?)}. + /// + /// Param [groupId] The group ID. + /// + /// **Return** The group instance. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + @Deprecated("Switch to using fetchGroupInfoFromServer instead.") + Future getGroupSpecificationFromServer(String groupId) async { + Map req = {'groupId': groupId}; + Map result = await _channel.invokeMethod( + ChatMethodKeys.getGroupSpecificationFromServer, req); try { EMError.hasErrorFromResult(result); - return EMGroup.fromJson(result[ChatMethodKeys.ignoreGroupPush]); + return EMGroup.fromJson( + result[ChatMethodKeys.getGroupSpecificationFromServer]); } on EMError catch (e) { throw e; } } - /// @nodoc addGroupChangeListener - Adds [listener] to be aware of group change events. - void addGroupChangeListener(EMGroupEventListener listener) { - _groupChangeListeners.add(listener); + /// + /// 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 {@link #fetchGroupInfoFromServer(String groupId)}. + /// + /// **Return** The list of groups that the current user joins. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + @Deprecated("Switch to using fetchJoinedGroupsFromServer instead.") + Future> getJoinedGroupsFromServer({ + int pageSize = 200, + int pageNum = 1, + }) async { + Map req = {'pageSize': pageSize, 'pageNum': pageNum}; + Map result = await _channel.invokeMethod( + ChatMethodKeys.getJoinedGroupsFromServer, req); + EMError.hasErrorFromResult(result); + List list = []; + result[ChatMethodKeys.getJoinedGroupsFromServer] + ?.forEach((element) => list.add(EMGroup.fromJson(element))); + return list; } - /// @nodoc removeGroupChangeListener - Remove [listener] from the listener list. - void removeGroupChangeListener(EMGroupEventListener listener) { - if (_groupChangeListeners.contains(listener)) { - _groupChangeListeners.remove(listener); + /// + /// Gets public groups from the server with pagination. + /// + /// Param [pageSize] The number of public groups per page. + /// + /// Param [cursor] The cursor position from which to start to get data next time. Sets the parameter as null for the first time. + /// + /// **Return** The result of {@link EMCursorResult}, including the cursor for getting data next time and the group list. + /// If `EMCursorResult.cursor` is an empty string (""), all data is fetched. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + @Deprecated("Switch to using fetchPublicGroupsFromServer instead.") + Future> getPublicGroupsFromServer({ + int pageSize = 200, + String? cursor, + }) async { + Map req = {'pageSize': pageSize}; + req.setValueWithOutNull("cursor", cursor); + Map result = await _channel.invokeMethod( + ChatMethodKeys.getPublicGroupsFromServer, req); + try { + EMError.hasErrorFromResult(result); + return EMCursorResult.fromJson( + result[ChatMethodKeys.getPublicGroupsFromServer], + dataItemCallback: (value) { + return EMGroup.fromJson(value); + }); + } on EMError catch (e) { + throw e; + } + } + + /// + /// Gets the group block list from server with pagination. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [pageSize] The number of groups per page. + /// + /// Param [pageNum] The page number, starting from 1. + /// + /// **Return** The group block list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + @Deprecated("Switch to using fetchBlockListFromServer instead.") + Future?> getBlockListFromServer( + String groupId, { + int pageSize = 200, + int pageNum = 1, + }) async { + Map req = {'groupId': groupId, 'pageNum': pageNum, 'pageSize': pageSize}; + Map result = await _channel.invokeMethod( + ChatMethodKeys.getGroupBlockListFromServer, req); + try { + EMError.hasErrorFromResult(result); + return result[ChatMethodKeys.getGroupBlockListFromServer]?.cast(); + } on EMError catch (e) { + throw e; + } + } + + /// + /// Gets the group announcement from the server. + /// + /// Group members can call this method. + /// + /// Param [groupId] The group ID. + /// + /// **Return** The group announcement. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + @Deprecated("Switch to using fetchAnnouncementFromServer instead.") + Future getGroupAnnouncementFromServer(String groupId) async { + Map req = {'groupId': groupId}; + Map result = await _channel.invokeMethod( + ChatMethodKeys.getGroupAnnouncementFromServer, req); + try { + EMError.hasErrorFromResult(result); + return result[ChatMethodKeys.getGroupAnnouncementFromServer]; + } on EMError catch (e) { + throw e; + } + } + + /// + /// Gets the shared files of the group from the server. + /// + /// Param [groupId] The group ID. + /// + /// Param [pageSize] The number of shared files per page. + /// + /// Param [pageNum] The page number, starting from 1. + /// + /// **Return** The shared files. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + @Deprecated("Switch to using fetchGroupFileListFromServer instead.") + Future?> getGroupFileListFromServer( + String groupId, { + int pageSize = 200, + int pageNum = 1, + }) async { + Map req = {'groupId': groupId, 'pageNum': pageNum, 'pageSize': pageSize}; + Map result = await _channel.invokeMethod( + ChatMethodKeys.getGroupFileListFromServer, req); + try { + EMError.hasErrorFromResult(result); + List list = []; + result[ChatMethodKeys.getGroupFileListFromServer]?.forEach((element) { + list.add(EMGroupSharedFile.fromJson(element)); + }); + return list; + } on EMError catch (e) { + throw e; + } + } + + /// + /// Gets the member list of the group with pagination. + /// + /// For example: + /// ```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] The group ID. + /// + /// Param [pageSize] The number of group members per page. + /// + /// Param [cursor] The cursor position from which to start to get data next time. Sets the parameter as null for the first time. + /// + /// **Return** The result of {@link EMCursorResult}, including the cursor for getting data next time and the group member list. + /// If `EMCursorResult.cursor` is an empty string (""), all data is fetched. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + @Deprecated("Switch to using fetchMemberListFromServer instead.") + Future> getGroupMemberListFromServer( + String groupId, { + int pageSize = 200, + String? cursor, + }) async { + Map req = { + 'groupId': groupId, + 'pageSize': pageSize, + }; + req.setValueWithOutNull("cursor", cursor); + Map result = await _channel.invokeMethod( + ChatMethodKeys.getGroupMemberListFromServer, + req, + ); + try { + EMError.hasErrorFromResult(result); + return EMCursorResult.fromJson( + result[ChatMethodKeys.getGroupMemberListFromServer], + dataItemCallback: (value) => value); + } on EMError catch (e) { + throw e; + } + } + + /// + /// Gets the mute list of the group from the server. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// Param [pageSize] The number of muted members per page. + /// + /// Param [pageNum] The page number, starting from 1. + /// + /// **Return** The group mute list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + @Deprecated("Switch to using fetchMuteListFromServer instead.") + Future?> getMuteListFromServer( + String groupId, { + int pageSize = 200, + int pageNum = 1, + }) async { + Map req = {'groupId': groupId, 'pageNum': pageNum, 'pageSize': pageSize}; + Map result = await _channel.invokeMethod( + ChatMethodKeys.getGroupMuteListFromServer, req); + try { + EMError.hasErrorFromResult(result); + return result[ChatMethodKeys.getGroupMuteListFromServer]?.cast(); + } on EMError catch (e) { + throw e; + } + } + + /// + /// Gets the allow list of the group from the server. + /// + /// Only the group owner or admin can call this method. + /// + /// Param [groupId] The group ID. + /// + /// **Return** The allow list of the group. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + @Deprecated("Switch to using fetchWhiteListFromServer instead.") + Future?> getWhiteListFromServer(String groupId) async { + Map req = {'groupId': groupId}; + Map result = await _channel.invokeMethod( + ChatMethodKeys.getGroupWhiteListFromServer, req); + try { + EMError.hasErrorFromResult(result); + return result[ChatMethodKeys.getGroupWhiteListFromServer]?.cast(); + } on EMError catch (e) { + throw e; } } - /// @nodoc Future _onGroupChanged(Map? map) async { for (EMGroupEventListener listener in _groupChangeListeners) { var type = map!['type']; diff --git a/lib/src/em_listeners.dart b/lib/src/em_listeners.dart index 0ba467f0..a3ba8e37 100644 --- a/lib/src/em_listeners.dart +++ b/lib/src/em_listeners.dart @@ -1,32 +1,91 @@ import '../im_flutter_sdk.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); +/// ``` +/// abstract class EMConnectionListener { - /// 网络已连接 + /// + /// Occurs when the SDK connects to the chat server successfully. + /// void onConnected(); - /// 连接失败,原因是[errorCode] + /// + /// 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(int? errorCode); - /// token 即将过期 + /// + /// Occurs when the token is about to expire. + /// void onTokenWillExpire(); - /// token 已经过期 + /// + /// Occurs when the token has expired. + /// void onTokenDidExpire(); } -/// @nodoc +/// +/// 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); +/// ``` abstract class EMMultiDeviceListener { - /// @nodoc + /// + /// The multi-device event callback of contact. + /// + /// Param [event] The event type. + /// + /// Param [username] The username. + /// + /// Param [ext] The extended Information. + /// void onContactEvent( - EMContactGroupEvent? event, - String? target, + EMMultiDevicesEvent event, + String username, String? ext, ); - /// @nodoc + /// + /// 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( - EMContactGroupEvent? event, - String? target, + EMMultiDevicesEvent event, + String groupId, List? usernames, ); } @@ -35,325 +94,786 @@ abstract class EMCustomListener { void onDataReceived(Map map); } -/// @nodoc -enum EMContactGroupEvent { - CONTACT_REMOVE, - CONTACT_ACCEPT, - CONTACT_DECLINE, - CONTACT_BAN, - CONTACT_ALLOW, - GROUP_CREATE, - GROUP_DESTROY, - GROUP_JOIN, - GROUP_LEAVE, - GROUP_APPLY, - GROUP_APPLY_ACCEPT, - GROUP_APPLY_DECLINE, - GROUP_INVITE, - GROUP_INVITE_ACCEPT, - GROUP_INVITE_DECLINE, - GROUP_KICK, - GROUP_BAN, - GROUP_ALLOW, - GROUP_BLOCK, - GROUP_UNBLOCK, - GROUP_ASSIGN_OWNER, - GROUP_ADD_ADMIN, - GROUP_REMOVE_ADMIN, - GROUP_ADD_MUTE, - GROUP_REMOVE_MUTE, -} - -abstract class EMContactEventListener { - /// 被[userName]添加为好友 - void onContactAdded(String? userName); +/// +/// 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.addContactListener(contactListener); +/// ``` +/// +/// Unregister the listener: +/// ```dart +/// EMClient.getInstance.contactManager.removeContactListener(contactListener); +/// ``` +/// +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); - /// 被[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); - /// 收到[userName]的好友申请,原因是[reason] - void onContactInvited(String? userName, String? reason); - - /// 发出的好友申请被[userName]同意 - void onFriendRequestAccepted(String? userName); - - /// 发出的好友申请被[userName]拒绝 /// - void onFriendRequestDeclined(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); -abstract class EMConversationListener { - void onConversationUpdate(); -} + /// + /// Occurs when a friend request is approved. + /// + /// Param [userName] The user who initiated the friend request. + /// + void onFriendRequestAccepted(String userName); -/// @nodoc -class EMChatRoomEvent { - static const String ON_CHAT_ROOM_DESTROYED = "onChatRoomDestroyed"; - static const String ON_MEMBER_JOINED = "onMemberJoined"; - static const String ON_MEMBER_EXITED = "onMemberExited"; - static const String ON_REMOVED_FROM_CHAT_ROOM = "onRemovedFromChatRoom"; - static const String ON_MUTE_LIST_ADDED = "onMuteListAdded"; - static const String ON_MUTE_LIST_REMOVED = "onMuteListRemoved"; - static const String ON_ADMIN_ADDED = "onAdminAdded"; - static const String ON_ADMIN_REMOVED = "onAdminRemoved"; - static const String ON_OWNER_CHANGED = "onOwnerChanged"; - static const String ON_ANNOUNCEMENT_CHANGED = "onAnnouncementChanged"; - static const String ON_WHITE_LIST_REMOVED = "onWhiteListRemoved"; - static const String ON_WHITE_LIST_ADDED = "onWhiteListAdded"; - static const String ON_ALL_MEMBER_MUTE_STATE_CHANGED = - "onAllMemberMuteStateChanged"; + /// + /// Occurs when a friend request is declined. + /// + /// Param [userName] The user who initiated the friend request. + /// + void onFriendRequestDeclined(String userName); } +// abstract class EMConversationListener { +// void onConversationUpdate(); +// } + +/// +/// The chat room change listener. +/// +/// Register the chat room change listener: +/// ```dart +/// EMClient.getInstance.chatRoomManager.addChatRoomChangeListener(listener); +/// ``` +/// +///Unregister the chat room change listener: +/// ```dart +/// EMClient.getInstance.chatRoomManager.removeChatRoomListener(listener); +/// ``` +/// abstract class EMChatRoomEventListener { - /// id是[roomId],名称是[roomName]的聊天室被销毁 + /// + /// Occurs when the chat room is destroyed. + /// + /// Param [roomId] The chatroom ID. + /// + /// Param [roomName] The chatroom subject. + /// void onChatRoomDestroyed(String roomId, String? roomName); - /// 有用户[participant]加入id是[roomId]的聊天室 + /// + /// 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); - /// 有用户[participant]离开id是[roomId],名字是[roomName]的聊天室 + /// + /// Occurs when a member leaves the chatroom. + /// + /// Param [roomId] The chatroom ID. + /// + /// Param [participant] The new member's username. + /// void onMemberExitedFromChatRoom( String roomId, String? roomName, String participant); - /// 用户[participant]被id是[roomId],名称[roomName]的聊天室删除 + /// + /// Occurs when a member is dismissed from a chat room. + /// + /// Param [roomId] The chatroom ID. + /// + /// Param [roomName] The chatroom subject. + /// + /// Param [participant] The member is dismissed from a chat room. + /// void onRemovedFromChatRoom( - String roomId, String? roomName, String? participant); + String roomId, + String? roomName, + String? participant, + ); - /// @nodoc id是[roomId]的聊天室禁言列表[mutes]有增加 + /// + /// 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); + String roomId, + List mutes, + String? expireTime, + ); - /// @nodoc id是[roomId]的聊天室禁言列表[mutes]有减少 - void onMuteListRemovedFromChatRoom(String roomId, List mutes); + /// + /// 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, + ); - /// @nodoc id是[roomId]的聊天室增加id是[admin]管理员 + /// + /// 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); - /// @nodoc id是[roomId]的聊天室移除id是[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); - /// @nodoc id是[roomId]的聊天室所有者由[oldOwner]变更为[newOwner] + /// + /// 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); - /// @nodoc id是[roomId]的聊天室公告变为[announcement] + /// + /// 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 onWhiteListAddedFromChatRoom(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 onWhiteListRemovedFromChatRoom(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); } -/// @nodoc -class EMGroupChangeEvent { - static const String ON_INVITATION_RECEIVED = "onInvitationReceived"; - static const String ON_INVITATION_ACCEPTED = "onInvitationAccepted"; - static const String ON_INVITATION_DECLINED = "onInvitationDeclined"; - static const String ON_AUTO_ACCEPT_INVITATION = - "onAutoAcceptInvitationFromGroup"; - static const String ON_USER_REMOVED = "onUserRemoved"; - static const String ON_REQUEST_TO_JOIN_RECEIVED = "onRequestToJoinReceived"; - static const String ON_REQUEST_TO_JOIN_DECLINED = "onRequestToJoinDeclined"; - static const String ON_REQUEST_TO_JOIN_ACCEPTED = "onRequestToJoinAccepted"; - static const String ON_GROUP_DESTROYED = "onGroupDestroyed"; - static const String ON_MUTE_LIST_ADDED = "onMuteListAdded"; - static const String ON_MUTE_LIST_REMOVED = "onMuteListRemoved"; - static const String ON_ADMIN_ADDED = "onAdminAdded"; - static const String ON_ADMIN_REMOVED = "onAdminRemoved"; - static const String ON_OWNER_CHANGED = "onOwnerChanged"; - static const String ON_MEMBER_JOINED = "onMemberJoined"; - static const String ON_MEMBER_EXITED = "onMemberExited"; - static const String ON_ANNOUNCEMENT_CHANGED = "onAnnouncementChanged"; - static const String ON_SHARED_FILE_ADDED = "onSharedFileAdded"; - static const String ON_SHARED_FILE__DELETED = "onSharedFileDeleted"; - static const String ON_WHITE_LIST_REMOVED = "onWhiteListRemoved"; - static const String ON_WHITE_LIST_ADDED = "onWhiteListAdded"; - static const String ON_ALL_MEMBER_MUTE_STATE_CHANGED = - "onAllMemberMuteStateChanged"; -} - @Deprecated('Use EMGroupEventListener.') abstract class EMGroupChangeListener { - /// id是[groupId], 名称是[groupName]的群邀请被[inviter]拒绝,理由是[reason] + /// + /// Occurs when an invitation is rejected by the inviter. + /// + /// Param [groupId] The group ID. + /// + /// Param [groupName] The group name. + /// + /// Param [inviter] The username of the inviter. + /// + /// Param [reason] The reason. + /// void onInvitationReceivedFromGroup( String groupId, String? groupName, String inviter, String? reason); - /// 收到用户[applicant]申请加入id是[groupId], 名称是[groupName]的群,原因是[reason] + /// + /// Occurs when a group join application is received from an applicant. + /// + /// Param [groupId] The group ID. + /// + /// Param [groupName] The group name. + /// + /// Param [applicant] The username of the applicant. + /// + /// Param [reason] The reason. + /// void onRequestToJoinReceivedFromGroup( String groupId, String? groupName, String applicant, String? reason); - /// 入群申请被同意 + /// + /// Occurs when a group-join application is accepted. + /// + /// Param [groupId] The group ID. + /// + /// Param [groupName] The group name. + /// + /// Param [accepter] The username of the accepter. + /// void onRequestToJoinAcceptedFromGroup( String groupId, String? groupName, String accepter); - /// 入群申请被拒绝 + /// + /// Occurs when a group-join application is declined. + /// + /// Param [groupId] The group ID. + /// + /// Param [groupName] The group name. + /// + /// Param [decliner] The username of the decliner. + /// + /// Param [reason] The reason. + /// void onRequestToJoinDeclinedFromGroup( String groupId, String? groupName, String decliner, String? reason); - /// 入群邀请被同意 + /// + /// Occurs when a group invitation is approved. + /// + /// Param [groupId] The group ID. + /// + /// Param [groupName] The group name. + /// + /// Param [invitee] The username of the invitee. + /// + /// Param [reason] The reason. + /// void onInvitationAcceptedFromGroup( String groupId, String invitee, String? reason); - /// 入群邀请被拒绝 + /// + /// Occurs when a group invitation is declined. + /// + /// Param [groupId] The group ID. + /// + /// Param [invitee] The username of the invitee. + /// + /// Param [reason] The reason. + /// void onInvitationDeclinedFromGroup( String groupId, String invitee, String? reason); - /// 被移出群组 + /// Occurs when a group member is removed from the group. + /// + /// 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); - /// @nodoc 自动同意加群 + /// Occurs when the group invitation is accepted automatically. + /// The SDK will join the group before notifying the app of the acceptance of the group invitation. + /// For settings, see {@link EMOptions#autoAcceptGroupInvitation(boolean value)}. + /// + /// 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 members are added to the mute list of the group. + /// + /// Param [groupId] The group ID. + /// + /// Param [mutes] The members to be muted. + /// + /// Param [muteExpire] Reserved parameter. The time when the mute state expires. + /// void onMuteListAddedFromGroup( String groupId, List mutes, int? muteExpire); - /// 群禁言列表减少 + /// Occurs when members are removed from the mute list of the group. + /// + /// Param [groupId] The group ID. + /// + /// Param [mutes] The members to be removed from the mute list. + /// void onMuteListRemovedFromGroup(String groupId, List mutes); - /// 群管理增加 + /// + /// Occurs when members are changed to admins. + /// + /// Param [groupId] The group ID. + /// + /// Param [admin] The members changed to be admins. + /// void onAdminAddedFromGroup(String groupId, String admin); - /// 群管理被移除 + /// + /// Occurs when an admin permission is removed. + /// + /// Param [groupId] The group ID. + /// + /// Param [admin] The member whose admin permission is removed. void onAdminRemovedFromGroup(String groupId, String admin); - /// 群所有者变更 + /// + /// Occurs when the chat room 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 the group. + /// + /// Param [groupId] The group ID. + /// + /// Param [member] The new member. void onMemberJoinedFromGroup(String groupId, String member); - /// 有用户离开群 + /// + /// Occurs when a member exits the group. + /// + /// Param [groupId] The group ID. + /// + /// Param [member] The member who exits the group. void onMemberExitedFromGroup(String groupId, String member); - /// 群公告变更 + /// + /// Occurs when the announcement changed. + /// + /// Param [groupId] The group ID. + /// + /// Param [member] The new announcement. void onAnnouncementChangedFromGroup(String groupId, String announcement); - /// 群共享文件增加 + /// Occurs when a shared file is added to the group. + /// + /// Param [groupId] The group ID. + /// + /// Param [member] The new shared File. + /// void onSharedFileAddedFromGroup(String groupId, EMGroupSharedFile sharedFile); - /// 群共享文件被删除 + /// + /// Occurs when a shared file is deleted. + /// + /// Param [groupId] The group ID. + /// + /// Param [member] The ID of the shared file that is deleted. + /// void onSharedFileDeletedFromGroup(String groupId, String fileId); - /// 有用户被添加到群组白名单 + /// + /// Occurs when one or more group members are added to the allow list. + /// + /// Param [groupId] The group ID. + /// + /// Param [members] The members that are added to the allow list. void onWhiteListAddedFromGroup(String groupId, List members); - /// 有用户从群组白名单被移除 + /// + /// Occurs when one or more group members are removed from the allow list. + /// + /// Param [groupId] The group ID. + /// + /// Param [members] The members that are removed from the allow list. void onWhiteListRemovedFromGroup(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); } +/// +/// 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. +/// +/// Registers a group change listener: +/// ```dart +/// EMClient.getInstance.groupManager.addGroupChangeListener(listener); +/// ``` +/// +/// Unregisters a group change listener: +/// ```dart +/// EMClient.getInstance.groupManager.removeGroupChangeListener(listener); +/// ``` abstract class EMGroupEventListener { - /// id是[groupId], 名称是[groupName]的群邀请被[inviter]拒绝,理由是[reason] + /// + /// 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); - /// 收到用户[applicant]申请加入id是[groupId], 名称是[groupName]的群,原因是[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); + 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); + 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); - /// @nodoc 自动同意加群 + /// + /// Occurs when the group invitation is accepted automatically. + /// For settings, see {@link EMOptions#autoAcceptGroupInvitation(boolean value)}. + /// 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 onWhiteListAddedFromGroup(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 onWhiteListRemovedFromGroup(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); } +/// +/// 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: {@link EMOptions#requireDeliveryAck(boolean)}. +/// If the peer reads the received message, a read receipt will be returned (read receipt needs to be enabled: {@link EMOptions#requireAck(boolean)}) +/// 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); +/// ``` +/// abstract class EMChatManagerListener { - /// 收到消息[messages] + /// + /// 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) {} - /// 收到cmd消息[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) {} - /// 收到[messages]消息已读 + /// + /// Occurs when a read receipt is received for a message. + /// + /// Param [messages] The has read messages. + /// void onMessagesRead(List messages) {} - /// 收到[groupMessageAcks]群消息已读回调 + /// + /// Occurs when a read receipt is received for a group message. + /// + /// Param [groupMessageAcks] The group message acks. + /// void onGroupMessageRead(List groupMessageAcks) {} - /// 收到[messages]消息已送达 + /// + /// Occurs when a delivery receipt is received. + /// + /// Param [messages] The has delivered messages. + /// void onMessagesDelivered(List messages) {} - /// 收到[messages]消息被撤回 + /// + /// Occurs when a received message is recalled. + /// + /// Param [messages] The recalled messages. + /// void onMessagesRecalled(List messages) {} - /// 会话列表变化 + /// + /// Occurs when the conversation updated. + /// void onConversationsUpdate() {} - /// 会话已读`from`是已读的发送方, `to`是已读的接收方 + /// + /// 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 `isAcked` 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 `isRead` 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) {} } diff --git a/lib/src/em_message_status_callback.dart b/lib/src/em_message_status_callback.dart new file mode 100644 index 00000000..6054fd3f --- /dev/null +++ b/lib/src/em_message_status_callback.dart @@ -0,0 +1,26 @@ +import 'package:flutter/foundation.dart'; + +import 'models/em_error.dart'; + +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_push_manager.dart b/lib/src/em_push_manager.dart index cfc11566..a211a845 100644 --- a/lib/src/em_push_manager.dart +++ b/lib/src/em_push_manager.dart @@ -1,19 +1,31 @@ import 'dart:io'; import 'package:flutter/services.dart'; - -import 'tools/em_extension.dart'; -import 'chat_method_keys.dart'; +import 'internal/chat_method_keys.dart'; import 'models/em_error.dart'; import 'models/em_push_configs.dart'; +/// +/// The push styles. +/// +/// +enum DisplayStyle { + /// The push message presentation style: SimpleBanner represents the presentation of a simple message. + Simple, + + /// The push message presentation style: MessageSummary represents the presentation of message content. + Summary, +} + +/// +/// The message push configuration options. +/// class EMPushManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( '$_channelPrefix/chat_push_manager', JSONMethodCodec()); - /// 从本地获取ImPushConfig - Future getImPushConfig() async { + Future getPushConfigsFromCache() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getImPushConfig); try { EMError.hasErrorFromResult(result); @@ -23,8 +35,8 @@ class EMPushManager { } } - /// 从服务器获取ImPushConfig - Future getImPushConfigFromServer() async { + /// Gets the push configurations from the server. + Future fetchPushConfigsFromServer() async { Map result = await _channel.invokeMethod(ChatMethodKeys.getImPushConfigFromServer); try { @@ -36,64 +48,262 @@ class EMPushManager { } } - /// 更新当前用户的[nickname],这样离线消息推送的时候可以显示用户昵称而不是id,需要登录环信服务器成功后调用才生效 - Future updatePushNickname(String nickname) async { + /// + /// Turns on the push notification. + /// + /// **Throws** A description of the issue that caused this exception. See {@link EMError} + /// + Future enableOfflinePush() async { + Map result = await _channel.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 {@link EMError} + /// + Future disableOfflinePush({ + required int start, + required int end, + }) async { + Map req = {'start': start, 'end': end}; + Map result = + await _channel.invokeMethod(ChatMethodKeys.disableOfflinePush, req); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } + } + + /// + /// 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 {@link EMError} + /// + Future updatePushServiceForGroup({ + required List groupIds, + required bool enablePush, + }) async { + Map req = {'noPush': !enablePush, 'group_ids': groupIds}; + Map result = + await _channel.invokeMethod(ChatMethodKeys.updateGroupPushService, req); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } + } + + /// + /// 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 {@link EMError} + /// + Future updatePushServiceFroUsers({ + required List userIds, + required bool enablePush, + }) async { + Map req = {'noPush': !enablePush, 'user_ids': userIds}; + Map result = + await _channel.invokeMethod(ChatMethodKeys.updateUserPushService, 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 {@link EMError} + /// + Future> getNoPushGroupsFromCache() async { + Map result = await _channel.invokeMethod(ChatMethodKeys.getNoPushGroups); + List list = []; + if (result.containsKey(ChatMethodKeys.getNoPushGroups)) { + list = result[ChatMethodKeys.getNoPushGroups]?.cast(); + } + return list; + } + + /// + /// 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 {@link EMError} + /// + Future> getNoPushUsersFromCache() async { + Map result = await _channel.invokeMethod(ChatMethodKeys.getNoPushUsers); + List list = []; + if (result.containsKey(ChatMethodKeys.getNoPushUsers)) { + list = result[ChatMethodKeys.getNoPushUsers]?.cast(); + } + return list; + } + + /// + /// 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. + /// When the app user changes the nickname in the user profile(use {@link EMUserInfoManager#updateOwnInfo(EMUserInfo, int?) + /// be sure to also call this method to update to prevent the display differences. + /// + /// 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 {@link EMError} + /// + Future updatePushNickname(String nickname) async { Map req = {'nickname': nickname}; Map result = await _channel.invokeMethod(ChatMethodKeys.updatePushNickname, req); try { EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.updatePushNickname); } on EMError catch (e) { throw e; } } - /// 上传华为推送token, 需要确保登录成功后再调用(可以是进入home页面后) - Future updateHMSPushToken(String token) async { + /// + /// Updates the push message style. The default value is {@link DisplayStyle#Simple}. + /// + /// Param [displayStyle] The push message display style. + /// + /// **Throws** A description of the issue that caused this exception. See {@link EMError} + /// + Future updatePushDisplayStyle(DisplayStyle displayStyle) async { + Map req = {'pushStyle': displayStyle == DisplayStyle.Simple ? 0 : 1}; + Map result = + await _channel.invokeMethod(ChatMethodKeys.updateImPushStyle, req); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } + } + + /// + /// Updates the HMS push token. + /// + /// Param [token] The HMS push token. + /// + /// **Throws** A description of the issue that caused this exception. See {@link EMError} + /// + Future updateHMSPushToken(String token) async { if (Platform.isAndroid) { Map req = {'token': token}; Map result = await _channel.invokeMethod(ChatMethodKeys.updateHMSPushToken, req); try { EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.updateHMSPushToken); } on EMError catch (e) { throw e; } } - return true; } - /// 上传FCM推送token, 需要确保登录成功后再调用(可以是进入home页面后) - Future updateFCMPushToken(String token) async { + /// + /// Updates the FCM push token. + /// + /// Param [token] The FCM push token. + /// + /// **Throws** A description of the issue that caused this exception. See {@link EMError} + /// + Future updateFCMPushToken(String token) async { if (Platform.isAndroid) { Map req = {'token': token}; Map result = await _channel.invokeMethod(ChatMethodKeys.updateFCMPushToken, req); try { EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.updateFCMPushToken); } on EMError catch (e) { throw e; } } - return true; } - /// 上传iOS推送deviceToken - Future updateAPNsDeviceToken(String token) async { + /// + /// Updates the APNs push token. + /// + /// Param [token] The APNs push token. + /// + /// **Throws** A description of the issue that caused this exception. See {@link EMError} + /// + Future updateAPNsDeviceToken(String token) async { if (Platform.isIOS) { Map req = {'token': token}; Map result = await _channel.invokeMethod(ChatMethodKeys.updateAPNsPushToken, req); try { EMError.hasErrorFromResult(result); - return true; } on EMError catch (e) { throw e; } } - return true; + } + + /// Gets push options from the local database. + @Deprecated('use - getPushConfigsFromCache method instead.') + Future getImPushConfig() async { + Map result = await _channel.invokeMethod(ChatMethodKeys.getImPushConfig); + try { + EMError.hasErrorFromResult(result); + return EMPushConfigs.fromJson(result[ChatMethodKeys.getImPushConfig]); + } on EMError catch (e) { + throw e; + } + } + + /// Gets push options from the server. + @Deprecated('use - getPushConfigsFromServer method instead.') + Future getImPushConfigFromServer() async { + Map result = + await _channel.invokeMethod(ChatMethodKeys.getImPushConfigFromServer); + try { + EMError.hasErrorFromResult(result); + return EMPushConfigs.fromJson( + result[ChatMethodKeys.getImPushConfigFromServer]); + } on EMError catch (e) { + throw e; + } + } + + /// Gets the push configurations from the server. + @Deprecated('use - fetchPushConfigsFromServer method instead.') + Future getPushConfigsFromServer() async { + Map result = + await _channel.invokeMethod(ChatMethodKeys.getImPushConfigFromServer); + try { + EMError.hasErrorFromResult(result); + return EMPushConfigs.fromJson( + result[ChatMethodKeys.getImPushConfigFromServer]); + } on EMError catch (e) { + throw e; + } } } diff --git a/lib/src/em_status_listener.dart b/lib/src/em_status_listener.dart new file mode 100644 index 00000000..bec97136 --- /dev/null +++ b/lib/src/em_status_listener.dart @@ -0,0 +1,22 @@ +import 'models/em_error.dart'; + +@Deprecated("Switch to using MessageStatusCallBack instead.") +abstract class StatusListener { + /// The status of a message. + void onProgress(int progress) {} + + /// The message fails to be delivered. + void onError(EMError error) {} + + /// The message is successfully delivered. + void onSuccess() {} + + /// The message is read. + void onReadAck() {} + + /// The message is delivered. + void onDeliveryAck() {} + + /// Occurs when the status of the message changes. + void onStatusChanged() {} +} diff --git a/lib/src/em_userInfo_manager.dart b/lib/src/em_userInfo_manager.dart index 0cdc9922..9990da71 100644 --- a/lib/src/em_userInfo_manager.dart +++ b/lib/src/em_userInfo_manager.dart @@ -1,11 +1,14 @@ import 'dart:async'; import 'package:flutter/services.dart'; -import 'chat_method_keys.dart'; +import 'internal/chat_method_keys.dart'; import 'em_client.dart'; import 'models/em_error.dart'; import 'models/em_userInfo.dart'; +/// +/// The user attribute manager class, which gets and sets the user attributes. +/// class EMUserInfoManager { static const _channelPrefix = 'com.chat.im'; static const MethodChannel _channel = const MethodChannel( @@ -13,52 +16,41 @@ class EMUserInfoManager { EMUserInfo? _ownUserInfo; - //有效的联系人map + // The map of effective contacts. Map _effectiveUserInfoMap = Map(); - EMUserInfoManager(); - - //更新自己的用户属性 - Future updateOwnUserInfo(EMUserInfo userInfo) async { + /// + /// Modifies the user attributes of the current user. + /// + /// Param [userInfo] The user attributes to be modified. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future updateOwnUserInfo(EMUserInfo userInfo) async { Map req = {'userInfo': userInfo.toJson()}; Map result = await _channel.invokeMethod(ChatMethodKeys.updateOwnUserInfo, req); try { EMError.hasErrorFromResult(result); - return EMUserInfo.fromJson(result[ChatMethodKeys.updateOwnUserInfo]); - } on EMError catch (e) { - throw e; - } - } - - /// 更新自己用户属性 - Future updateOwnUserInfoWithType( - EMUserInfoType type, String userInfoValue) async { - Map req = { - 'userInfoType': _userInfoTypeToInt(type), - 'userInfoValue': userInfoValue - }; - Map result = await _channel.invokeMethod( - ChatMethodKeys.updateOwnUserInfoWithType, req); - try { - EMError.hasErrorFromResult(result); - if (result[ChatMethodKeys.updateOwnUserInfoWithType] != null) { - _ownUserInfo = EMUserInfo.fromJson( - result[ChatMethodKeys.updateOwnUserInfoWithType]); - _effectiveUserInfoMap[_ownUserInfo!.userId] = _ownUserInfo!; - } - - return _ownUserInfo; } on EMError catch (e) { throw e; } } - Future fetchOwnInfo({int expireTime = 3600}) async { + /// + /// Gets the current user's attributes from the server. + /// + /// Param [expireTime] The time period(seconds) when the user attibutes in the cache expire. If the interval between two calles 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 user properties that are obtained. See {@link EMUserInfo}. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future fetchOwnInfo({int expireTime = 0}) async { String? currentUser = await EMClient.getInstance.getCurrentUsername(); if (currentUser != null) { try { - Map ret = await fetchUserInfoByIdWithExpireTime( + Map ret = await fetchUserInfoById( [currentUser], expireTime: expireTime, ); @@ -70,12 +62,21 @@ class EMUserInfoManager { return _ownUserInfo; } - /// 获取指定id的用户的用户属性, - /// `userIds` 需要获取的环信id; - /// `expireTime` 过期时间,单位秒。如果之前获取过, 如果距当前时间小于过期时间则不会重复获取 - Future> fetchUserInfoByIdWithExpireTime( - List userIds, - {int expireTime = 3600}) async { + /// + /// Gets user attributes of the specified users. + /// + /// Param [userIds] The username array. + /// + /// Param [expireTime] The time period(seconds) when the user attibutes in the cache expire. If the interval between two calles 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** 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 {@link EMError}. + /// + Future> fetchUserInfoById( + List userIds, { + int expireTime = 0, + }) async { List needReqIds = userIds .where((element) => !_effectiveUserInfoMap.containsKey(element) || @@ -112,144 +113,6 @@ class EMUserInfoManager { } } - /// 获取指定id的用户的指定类型的用户属性 - /// `userIds` 需要获取的环信id; - /// `types` 需要获取的属性 - /// `expireTime` 过期时间,单位秒。如果之前获取过, 如果距当前时间小于过期时间则不会重复获取 - @Deprecated( - 'Use userInfoManager.fetchUserInfoByIdWithExpireTime() method instead.') - Future> fetchUserInfoByIdWithType( - List userIds, List types, - {int expireTime = 3600}) async { - List userInfoTypes = []; - types.forEach((element) { - int type = _userInfoTypeToInt(element); - userInfoTypes.add(type); - }); - - List reqIds = userIds - .where((element) => - !_effectiveUserInfoMap.containsKey(element) || - (_effectiveUserInfoMap.containsKey(element) && - DateTime.now().millisecondsSinceEpoch - - _effectiveUserInfoMap[element]!.expireTime > - expireTime * 1000)) - .toList(); - Map resultMap = Map(); - - Map req = {'userIds': reqIds, 'userInfoTypes': userInfoTypes}; - Map result = await _channel.invokeMethod( - ChatMethodKeys.fetchUserInfoByIdWithType, req); - - try { - EMError.hasErrorFromResult(result); - result[ChatMethodKeys.fetchUserInfoByIdWithType].forEach((key, value) { - EMUserInfo eUserInfo = EMUserInfo.fromJson(value); - resultMap[key] = eUserInfo; - - _effectiveUserInfoMap[key] = eUserInfo; - }); - - return resultMap as FutureOr>; - } on EMError catch (e) { - throw e; - } - } - - // 整型转化用户属性类型 【int => EMUserInfoType】 - static EMUserInfoType userInfoTypeFromInt(int type) { - EMUserInfoType ret = EMUserInfoType.NickName; - switch (type) { - case 0: - { - ret = EMUserInfoType.NickName; - } - break; - case 1: - { - ret = EMUserInfoType.AvatarURL; - } - break; - case 2: - { - ret = EMUserInfoType.Phone; - } - break; - case 3: - { - ret = EMUserInfoType.Mail; - } - break; - case 4: - { - ret = EMUserInfoType.Gender; - } - break; - case 5: - { - ret = EMUserInfoType.Sign; - } - break; - case 6: - { - ret = EMUserInfoType.Birth; - } - break; - case 7: - { - ret = EMUserInfoType.Ext; - } - } - return ret; - } - - // 用户属性类型转化整型 【EMUserInfoType => int】 - static int _userInfoTypeToInt(EMUserInfoType type) { - int ret = 0; - switch (type) { - case EMUserInfoType.NickName: - { - ret = 0; - } - break; - case EMUserInfoType.AvatarURL: - { - ret = 1; - } - break; - case EMUserInfoType.Phone: - { - ret = 2; - } - break; - case EMUserInfoType.Mail: - { - ret = 3; - } - break; - case EMUserInfoType.Gender: - { - ret = 4; - } - break; - case EMUserInfoType.Sign: - { - ret = 5; - } - break; - case EMUserInfoType.Birth: - { - ret = 6; - } - break; - case EMUserInfoType.Ext: - { - ret = 7; - } - } - return ret; - } - void clearUserInfoCache() { _ownUserInfo = null; _effectiveUserInfoMap.clear(); diff --git a/lib/src/internal/chat_method_keys.dart b/lib/src/internal/chat_method_keys.dart new file mode 100644 index 00000000..c04f30ec --- /dev/null +++ b/lib/src/internal/chat_method_keys.dart @@ -0,0 +1,235 @@ +class ChatMethodKeys { + /// EMClient methods + static const String init = "init"; + static const String createAccount = "createAccount"; + static const String login = "login"; + static const String loginWithAgoraToken = "loginWithAgoraToken"; + static const String renewToken = "renewToken"; + static const String logout = "logout"; + static const String changeAppKey = "changeAppKey"; + + static const String uploadLog = "uploadLog"; + static const String compressLogs = "compressLogs"; + static const String kickDevice = "kickDevice"; + static const String kickAllDevices = "kickAllDevices"; + static const String getLoggedInDevicesFromServer = + "getLoggedInDevicesFromServer"; + + static const String getToken = "getToken"; + static const String getCurrentUser = "getCurrentUser"; + static const String isLoggedInBefore = "isLoggedInBefore"; + static const String isConnected = "isConnected"; + + /// EMClient listener + static const String onMultiDeviceEvent = "onMultiDeviceEvent"; + static const String onConnected = "onConnected"; + static const String onDisconnected = "onDisconnected"; + static const String onSendDataToFlutter = "onSendDataToFlutter"; + static const String onTokenWillExpire = "onTokenWillExpire"; + static const String onTokenDidExpire = "onTokenDidExpire"; + + /// EMContactManager methods + static const String addContact = "addContact"; + static const String deleteContact = "deleteContact"; + static const String getAllContactsFromServer = "getAllContactsFromServer"; + static const String getAllContactsFromDB = "getAllContactsFromDB"; + static const String addUserToBlockList = "addUserToBlockList"; + static const String removeUserFromBlockList = "removeUserFromBlockList"; + static const String getBlockListFromServer = "getBlockListFromServer"; + static const String getBlockListFromDB = "getBlockListFromDB"; + static const String acceptInvitation = "acceptInvitation"; + static const String declineInvitation = "declineInvitation"; + static const String getSelfIdsOnOtherPlatform = "getSelfIdsOnOtherPlatform"; + + /// EMContactManager listener + static const String onContactChanged = "onContactChanged"; + + /// EMChatManager methods + static const String sendMessage = "sendMessage"; + static const String resendMessage = "resendMessage"; + static const String ackMessageRead = "ackMessageRead"; + static const String ackGroupMessageRead = "ackGroupMessageRead"; + static const String ackConversationRead = "ackConversationRead"; + static const String recallMessage = "recallMessage"; + static const String getConversation = "getConversation"; + static const String markAllChatMsgAsRead = "markAllChatMsgAsRead"; + static const String getUnreadMessageCount = "getUnreadMessageCount"; + static const String updateChatMessage = "updateChatMessage"; + static const String downloadAttachment = "downloadAttachment"; + static const String downloadThumbnail = "downloadThumbnail"; + static const String importMessages = "importMessages"; + static const String loadAllConversations = "loadAllConversations"; + static const String getConversationsFromServer = "getConversationsFromServer"; + static const String deleteConversation = "deleteConversation"; + + static const String fetchHistoryMessages = "fetchHistoryMessages"; + static const String searchChatMsgFromDB = "searchChatMsgFromDB"; + static const String getMessage = "getMessage"; + static const String asyncFetchGroupAcks = "asyncFetchGroupAcks"; + static const String deleteRemoteConversation = "deleteRemoteConversation"; + + /// EMChatManager listener + static const String onMessagesReceived = "onMessagesReceived"; + static const String onCmdMessagesReceived = "onCmdMessagesReceived"; + static const String onMessagesRead = "onMessagesRead"; + static const String onGroupMessageRead = "onGroupMessageRead"; + static const String onMessagesDelivered = "onMessagesDelivered"; + static const String onMessagesRecalled = "onMessagesRecalled"; + static const String onMessageChanged = "onMessageChanged"; + + static const String onConversationUpdate = "onConversationUpdate"; + static const String onConversationHasRead = "onConversationHasRead"; + + /// EMMessage listener + static const String onMessageProgressUpdate = "onMessageProgressUpdate"; + static const String onMessageError = "onMessageError"; + static const String onMessageSuccess = "onMessageSuccess"; + static const String onMessageReadAck = "onMessageReadAck"; + static const String onMessageDeliveryAck = "onMessageDeliveryAck"; + + /// EMConversation + static const String getUnreadMsgCount = "getUnreadMsgCount"; + static const String markAllMessagesAsRead = "markAllMessagesAsRead"; + static const String markMessageAsRead = "markMessageAsRead"; + static const String syncConversationExt = "syncConversationExt"; + static const String removeMessage = "removeMessage"; + static const String getLatestMessage = "getLatestMessage"; + static const String getLatestMessageFromOthers = "getLatestMessageFromOthers"; + static const String clearAllMessages = "clearAllMessages"; + static const String insertMessage = "insertMessage"; + static const String appendMessage = "appendMessage"; + static const String updateConversationMessage = "updateConversationMessage"; + + // 根据消息id获取消息 + static const String loadMsgWithId = "loadMsgWithId"; + // 根据起始消息id获取消息 + static const String loadMsgWithStartId = "loadMsgWithStartId"; + // 根据关键字获取消息 + static const String loadMsgWithKeywords = "loadMsgWithKeywords"; + // 根据消息类型获取消息 + static const String loadMsgWithMsgType = "loadMsgWithMsgType"; + // 通过时间获取消息 + static const String loadMsgWithTime = "loadMsgWithTime"; + + /// EMChatRoomManager methods + static const String joinChatRoom = "joinChatRoom"; + static const String leaveChatRoom = "leaveChatRoom"; + static const String fetchPublicChatRoomsFromServer = + "fetchPublicChatRoomsFromServer"; + static const String fetchChatRoomInfoFromServer = + "fetchChatRoomInfoFromServer"; + static const String getChatRoom = "getChatRoom"; + static const String getAllChatRooms = "getAllChatRooms"; + static const String createChatRoom = "createChatRoom"; + static const String destroyChatRoom = "destroyChatRoom"; + static const String changeChatRoomSubject = "changeChatRoomSubject"; + static const String changeChatRoomDescription = "changeChatRoomDescription"; + static const String fetchChatRoomMembers = "fetchChatRoomMembers"; + static const String muteChatRoomMembers = "muteChatRoomMembers"; + static const String unMuteChatRoomMembers = "unMuteChatRoomMembers"; + static const String changeChatRoomOwner = "changeChatRoomOwner"; + static const String addChatRoomAdmin = "addChatRoomAdmin"; + static const String removeChatRoomAdmin = "removeChatRoomAdmin"; + static const String fetchChatRoomMuteList = "fetchChatRoomMuteList"; + static const String removeChatRoomMembers = "removeChatRoomMembers"; + static const String blockChatRoomMembers = "blockChatRoomMembers"; + static const String unBlockChatRoomMembers = "unBlockChatRoomMembers"; + static const String fetchChatRoomBlockList = "fetchChatRoomBlockList"; + static const String updateChatRoomAnnouncement = "updateChatRoomAnnouncement"; + static const String fetchChatRoomAnnouncement = "fetchChatRoomAnnouncement"; + static const String addMembersToChatRoomWhiteList = + "addMembersToChatRoomWhiteList"; + static const String removeMembersFromChatRoomWhiteList = + "removeMembersFromChatRoomWhiteList"; + static const String fetchChatRoomWhiteListFromServer = + "fetchChatRoomWhiteListFromServer"; + static const String isMemberInChatRoomWhiteListFromServer = + "isMemberInChatRoomWhiteListFromServer"; + + static const String muteAllChatRoomMembers = "muteAllChatRoomMembers"; + static const String unMuteAllChatRoomMembers = "unMuteAllChatRoomMembers"; + + /// EMChatRoomManagerListener + static const String chatRoomChange = "onChatRoomChanged"; + + /// EMGroupManager + static const String getGroupWithId = "getGroupWithId"; + static const String getJoinedGroups = "getJoinedGroups"; + static const String getGroupsWithoutPushNotification = + "getGroupsWithoutPushNotification"; + static const String getJoinedGroupsFromServer = "getJoinedGroupsFromServer"; + static const String getPublicGroupsFromServer = "getPublicGroupsFromServer"; + static const String createGroup = "createGroup"; + static const String getGroupSpecificationFromServer = + "getGroupSpecificationFromServer"; + static const String getGroupMemberListFromServer = + "getGroupMemberListFromServer"; + static const String getGroupBlockListFromServer = + "getGroupBlockListFromServer"; + static const String getGroupMuteListFromServer = "getGroupMuteListFromServer"; + static const String getGroupWhiteListFromServer = + "getGroupWhiteListFromServer"; + static const String isMemberInWhiteListFromServer = + "isMemberInWhiteListFromServer"; + static const String getGroupFileListFromServer = "getGroupFileListFromServer"; + static const String getGroupAnnouncementFromServer = + "getGroupAnnouncementFromServer"; + static const String addMembers = "addMembers"; + static const String inviterUser = "inviterUser"; + static const String removeMembers = "removeMembers"; + static const String blockMembers = "blockMembers"; + static const String unblockMembers = "unblockMembers"; + static const String updateGroupSubject = "updateGroupSubject"; + static const String updateDescription = "updateDescription"; + static const String leaveGroup = "leaveGroup"; + static const String destroyGroup = "destroyGroup"; + static const String blockGroup = "blockGroup"; + static const String unblockGroup = "unblockGroup"; + static const String updateGroupOwner = "updateGroupOwner"; + static const String addAdmin = "addAdmin"; + static const String removeAdmin = "removeAdmin"; + static const String muteMembers = "muteMembers"; + static const String unMuteMembers = "unMuteMembers"; + static const String muteAllMembers = "muteAllMembers"; + static const String unMuteAllMembers = "unMuteAllMembers"; + static const String addWhiteList = "addWhiteList"; + static const String removeWhiteList = "removeWhiteList"; + static const String uploadGroupSharedFile = "uploadGroupSharedFile"; + static const String downloadGroupSharedFile = "downloadGroupSharedFile"; + static const String removeGroupSharedFile = "removeGroupSharedFile"; + static const String updateGroupAnnouncement = "updateGroupAnnouncement"; + static const String updateGroupExt = "updateGroupExt"; + static const String joinPublicGroup = "joinPublicGroup"; + static const String requestToJoinPublicGroup = "requestToJoinPublicGroup"; + static const String acceptJoinApplication = "acceptJoinApplication"; + static const String declineJoinApplication = "declineJoinApplication"; + static const String acceptInvitationFromGroup = "acceptInvitationFromGroup"; + static const String declineInvitationFromGroup = "declineInvitationFromGroup"; + static const String ignoreGroupPush = "ignoreGroupPush"; + + /// EMGroupManagerListener + static const String onGroupChanged = "onGroupChanged"; + + /// EMPushManager + static const String getImPushConfig = "getImPushConfig"; + static const String getImPushConfigFromServer = "getImPushConfigFromServer"; + static const String enableOfflinePush = "enableOfflinePush"; + static const String disableOfflinePush = "disableOfflinePush"; + static const String updateImPushStyle = "updateImPushStyle"; + static const String updatePushNickname = "updatePushNickname"; + + static const String updateGroupPushService = "updateGroupPushService"; + static const String getNoPushGroups = "getNoPushGroups"; + static const String updateUserPushService = "updateUserPushService"; + static const String getNoPushUsers = "getNoPushUsers"; + + static const String updateHMSPushToken = "updateHMSPushToken"; + static const String updateFCMPushToken = "updateFCMPushToken"; + static const String updateAPNsPushToken = "updateAPNsPushToken"; + + /// EMUserInfoManager methods + static const String updateOwnUserInfo = "updateOwnUserInfo"; + static const String updateOwnUserInfoWithType = "updateOwnUserInfoWithType"; + static const String fetchUserInfoById = "fetchUserInfoById"; + static const String fetchUserInfoByIdWithType = "fetchUserInfoByIdWithType"; +} diff --git a/lib/src/internal/em_event_keys.dart b/lib/src/internal/em_event_keys.dart new file mode 100644 index 00000000..f4e64938 --- /dev/null +++ b/lib/src/internal/em_event_keys.dart @@ -0,0 +1,51 @@ +class EMContactChangeEvent { + static const String CONTACT_ADD = 'onContactAdded'; + static const String CONTACT_DELETE = 'onContactDeleted'; + static const String INVITED = 'onContactInvited'; + static const String INVITATION_ACCEPTED = 'onFriendRequestAccepted'; + static const String INVITATION_DECLINED = 'onFriendRequestDeclined'; +} + +class EMChatRoomEvent { + static const String ON_CHAT_ROOM_DESTROYED = "onChatRoomDestroyed"; + static const String ON_MEMBER_JOINED = "onMemberJoined"; + static const String ON_MEMBER_EXITED = "onMemberExited"; + static const String ON_REMOVED_FROM_CHAT_ROOM = "onRemovedFromChatRoom"; + static const String ON_MUTE_LIST_ADDED = "onMuteListAdded"; + static const String ON_MUTE_LIST_REMOVED = "onMuteListRemoved"; + static const String ON_ADMIN_ADDED = "onAdminAdded"; + static const String ON_ADMIN_REMOVED = "onAdminRemoved"; + static const String ON_OWNER_CHANGED = "onOwnerChanged"; + static const String ON_ANNOUNCEMENT_CHANGED = "onAnnouncementChanged"; + static const String ON_WHITE_LIST_REMOVED = "onWhiteListRemoved"; + static const String ON_WHITE_LIST_ADDED = "onWhiteListAdded"; + static const String ON_ALL_MEMBER_MUTE_STATE_CHANGED = + "onAllMemberMuteStateChanged"; +} + +class EMGroupChangeEvent { + static const String ON_INVITATION_RECEIVED = "onInvitationReceived"; + static const String ON_INVITATION_ACCEPTED = "onInvitationAccepted"; + static const String ON_INVITATION_DECLINED = "onInvitationDeclined"; + static const String ON_AUTO_ACCEPT_INVITATION = + "onAutoAcceptInvitationFromGroup"; + static const String ON_USER_REMOVED = "onUserRemoved"; + static const String ON_REQUEST_TO_JOIN_RECEIVED = "onRequestToJoinReceived"; + static const String ON_REQUEST_TO_JOIN_DECLINED = "onRequestToJoinDeclined"; + static const String ON_REQUEST_TO_JOIN_ACCEPTED = "onRequestToJoinAccepted"; + static const String ON_GROUP_DESTROYED = "onGroupDestroyed"; + static const String ON_MUTE_LIST_ADDED = "onMuteListAdded"; + static const String ON_MUTE_LIST_REMOVED = "onMuteListRemoved"; + static const String ON_ADMIN_ADDED = "onAdminAdded"; + static const String ON_ADMIN_REMOVED = "onAdminRemoved"; + static const String ON_OWNER_CHANGED = "onOwnerChanged"; + static const String ON_MEMBER_JOINED = "onMemberJoined"; + static const String ON_MEMBER_EXITED = "onMemberExited"; + static const String ON_ANNOUNCEMENT_CHANGED = "onAnnouncementChanged"; + static const String ON_SHARED_FILE_ADDED = "onSharedFileAdded"; + static const String ON_SHARED_FILE__DELETED = "onSharedFileDeleted"; + static const String ON_WHITE_LIST_REMOVED = "onWhiteListRemoved"; + static const String ON_WHITE_LIST_ADDED = "onWhiteListAdded"; + static const String ON_ALL_MEMBER_MUTE_STATE_CHANGED = + "onAllMemberMuteStateChanged"; +} diff --git a/lib/src/models/em_push_config.dart b/lib/src/internal/em_push_config.dart similarity index 94% rename from lib/src/models/em_push_config.dart rename to lib/src/internal/em_push_config.dart index d3cdcb74..acfbd6f2 100644 --- a/lib/src/models/em_push_config.dart +++ b/lib/src/internal/em_push_config.dart @@ -1,5 +1,6 @@ import '../tools/em_extension.dart'; +/// The push configuration class, which contains the push configuration information, such as the push style. class EMPushConfig { String? mzAppId = ''; String? mzAppKey = ''; @@ -27,6 +28,7 @@ class EMPushConfig { EMPushConfig(); + /// @nodoc void updateFromJson(Map json) { miAppId = json.stringValue("mzAppId"); mzAppKey = json.stringValue("mzAppKey"); @@ -45,6 +47,7 @@ class EMPushConfig { enableAPNS = json.boolValue('enableAPNS'); } + /// @nodoc Map toJson() { final Map data = new Map(); data.setValueWithOutNull("mzAppId", mzAppId); diff --git a/lib/src/internal/em_transform_tools.dart b/lib/src/internal/em_transform_tools.dart new file mode 100644 index 00000000..3f8eae74 --- /dev/null +++ b/lib/src/internal/em_transform_tools.dart @@ -0,0 +1,311 @@ +import '../models/em_chat_enums.dart'; + +EMMultiDevicesEvent? convertIntToEMContactGroupEvent(int? i) { + switch (i) { + case 2: + return EMMultiDevicesEvent.CONTACT_REMOVE; + case 3: + return EMMultiDevicesEvent.CONTACT_ACCEPT; + case 4: + return EMMultiDevicesEvent.CONTACT_DECLINE; + case 5: + return EMMultiDevicesEvent.CONTACT_BAN; + case 6: + return EMMultiDevicesEvent.CONTACT_ALLOW; + case 10: + return EMMultiDevicesEvent.GROUP_CREATE; + case 11: + return EMMultiDevicesEvent.GROUP_DESTROY; + case 12: + return EMMultiDevicesEvent.GROUP_JOIN; + case 13: + return EMMultiDevicesEvent.GROUP_LEAVE; + case 14: + return EMMultiDevicesEvent.GROUP_APPLY; + case 15: + return EMMultiDevicesEvent.GROUP_APPLY_ACCEPT; + case 16: + return EMMultiDevicesEvent.GROUP_APPLY_DECLINE; + case 17: + return EMMultiDevicesEvent.GROUP_INVITE; + case 18: + return EMMultiDevicesEvent.GROUP_INVITE_ACCEPT; + case 19: + return EMMultiDevicesEvent.GROUP_INVITE_DECLINE; + case 20: + return EMMultiDevicesEvent.GROUP_KICK; + case 21: + return EMMultiDevicesEvent.GROUP_BAN; + case 22: + return EMMultiDevicesEvent.GROUP_ALLOW; + case 23: + return EMMultiDevicesEvent.GROUP_BLOCK; + case 24: + return EMMultiDevicesEvent.GROUP_UNBLOCK; + case 25: + return EMMultiDevicesEvent.GROUP_ASSIGN_OWNER; + case 26: + return EMMultiDevicesEvent.GROUP_ADD_ADMIN; + case 27: + return EMMultiDevicesEvent.GROUP_REMOVE_ADMIN; + case 28: + return EMMultiDevicesEvent.GROUP_ADD_MUTE; + case 29: + return EMMultiDevicesEvent.GROUP_REMOVE_MUTE; + } + return null; +} + +String messageTypeToTypeStr(MessageType type) { + switch (type) { + case MessageType.TXT: + return 'txt'; + case MessageType.LOCATION: + return 'loc'; + case MessageType.CMD: + return 'cmd'; + case MessageType.CUSTOM: + return 'custom'; + case MessageType.FILE: + return 'file'; + case MessageType.IMAGE: + return 'img'; + case MessageType.VIDEO: + return 'video'; + case MessageType.VOICE: + return 'voice'; + } +} + +int chatTypeToInt(ChatType type) { + if (type == ChatType.ChatRoom) { + return 2; + } else if (type == ChatType.GroupChat) { + return 1; + } else { + return 0; + } +} + +ChatType chatTypeFromInt(int? type) { + if (type == 2) { + return ChatType.ChatRoom; + } else if (type == 1) { + return ChatType.GroupChat; + } else { + return ChatType.Chat; + } +} + +int messageStatusToInt(MessageStatus status) { + if (status == MessageStatus.FAIL) { + return 3; + } else if (status == MessageStatus.SUCCESS) { + return 2; + } else if (status == MessageStatus.PROGRESS) { + return 1; + } else { + return 0; + } +} + +MessageStatus messageStatusFromInt(int? status) { + if (status == 3) { + return MessageStatus.FAIL; + } else if (status == 2) { + return MessageStatus.SUCCESS; + } else if (status == 1) { + return MessageStatus.PROGRESS; + } else { + return MessageStatus.CREATE; + } +} + +int downloadStatusToInt(DownloadStatus status) { + if (status == DownloadStatus.DOWNLOADING) { + return 0; + } else if (status == DownloadStatus.SUCCESS) { + return 1; + } else if (status == DownloadStatus.FAILED) { + return 2; + } else { + return 3; + } +} + +EMGroupPermissionType permissionTypeFromInt(int? type) { + EMGroupPermissionType ret = EMGroupPermissionType.Member; + switch (type) { + case -1: + { + ret = EMGroupPermissionType.None; + } + break; + case 0: + { + ret = EMGroupPermissionType.Member; + } + break; + case 1: + { + ret = EMGroupPermissionType.Admin; + } + break; + case 2: + { + ret = EMGroupPermissionType.Owner; + } + break; + } + return ret; +} + +int permissionTypeToInt(EMGroupPermissionType? type) { + int ret = 0; + if (type == null) return ret; + switch (type) { + case EMGroupPermissionType.None: + { + ret = -1; + } + break; + case EMGroupPermissionType.Member: + { + ret = 0; + } + break; + case EMGroupPermissionType.Admin: + { + ret = 1; + } + break; + case EMGroupPermissionType.Owner: + { + ret = 2; + } + break; + } + return ret; +} + +EMGroupStyle groupStyleTypeFromInt(int? type) { + EMGroupStyle ret = EMGroupStyle.PrivateOnlyOwnerInvite; + switch (type) { + case 0: + { + ret = EMGroupStyle.PrivateOnlyOwnerInvite; + } + break; + case 1: + { + ret = EMGroupStyle.PrivateMemberCanInvite; + } + break; + case 2: + { + ret = EMGroupStyle.PublicJoinNeedApproval; + } + break; + case 3: + { + ret = EMGroupStyle.PublicOpenJoin; + } + break; + } + return ret; +} + +int groupStyleTypeToInt(EMGroupStyle? type) { + int ret = 0; + if (type == null) return ret; + switch (type) { + case EMGroupStyle.PrivateOnlyOwnerInvite: + { + ret = 0; + } + break; + case EMGroupStyle.PrivateMemberCanInvite: + { + ret = 1; + } + break; + case EMGroupStyle.PublicJoinNeedApproval: + { + ret = 2; + } + break; + case EMGroupStyle.PublicOpenJoin: + { + ret = 3; + } + break; + } + return ret; +} + +EMChatRoomPermissionType chatRoomPermissionTypeFromInt(int? type) { + EMChatRoomPermissionType ret = EMChatRoomPermissionType.Member; + switch (type) { + case -1: + return EMChatRoomPermissionType.None; + case 0: + return EMChatRoomPermissionType.Member; + case 1: + return EMChatRoomPermissionType.Admin; + case 2: + return EMChatRoomPermissionType.Owner; + } + return ret; +} + +int chatRoomPermissionTypeToInt(EMChatRoomPermissionType type) { + int ret = 0; + switch (type) { + case EMChatRoomPermissionType.None: + ret = -1; + break; + case EMChatRoomPermissionType.Member: + ret = 0; + break; + case EMChatRoomPermissionType.Admin: + ret = 1; + break; + case EMChatRoomPermissionType.Owner: + ret = 2; + break; + } + return ret; +} + +int conversationTypeToInt(EMConversationType? type) { + int ret = 0; + if (type == null) return ret; + switch (type) { + case EMConversationType.Chat: + ret = 0; + break; + case EMConversationType.GroupChat: + ret = 1; + break; + case EMConversationType.ChatRoom: + ret = 2; + break; + } + return ret; +} + +EMConversationType conversationTypeFromInt(int? type) { + EMConversationType ret = EMConversationType.Chat; + switch (type) { + case 0: + ret = EMConversationType.Chat; + break; + case 1: + ret = EMConversationType.GroupChat; + break; + case 2: + ret = EMConversationType.ChatRoom; + break; + } + return ret; +} diff --git a/lib/src/models/em_chat_enums.dart b/lib/src/models/em_chat_enums.dart index fe52229a..a67ff915 100644 --- a/lib/src/models/em_chat_enums.dart +++ b/lib/src/models/em_chat_enums.dart @@ -1,18 +1,253 @@ +/// +/// The enumeration of group types. +/// enum EMGroupStyle { - PrivateOnlyOwnerInvite, // 私有群,只有群主能邀请他人进群,被邀请人会收到邀请信息,同意后可入群; - PrivateMemberCanInvite, // 私有群,所有人都可以邀请他人进群,被邀请人会收到邀请信息,同意后可入群; - PublicJoinNeedApproval, // 公开群,可以通过获取公开群列表api取的,申请加入时需要管理员以上权限用户同意; - PublicOpenJoin, // 公开群,可以通过获取公开群列表api取的,可以直接进入; + /// Private groups where only the the group owner can invite users to join. + PrivateOnlyOwnerInvite, + + /// Private groups where all group members can invite users to join. + PrivateMemberCanInvite, + + /// 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). + PublicJoinNeedApproval, + + /// Public groups where users can join freely. + PublicOpenJoin, +} + +/// The conversation types. +enum EMConversationType { + /// One-to-one chat. + Chat, + + /// Group chat. + GroupChat, + + /// Chat room. + ChatRoom, +} + +@Deprecated('Switch to using EMPushManager#DisplayStyle instead') +enum EMPushStyle { + Simple, + Summary, } +/// +/// The enumeration of chat types. +/// +/// There are three chat types: one-to-one chat, group chat, and chat room. +/// +enum ChatType { + /// One-to-one chat. + Chat, + + /// Group chat. + GroupChat, + + /// Chat room. + ChatRoom, +} + +/// +/// The enumeration of the message directions. +/// +/// Whether the message is sent or received. +/// +enum MessageDirection { + /// This message is sent from the local user. + SEND, + + /// The message is received by the local user. + RECEIVE, +} + +/// +/// The enumeration of the message sending/reception status. +/// +enum MessageStatus { + /// The message is created. + CREATE, + + /// The message is being delivered/received. + PROGRESS, + + /// The message is successfully delivered/received. + SUCCESS, + + /// The message fails to be delivered/received. + FAIL, +} + +/// +/// The download status of the attachment file. +/// +enum DownloadStatus { + /// The file message download is pending. + PENDING, + + /// The file message is being downloaded. + DOWNLOADING, + + /// The file message download succeeds. + SUCCESS, + + /// The file message download fails. + FAILED, +} + +/// +/// The enumeration of message types. +/// +enum MessageType { + /// The text message. + TXT, + + /// The image message. + IMAGE, + + /// The video message. + VIDEO, + + /// The location message. + LOCATION, + + /// The voice message. + VOICE, + + /// The file message. + FILE, + + /// The command message. + CMD, + + /// The custom message. + CUSTOM, +} + +/// +/// The enumeration of group permission types. +/// +enum EMGroupPermissionType { + /// Unknown. + None, + + /// The group member. + Member, + + /// The group admin. + Admin, + + /// The group owner. + Owner, +} + +/// +/// The enumeration of chat room role types. +/// enum EMChatRoomPermissionType { + /// Unknown. None, + + /// The chat room member. Member, + + /// The chat room admin. Admin, + + /// The chat room owner. Owner, } -enum EMConversationType { - Chat, // 单聊消息 - GroupChat, // 群聊消息 - ChatRoom, // 聊天室消息 + +/// +/// The enumeration of message search directions. +/// +enum EMSearchDirection { + /// Messages are retrieved in the reverse chronological order of when the server receives the message. + Up, + + /// Messages are retrieved in the chronological order of when the server receives the message. + Down, +} + +/// +/// 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. +/// +enum EMMultiDevicesEvent { + /// The current user removed a contact on another device. + CONTACT_REMOVE, + + /// The current user accepted a friend request on another device. + CONTACT_ACCEPT, + + /// The current user declined a friend request on another device. + CONTACT_DECLINE, + + /// The current user added a contact to the block list on another device. + CONTACT_BAN, + + /// The current user removed a contact from the block list on another device. + CONTACT_ALLOW, + + /// The current user created a group on another device. + GROUP_CREATE, + + /// The current user destroyed a group on another device. + GROUP_DESTROY, + + /// The current user joined a group on another device. + GROUP_JOIN, + + /// The current user left a group on another device. + GROUP_LEAVE, + + /// The current user requested to join a group on another device. + GROUP_APPLY, + + /// The current user accepted a group request on another device. + GROUP_APPLY_ACCEPT, + + /// The current user declined a group request on another device. + GROUP_APPLY_DECLINE, + + /// The current user invited a user to join the group on another device. + GROUP_INVITE, + + /// The current user accepted a group invitation on another device. + GROUP_INVITE_ACCEPT, + + /// The current user declined a group invitation on another device. + GROUP_INVITE_DECLINE, + + /// The current user kicked a member out of a group on another device. + GROUP_KICK, + + /// The current user added a member to a group block list on another device. + GROUP_BAN, + + /// The current user removed a member from a group block list on another device. + GROUP_ALLOW, + + /// The current user blocked a group on another device. + GROUP_BLOCK, + + /// The current user unblocked a group on another device. + GROUP_UNBLOCK, + + /// The current user transferred the group ownership on another device. + GROUP_ASSIGN_OWNER, + + /// The current user added an admin on another device. + GROUP_ADD_ADMIN, + + /// The current user removed an admin on another device. + GROUP_REMOVE_ADMIN, + + /// The current user muted a member on another device. + GROUP_ADD_MUTE, + + /// The current user unmuted a member on another device. + GROUP_REMOVE_MUTE, } diff --git a/lib/src/models/em_chat_room.dart b/lib/src/models/em_chat_room.dart index 2259c86d..719c4c5b 100644 --- a/lib/src/models/em_chat_room.dart +++ b/lib/src/models/em_chat_room.dart @@ -1,120 +1,173 @@ +import '../internal/em_transform_tools.dart'; + import '../../src/tools/em_extension.dart'; import 'em_chat_enums.dart'; +/// +/// The chat room instance class. +/// +/// **Note** +/// To get the correct value, ensure that you call {@ link EMChatRoomManager#fetchChatRoomInfoFromServer(String)} before calling this method. +/// class EMChatRoom { - EMChatRoom._private(); + EMChatRoom._private({ + required this.roomId, + this.name, + this.description, + this.owner, + this.announcement, + this.memberCount, + this.maxUsers, + this.adminList, + this.memberList, + this.blockList, + this.muteList, + this.isAllMemberMuted, + this.permissionType = EMChatRoomPermissionType.None, + }); String toString() => toJson().toString(); + /// @nodoc factory EMChatRoom.fromJson(Map map) { - return EMChatRoom._private() - .._roomId = map['roomId'] as String - .._name = map.stringValue("name") - .._description = map.stringValue("desc") - .._owner = map.stringValue("owner") - .._memberCount = map.intValue("memberCount") - .._maxUsers = map.intValue("maxUsers") - .._adminList = map.listValue("adminList") - .._memberList = map.listValue("memberList") - .._blockList = map.listValue("blockList") - .._muteList = map.listValue("muteList") - .._announcement = map.stringValue("announcement") - .._permissionType = - EMChatRoom.permissionTypeFromInt(map['permissionType']) - .._isAllMemberMuted = map.boolValue('isAllMemberMuted'); + return EMChatRoom._private( + roomId: map["roomId"], + name: map.getStringValue("name"), + description: map.getStringValue("desc"), + owner: map.getStringValue("owner"), + memberCount: map.getIntValue("memberCount"), + maxUsers: map.getIntValue("maxUsers"), + adminList: map.listValue("adminList"), + memberList: map.listValue("memberList"), + blockList: map.listValue("blockList"), + muteList: map.listValue("muteList"), + announcement: map.getStringValue("announcement"), + permissionType: + chatRoomPermissionTypeFromInt(map.getIntValue("permissionType")), + isAllMemberMuted: map.boolValue("isAllMemberMuted")); } + /// @nodoc Map toJson() { final Map data = new Map(); - data['roomId'] = _roomId; - data.setValueWithOutNull("name", _name); - data.setValueWithOutNull("desc", _description); + data['roomId'] = roomId; + data.setValueWithOutNull("name", name); + data.setValueWithOutNull("desc", description); data.setValueWithOutNull("owner", owner); - data.setValueWithOutNull("memberCount", _memberCount); - data.setValueWithOutNull("maxUsers", _maxUsers); - data.setValueWithOutNull("adminList", _adminList); - data.setValueWithOutNull("memberList", _memberList); - data.setValueWithOutNull("blockList", _blockList); - data.setValueWithOutNull("muteList", _muteList); - data.setValueWithOutNull("announcement", _announcement); - data.setValueWithOutNull("isAllMemberMuted", _isAllMemberMuted); - data['permissionType'] = EMChatRoom.permissionTypeToInt(_permissionType); + data.setValueWithOutNull("memberCount", memberCount); + data.setValueWithOutNull("maxUsers", maxUsers); + data.setValueWithOutNull("adminList", adminList); + data.setValueWithOutNull("memberList", memberList); + data.setValueWithOutNull("blockList", blockList); + data.setValueWithOutNull("muteList", muteList); + data.setValueWithOutNull("announcement", announcement); + data.setValueWithOutNull("isAllMemberMuted", isAllMemberMuted); + data['permissionType'] = chatRoomPermissionTypeToInt(permissionType); return data; } - // 房间id - late String _roomId; - // 房间名称 - String? _name = ''; - // 房间描述 - String? _description = ''; - // 房主 - String? _owner = ''; - //公告 - String? _announcement = ''; - // 当前人数 - int? _memberCount = 0; - // 最大人数 - int? _maxUsers = 0; - // 管理员列表 - List? _adminList; - // 成员列表 - List? _memberList; - // 黑名单列表 - List? _blockList; - // 禁言列表 - List? _muteList; - // 是否全员禁言 - bool? _isAllMemberMuted; - // 在聊天室中的角色 - EMChatRoomPermissionType _permissionType = EMChatRoomPermissionType.None; - - String get roomId => _roomId; - get name => _name; - get description => _description; - get owner => _owner; - get announcement => _announcement; - get memberCount => _memberCount; - get maxUsers => _maxUsers; - get adminList => _adminList; - get memberList => _memberList; - get blockList => _blockList; - get muteList => _muteList; - get isAllMemberMuted => _isAllMemberMuted; - get permissionType => _permissionType; - - static EMChatRoomPermissionType permissionTypeFromInt(int? type) { - EMChatRoomPermissionType ret = EMChatRoomPermissionType.Member; - switch (type) { - case -1: - return EMChatRoomPermissionType.None; - case 0: - return EMChatRoomPermissionType.Member; - case 1: - return EMChatRoomPermissionType.Admin; - case 2: - return EMChatRoomPermissionType.Owner; - } - return ret; - } + /// + /// Gets the chat room ID. + /// + /// **Note** + /// To get the correct value, ensure that you call {@ link EMChatRoomManager#fetchChatRoomInfoFromServer(String)} before calling this method. + /// + final String roomId; - static int permissionTypeToInt(EMChatRoomPermissionType type) { - int ret = 0; - switch (type) { - case EMChatRoomPermissionType.None: - ret = -1; - break; - case EMChatRoomPermissionType.Member: - ret = 0; - break; - case EMChatRoomPermissionType.Admin: - ret = 1; - break; - case EMChatRoomPermissionType.Owner: - ret = 2; - break; - } - return ret; - } + /// + /// Gets the chat room name from the memory. + /// + /// **Note** + /// To get the correct value, ensure that you call {@ link EMChatRoomManager#fetchChatRoomInfoFromServer(String)} before calling this method. + /// + final String? name; + + /// + /// Gets the chat room description from the memory. + /// + /// **Note** + /// To get the correct value, ensure that you call {@ link EMChatRoomManager#fetchChatRoomInfoFromServer(String)} before calling this method. + /// + final String? description; + + /// + /// 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 {@ link EMChatRoomManager#fetchChatRoomInfoFromServer(String)} before calling this method. + /// + final String? owner; + + /// + /// Gets the chat room announcement in the chat room from the memory. + /// + /// **Note** + /// To get the correct value, ensure that you call {@ link EMChatRoomManager#fetchChatRoomAnnouncement(String)} before calling this method. Otherwise, the return value may not be correct. + /// + final String? announcement; + + /// + /// Gets the number of online members from the memory. + /// + /// **Note** + /// To get the correct value, ensure that you call {@ link EMChatRoomManager#fetchChatRoomInfoFromServer(String)} before calling this method. + /// + final int? memberCount; + + /// + /// 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 {@ link EMChatRoomManager#fetchChatRoomInfoFromServer(String)} before calling this method. + /// + final int? maxUsers; + + /// + /// Gets the chat room admin list. + /// + /// **Note** + /// To get the correct value, ensure that you call {@ link EMChatRoomManager#fetchChatRoomInfoFromServer(String)} before calling this method. + /// + final List? adminList; + + /// + /// Gets the member list. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMChatRoomManager#fetchChatRoomMembers(String, bool?)} + /// + final List? memberList; + + /// + /// Gets the chat room block list. + /// + /// **Note** + /// To get the block list, you can call {@link EMChatRoomManager#fetchChatRoomBlockList(String, int?, int?)}. + /// + final List? blockList; + + /// + /// Gets the mute list of the chat room. + /// + /// **Note** + /// To get the mute list, you can call {@link EMChatRoomManager#fetchChatRoomMuteList(String, int?, int?)}. + /// + final List? muteList; + + /// + /// Checks whether all members are muted in the chat room from the memory. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMChatRoomManager#fetchChatRoomInfoFromServer(String)} before calling this method. + /// + final bool? isAllMemberMuted; + + /// + /// Gets the current user's role in the chat room. The role types: {@link EMChatRoomPermissionType}. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMChatRoomManager#fetchChatRoomInfoFromServer(String)} before calling this method. + /// + final EMChatRoomPermissionType permissionType; } diff --git a/lib/src/models/em_cmd_message_body.dart b/lib/src/models/em_cmd_message_body.dart new file mode 100644 index 00000000..fcfb17ef --- /dev/null +++ b/lib/src/models/em_cmd_message_body.dart @@ -0,0 +1,44 @@ +import '../tools/em_extension.dart'; + +import 'em_chat_enums.dart'; +import 'em_message_body.dart'; + +/// +/// The command message body. +/// +class EMCmdMessageBody extends EMMessageBody { + /// + /// Creates a command message. + /// + EMCmdMessageBody({required this.action, this.deliverOnlineOnly = false}) + : super(type: MessageType.CMD); + + /// @nodoc + EMCmdMessageBody.fromJson({required Map map}) + : super.fromJson(map: map, type: MessageType.CMD) { + this.action = map["action"]; + this.deliverOnlineOnly = + map.getBoolValue("deliverOnlineOnly", defaultValue: false)!; + } + + /// @nodoc + @override + Map toJson() { + final Map data = super.toJson(); + data.setValueWithOutNull("action", action); + data.setValueWithOutNull("deliverOnlineOnly", deliverOnlineOnly); + + return data; + } + + /// The command action content. + late final String action; + + /// + /// Checks whether this command message is only delivered to online users. + /// + /// - `true`: Yes. + /// - `false`: No. + /// + bool deliverOnlineOnly = false; +} diff --git a/lib/src/models/em_conversation.dart b/lib/src/models/em_conversation.dart index db35b30a..17eff08b 100644 --- a/lib/src/models/em_conversation.dart +++ b/lib/src/models/em_conversation.dart @@ -3,300 +3,482 @@ import 'package:flutter/services.dart'; import '../tools/em_extension.dart'; import '../../im_flutter_sdk.dart'; -import '../chat_method_keys.dart'; - -enum EMMessageSearchDirection { Up, Down } - +import '../internal/chat_method_keys.dart'; +import '../internal/em_transform_tools.dart'; + +/// +/// The conversation class, indicating a one-to-one chat, a group chat, or a converation chat. It contains the messages that are sent and received within the converation. +/// +/// The following code shows how to get the number of the unread messages from the conversation. +/// ```dart +/// // 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; +/// ``` +/// class EMConversation { - EMConversation._private(); + EMConversation._private( + this.id, + this.type, + this._ext, + ); + /// @nodoc factory EMConversation.fromJson(Map map) { - Map? ext = map['ext']?.cast(); - String? name; - if (ext != null) { - if (ext.containsKey("con_name")) { - name = ext['con_name']!; - ext.remove('con_name'); - } - } + Map? ext = map["ext"]?.cast(); + EMConversation ret = EMConversation._private( + map["con_id"], + conversationTypeFromInt(map["type"]), + ext, + ); - EMConversation ret = EMConversation._private(); - ret.type = typeFromInt(map['type']); - ret.id = map['con_id']; - ret._unreadCount = map['unreadCount']; - ret._ext = ext; - ret._name = name ?? ''; - if (map['latestMessage'] != null) { - ret._latestMessage = EMMessage.fromJson(map['latestMessage']); - } - if (map['lastReceivedMessage'] != null) { - ret._lastReceivedMessage = EMMessage.fromJson(map['lastReceivedMessage']); - } return ret; } - Map toJson() { + /// @nodoc + Map _toJson() { final Map data = new Map(); - data['type'] = typeToInt(this.type); - data['con_id'] = this.id; + data["type"] = conversationTypeToInt(this.type); + data["con_id"] = this.id; return data; } - late String id; - late EMConversationType type; + /// + /// 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. + /// + final String id; + + /// + /// The conversation type. + /// + final EMConversationType type; - int _unreadCount = 0; Map? _ext; - String? _name; - EMMessage? _latestMessage; - EMMessage? _lastReceivedMessage; - - static int typeToInt(EMConversationType? type) { - int ret = 0; - if (type == null) return ret; - switch (type) { - case EMConversationType.Chat: - ret = 0; - break; - case EMConversationType.GroupChat: - ret = 1; - break; - case EMConversationType.ChatRoom: - ret = 2; - break; - } - return ret; - } - - static EMConversationType typeFromInt(int? type) { - EMConversationType ret = EMConversationType.Chat; - switch (type) { - case 0: - ret = EMConversationType.Chat; - break; - case 1: - ret = EMConversationType.GroupChat; - break; - case 2: - ret = EMConversationType.ChatRoom; - break; - } - return ret; - } } extension EMConversationExtension on EMConversation { static const MethodChannel _emConversationChannel = const MethodChannel('com.chat.im/chat_conversation', JSONMethodCodec()); - int get unreadCount { - return _unreadCount; - } - - EMMessage? get latestMessage { - return _latestMessage; - } + Map? get ext => _ext; - EMMessage? get lastReceivedMessage { - return _lastReceivedMessage; - } - - String get name { - if (this._name != null && this._name!.length > 0) - return this._name!; - else - return this.id; - } - - set name(String name) { - this._name = name; - _syncNameToNative(); - } - - Map? get ext { - return this._ext; + Future setExt(Map? ext) async { + Map req = this._toJson(); + req.setValueWithOutNull("ext", ext); + Map result = await _emConversationChannel.invokeMethod( + ChatMethodKeys.syncConversationExt, req); + try { + EMError.hasErrorFromResult(result); + _ext = ext; + } on EMError catch (e) { + throw e; + } } - set ext(Map? map) { - this._ext = map; - _syncExtToNative(); + /// + /// Gets the lastest message from the conversation. + /// + /// The operation does not change the unread message count. + /// + /// 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. + /// + Future latestMessage() async { + Map req = this._toJson(); + Map result = await _emConversationChannel.invokeMethod( + ChatMethodKeys.getLatestMessage, req); + try { + EMError.hasErrorFromResult(result); + if (result.containsKey(ChatMethodKeys.getLatestMessage)) { + return EMMessage.fromJson(result[ChatMethodKeys.getLatestMessage]); + } else { + return null; + } + } on EMError catch (e) { + throw e; + } } - Future _syncNameToNative() async { - Map req = this.toJson(); - req['con_name'] = this._name ?? ''; - await _emConversationChannel.invokeMethod( - ChatMethodKeys.syncConversationName, req); + /// + /// Gets the latest message from the conversation. + /// + /// **Return** The message instance. + /// + Future lastReceivedMessage() async { + Map req = this._toJson(); + Map result = await _emConversationChannel.invokeMethod( + ChatMethodKeys.getLatestMessageFromOthers, req); + try { + EMError.hasErrorFromResult(result); + if (result.containsKey(ChatMethodKeys.getLatestMessageFromOthers)) { + return EMMessage.fromJson( + result[ChatMethodKeys.getLatestMessageFromOthers]); + } else { + return null; + } + } on EMError catch (e) { + throw e; + } } - Future _syncExtToNative() async { - Map req = this.toJson(); - req['ext'] = this._ext ?? ''; - await _emConversationChannel.invokeMethod( - ChatMethodKeys.syncConversationExt, req); + /// + /// Gets the unread message count of the conversation. + /// + /// **Return** The unread message count of the conversation. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future unreadCount() async { + Map req = this._toJson(); + Map result = await _emConversationChannel.invokeMethod( + ChatMethodKeys.getUnreadMsgCount, req); + try { + EMError.hasErrorFromResult(result); + if (result.containsKey(ChatMethodKeys.getUnreadMsgCount)) { + return result[ChatMethodKeys.getUnreadMsgCount]; + } else { + return 0; + } + } on EMError catch (e) { + throw e; + } } - /// 根据消息id设置消息已读,如果消息不属于当前会话则设置无效 - Future markMessageAsRead(String messageId) async { - Map req = this.toJson(); + /// + /// Marks a message as read. + /// + /// Param [messageId] The message ID. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future markMessageAsRead(String messageId) async { + Map req = this._toJson(); req['msg_id'] = messageId; Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.markMessageAsRead, req); - EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.markMessageAsRead); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } } - /// 设置当前会话中所有消息为已读 + /// + /// Marks all messages as read. + /// Future markAllMessagesAsRead() async { Map result = await _emConversationChannel.invokeMethod( - ChatMethodKeys.markAllMessagesAsRead, this.toJson()); - EMError.hasErrorFromResult(result); + ChatMethodKeys.markAllMessagesAsRead, this._toJson()); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } } - /// 插入消息,插入的消息会根据消息时间插入到对应的位置 - Future insertMessage(EMMessage message) async { - Map req = this.toJson(); + /// + /// Inserts a message to a conversation in the local database and the SDK will automatically update the lastest message. + /// + /// Make sure you set the conversation ID as that of the conversation where you want to insert the message. + /// + /// Param [message] The message instance. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future insertMessage(EMMessage message) async { + Map req = this._toJson(); req['msg'] = message.toJson(); Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.insertMessage, req); - EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.insertMessage); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } } - /// 添加消息,添加的消息会添加到最后一条消息的位置 - Future appendMessage(EMMessage message) async { - Map req = this.toJson(); + /// + /// 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. + /// + /// Param [message] The message instance. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future appendMessage(EMMessage message) async { + Map req = this._toJson(); req['msg'] = message.toJson(); Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.appendMessage, req); - return result.boolValue(ChatMethodKeys.appendMessage); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } } - /// 更新消息 - Future updateMessage(EMMessage message) async { - Map req = this.toJson(); + /// + /// 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. + /// + /// Param [message] The message to be updated. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future updateMessage(EMMessage message) async { + Map req = this._toJson(); req['msg'] = message.toJson(); Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.updateConversationMessage, req); EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.updateConversationMessage); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } } - /// 根据消息id [messageId] 删除消息 - Future deleteMessage(String messageId) async { - Map req = this.toJson(); + /// + /// Deletes a message in the local database. + /// + /// **Note** + /// After this method is called, the message is only deleted both from the memory and the local database. + /// + /// Param [messageId] The ID of message to be deleted. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future deleteMessage(String messageId) async { + Map req = this._toJson(); req['msg_id'] = messageId; Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.removeMessage, req); - EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.removeMessage); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } } - // 删除当前会话中所有消息 - Future deleteAllMessages() async { + /// + /// Deletes all the messages of the conversation from both the memory and local database. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future deleteAllMessages() async { Map result = await _emConversationChannel.invokeMethod( - ChatMethodKeys.clearAllMessages, this.toJson()); - EMError.hasErrorFromResult(result); - return result.boolValue(ChatMethodKeys.clearAllMessages); + ChatMethodKeys.clearAllMessages, this._toJson()); + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } } - /// 根据消息id获取消息,如果消息id不属于当前会话,则无法获取到 + /// + /// 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. + /// + /// Param [messageId] The message ID. + /// + /// **Return** The message instance. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future loadMessage(String messageId) async { - Map req = this.toJson(); + Map req = this._toJson(); req['msg_id'] = messageId; Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.loadMsgWithId, req); - EMError.hasErrorFromResult(result); - if (result[ChatMethodKeys.loadMsgWithId] != null) { - return EMMessage.fromJson(result[ChatMethodKeys.loadMsgWithId]); - } else { - return null; + try { + EMError.hasErrorFromResult(result); + if (result[ChatMethodKeys.loadMsgWithId] != null) { + return EMMessage.fromJson(result[ChatMethodKeys.loadMsgWithId]); + } else { + return null; + } + } on EMError catch (e) { + throw e; } } - /// 根据类型获取当前会话汇总的消息 - Future> loadMessagesWithMsgType({ - required EMMessageBodyType type, + /// + /// Retrieves messages from the database according to the following parameters: the message type, the Unix timestamp, max count, sender. + /// + /// **Note** + /// Be cautious about the memory usage when the maxCount is large. + /// + /// Param [type] The message type, including TXT, VOICE, IMAGE, and so on. + /// + /// Param [timestamp] The Unix timestamp for the search. + /// + /// Param [count] The max number of messages to search. + /// + /// Param [sender] The sender of the message. The param can also be used to search in group chat or chat room. + /// + /// Param [direction] The direction in which the message is loaded: EMSearchDirection. + /// - `EMSearchDirection.Up`: Messages are retrieved in the reverse chronological order of when the server received messages. + /// - `EMSearchDirection.Down`: Messages are retrieved in the chronological order of when the server received messages. + /// + /// **Return** The message list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future?> loadMessagesWithMsgType({ + required MessageType type, int timestamp = -1, int count = 20, String? sender, - EMMessageSearchDirection direction = EMMessageSearchDirection.Up, + EMSearchDirection direction = EMSearchDirection.Up, }) async { - Map req = this.toJson(); - req['type'] = EMMessageBody.bodyTypeToTypeStr(type); + Map req = this._toJson(); + req['type'] = messageTypeToTypeStr(type); req['timestamp'] = timestamp; req['count'] = count; req['sender'] = sender; - req['direction'] = direction == EMMessageSearchDirection.Up ? "up" : "down"; + req['direction'] = direction == EMSearchDirection.Up ? "up" : "down"; Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.loadMsgWithMsgType, req); - EMError.hasErrorFromResult(result); - - List list = []; - result[ChatMethodKeys.loadMsgWithMsgType]?.forEach((element) { - list.add(EMMessage.fromJson(element)); - }); - return list; + try { + EMError.hasErrorFromResult(result); + List list = []; + result[ChatMethodKeys.loadMsgWithMsgType]?.forEach((element) { + list.add(EMMessage.fromJson(element)); + }); + return list; + } on EMError catch (e) { + throw e; + } } - /// 根据起始消息id获取消息 - Future> loadMessages({ + /// + /// Loads multiple messages from the local database. + /// + /// Loads messages from the local database before the specified message. + /// + /// The loaded messages will also join the existing messages of the conversation stored in the memory. + /// The {@link #getAllMessages()} method returns all messages of the conversation loaded in the memory. + /// + /// Param [startMsgId] The starting message ID. Message loaded in the memory before this message ID will be loaded. If the `startMsgId` is set as "" or null, the SDK will first load the latest messages in the database. + /// + /// Param [loadCount] The number of messages per page. + /// + /// Param [direction] The direction in which the message is loaded: EMSearchDirection. + /// - `EMSearchDirection.Up`: Messages are retrieved in the reverse chronological order of when the server received messages. + /// - `EMSearchDirection.Down`: Messages are retrieved in the chronological order of when the server received messages. + /// + /// **Return** The message list. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// + Future?> loadMessages({ String startMsgId = '', int loadCount = 20, - EMMessageSearchDirection direction = EMMessageSearchDirection.Up, + EMSearchDirection direction = EMSearchDirection.Up, }) async { - Map req = this.toJson(); + Map req = this._toJson(); req["startId"] = startMsgId; req['count'] = loadCount; - req['direction'] = direction == EMMessageSearchDirection.Up ? "up" : "down"; + req['direction'] = direction == EMSearchDirection.Up ? "up" : "down"; Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.loadMsgWithStartId, req); - EMError.hasErrorFromResult(result); - - List msgList = []; - result[ChatMethodKeys.loadMsgWithStartId]?.forEach((element) { - msgList.add(EMMessage.fromJson(element)); - }); - return msgList; + try { + EMError.hasErrorFromResult(result); + List msgList = []; + result[ChatMethodKeys.loadMsgWithStartId]?.forEach((element) { + msgList.add(EMMessage.fromJson(element)); + }); + return msgList; + } on EMError catch (e) { + throw e; + } } + /// + /// 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. + /// + /// Param [keywords] The keywords in message. + /// + /// Param [sender] The message sender. The param can also be used to search in group chat. + /// + /// Param [timestamp] The timestamp for search. + /// + /// Param [count] The maximum number of messages to search. + /// + /// Param [direction] The direction in which the message is loaded: EMSearchDirection. + /// `EMSearchDirection.Up`: Gets the messages loaded before the timestamp of the specified message ID. + /// `EMSearchDirection.Down`: Gets the messages loaded after the timestamp of the specified message ID. + /// + /// **Returns** The list of retrieved messages. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> loadMessagesWithKeyword( String keywords, { String? sender, int timestamp = -1, int count = 20, - EMMessageSearchDirection direction = EMMessageSearchDirection.Up, + EMSearchDirection direction = EMSearchDirection.Up, }) async { - Map req = this.toJson(); + Map req = this._toJson(); req["keywords"] = keywords; req['count'] = count; if (sender != null) { req['sender'] = sender; } req['timestamp'] = timestamp; - req['direction'] = direction == EMMessageSearchDirection.Up ? "up" : "down"; + req['direction'] = direction == EMSearchDirection.Up ? "up" : "down"; Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.loadMsgWithKeywords, req); - EMError.hasErrorFromResult(result); - - List msgList = []; - result[ChatMethodKeys.loadMsgWithKeywords]?.forEach((element) { - msgList.add(EMMessage.fromJson(element)); - }); - return msgList; + try { + EMError.hasErrorFromResult(result); + List msgList = []; + result[ChatMethodKeys.loadMsgWithKeywords]?.forEach((element) { + msgList.add(EMMessage.fromJson(element)); + }); + return msgList; + } on EMError catch (e) { + throw e; + } } + /// + /// 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. + /// + /// Param [startTime] The starting Unix timestamp for search. + /// + /// Param [endTime] The ending Unix timestamp for search. + /// + /// Param [count] The maximum number of message to retrieve. + /// + /// **Returns** The list of searched messages. + /// + /// **Throws** A description of the exception. See {@link EMError}. + /// Future> loadMessagesFromTime({ required int startTime, required int endTime, int count = 20, }) async { - Map req = this.toJson(); + Map req = this._toJson(); req["startTime"] = startTime; req['endTime'] = endTime; req['count'] = count; @@ -304,12 +486,15 @@ extension EMConversationExtension on EMConversation { Map result = await _emConversationChannel.invokeMethod( ChatMethodKeys.loadMsgWithTime, req); - EMError.hasErrorFromResult(result); - - List msgList = []; - result[ChatMethodKeys.loadMsgWithTime]?.forEach((element) { - msgList.add(EMMessage.fromJson(element)); - }); - return msgList; + try { + EMError.hasErrorFromResult(result); + List msgList = []; + result[ChatMethodKeys.loadMsgWithTime]?.forEach((element) { + msgList.add(EMMessage.fromJson(element)); + }); + return msgList; + } on EMError catch (e) { + throw e; + } } } diff --git a/lib/src/models/em_cursor_result.dart b/lib/src/models/em_cursor_result.dart index b51ee49d..d9a50c8f 100644 --- a/lib/src/models/em_cursor_result.dart +++ b/lib/src/models/em_cursor_result.dart @@ -1,23 +1,36 @@ typedef CursorResultCallback = Object Function(dynamic obj); +/// +/// 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. +/// +/// ```dart +/// String? cursor; +/// EMCursorResult result = await EMClient.getInstance.groupManager.fetchPublicGroupsFromServer(pageSize: 10, cursor: cursor); +/// List? group = result.data; +/// cursor = result.cursor; +/// ``` +/// class EMCursorResult { - EMCursorResult._private(); + EMCursorResult._private( + this.cursor, + this.data, + ); + /// @nodoc factory EMCursorResult.fromJson(Map map, {dataItemCallback: CursorResultCallback}) { - EMCursorResult result = EMCursorResult._private() - .._cursor = map['cursor'] - .._data = []; - + List list = []; (map['list'] as List) - .forEach((element) => result._data!.add(dataItemCallback(element))); + .forEach((element) => list.add(dataItemCallback(element))); + EMCursorResult result = EMCursorResult._private(map['cursor'], list); return result; } - String? _cursor; - List? _data; + /// Gets the cursor. + final String? cursor; - String? get cursor => _cursor; - List? get data => _data; + /// Gets the data list. + final List data; } diff --git a/lib/src/models/em_custom_message_body.dart b/lib/src/models/em_custom_message_body.dart new file mode 100644 index 00000000..047ba8d3 --- /dev/null +++ b/lib/src/models/em_custom_message_body.dart @@ -0,0 +1,38 @@ +import '../tools/em_extension.dart'; + +import 'em_chat_enums.dart'; +import 'em_message_body.dart'; + +/// +/// The custom message body. +/// +class EMCustomMessageBody extends EMMessageBody { + /// + /// Creates a custom message. + /// + EMCustomMessageBody({ + required this.event, + this.params, + }) : super(type: MessageType.CUSTOM); + EMCustomMessageBody.fromJson({required Map map}) + : super.fromJson(map: map, type: MessageType.CUSTOM) { + this.event = map["event"]; + this.params = map["params"]?.cast(); + } + + /// @nodoc + @override + Map toJson() { + final Map data = super.toJson(); + data.setValueWithOutNull("event", event); + data.setValueWithOutNull("params", params); + + return data; + } + + /// The event. + late final String event; + + /// The custom params map. + Map? params; +} diff --git a/lib/src/models/em_deviceInfo.dart b/lib/src/models/em_deviceInfo.dart index 04245b9f..faf78bb7 100644 --- a/lib/src/models/em_deviceInfo.dart +++ b/lib/src/models/em_deviceInfo.dart @@ -1,31 +1,40 @@ +import '../tools/em_extension.dart'; + +/// +/// The EMDeviceInfo class, which contains the multi-device information. +/// class EMDeviceInfo { - EMDeviceInfo._private(); + EMDeviceInfo._private( + this.resource, + this.deviceUUID, + this.deviceName, + ); + /// @nodoc Map toJson() { Map data = Map(); - data['resource'] = _resource; - data['deviceUUID'] = _deviceUUID; - data['deviceName'] = _deviceName; + data.setValueWithOutNull("resource", resource); + data.setValueWithOutNull("deviceUUID", deviceUUID); + data.setValueWithOutNull("deviceName", deviceName); + return data; } + /// @nodoc factory EMDeviceInfo.fromJson(Map map) { - return EMDeviceInfo._private() - .._resource = map['resource'] - .._deviceUUID = map['deviceUUID'] - .._deviceName = map['deviceName']; + return EMDeviceInfo._private( + map.getStringValue("resource"), + map.getStringValue("deviceUUID"), + map.getStringValue("deviceName"), + ); } - /// 设备资源描述 - String? get resource => _resource; - - /// 设备的UUID - String? get deviceUUID => _deviceUUID; + /// The information of other login devices. + final String? resource; - /// 设备名称 - String? get deviceName => _deviceName; + /// The UUID of the device. + final String? deviceUUID; - String? _resource; - String? _deviceUUID; - String? _deviceName; + /// The device type. For example: "Pixel 6 Pro". + final String? deviceName; } diff --git a/lib/src/models/em_error.dart b/lib/src/models/em_error.dart index 76c711dd..8947b402 100644 --- a/lib/src/models/em_error.dart +++ b/lib/src/models/em_error.dart @@ -1,23 +1,25 @@ +/// +/// The error class defined by the SDK. +/// class EMError { - EMError._private([int? code, String? desc]) - : _code = code ?? 0, - _description = desc ?? ""; + EMError._private(this.code, this.description); - late int _code; - late String _description; + /// + /// The error code. + /// + final int code; - int get code { - return _code; - } - - String get description { - return _description; - } + /// + /// The error description. + /// + final String description; + /// @nodoc factory EMError.fromJson(Map map) { return EMError._private(map['code'], map['description']); } + /// @nodoc static hasErrorFromResult(Map map) { if (map['error'] == null) { return; diff --git a/lib/src/models/em_file_message_body.dart b/lib/src/models/em_file_message_body.dart new file mode 100644 index 00000000..35ed2ddd --- /dev/null +++ b/lib/src/models/em_file_message_body.dart @@ -0,0 +1,86 @@ +import 'package:im_flutter_sdk/src/internal/em_transform_tools.dart'; +import 'package:im_flutter_sdk/src/tools/em_extension.dart'; + +import 'em_chat_enums.dart'; +import 'em_message_body.dart'; + +/// +/// The base class of file messages. +/// +class EMFileMessageBody extends EMMessageBody { + /// Creates a message with an attachment. + /// + /// Param [localPath] The path of the image file. + /// + /// Param [displayName] The file name. + /// + /// Param [fileSize] The size of the file in bytes. + /// + /// Param [type] The file type. + /// + EMFileMessageBody({ + required this.localPath, + this.displayName, + this.fileSize, + MessageType type = MessageType.FILE, + }) : super(type: type); + + /// @nodoc + EMFileMessageBody.fromJson( + {required Map map, MessageType type = MessageType.FILE}) + : super.fromJson(map: map, type: type) { + this.secret = map.getStringValue("secret"); + this.remotePath = map.getStringValue("remotePath"); + this.fileSize = map.getIntValue("fileSize"); + this.localPath = map.getStringValue("localPath", defaultValue: "")!; + this.displayName = map.getStringValue("displayName"); + this.fileStatus = EMFileMessageBody.downloadStatusFromInt( + map.getIntValue("fileStatus"), + ); + } + + /// @nodoc + @override + Map toJson() { + final Map data = super.toJson(); + data.setValueWithOutNull("secret", this.secret); + data.setValueWithOutNull("remotePath", this.remotePath); + data.setValueWithOutNull("fileSize", this.fileSize); + data.setValueWithOutNull("localPath", this.localPath); + data.setValueWithOutNull("displayName", this.displayName); + data.setValueWithOutNull( + "fileStatus", downloadStatusToInt(this.fileStatus)); + + return data; + } + + /// The local path of the attachment. + late final String localPath; + + /// The token used to get the attachment. + String? secret; + + /// The attachment path in the server. + String? remotePath; + + /// The download status of the attachment. + DownloadStatus fileStatus = DownloadStatus.PENDING; + + /// The size of the attachment in bytes. + int? fileSize; + + /// The attachment name. + String? displayName; + + static DownloadStatus downloadStatusFromInt(int? status) { + if (status == 0) { + return DownloadStatus.DOWNLOADING; + } else if (status == 1) { + return DownloadStatus.SUCCESS; + } else if (status == 2) { + return DownloadStatus.FAILED; + } else { + return DownloadStatus.PENDING; + } + } +} diff --git a/lib/src/models/em_group.dart b/lib/src/models/em_group.dart index a464b04a..3f25d019 100644 --- a/lib/src/models/em_group.dart +++ b/lib/src/models/em_group.dart @@ -1,21 +1,20 @@ +import '../internal/em_transform_tools.dart'; + import '../tools/em_extension.dart'; +import 'em_chat_enums.dart'; import 'em_group_options.dart'; -enum EMGroupPermissionType { - None, - Member, - Admin, - Owner, -} - +/// +/// The EMGroup class, which contains the information of the chat group. +/// class EMGroup { EMGroup._private(); late String _groupId; String? _name; - String? _description = ''; - String? _owner = ''; - String? _announcement = ''; + String? _description; + String? _owner; + String? _announcement; int? _memberCount; List? _memberList; List? _adminList; @@ -28,22 +27,167 @@ class EMGroup { EMGroupOptions? _options; EMGroupPermissionType? _permissionType; + /// + /// Gets the group ID. + /// String get groupId => _groupId; + + /// + /// Gets the group name. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMGroupManager#fetchGroupInfoFromServer(String groupId)} before calling this method. + /// String? get name => _name; + + /// + /// Gets the group description. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMGroupManager#fetchGroupInfoFromServer(String groupId)} before calling this method. + /// String? get description => _description; + + /// + /// Gets the user ID of the group owner. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMGroupManager#fetchGroupInfoFromServer(String groupId)} before calling this method. + /// String? get owner => _owner; + + /// The content of the group announcement. String? get announcement => _announcement; + + /// + /// Gets the member count of the group. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMGroupManager#fetchGroupInfoFromServer(String groupId)} before calling this method. + /// int? get memberCount => _memberCount; + + /// + /// Gets the member list of the group. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMGroupManager#fetchMemberListFromServer(String, int?, String?)} before calling this method. + /// List? get memberList => _memberList; + + /// + /// Gets the admin list of the group. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMGroupManager#fetchGroupInfoFromServer(String)} before calling this method. + /// List? get adminList => _adminList; + + /// + /// 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 {@link EMGroupManager#fetchBlockListFromServer(String, int?, int?)} before calling this method. + /// List? get blockList => _blockList; + + /// + /// Gets the mute list of the group. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMGroupManager#fetchMuteListFromServer(String, int?, int?)} before calling this method. + /// List? get muteList => _muteList; + + @Deprecated("") bool? get noticeEnable => _noticeEnable; + + /// + /// Gets whether the group message is blocked. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMGroupManager#fetchGroupInfoFromServer(String)} before calling this method. + /// bool? get messageBlocked => _messageBlocked; + + /// + /// Gets Whether all members are muted. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMGroupManager#fetchGroupInfoFromServer(String)} before calling this method. + /// bool? get isAllMemberMuted => _isAllMemberMuted; + + @Deprecated( + "Switch to using isMemberOnly | isMemberAllowToInvite | maxUserCount to instead.") EMGroupOptions? get settings => _options; + + /// + /// Gets the current user's role in group. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMGroupManager#fetchGroupInfoFromServer(String)} before calling this method. + /// EMGroupPermissionType? get permissionType => _permissionType; + /// + /// 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 {@link EMGroupManager#fetchGroupInfoFromServer(String)} before calling this method. + /// + int? get maxUserCount => _options?.maxCount; + + /// + /// 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(PublicOpenJoin). + /// + /// **Note** + /// There are four types of group properties used to define the style of a group: {@link EMGroupManager.EMGroupStyle}. + /// + /// **Return** + /// 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. + /// + bool get isMemberOnly { + if (_options == null) { + return true; + } + + if (_options?.style == EMGroupStyle.PrivateMemberCanInvite || + _options?.style == EMGroupStyle.PrivateOnlyOwnerInvite || + _options?.style == EMGroupStyle.PublicJoinNeedApproval) { + return true; + } + return false; + } + + /// + /// Checks whether a group member is allowed to invite other users to join the group. + /// + /// **Note** + /// To get the correct value, ensure that you call {@link EMGroupManager#fetchGroupInfoFromServer(String)} before calling this method. + /// + /// **Return** + /// - `true`: Yes; + /// - `false`: No. Only the group owner or admin can invite others to join the group. + /// + bool get isMemberAllowToInvite { + if (_options == null) { + return true; + } + if (_options?.style == EMGroupStyle.PrivateMemberCanInvite) { + return true; + } + + return false; + } + + /// @nodoc factory EMGroup.fromJson(Map map) { return EMGroup._private() .._groupId = map['groupId'] @@ -51,7 +195,7 @@ class EMGroup { .._description = map.stringValue("desc") .._owner = map.stringValue("owner") .._announcement = map.stringValue("announcement") - .._memberCount = map['memberCount'] + .._memberCount = map["memberCount"] .._memberList = map.listValue("memberList") .._adminList = map.listValue("adminList") .._blockList = map.listValue("blockList") @@ -60,9 +204,10 @@ class EMGroup { .._messageBlocked = map.boolValue('messageBlocked') .._isAllMemberMuted = map.boolValue('isAllMemberMuted') .._options = EMGroupOptions.fromJson(map['options']) - .._permissionType = EMGroup.permissionTypeFromInt(map['permissionType']); + .._permissionType = permissionTypeFromInt(map['permissionType']); } + /// @nodoc Map toJson() { Map data = Map(); data.setValueWithOutNull("id", _groupId); @@ -75,71 +220,15 @@ class EMGroup { data.setValueWithOutNull("adminList", _adminList); data.setValueWithOutNull("blockList", _blockList); data.setValueWithOutNull("muteList", _muteList); - data.setValueWithOutNull("owner", _owner); data.setValueWithOutNull("noticeEnable", _noticeEnable); data.setValueWithOutNull("messageBlocked", _messageBlocked); data.setValueWithOutNull("isAllMemberMuted", _isAllMemberMuted); data.setValueWithOutNull("options", _options?.toJson()); data.setValueWithOutNull( - "permissionType", EMGroup.permissionTypeToInt(_permissionType)); + "permissionType", permissionTypeToInt(_permissionType)); return data; } - static EMGroupPermissionType permissionTypeFromInt(int? type) { - EMGroupPermissionType ret = EMGroupPermissionType.Member; - switch (type) { - case -1: - { - ret = EMGroupPermissionType.None; - } - break; - case 0: - { - ret = EMGroupPermissionType.Member; - } - break; - case 1: - { - ret = EMGroupPermissionType.Admin; - } - break; - case 2: - { - ret = EMGroupPermissionType.Owner; - } - break; - } - return ret; - } - - static int permissionTypeToInt(EMGroupPermissionType? type) { - int ret = 0; - if (type == null) return ret; - switch (type) { - case EMGroupPermissionType.None: - { - ret = -1; - } - break; - case EMGroupPermissionType.Member: - { - ret = 0; - } - break; - case EMGroupPermissionType.Admin: - { - ret = 1; - } - break; - case EMGroupPermissionType.Owner: - { - ret = 2; - } - break; - } - return ret; - } - @override String toString() { return this.toJson().toString(); diff --git a/lib/src/models/em_group_message_ack.dart b/lib/src/models/em_group_message_ack.dart index 1c02809e..846d92d4 100644 --- a/lib/src/models/em_group_message_ack.dart +++ b/lib/src/models/em_group_message_ack.dart @@ -1,30 +1,78 @@ +import '../tools/em_extension.dart'; + +/// +/// The class for group message read receipts. +/// +/// To get the chat group message receipts, call {@link EMChatManager#fetchGroupAcks(String, String?, int)}. +/// +/// ```dart +/// EMCursorResult result = await EMClient.getInstance.chatManager.fetchGroupAcks("msgId"); +/// ``` +/// class EMGroupMessageAck { - /// 对应的消息id - late String messageId; + /// + /// Gets the group message ID. + /// + /// **Return** The group message ID. + /// + final String messageId; + + /// + /// Gets the ID of the group message read receipt. + /// + /// **Return** The read receipt ID. + /// + final String ackId; - /// 已读发送方id - late String from; + /// + /// Gets the username of the user who sends the read receipt. + /// + /// **Return** The username of the read receipt sender. + /// + final String from; - /// 已读回复内容 - String? content; + /// + /// Gets the read receipt extension. + /// + /// For how to set the extension, see {@link EMChatManager#sendGroupMessageReadAck(String, String, String?)}. + /// + /// **Return** The read receipt extension. + /// + final String? content; - /// 群消息已读人数 - int readCount = 0; + /// + /// Gets the number read receipts of group messages. + /// + /// **Return** The count in which read receipts of group messages are sent. + /// + final int readCount; - /// 本条已读发送时间 - int timestamp = 0; + /// + /// Gets the timestamp of sending read receipts of group messages. + /// + /// **Return** The timestamp of sending read receipts of group messages. + final int timestamp; + /// @nodoc factory EMGroupMessageAck.fromJson(Map map) { - EMGroupMessageAck ack = EMGroupMessageAck._private(); - ack.messageId = map["msg_id"] as String; - ack.from = map["from"] as String; - if (map.containsKey("content")) { - ack.content = map["content"] as String; - } - ack.readCount = map["count"] as int; - ack.timestamp = map["timestamp"] as int; + EMGroupMessageAck ack = EMGroupMessageAck._private( + ackId: map["ack_id"] as String, + messageId: map["msg_id"] as String, + from: map["from"] as String, + content: map["content"], + readCount: map.getIntValue("count", defaultValue: 0)!, + timestamp: map.getIntValue("timestamp", defaultValue: 0)!, + ); + return ack; } - EMGroupMessageAck._private(); + EMGroupMessageAck._private({ + required this.ackId, + required this.messageId, + required this.from, + required this.content, + required this.readCount, + required this.timestamp, + }); } diff --git a/lib/src/models/em_group_options.dart b/lib/src/models/em_group_options.dart index f8fed8b0..26d0d58c 100644 --- a/lib/src/models/em_group_options.dart +++ b/lib/src/models/em_group_options.dart @@ -1,14 +1,36 @@ +import '../internal/em_transform_tools.dart'; + import 'em_chat_enums.dart'; import '../tools/em_extension.dart'; +/// +/// The group options to be configured when the chat group is created. +/// class EMGroupOptions { EMGroupOptions._private(); - EMGroupOptions( - {required EMGroupStyle style, - int count = 200, - bool inviteNeedConfirm = false, - String extension = ''}) { + /// + /// Sets the group options. + /// + /// Param [style] The group style: {EMGroupStyle}. + /// + /// Param [count] The maximum number of members in a group. The default value is 200. + /// + /// Param [inviteNeedConfirm] Whether you can automatically add a user to the chat group depends on the settings of {GroupOptions#inviteNeedConfirm} and {EMOptions#autoAcceptGroupInvitation}. + /// + /// - If `inviteNeedConfirm` is set to `false`, you can add the invitee directly to the chat group, regardless of the settings of `EMOptions#autoAcceptGroupInvitation`. + /// - If `inviteNeedConfirm` is set to `true`, whether the invitee automatically joins the chat group or not depends on the settings of {@link EMOptions#autoAcceptGroupInvitation(boolean)} on the invitee's client. + /// - If `autoAcceptGroupInvitation` is set to `true`, the invitee automatically joins the chat group. + /// - If `autoAcceptGroupInvitation` is set to `false`, the invitee does not join the chat group until this invitee approves the group invitation. + /// + /// Param [extension] Group detail extensions which can be in the JSON format to contain more group information. + /// + EMGroupOptions({ + EMGroupStyle style = EMGroupStyle.PrivateOnlyOwnerInvite, + int count = 200, + bool inviteNeedConfirm = false, + String? extension, + }) { _style = style; _maxCount = count; _inviteNeedConfirm = inviteNeedConfirm; @@ -20,83 +42,54 @@ class EMGroupOptions { bool? _inviteNeedConfirm; String? _ext; + /// + /// Gets the group style. + /// + /// **Return** The group style. See {EMGroupStyle}. + /// EMGroupStyle? get style => _style; + + /// + /// Gets the maximum number of members in a group. + /// + /// **Return** The maximum number of members in a group. + /// int? get maxCount => _maxCount; + + /// + /// 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 {GroupOptions#inviteNeedConfirm} and {EMOptions#autoAcceptGroupInvitation}. + /// + /// - If `inviteNeedConfirm` is set to `false`, you can add the invitee directly to the chat group, regardless of the settings of `EMOptions#autoAcceptGroupInvitation`. + /// - If `inviteNeedConfirm` is set to `true`, whether the invitee automatically joins the chat group or not depends on the settings of {@link EMOptions#autoAcceptGroupInvitation(boolean)} on the invitee's client. + /// - If `autoAcceptGroupInvitation` is set to `true`, the invitee automatically joins the chat group. + /// - 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. + /// bool? get inviteNeedConfirm => _inviteNeedConfirm; String? get ext => _ext; + /// @nodoc factory EMGroupOptions.fromJson(Map? map) { return EMGroupOptions._private() - .._style = EMGroupOptions.styleTypeFromInt(map?['style']) + .._style = groupStyleTypeFromInt(map?['style']) .._maxCount = map?['maxCount'] .._ext = map?['ext'] .._inviteNeedConfirm = map?.boolValue('inviteNeedConfirm'); } + /// @nodoc Map toJson() { Map data = Map(); - data['style'] = EMGroupOptions.styleTypeToInt(_style); + data['style'] = groupStyleTypeToInt(_style); data['maxCount'] = _maxCount; data['inviteNeedConfirm'] = _inviteNeedConfirm; - data['ext'] = _ext; + data.setValueWithOutNull("ext", _ext); return data; } - static EMGroupStyle styleTypeFromInt(int? type) { - EMGroupStyle ret = EMGroupStyle.PrivateOnlyOwnerInvite; - switch (type) { - case 0: - { - ret = EMGroupStyle.PrivateOnlyOwnerInvite; - } - break; - case 1: - { - ret = EMGroupStyle.PrivateMemberCanInvite; - } - break; - case 2: - { - ret = EMGroupStyle.PublicJoinNeedApproval; - } - break; - case 3: - { - ret = EMGroupStyle.PublicOpenJoin; - } - break; - } - return ret; - } - - static int styleTypeToInt(EMGroupStyle? type) { - int ret = 0; - if (type == null) return ret; - switch (type) { - case EMGroupStyle.PrivateOnlyOwnerInvite: - { - ret = 0; - } - break; - case EMGroupStyle.PrivateMemberCanInvite: - { - ret = 1; - } - break; - case EMGroupStyle.PublicJoinNeedApproval: - { - ret = 2; - } - break; - case EMGroupStyle.PublicOpenJoin: - { - ret = 3; - } - break; - } - return ret; - } - @override String toString() { return this.toJson().toString(); diff --git a/lib/src/models/em_group_shared_file.dart b/lib/src/models/em_group_shared_file.dart index 9f3e45b7..d86d3e37 100644 --- a/lib/src/models/em_group_shared_file.dart +++ b/lib/src/models/em_group_shared_file.dart @@ -1,5 +1,13 @@ import '../tools/em_extension.dart'; +/// +/// The EMGroupSharedFile class, which manages the chat group shared files. +/// +/// To get the information of the chat group shared file, call {@link EMGroupManager#fetchGroupFileListFromServer(String, int?, int?)}. +/// +/// ```dart +/// List? list = await EMClient.getInstance.groupManager.fetchGroupFileListFromServer(groupId); +/// ``` class EMGroupSharedFile { EMGroupSharedFile._private(); @@ -9,12 +17,42 @@ class EMGroupSharedFile { int? _createTime; int? _fileSize; + /// + /// Gets the shared file ID. + /// + /// **Return** The shared file ID. + /// String? get fileId => _fileId; + + /// + /// Gets the shared file name. + /// + /// **Return** The shared file name. + /// String? get fileName => _fileName; + + /// + /// Gets the username that uploads the shared file. + /// + /// **Return** The username that uploads the shared file. + /// String? get fileOwner => _fileOwner; + + /// + /// Gets the Unix timestamp for uploading the shared file, in milliseconds. + /// + /// **Return** The Unix timestamp for uploading the shared file, in milliseconds. + /// int? get createTime => _createTime; + + /// + /// Gets the data length of the shared file, in bytes. + /// + /// **Return** The data length of the shared file, in bytes. + /// int? get fileSize => _fileSize; + /// @nodoc factory EMGroupSharedFile.fromJson(Map? map) { return EMGroupSharedFile._private() .._fileId = map?["fileId"] @@ -24,6 +62,7 @@ class EMGroupSharedFile { .._fileSize = map?["fileSize"]; } + /// @nodoc Map toJson() { Map data = Map(); data.setValueWithOutNull("fileId", _fileId); diff --git a/lib/src/models/em_image_message_body.dart b/lib/src/models/em_image_message_body.dart new file mode 100644 index 00000000..a6da6246 --- /dev/null +++ b/lib/src/models/em_image_message_body.dart @@ -0,0 +1,101 @@ +import '../internal/em_transform_tools.dart'; + +import '../tools/em_extension.dart'; + +import 'em_chat_enums.dart'; +import 'em_file_message_body.dart'; + +/// +/// The image message body class. +/// +class EMImageMessageBody extends EMFileMessageBody { + /// + /// Creates an image message body with an image file. + /// + /// Param [localPath] The local path of the image file. + /// + /// Param [displayName] The image name. + /// + /// Param [thumbnailLocalPath] The local path of the image thumbnail. + /// + /// Param [sendOriginalImage] The original image included in the image message to be sent. + /// + /// Param [fileSize] The size of the image file in bytes. + /// + /// Param [width] The image width in pixels. + /// + /// Param [height] The image height in pixels. + /// + EMImageMessageBody({ + required String localPath, + String? displayName, + this.thumbnailLocalPath, + this.sendOriginalImage = false, + int? fileSize, + this.width, + this.height, + }) : super( + localPath: localPath, + displayName: displayName, + fileSize: fileSize, + type: MessageType.IMAGE, + ); + + /// @nodoc + EMImageMessageBody.fromJson({required Map map}) + : super.fromJson(map: map, type: MessageType.IMAGE) { + this.thumbnailLocalPath = map.getStringValue("thumbnailLocalPath"); + this.thumbnailRemotePath = map.getStringValue("thumbnailRemotePath"); + this.thumbnailSecret = map.getStringValue("thumbnailSecret"); + this.sendOriginalImage = map.getBoolValue( + "sendOriginalImage", + defaultValue: false, + )!; + this.height = map.getDoubleValue("height"); + this.width = map.getDoubleValue("width"); + this.thumbnailStatus = EMFileMessageBody.downloadStatusFromInt( + map.getIntValue("thumbnailStatus"), + ); + } + + /// @nodoc + @override + Map toJson() { + final Map data = super.toJson(); + data.setValueWithOutNull("thumbnailLocalPath", thumbnailLocalPath); + data.setValueWithOutNull("thumbnailRemotePath", thumbnailRemotePath); + data.setValueWithOutNull("thumbnailSecret", thumbnailSecret); + data.setValueWithOutNull("sendOriginalImage", sendOriginalImage); + data.setValueWithOutNull("height", height); + data.setValueWithOutNull("width", width); + data.setValueWithOutNull( + "thumbnailStatus", downloadStatusToInt(this.thumbnailStatus)); + return data; + } + + /// + /// 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. + /// + bool sendOriginalImage = false; + + /// The local path or the URI (a string) of the thumbnail. + String? thumbnailLocalPath; + + /// The URL of the thumbnail on the server. + String? thumbnailRemotePath; + + /// The secret to access the thumbnail. A secret is required for verification for thumbnail download. + String? thumbnailSecret; + + /// The download status of the thumbnail. + DownloadStatus thumbnailStatus = DownloadStatus.PENDING; + + /// The image width in pixels. + double? width; + + /// The image height in pixels. + double? height; +} diff --git a/lib/src/models/em_location_message_body.dart b/lib/src/models/em_location_message_body.dart new file mode 100644 index 00000000..d9ac9143 --- /dev/null +++ b/lib/src/models/em_location_message_body.dart @@ -0,0 +1,65 @@ +import '../tools/em_extension.dart'; + +import 'em_chat_enums.dart'; +import 'em_message_body.dart'; + +/// +/// The location message class. +/// +class EMLocationMessageBody extends EMMessageBody { + /// + /// Creates a location message body instance. + /// + /// Param [latitude] The latitude. + /// + /// Param [longitude] The longitude. + /// + /// Param [address] The address. + /// + /// Param [buildingName] The building name. + /// + EMLocationMessageBody({ + required this.latitude, + required this.longitude, + String? address, + String? buildingName, + }) : super(type: MessageType.LOCATION) { + _address = address; + _buildingName = buildingName; + } + + /// @nodoc + EMLocationMessageBody.fromJson({required Map map}) + : super.fromJson(map: map, type: MessageType.LOCATION) { + this.latitude = map.getDoubleValue("latitude", defaultValue: 0.0)!; + this.longitude = map.getDoubleValue("longitude", defaultValue: 0.0)!; + this._address = map.getStringValue("address"); + this._buildingName = map.getStringValue("buildingName"); + } + + /// @nodoc + @override + Map toJson() { + final Map data = super.toJson(); + data['latitude'] = this.latitude; + data['longitude'] = this.longitude; + data.setValueWithOutNull("address", this._address); + data.setValueWithOutNull("buildingName", this._buildingName); + return data; + } + + String? _address; + String? _buildingName; + + /// The address. + String? get address => _address; + + /// The building name. + String? get buildingName => _buildingName; + + /// The latitude. + late final double latitude; + + /// The longitude. + late final double longitude; +} diff --git a/lib/src/models/em_message.dart b/lib/src/models/em_message.dart index eb0c3742..c2919349 100644 --- a/lib/src/models/em_message.dart +++ b/lib/src/models/em_message.dart @@ -1,209 +1,241 @@ import 'dart:math'; import 'package:flutter/services.dart'; + +import '../internal/chat_method_keys.dart'; +import '../internal/em_transform_tools.dart'; import '../tools/em_extension.dart'; import '../../im_flutter_sdk.dart'; -import '../chat_method_keys.dart'; - -// 消息类型 -enum EMMessageChatType { - Chat, // 单聊消息 - GroupChat, // 群聊消息 - ChatRoom, // 聊天室消息 -} - -// 消息方向 -enum EMMessageDirection { - SEND, // 发送的消息 - RECEIVE, // 接收的消息 -} - -// 消息状态 -enum EMMessageStatus { - CREATE, // 创建 - PROGRESS, // 发送中 - SUCCESS, // 发送成功 - FAIL, // 发送失败 -} - -// 附件状态 -enum EMDownloadStatus { - PENDING, // 下载未开始 - DOWNLOADING, // 下载中 - SUCCESS, // 下载成功 - FAILED, // 下载失败 -} -/// body类型 -enum EMMessageBodyType { - TXT, // 文字消息 - IMAGE, // 图片消息 - VIDEO, // 视频消息 - LOCATION, // 位置消息 - VOICE, // 音频消息 - FILE, // 文件消息 - CMD, // CMD消息 - CUSTOM, // CUSTOM消息 -} - -abstract class EMMessageStatusListener { - /// 消息进度 - void onProgress(int progress) {} - - /// 消息发送失败 - void onError(EMError error) {} - - /// 消息发送成功 - void onSuccess() {} - - /// 消息已读 - void onReadAck() {} - - /// 消息已送达 - void onDeliveryAck() {} +/// +/// The message class. +/// +/// The sample code for constructing a text message to send is as follows. +/// +/// ```dart +/// EMMessage msg = EMMessage.createTxtSendMessage( +/// username: "user1", +/// content: "hello", +/// ); +/// ``` +/// +class EMMessage { + int _groupAckCount = 0; + + /// 消息 ID。 + String? _msgId; + String _msgLocalId = DateTime.now().millisecondsSinceEpoch.toString() + + Random().nextInt(99999).toString(); + + /// + /// Gets the message ID. + /// + /// **return** The message ID. + String get msgId => _msgId ?? _msgLocalId; + + /// + /// The conversation ID. + /// + String? conversationId; - /// 消息状态发生改变 - void onStatusChanged() {} -} + /// + /// 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. + /// + String? from = ''; -class MessageCallBackManager { - static const _channelPrefix = 'com.chat.im'; + /// + /// 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. + /// + String? to = ''; - static const MethodChannel _emMessageChannel = - const MethodChannel('$_channelPrefix/chat_message', JSONMethodCodec()); + /// + /// The local timestamp when the message is created on the local device, in milliseconds. + /// + int localTime = DateTime.now().millisecondsSinceEpoch; - Map cacheMessageMap = {}; + /// + /// The timestamp when the message is received by the server. + /// + int serverTime = DateTime.now().millisecondsSinceEpoch; - static MessageCallBackManager? _instance; + /// + /// 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. + /// + bool hasDeliverAck = false; - static MessageCallBackManager get getInstance => - _instance = _instance ?? MessageCallBackManager._internal(); + /// + /// Whether the recipient has read the message. + /// - `true`: Yes. + /// - `false`: No. + /// + bool hasReadAck = false; - MessageCallBackManager._internal() { - _emMessageChannel.setMethodCallHandler((MethodCall call) async { - Map argMap = call.arguments; - int? localTime = argMap['localTime']; - EMMessage? msg = cacheMessageMap[localTime.toString()]; - if (msg == null) { - return null; - } - if (call.method == ChatMethodKeys.onMessageProgressUpdate) { - return msg._onMessageProgressChanged(argMap); - } else if (call.method == ChatMethodKeys.onMessageError) { - return msg._onMessageError(argMap); - } else if (call.method == ChatMethodKeys.onMessageSuccess) { - return msg._onMessageSuccess(argMap); - } else if (call.method == ChatMethodKeys.onMessageReadAck) { - return msg._onMessageReadAck(argMap); - } else if (call.method == ChatMethodKeys.onMessageDeliveryAck) { - return msg._onMessageDeliveryAck(argMap); - } else if (call.method == ChatMethodKeys.onMessageStatusChanged) { - return msg._onMessageStatusChanged(argMap); - } - return null; - }); - } + /// + /// Whether read receipts are required for group messages. + /// + /// - `true`: Yes. + /// - `false`: No. + /// + /// + bool needGroupAck = false; - addMessage(EMMessage message) { - cacheMessageMap[message.localTime.toString()] = message; - } + /// + /// Gets the number of members that have read the group message. + /// + int get groupAckCount => _groupAckCount; + + /// + /// Whether the message is read. + /// - `true`: Yes. + /// - `false`: No. + /// + /// + bool hasRead = false; - removeMessage(EMMessage message) { - if (cacheMessageMap.containsKey(message.localTime.toString())) { - cacheMessageMap.remove(message.localTime.toString()); + /// + /// The enumeration of the chat type. + /// + /// There are three chat types: one-to-one chat, group chat, and chat room. + /// + ChatType chatType = ChatType.Chat; + + /// + /// The message direction. see {@link MessageDirection} + /// + MessageDirection direction = MessageDirection.SEND; + + /// + /// Gets the message sending/reception status. see {@link MessageStatus} + /// + MessageStatus status = MessageStatus.CREATE; + + /// + /// Message's extension attribute. + /// + Map? attributes; + + /// + /// Message body. We recommend you use {@link EMMessageBody)}. + /// + late EMMessageBody body; + + /// + /// Sets the message status change callback. + /// Your app should set messageStatusCallBack to get the message status and then refresh the UI accordingly. + /// + MessageStatusCallBack? _messageStatusCallBack; + + void setMessageStatusCallBack(MessageStatusCallBack? callback) { + _messageStatusCallBack = callback; + if (callback != null) { + MessageCallBackManager.getInstance.addMessage(this); + } else { + MessageCallBackManager.getInstance.removeMessage(localTime.toString()); } } -} -class EMMessage { EMMessage._private(); - /// 构造接收的消息 + /// + /// Creates a received message instance. + /// + /// Param [body] The message body. + /// + /// **Return** The message instance. + /// EMMessage.createReceiveMessage({ required this.body, - this.direction = EMMessageDirection.RECEIVE, - }); - - /// 构造发送的消息 + }) { + this.direction = MessageDirection.RECEIVE; + } + + /// + /// Creates a message instance for sending. + /// + /// Param [body] The message body. + /// + /// Param [to] 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. + /// + /// **Return** The message instance. + /// EMMessage.createSendMessage({ required this.body, - this.direction = EMMessageDirection.SEND, this.to, - this.hasRead = true, }) : this.from = EMClient.getInstance.currentUsername, - this.conversationId = to; + this.conversationId = to { + this.hasRead = true; + this.direction = MessageDirection.SEND; + } void dispose() { - MessageCallBackManager.getInstance.removeMessage(this); + MessageCallBackManager.getInstance.removeMessage(localTime.toString()); } - Future? _onMessageError(Map map) { - EMLog.v('发送失败 -- ' + map.toString()); + void _onMessageError(Map map) { EMMessage msg = EMMessage.fromJson(map['message']); this._msgId = msg.msgId; this.status = msg.status; this.body = msg.body; - if (listener != null) { - listener!.onError(EMError.fromJson(map['error'])); - } + _messageStatusCallBack?.onError?.call(EMError.fromJson(map['error'])); return null; } - Future? _onMessageProgressChanged(Map map) { - EMLog.v( - '发送 -- ' + ' msg_id: ' + this.msgId! + ' ' + map['progress'].toString(), - ); - if (this.listener != null) { - int progress = map['progress']; - listener!.onProgress(progress); - } + void _onMessageProgressChanged(Map map) { + int progress = map['progress']; + _messageStatusCallBack?.onProgress?.call(progress); return null; } - Future? _onMessageSuccess(Map map) { + void _onMessageSuccess(Map map) { EMMessage msg = EMMessage.fromJson(map['message']); this._msgId = msg.msgId; this.status = msg.status; this.body = msg.body; - if (listener != null) { - listener!.onSuccess(); - } - EMLog.v('发送成功 -- ' + this.toString()); + _messageStatusCallBack?.onSuccess?.call(); + return null; } - Future? _onMessageReadAck(Map map) { - EMLog.v('消息已读 -- ' + ' msg_id: ' + this.msgId!); + void _onMessageReadAck(Map map) { EMMessage msg = EMMessage.fromJson(map); this.hasReadAck = msg.hasReadAck; + _messageStatusCallBack?.onReadAck?.call(); - if (listener != null) { - listener!.onReadAck(); - } return null; } - Future? _onMessageDeliveryAck(Map map) { + void _onMessageDeliveryAck(Map map) { EMMessage msg = EMMessage.fromJson(map); this.hasDeliverAck = msg.hasDeliverAck; - - if (listener != null) { - listener!.onDeliveryAck(); - } - return null; - } - - Future? _onMessageStatusChanged(Map map) { - EMMessage msg = EMMessage.fromJson(map); - this.status = msg.status; - - if (listener != null) { - listener!.onStatusChanged(); - } + _messageStatusCallBack?.onDeliveryAck?.call(); return null; } - /// 构造发送的文字消息 + /// + /// Creates a text message for sending. + /// + /// Param [username] 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 [content] The text content. + /// + /// **Return** The message instance. + /// EMMessage.createTxtSendMessage({ required String username, required String content, @@ -212,11 +244,26 @@ class EMMessage { body: EMTextMessageBody(content: content), ); - /// 构造发送的文件消息 + /// + /// Creates a file message for sending. + /// + /// Param [username] 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 [filePath] The file path. + /// + /// Param [displayName] The file name. + /// + /// Param [fileSize] The file size in bytes. + /// + /// **Return** The message instance. + /// EMMessage.createFileSendMessage({ required String username, required String filePath, - String displayName = '', + String? displayName, int? fileSize, }) : this.createSendMessage( to: username, @@ -226,16 +273,41 @@ class EMMessage { displayName: displayName, )); - /// 构造发送的图片消息 + /// + /// Creates an image message for sending. + /// + /// Param [username] 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 [filePath] The image path. + /// + /// Param [displayName] The image name. + /// + /// Param [thumbnailLocalPath] The local path of the image thumbnail. + /// + /// Param [sendOriginalImage] Whether to send the original image. + /// - `true`: Yes. + /// - `false`: (default) No. For an image greater than 100 KB, the SDK will compress it and send the thumbnail. + /// + /// Param [fileSize] The image file size in bytes. + /// + /// Param [width] The image width in pixels. + /// + /// Param [height] The image height in pixels. + /// + /// **Return** The message instance. + /// EMMessage.createImageSendMessage({ required String username, required String filePath, - String displayName = '', - String thumbnailLocalPath = '', + String? displayName, + String? thumbnailLocalPath, bool sendOriginalImage = false, int? fileSize, - double width = 0, - double height = 0, + double? width, + double? height, }) : this.createSendMessage( to: username, body: EMImageMessageBody( @@ -247,16 +319,39 @@ class EMMessage { height: height, )); - /// 构造发送的视频消息 + /// + /// Creates a video message instance for sending. + /// + /// Param [username] 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 [filePath] The path of the video file. + /// + /// Param [displayName] The video name. + /// + /// Param [duration] The video duration in seconds. + /// + /// Param [fileSize] The video file size in bytes. + /// + /// Param [thumbnailLocalPath] The local path of the thumbnail, which is usually the first frame of video. + /// + /// Param [width] The width of the video thumbnail, in pixels. + /// + /// Param [height] The height of the video thumbnail, in pixels. + /// + /// **Return** The message instance. + /// EMMessage.createVideoSendMessage({ required String username, required String filePath, - String displayName = '', + String? displayName, int duration = 0, int? fileSize, - String thumbnailLocalPath = '', - double width = 0, - double height = 0, + String? thumbnailLocalPath, + double? width, + double? height, }) : this.createSendMessage( to: username, body: EMVideoMessageBody( @@ -269,13 +364,30 @@ class EMMessage { height: height, )); - /// 构造发送的音频消息 + /// + /// Creates a voice message for sending. + /// + /// Param [username] 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 [filePath] The path of the voice file. + /// + /// Param [duration] The voice duration in seconds. + /// + /// Param [fileSize] The size of the voice file, in bytes. + /// + /// 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. + /// EMMessage.createVoiceSendMessage({ required String username, required String filePath, int duration = 0, int? fileSize, - String displayName = '', + String? displayName, }) : this.createSendMessage( to: username, body: EMVoiceMessageBody( @@ -284,179 +396,125 @@ class EMMessage { fileSize: fileSize, displayName: displayName)); - /// 构造发送的位置消息 + /// + /// Creates a location message for sending. + /// + /// Param [username] 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 [latitude] The latitude. + /// + /// Param [longitude] The longitude. + /// + /// Param [address] The address. + /// + /// Param [buildingName] The building name. + /// + /// **Return** The message instance. + /// EMMessage.createLocationSendMessage({ required String username, required double latitude, required double longitude, - String address = '', + String? address, + String? buildingName, }) : this.createSendMessage( to: username, body: EMLocationMessageBody( - latitude: latitude, longitude: longitude, address: address)); + latitude: latitude, + longitude: longitude, + address: address, + )); - /// 构造发送的cmd消息 + /// Creates a command message for sending. + /// + /// Param [username] 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 [action] The command action. + /// + /// **Return** The message instance. + /// EMMessage.createCmdSendMessage({required String username, required action}) : this.createSendMessage( to: username, body: EMCmdMessageBody(action: action)); - /// 构造发送的自定义消息 + /// Creates a custom message for sending. + /// + /// Param [username] 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 [event] The event. + /// + /// Param [Map? params] The params map. + /// + /// **Return** The message instance. + /// EMMessage.createCustomSendMessage( {required String username, required event, Map? params}) : this.createSendMessage( to: username, body: EMCustomMessageBody(event: event, params: params)); - EMMessageStatusListener? listener; + @Deprecated("Switch to using messageStatusCallBack instead.") + StatusListener? listener; - void setMessageListener(EMMessageStatusListener? listener) { + @Deprecated("Switch to using messageStatusCallBack instead.") + void setMessageStatusListener(StatusListener? listener) { this.listener = listener; - if (listener != null) { - MessageCallBackManager.getInstance.addMessage(this); - } else { - MessageCallBackManager.getInstance.removeMessage(this); - } } - /// 消息id - String? _msgId, - msgLocalId = DateTime.now().millisecondsSinceEpoch.toString() + - Random().nextInt(99999).toString(); - - String? get msgId => _msgId ?? msgLocalId; - - /// 消息所属会话id - String? conversationId; - - /// 消息发送方 - String? from = ''; - - /// 消息接收方 - String? to = ''; - - /// 消息本地时间 - int localTime = DateTime.now().millisecondsSinceEpoch; - - /// 消息的服务器时间 - int serverTime = DateTime.now().millisecondsSinceEpoch; - - /// 消息是否收到已送达回执 - bool hasDeliverAck = false; - - /// 消息是否发送/收到已读回执 - bool hasReadAck = false; - - /// 是否需要群消息已读回执,默认为false - bool needGroupAck = false; - - /// 群消息已读数量,只有在群消息时有效 - int groupAckCount = 0; - - /// 是否已读 - bool hasRead = false; - - /// 消息类型 - EMMessageChatType chatType = EMMessageChatType.Chat; - - /// 消息方向 - EMMessageDirection direction = EMMessageDirection.SEND; - - /// 消息状态 - EMMessageStatus status = EMMessageStatus.CREATE; - - /// 消息扩展 - Map attributes = {}; - - /// msg body - EMMessageBody? body; - + /// @nodoc Map toJson() { final Map data = new Map(); - data['from'] = this.from; - data['to'] = this.to; - data['body'] = this.body!.toJson(); - data['attributes'] = this.attributes; - data['direction'] = - this.direction == EMMessageDirection.SEND ? 'send' : 'rec'; - data['hasRead'] = this.hasRead; - data['hasReadAck'] = this.hasReadAck; - data['hasDeliverAck'] = this.hasDeliverAck; - data['needGroupAck'] = this.needGroupAck; - data['groupAckCount'] = this.groupAckCount; - data['msgId'] = this.msgId; - data['conversationId'] = this.conversationId ?? this.to; - data['chatType'] = chatTypeToInt(this.chatType); - data['localTime'] = this.localTime; - data['serverTime'] = this.serverTime; - data['status'] = _chatStatusToInt(this.status); + data.setValueWithOutNull("from", from); + data.setValueWithOutNull("to", to); + data.setValueWithOutNull("body", body.toJson()); + data.setValueWithOutNull("attributes", attributes); + data.setValueWithOutNull( + "direction", this.direction == MessageDirection.SEND ? 'send' : 'rec'); + data.setValueWithOutNull("hasRead", hasRead); + data.setValueWithOutNull("hasReadAck", hasReadAck); + data.setValueWithOutNull("hasDeliverAck", hasDeliverAck); + data.setValueWithOutNull("needGroupAck", needGroupAck); + data.setValueWithOutNull("groupAckCount", groupAckCount); + data.setValueWithOutNull("msgId", msgId); + data.setValueWithOutNull("conversationId", this.conversationId ?? this.to); + data.setValueWithOutNull("chatType", chatTypeToInt(chatType)); + data.setValueWithOutNull("localTime", localTime); + data.setValueWithOutNull("serverTime", serverTime); + data.setValueWithOutNull("status", messageStatusToInt(this.status)); return data; } + /// @nodoc factory EMMessage.fromJson(Map map) { return EMMessage._private() - ..to = map['to'] as String? - ..from = map['from'] as String? - ..body = _bodyFromMap(map['body']) - ..attributes = map['attributes'] ?? {} - ..direction = map['direction'] == 'send' - ? EMMessageDirection.SEND - : EMMessageDirection.RECEIVE + ..to = map.getStringValue("to") + ..from = map.getStringValue("from") + ..body = _bodyFromMap(map["body"])! + ..attributes = map.getMapValue("attributes") + ..direction = map.getStringValue("direction") == 'send' + ? MessageDirection.SEND + : MessageDirection.RECEIVE ..hasRead = map.boolValue('hasRead') ..hasReadAck = map.boolValue('hasReadAck') ..needGroupAck = map.boolValue('needGroupAck') - ..groupAckCount = map["groupAckCount"] as int? ?? 0 + .._groupAckCount = map.getIntValue("groupAckCount", defaultValue: 0)! ..hasDeliverAck = map.boolValue('hasDeliverAck') - .._msgId = map['msgId'] as String? - ..conversationId = map['conversationId'] as String? - ..chatType = chatTypeFromInt(map['chatType'] as int?) - ..localTime = map['localTime'] as int - ..serverTime = map['serverTime'] as int - ..status = _chatStatusFromInt(map['status'] as int?); - } - - static int chatTypeToInt(EMMessageChatType type) { - if (type == EMMessageChatType.ChatRoom) { - return 2; - } else if (type == EMMessageChatType.GroupChat) { - return 1; - } else { - return 0; - } - } - - static EMMessageChatType chatTypeFromInt(int? type) { - if (type == 2) { - return EMMessageChatType.ChatRoom; - } else if (type == 1) { - return EMMessageChatType.GroupChat; - } else { - return EMMessageChatType.Chat; - } - } - - static int _chatStatusToInt(EMMessageStatus status) { - if (status == EMMessageStatus.FAIL) { - return 3; - } else if (status == EMMessageStatus.SUCCESS) { - return 2; - } else if (status == EMMessageStatus.PROGRESS) { - return 1; - } else { - return 0; - } - } - - static EMMessageStatus _chatStatusFromInt(int? status) { - if (status == 3) { - return EMMessageStatus.FAIL; - } else if (status == 2) { - return EMMessageStatus.SUCCESS; - } else if (status == 1) { - return EMMessageStatus.PROGRESS; - } else { - return EMMessageStatus.CREATE; - } + .._msgId = map.getStringValue("msgId") + ..conversationId = map.getStringValue("conversationId") + ..chatType = chatTypeFromInt(map.getIntValue("chatType")) + ..localTime = map.getIntValue("localTime", defaultValue: 0)! + ..serverTime = map.getIntValue("serverTime", defaultValue: 0)! + ..status = messageStatusFromInt(map.intValue("status")); } static EMMessageBody? _bodyFromMap(Map map) { @@ -498,392 +556,43 @@ class EMMessage { } } -// message body -abstract class EMMessageBody { - EMMessageBody({required this.type}); - - EMMessageBody.fromJson({required Map map, this.type}); - - Map toJson() { - final Map data = new Map(); - data['type'] = EMMessageBody.bodyTypeToTypeStr(this.type!); - return data; - } - - @override - String toString() { - return toJson().toString(); - } - - static String bodyTypeToTypeStr(EMMessageBodyType type) { - switch (type) { - case EMMessageBodyType.TXT: - return 'txt'; - case EMMessageBodyType.LOCATION: - return 'loc'; - case EMMessageBodyType.CMD: - return 'cmd'; - case EMMessageBodyType.CUSTOM: - return 'custom'; - case EMMessageBodyType.FILE: - return 'file'; - case EMMessageBodyType.IMAGE: - return 'img'; - case EMMessageBodyType.VIDEO: - return 'video'; - case EMMessageBodyType.VOICE: - return 'voice'; - } - } - - // body 类型 - EMMessageBodyType? type; -} - -/// text body -class EMTextMessageBody extends EMMessageBody { - EMTextMessageBody({required this.content}) - : super(type: EMMessageBodyType.TXT); - - EMTextMessageBody.fromJson({required Map map}) - : super.fromJson(map: map, type: EMMessageBodyType.TXT) { - this.content = map['content']; - } - - @override - Map toJson() { - final Map data = super.toJson(); - data['content'] = this.content; - return data; - } - - String? content = ''; -} - -/// location body -class EMLocationMessageBody extends EMMessageBody { - EMLocationMessageBody( - {required this.latitude, required this.longitude, this.address}) - : super(type: EMMessageBodyType.LOCATION); - - EMLocationMessageBody.fromJson({required Map map}) - : super.fromJson(map: map, type: EMMessageBodyType.LOCATION) { - this.latitude = map['latitude']; - this.longitude = map['longitude']; - this.address = map['address']; - } - - @override - Map toJson() { - final Map data = super.toJson(); - data['address'] = this.address; - data['latitude'] = this.latitude; - data['longitude'] = this.longitude; - return data; - } - - /// 地址 - String? address = ''; - - /// 经纬度 - double? latitude = 0; - double? longitude = 0; -} - -/// file body -class EMFileMessageBody extends EMMessageBody { - EMFileMessageBody({ - this.localPath, - this.displayName, - int? fileSize, - EMMessageBodyType type = EMMessageBodyType.FILE, - }) : super(type: type) { - this.fileSize = fileSize ?? 0; - } - - EMFileMessageBody.fromJson( - {required Map map, EMMessageBodyType type = EMMessageBodyType.FILE}) - : super.fromJson(map: map, type: type) { - this.secret = map['secret']; - this.remotePath = map['remotePath']; - this.fileSize = map['fileSize']; - this.localPath = map['localPath']; - this.displayName = map['displayName']; - this.fileStatus = EMFileMessageBody.downloadStatusFromInt( - map['fileStatus'], - ); - } - - @override - Map toJson() { - final Map data = super.toJson(); - data['secret'] = this.secret; - data['remotePath'] = this.remotePath; - // if (this.fileSize != 0) { - data['fileSize'] = this.fileSize; - // } - data['localPath'] = this.localPath; - data['displayName'] = this.displayName ?? ''; - data['fileStatus'] = EMFileMessageBody.downloadStatusToInt(this.fileStatus); - return data; - } - - /// 本地路径 - String? localPath = ''; - - /// secret - String? secret = ''; - - /// 服务器路径 - String? remotePath = ''; - - /// 附件状态 - EMDownloadStatus fileStatus = EMDownloadStatus.PENDING; - - /// 文件大小 - int? fileSize = 0; - - /// 文件名称 - String? displayName = ''; - - static EMDownloadStatus downloadStatusFromInt(int? status) { - if (status == 0) { - return EMDownloadStatus.DOWNLOADING; - } else if (status == 1) { - return EMDownloadStatus.SUCCESS; - } else if (status == 2) { - return EMDownloadStatus.FAILED; - } else { - return EMDownloadStatus.PENDING; - } - } - - static int downloadStatusToInt(EMDownloadStatus status) { - if (status == EMDownloadStatus.DOWNLOADING) { - return 0; - } else if (status == EMDownloadStatus.SUCCESS) { - return 1; - } else if (status == EMDownloadStatus.FAILED) { - return 2; - } else { - return 3; - } - } -} - -/// image body -class EMImageMessageBody extends EMFileMessageBody { - EMImageMessageBody({ - String? localPath, - String? displayName, - this.thumbnailLocalPath, - this.sendOriginalImage, - int? fileSize, - this.width, - this.height, - }) : super( - localPath: localPath, - displayName: displayName, - fileSize: fileSize, - type: EMMessageBodyType.IMAGE, - ); - - EMImageMessageBody.fromJson({required Map map}) - : super.fromJson(map: map, type: EMMessageBodyType.IMAGE) { - this.thumbnailLocalPath = map['thumbnailLocalPath']; - this.thumbnailRemotePath = map['thumbnailRemotePath']; - this.thumbnailSecret = map['thumbnailSecret']; - this.sendOriginalImage = map.boolValue('sendOriginalImage'); - this.height = map['height']?.toDouble(); - this.width = map['width']?.toDouble(); - this.thumbnailStatus = EMFileMessageBody.downloadStatusFromInt( - map['thumbnailStatus'], - ); - } - - @override - Map toJson() { - final Map data = super.toJson(); - data['thumbnailLocalPath'] = this.thumbnailLocalPath; - data['thumbnailRemotePath'] = this.thumbnailRemotePath; - data['thumbnailSecret'] = this.thumbnailSecret; - data['sendOriginalImage'] = this.sendOriginalImage; - data['height'] = this.height; - data['width'] = this.width; - data['thumbnailStatus'] = - EMFileMessageBody.downloadStatusToInt(this.thumbnailStatus); - return data; - } - - /// 是否是原图 - bool? sendOriginalImage = false; - - /// 缩略图本地地址 - String? thumbnailLocalPath = ''; - - /// 缩略图服务器地址 - String? thumbnailRemotePath = ''; - - /// 缩略图 secret - String? thumbnailSecret = ''; - - /// 缩略图状态 - EMDownloadStatus thumbnailStatus = EMDownloadStatus.PENDING; - - /// 宽 - double? width = 0; - - /// 高 - double? height = 0; -} - -/// video body -class EMVideoMessageBody extends EMFileMessageBody { - EMVideoMessageBody({ - String? localPath, - String? displayName, - this.duration, - int? fileSize, - this.thumbnailLocalPath, - this.height, - this.width, - }) : super( - localPath: localPath, - displayName: displayName, - fileSize: fileSize, - type: EMMessageBodyType.VIDEO, - ); - - EMVideoMessageBody.fromJson({required Map map}) - : super.fromJson(map: map, type: EMMessageBodyType.VIDEO) { - this.duration = map['duration'] as int?; - this.thumbnailLocalPath = map['thumbnailLocalPath'] as String?; - this.thumbnailRemotePath = map['thumbnailRemotePath'] as String?; - this.thumbnailSecret = map['thumbnailSecret'] as String?; - this.height = map['height']?.toDouble(); - this.width = map['width']?.toDouble(); - this.thumbnailStatus = EMFileMessageBody.downloadStatusFromInt( - map['thumbnailStatus'], - ); - } - - @override - Map toJson() { - final Map data = super.toJson(); - data['duration'] = this.duration; - data['thumbnailLocalPath'] = this.thumbnailLocalPath; - data['thumbnailRemotePath'] = this.thumbnailRemotePath; - data['thumbnailSecret'] = this.thumbnailSecret; - data['height'] = this.height; - data['width'] = this.width; - data['thumbnailStatus'] = - EMFileMessageBody.downloadStatusToInt(this.thumbnailStatus); - return data; - } - - /// 时长。秒 - int? duration = 0; - - /// 缩略图本地地址 - String? thumbnailLocalPath = ''; - - /// 缩略图服务器地址 - String? thumbnailRemotePath = ''; - - /// 缩略图 secret - String? thumbnailSecret = ''; - - /// 缩略图状态 - EMDownloadStatus thumbnailStatus = EMDownloadStatus.PENDING; - - /// 宽 - double? width = 0; - - /// 高 - double? height = 0; -} - -/// voice body -class EMVoiceMessageBody extends EMFileMessageBody { - EMVoiceMessageBody({ - localPath, - String? displayName, - int? fileSize, - this.duration, - }) : super( - localPath: localPath, - displayName: displayName, - fileSize: fileSize, - type: EMMessageBodyType.VOICE, - ); - - EMVoiceMessageBody.fromJson({required Map map}) - : super.fromJson(map: map, type: EMMessageBodyType.VOICE) { - this.duration = map['duration']; - } - - @override - Map toJson() { - final Map data = super.toJson(); - data['duration'] = this.duration; - return data; - } - - /// 时长, 秒 - int? duration = 0; -} - -/// cmd body -class EMCmdMessageBody extends EMMessageBody { - EMCmdMessageBody({required this.action, this.deliverOnlineOnly = false}) - : super(type: EMMessageBodyType.CMD); +class MessageCallBackManager { + static const _channelPrefix = 'com.chat.im'; + static const MethodChannel _emMessageChannel = + const MethodChannel('$_channelPrefix/chat_message', JSONMethodCodec()); + Map cacheHandleMap = {}; + static MessageCallBackManager? _instance; + static MessageCallBackManager get getInstance => + _instance = _instance ?? MessageCallBackManager._internal(); - EMCmdMessageBody.fromJson({required Map map}) - : super.fromJson(map: map, type: EMMessageBodyType.CMD) { - this.action = map['action']; - this.deliverOnlineOnly = map['deliverOnlineOnly'] == 0 ? false : true; - } + MessageCallBackManager._internal() { + _emMessageChannel.setMethodCallHandler((MethodCall call) async { + Map argMap = call.arguments; + int? localTime = argMap['localTime']; + EMMessage? handle = cacheHandleMap[localTime.toString()]; - @override - Map toJson() { - final Map data = super.toJson(); - data['action'] = this.action; - data['deliverOnlineOnly'] = this.deliverOnlineOnly; - return data; + if (call.method == ChatMethodKeys.onMessageProgressUpdate) { + return handle?._onMessageProgressChanged(argMap); + } else if (call.method == ChatMethodKeys.onMessageError) { + return handle?._onMessageError(argMap); + } else if (call.method == ChatMethodKeys.onMessageSuccess) { + return handle?._onMessageSuccess(argMap); + } else if (call.method == ChatMethodKeys.onMessageReadAck) { + return handle?._onMessageReadAck(argMap); + } else if (call.method == ChatMethodKeys.onMessageDeliveryAck) { + return handle?._onMessageDeliveryAck(argMap); + } + return null; + }); } - /// cmd 标识 - String? action = ''; - - /// 只投在线 - bool? deliverOnlineOnly = false; -} - -/// custom body -class EMCustomMessageBody extends EMMessageBody { - EMCustomMessageBody({required this.event, this.params}) - : super(type: EMMessageBodyType.CUSTOM); - - EMCustomMessageBody.fromJson({required Map map}) - : super.fromJson(map: map, type: EMMessageBodyType.CUSTOM) { - this.event = map['event']; - this.params = map['params']?.cast(); + void addMessage(EMMessage message) { + cacheHandleMap[message.localTime.toString()] = message; } - @override - Map toJson() { - final Map data = super.toJson(); - data['event'] = event; - if (params != null) { - data['params'] = params; + void removeMessage(String key) { + if (cacheHandleMap.containsKey(key)) { + cacheHandleMap.remove(key); } - - return data; } - - /// 自定义事件key - String? event = ''; - - /// 附加参数 - Map? params = {}; } diff --git a/lib/src/models/em_message_body.dart b/lib/src/models/em_message_body.dart new file mode 100644 index 00000000..5ec9c221 --- /dev/null +++ b/lib/src/models/em_message_body.dart @@ -0,0 +1,28 @@ +import '../internal/em_transform_tools.dart'; +import 'em_chat_enums.dart'; + +/// @nodoc +abstract class EMMessageBody { + EMMessageBody({required this.type}); + + /// @nodoc + EMMessageBody.fromJson({ + required Map map, + required this.type, + }); + + /// @nodoc + Map toJson() { + final Map data = new Map(); + data['type'] = messageTypeToTypeStr(this.type); + return data; + } + + @override + String toString() { + return toJson().toString(); + } + + /// Gets the chat message type. + MessageType type; +} diff --git a/lib/src/models/em_options.dart b/lib/src/models/em_options.dart index 584d4e5d..69622ab1 100644 --- a/lib/src/models/em_options.dart +++ b/lib/src/models/em_options.dart @@ -1,137 +1,321 @@ import '../tools/em_extension.dart'; -import 'em_push_config.dart'; +import '../internal/em_push_config.dart'; +/// +/// 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. +/// class EMOptions { - /// 环信 appKey, 必须设置。 - String? appKey = ''; + /// The app key that you get from the console when creating the app. + late final String appKey; - /// 是否自动登录,当为`true`时,首次登录成功后,您再次启动App时,sdk会在 - /// 初始化后自定为您登录上一次登录的账号。 - bool? autoLogin = true; + /// + /// Whether to enable automatic login. + /// + /// - `true`: (Default) Yes; + /// - `false`: No. + /// + final bool autoLogin; - bool? debugModel = false; + /// + /// Whether to output the debug information. Make sure to call the method after initializing the EMClient using {@link #init(Context, EMOptions)}. + /// + /// - `true`: Yes. + /// - `false`: (Default)No. + /// + final bool debugModel; - /// 自动同意好友申请,当设置为`true`时, - /// 您在线时收到好友申请将自动同意, - /// 如您不在线,等您上线后会自动同意。 - bool? acceptInvitationAlways = false; + /// + /// Whether to accept friend invitations from other users automatically. + /// + /// - `true`: (Default) Yes; + /// - `false`: No. + final bool acceptInvitationAlways; - /// 是否自动同意群邀请,当设置为`true`时, - /// 您在线时收到加群邀请会自动同意, - /// 如您不在线,等您上线后会自动同意。 - bool? autoAcceptGroupInvitation = false; + /// + /// Whether to accept group invitations automatically. + /// + /// - `true`: (Default) Yes; + /// - `false`: No. + /// + final bool autoAcceptGroupInvitation; - /// 是否允许发送已读回执,默认值为`ture`, - /// 当为false时,当您通过EMChatManager调用sendMessageReadAck无效; - bool? requireAck = true; + /// + /// Whether to require read receipt after sending a message. + /// + /// - `true`: (Default) Yes; + /// - `false`: No. + /// + final bool requireAck; - /// 是否发送已送达回执,默认为`false`, 当为`ture`时, - /// 您收到消息后会自动相对方发送已送达回执。 - /// 对方可以通过`onMessagesDelivered()`方法监听; - bool? requireDeliveryAck = false; + /// + /// Whether to require the delivery receipt after sending a message. + /// + /// - `true`: (Default) Yes; + /// - `false`: No. + /// + final bool requireDeliveryAck; - /// 退出群组时是否删除相应会话, 当为`true`时, - /// 您离开群组后对应的群消息会被删除。 - bool? deleteMessagesAsExitGroup = true; + /// + /// Whether to delete the group messages when leaving a group. + /// + /// - `true`: (Default) Yes; + /// - `false`: No. + /// + final bool deleteMessagesAsExitGroup; - /// 退出聊天室时是否删除相应会话, 当为`true`时, - /// 您离开聊天室后对应的聊天室消息会被删除。 - bool? deleteMessagesAsExitChatRoom = true; + /// + /// Whether to delete the chat room messages when leaving the chat room. + /// + /// - `true`: (Default) Yes; + /// - `false`: No. + /// + final bool deleteMessagesAsExitChatRoom; - /// 是否允许聊天室创建者退出聊天室,当为`true`时, - /// 聊天室创建者可以退出聊天室。 - bool? isChatRoomOwnerLeaveAllowed = true; + /// + /// Whether to allow the chat room owner to leave the chat room. + /// + /// - `true`: (Default) Yes; + /// - `false`: No. + /// + final bool isChatRoomOwnerLeaveAllowed; - /// 消息按照服务器时间排序, 当为`true`时,您从数据库中 - /// 获取的消息是按照服务器时间排序的,否则是按照消息的本地时间排序。 - bool? sortMessageByServerTime = true; + /// + /// Whether to sort the messages by the time when the messages are received by the server. + /// + /// - `true`: (Default) Yes; + /// - `false`: No. + /// + final bool sortMessageByServerTime; - bool? usingHttpsOnly = false; - bool? serverTransfer = true; - bool? isAutoDownload = true; + /// + /// Whether only HTTPS is used for REST operations. + /// + /// - `true`: (Default) Only HTTPS is used. + /// - `false`: Both HTTP and HTTPS are allowed. + /// + final bool usingHttpsOnly; - EMPushConfig _pushConfig = EMPushConfig(); + /// + /// Whether to upload the message attachments automatically to the chat server. + /// + /// - `true`: (Default) Yes; + /// - `false`: No. Message attachments are uploaded to a custom path. + /// + final bool serverTransfer; + + /// + /// Whether to automatically download the thumbnail. + /// + /// - `true`: (Default) Yes; + /// - `false`: No. + /// + final bool isAutoDownloadThumbnail; + + /// + /// Whether to enable DNS. + /// + /// - `true`: (Default) Yes; + /// - `false`: No. + /// + final bool enableDNSConfig; + + /// The DNS URL. + final String? dnsUrl; - bool? enableDNSConfig = true; - String? dnsUrl = ''; - String? restServer = ''; - String? imServer = ''; - int? imPort = 0; + /// The custom REST server. + final String? restServer; + + /// The custom IM message server url. + final String? imServer; + + /// The custom IM server port. + final int? imPort; + + EMPushConfig _pushConfig = EMPushConfig(); - /// 开启Oppo推送,`appkey`是Oppo的appkey,`secret`是Oppo的secret。申请流程访问 - /// `http://docs-im.easemob.com/im/android/push/thirdpartypush` - void enableOppPush(String appKey, String secret) { + /// Enable OPPO PUSH on OPPO devices. + /// + /// Param [appId] The app ID for OPPO PUSH. + /// + /// Param [appKey] The app key for OPPO PUSH. + /// + void enableOppoPush(String appKey, String secret) { _pushConfig.enableOppoPush = true; _pushConfig.oppoAppKey = appKey; _pushConfig.oppoAppSecret = secret; } - /// 开启小米推送, `appId`是推送用AppId, `appKey`是推送用AppKey。申请流程请访问 - /// `http://docs-im.easemob.com/im/android/push/thirdpartypush` + /// + /// Enable Mi Push on Mi devices. + /// + /// Param [appId] The app ID for Mi Push. + /// + /// Param [appKey] The app key for Mi Push. + /// void enableMiPush(String appId, String appKey) { _pushConfig.enableMiPush = true; _pushConfig.miAppId = appId; _pushConfig.miAppKey = appKey; } + /// + /// Enable Firebase Cloud Messaging (FCM) push on devices that support Google Play. + /// + /// Param [appId] The app ID for FCM push. + /// void enableFCM(String appId) { _pushConfig.enableFCM = true; _pushConfig.fcmId = appId; } + /// Enable vivo Push on vivo devices. + /// + /// Param [appId] The app ID for vivo Push. + /// + /// Param [appKey] The app key for vivo Push. + /// void enableVivoPush() { _pushConfig.enableVivoPush = true; } - /// 华为推送,具体流程请访问 - /// `http://docs-im.easemob.com/im/android/push/thirdpartypush` + /// Enable Huawei Push on Huawei devices. + /// + /// Param [appId] The app ID for HuaWei Push. + /// + /// Param [appKey] The app key for HuaWei Push. + /// void enableHWPush() { _pushConfig.enableHWPush = true; } - /// 开启苹果推送,具体申请证书和上传流程请参考文档 - /// `http://docs-im.easemob.com/im/ios/apns/deploy` + /// + /// Enables Apple Push Notification service (APNs) on iOS devices. + /// + /// Param [certName] The APNs certificate name. void enableAPNs(String certName) { _pushConfig.enableAPNS = true; _pushConfig.apnsCertName = certName; } - EMOptions({required this.appKey}); - - /// 设置自定义server地址 - void customServerInfo({ - required String customRestServer, - required String customImServer, - required int customImPort, - }) { - restServer = customRestServer; - imServer = customImServer; - imPort = customImPort; - enableDNSConfig = false; - } + /// + /// Sets the app options. + /// + 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 {@link #init(Context, EMOptions)}. + /// - `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}); + + /// @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') - ..deleteMessagesAsExitChatRoom = - json.boolValue('deleteMessagesAsExitChatRoom') - ..isAutoDownload = json.boolValue('isAutoDownload') - ..isChatRoomOwnerLeaveAllowed = - json.boolValue('isChatRoomOwnerLeaveAllowed') - ..serverTransfer = json.boolValue('serverTransfer') - ..usingHttpsOnly = json.boolValue('usingHttpsOnly') - ..enableDNSConfig = json.boolValue('enableDNSConfig') - ..imPort = json.intValue("imPort") - ..imServer = json.stringValue("imServer") - ..restServer = json.stringValue("restServer") - ..dnsUrl = json.stringValue("dnsUrl"); + 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'), + 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.intValue("imPort"), + imServer: json.stringValue("imServer"), + restServer: json.stringValue("restServer"), + dnsUrl: json.stringValue("dnsUrl"), + ); + ret._pushConfig = EMPushConfig(); if (json['pushConfig'] != null) { ret._pushConfig.updateFromJson(json); @@ -140,6 +324,7 @@ class EMOptions { return ret; } + /// @nodoc Map toJson() { Map data = new Map(); data.setValueWithOutNull("appKey", appKey); @@ -158,7 +343,7 @@ class EMOptions { data.setValueWithOutNull("enableDNSConfig", enableDNSConfig); data.setValueWithOutNull("imPort", imPort); data.setValueWithOutNull("imServer", imServer); - data.setValueWithOutNull("isAutoDownload", isAutoDownload); + data.setValueWithOutNull("isAutoDownload", isAutoDownloadThumbnail); data.setValueWithOutNull( "isChatRoomOwnerLeaveAllowed", isChatRoomOwnerLeaveAllowed); data.setValueWithOutNull("requireAck", requireAck); @@ -169,9 +354,8 @@ class EMOptions { "sortMessageByServerTime", sortMessageByServerTime); data.setValueWithOutNull("usingHttpsOnly", usingHttpsOnly); - data['sortMessageByServerTime'] = this.sortMessageByServerTime; - data['usingHttpsOnly'] = this.usingHttpsOnly; - data['pushConfig'] = this._pushConfig.toJson(); + data["usingHttpsOnly"] = this.usingHttpsOnly; + data["pushConfig"] = this._pushConfig.toJson(); return data; } diff --git a/lib/src/models/em_page_result.dart b/lib/src/models/em_page_result.dart index 1b680a38..8067dccd 100644 --- a/lib/src/models/em_page_result.dart +++ b/lib/src/models/em_page_result.dart @@ -1,8 +1,15 @@ typedef PageResultCallback = Object Function(dynamic obj); +/// +/// 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. +/// class EMPageResult { EMPageResult._private(); + /// @nodoc factory EMPageResult.fromJson(Map map, {dataItemCallback: PageResultCallback}) { EMPageResult result = EMPageResult._private(); @@ -18,6 +25,9 @@ class EMPageResult { int? _pageCount; List? _data; + /// The page count. get pageCount => _pageCount; + + /// The result data. List? get data => _data; } diff --git a/lib/src/models/em_push_configs.dart b/lib/src/models/em_push_configs.dart index 1b28a870..8aaca7ef 100644 --- a/lib/src/models/em_push_configs.dart +++ b/lib/src/models/em_push_configs.dart @@ -1,51 +1,75 @@ import 'package:flutter/services.dart'; -import '../../im_flutter_sdk.dart'; -import '../chat_method_keys.dart'; -import '../tools/em_extension.dart'; -enum EMPushStyle { Simple, Summary } +import '../internal/chat_method_keys.dart'; +import '../tools/em_extension.dart'; +import 'em_chat_enums.dart'; +import 'em_error.dart'; +import '../em_push_manager.dart'; +/// The push configuration class. class EMPushConfigs { - EMPushConfigs._private(); + EMPushConfigs._private({ + this.displayStyle = DisplayStyle.Simple, + this.noDisturb = false, + this.noDisturbStartHour = -1, + this.noDisturbEndHour = -1, + }); + + /// + /// The display type of push notifications. + /// + final DisplayStyle displayStyle; + + /// + /// Whether to enable the do-not-disturb mode for push notifications. + /// - `true`: Yes. + /// - `false`: No. + /// Sets it by {@link EMPushManager#disableOfflinePush(int, int)}. + /// + final bool noDisturb; - EMPushStyle? _pushStyle; + /// + /// The start hour of the do-not-disturb mode for push notifications. + /// + final int noDisturbStartHour; + + /// + /// The end hour of the do-not-disturb mode for push notifications. + /// + final int noDisturbEndHour; + + // ignore: unused_field + DisplayStyle? _displayStyle; + // ignore: unused_field bool? _noDisturb; + // ignore: unused_field int? _noDisturbStartHour; + // ignore: unused_field int? _noDisturbEndHour; + // ignore: unused_field List? _noDisturbGroups = []; - EMPushStyle? get pushStyle => _pushStyle; - bool? get noDisturb => _noDisturb; - int? get noDisturbStartHour => _noDisturbStartHour; - int? get noDisturbEndHour => _noDisturbEndHour; - List? get noDisturbGroups => _noDisturbGroups; - + /// @nodoc factory EMPushConfigs.fromJson(Map map) { - return EMPushConfigs._private() - .._pushStyle = - map['pushStyle'] == 0 ? EMPushStyle.Simple : EMPushStyle.Summary - .._noDisturb = map.boolValue('noDisturb') - .._noDisturbStartHour = map['noDisturbStartHour'] - .._noDisturbEndHour = map['noDisturbEndHour']; - } - - Map toJson() { - Map data = Map(); - data['pushStyle'] = _pushStyle == EMPushStyle.Simple; - data['noDisturb'] = _noDisturb; - data['noDisturbStartHour'] = _noDisturbStartHour; - data['noDisturbEndHour'] = _noDisturbEndHour; - return data; + return EMPushConfigs._private( + displayStyle: + map['pushStyle'] == 0 ? DisplayStyle.Simple : DisplayStyle.Summary, + noDisturb: map.boolValue('noDisturb'), + noDisturbStartHour: map['noDisturbStartHour'], + noDisturbEndHour: map['noDisturbEndHour'], + ); } } +/// @nodoc extension EMPushConfigsExtension on EMPushConfigs { // channel的命名与pushManager中的channel一致,本质上还是一个channel。 static const MethodChannel _channel = const MethodChannel('com.chat.im/chat_push_manager', JSONMethodCodec()); - /// 设置是否免打扰[isNoDisturb], [startTime], [endTime] - Future setNoDisturb( + @Deprecated( + "Switch to using EMPushManager#enableOfflinePush and EMPushManager#disableOfflinePush instead") + Future setNoDisturb( bool isNoDisturb, [ int startTime = 0, int endTime = 24, @@ -57,53 +81,56 @@ extension EMPushConfigsExtension on EMPushConfigs { 'startTime': startTime, 'endTime': endTime }; - Map result = - await _channel.invokeMethod(ChatMethodKeys.imPushNoDisturb, req); - EMError.hasErrorFromResult(result); - bool success = result.boolValue(ChatMethodKeys.imPushNoDisturb); - if (success) { - _noDisturb = isNoDisturb; - _noDisturbStartHour = startTime; - _noDisturbEndHour = endTime; + Map result = await _channel.invokeMethod("imPushNoDisturb", req); + try { + EMError.hasErrorFromResult(result); + bool success = result.boolValue("imPushNoDisturb"); + if (success) { + _noDisturb = isNoDisturb; + _noDisturbStartHour = startTime; + _noDisturbEndHour = endTime; + } + } on EMError catch (e) { + throw e; } - return success; } - /// 设置消息推送显示样式[pushStyle] - Future setPushStyle(EMPushStyle pushStyle) async { - EMLog.v('setPushStyle: ' + pushStyle.toString()); + @Deprecated("Switch to using EMPushManager#updatePushDisplayStyle instead") + Future setPushStyle(EMPushStyle pushStyle) async { Map req = {'pushStyle': pushStyle == EMPushStyle.Simple ? 0 : 1}; Map result = await _channel.invokeMethod(ChatMethodKeys.updateImPushStyle, req); - EMError.hasErrorFromResult(result); - bool success = result.boolValue(ChatMethodKeys.updateImPushStyle); - if (success) _pushStyle = pushStyle; - return success; + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } } - /// 通过群id[groupId]设置群组是否免打扰[isNoDisturb] - Future setGroupToDisturb( + @Deprecated("Switch to using EMPushManager#updatePushServiceForGroup instead") + Future setGroupToDisturb( String groupId, bool isNoDisturb, ) async { Map req = {'noDisturb': isNoDisturb, 'group_id': groupId}; - EMLog.v('setGroupToDisturb: ' + req.toString()); Map result = await _channel.invokeMethod(ChatMethodKeys.updateGroupPushService, req); - EMError.hasErrorFromResult(result); - EMGroup group = - EMGroup.fromJson(result[ChatMethodKeys.updateGroupPushService]); - _noDisturbGroups!.removeWhere((e) => e == group.groupId); - if (isNoDisturb) _noDisturbGroups!.add(group.groupId); - return group; + try { + EMError.hasErrorFromResult(result); + } on EMError catch (e) { + throw e; + } } - /// 获取免打扰群组列表 + @Deprecated("Switch to using EMPushManager#getNoPushGroups instead") Future?> noDisturbGroupsFromServer() async { - Map result = await _channel.invokeMethod(ChatMethodKeys.getNoDisturbGroups); - EMError.hasErrorFromResult(result); - _noDisturbGroups = - result[ChatMethodKeys.getNoDisturbGroups]?.cast(); - return _noDisturbGroups; + Map result = await _channel.invokeMethod("getNoDisturbGroups"); + try { + EMError.hasErrorFromResult(result); + _noDisturbGroups = result["getNoDisturbGroups"]?.cast(); + return _noDisturbGroups; + } on EMError catch (e) { + throw e; + } } } diff --git a/lib/src/models/em_text_message_body.dart b/lib/src/models/em_text_message_body.dart new file mode 100644 index 00000000..670c144e --- /dev/null +++ b/lib/src/models/em_text_message_body.dart @@ -0,0 +1,34 @@ +import '../tools/em_extension.dart'; + +import 'em_chat_enums.dart'; +import 'em_message_body.dart'; + +/// +/// The text message class. +/// +class EMTextMessageBody extends EMMessageBody { + /// + /// Creates a text message. + /// + /// Param [content] The text content. + /// + EMTextMessageBody({required this.content}) : super(type: MessageType.TXT); + + /// @nodoc + EMTextMessageBody.fromJson({required Map map}) + : super.fromJson(map: map, type: MessageType.TXT) { + this.content = map.getStringValue("content", defaultValue: "")!; + } + + @override + + ///@nodoc + Map toJson() { + final Map data = super.toJson(); + data['content'] = this.content; + return data; + } + + /// The text content. + late final String content; +} diff --git a/lib/src/models/em_userInfo.dart b/lib/src/models/em_userInfo.dart index bc956df6..9018989c 100644 --- a/lib/src/models/em_userInfo.dart +++ b/lib/src/models/em_userInfo.dart @@ -1,17 +1,25 @@ -//用户属性类型 -enum EMUserInfoType { - NickName, - AvatarURL, - Phone, - Mail, - Gender, - Sign, - Birth, - Ext, -} +import '../tools/em_extension.dart'; +/// +/// The EMUserInfo class, which contains the user attributes, such as the nickname, description, and avatar. +/// class EMUserInfo { - EMUserInfo(String aUserId); + /// + /// Creates a user attribute. + /// + /// Param [userId] The username. + /// + EMUserInfo( + this.userId, { + this.nickName, + this.avatarUrl, + this.mail, + this.phone, + this.gender = 0, + this.sign, + this.birth, + this.ext, + }); EMUserInfo._private({ required this.userId, @@ -19,39 +27,59 @@ class EMUserInfo { this.avatarUrl, this.mail, this.phone, - this.gender, + this.gender = 0, this.sign, this.birth, this.ext, }); + /// @nodoc factory EMUserInfo.fromJson(Map map) { - EMUserInfo info = EMUserInfo._private( - userId: map['userId'], + EMUserInfo info = EMUserInfo( + map["userId"], + nickName: map.getStringValue("nickName"), + avatarUrl: map.getStringValue("avatarUrl"), + mail: map.getStringValue("mail"), + phone: map.getStringValue("phone"), + gender: map.getIntValue("gender", defaultValue: 0)!, + sign: map.getStringValue("sign"), + birth: map.getStringValue("birth"), + ext: map.getStringValue("ext"), ); - info.nickName = map['nickName']; - info.avatarUrl = map['avatarUrl']; - info.mail = map['mail']; - info.phone = map['phone']; - if (map.containsKey("gender")) { - if (map['gender'] as int != 0) { - info.gender = map['gender'] as int; - } - } - info.sign = map['sign']; - info.birth = map['birth']; - info.ext = map['ext']; return info; } + /// + /// Sets user attributes. + /// + /// **Return** The new user information instance. + /// EMUserInfo copyWith({ + /// Param [nickName] The user's nickname. String? nickName, + + /// Param [avatarUrl] The avatar URL of the user. String? avatarUrl, + + /// Param [mail] The email address of the user. String? mail, + + /// Param [phone] The phone number of the user. String? phone, + + /// Param [gender] The user's gender. The value can only be `0`, `1`, or `2`. Other values are invalid. + /// - `0`: (Default) Unknow; + /// - `1`: Male; + /// - `2`: Female. int? gender, + + /// Param [sign] The user's signature. String? sign, + + /// Param [birth] The user's data of birth. String? birth, + + /// Param [ext] The user's extension information. You can set it to an empty string or type custom information and encapsulate them as a JSON string. String? ext, }) { return EMUserInfo._private( @@ -67,6 +95,7 @@ class EMUserInfo { ); } + /// @nodoc Map toJson() { Map data = Map(); data['userId'] = userId; @@ -82,9 +111,7 @@ class EMUserInfo { if (phone != null) { data['phone'] = phone; } - if (gender != null) { - data['gender'] = gender; - } + data['gender'] = gender; if (sign != null) { data['sign'] = sign; } @@ -98,14 +125,77 @@ class EMUserInfo { return data; } - String userId = ''; - String? nickName; - String? avatarUrl; - String? mail; - String? phone; - int? gender; - String? sign; - String? birth; - String? ext; - int expireTime = DateTime.now().millisecondsSinceEpoch; + /// Gets the username. + /// + /// **Return** + /// The user's username. + /// + final String userId; + + /// Gets the user's nickname. + /// + /// **Return** + /// The user's nickname. + /// + final String? nickName; + + /// Gets the avatar URL of the user. + /// + /// **Return** + /// The avatar URL of the user. + /// + final String? avatarUrl; + + /// Gets the email address of the user. + /// + /// **Return** + /// The email address of the user. + /// + final String? mail; + + /// Gets the mobile numbers of the user. + /// + /// **Return** + /// The mobile numbers of the user. + /// + final String? phone; + + /// Gets the user's gender. + /// + /// **Return** + /// The user's gender: + /// - `0`: (Default) Unknow; + /// - `1`: Male; + /// - `2`: Female. + /// + final int gender; + + /// Gets the user's signature. + /// + /// **Return** + /// The user's signature. + /// + final String? sign; + + /// Gets the user's data of birth. + /// + /// **Return** + /// The user's data of birth. + /// + final String? birth; + + /// Gets the user's extension information. + /// + /// **Return** + /// The user's extension information. + /// + final String? ext; + + /// Gets the time period(seconds) when the user attibutes in the cache expire. + /// If the interval between two calles 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 attibutes in the cache expire. + /// + final int expireTime = DateTime.now().millisecondsSinceEpoch; } diff --git a/lib/src/models/em_video_message_body.dart b/lib/src/models/em_video_message_body.dart new file mode 100644 index 00000000..c628032d --- /dev/null +++ b/lib/src/models/em_video_message_body.dart @@ -0,0 +1,92 @@ +import '../internal/em_transform_tools.dart'; +import '../tools/em_extension.dart'; + +import 'em_chat_enums.dart'; +import 'em_file_message_body.dart'; + +/// +/// The video message body class. +/// +class EMVideoMessageBody extends EMFileMessageBody { + /// + /// Creates a video message. + /// + /// Param [localPath] The local path of the video file. + /// + /// Param [displayName] The video name. + /// + /// Param [duration] The video duration in seconds. + /// + /// Param [fileSize] The size of the video file in bytes. + /// + /// Param [thumbnailLocalPath] The local path of the video thumbnail. + /// + /// Param [height] The video height in pixels. + /// + /// Param [width] The video width in pixels. + /// + EMVideoMessageBody({ + required String localPath, + String? displayName, + this.duration = 0, + int? fileSize, + this.thumbnailLocalPath, + this.height, + this.width, + }) : super( + localPath: localPath, + displayName: displayName, + fileSize: fileSize, + type: MessageType.VIDEO, + ); + + /// @nodoc + EMVideoMessageBody.fromJson({required Map map}) + : super.fromJson(map: map, type: MessageType.VIDEO) { + this.duration = map.getIntValue("duration", defaultValue: 0)!; + this.thumbnailLocalPath = map.getStringValue("thumbnailLocalPath"); + this.thumbnailRemotePath = map.getStringValue("thumbnailRemotePath"); + this.thumbnailSecret = map.getStringValue("thumbnailSecret"); + this.height = map.getDoubleValue("height")?.toDouble(); + this.width = map.getDoubleValue("width")?.toDouble(); + this.thumbnailStatus = EMFileMessageBody.downloadStatusFromInt( + map.getIntValue("thumbnailStatus")); + } + + /// @nodoc + @override + Map toJson() { + final Map data = super.toJson(); + data.setValueWithOutNull("duration", duration); + data.setValueWithOutNull("thumbnailLocalPath", thumbnailLocalPath); + data.setValueWithOutNull("thumbnailRemotePath", thumbnailRemotePath); + data.setValueWithOutNull("thumbnailSecret", thumbnailSecret); + data.setValueWithOutNull("height", height); + data.setValueWithOutNull("width", width); + data.setValueWithOutNull( + "thumbnailStatus", downloadStatusToInt(this.thumbnailStatus)); + + return data; + } + + /// The video duration in seconds. + int? duration; + + /// The local path of the video thumbnail. + String? thumbnailLocalPath; + + /// The URL of the thumbnail on the server. + String? thumbnailRemotePath; + + /// The secret key of the video thumbnail. + String? thumbnailSecret; + + /// The download status of the video thumbnail. + DownloadStatus thumbnailStatus = DownloadStatus.PENDING; + + /// The video width in pixels. + double? width; + + /// The video height in pixels. + double? height; +} diff --git a/lib/src/models/em_voice_message_body.dart b/lib/src/models/em_voice_message_body.dart new file mode 100644 index 00000000..c818c778 --- /dev/null +++ b/lib/src/models/em_voice_message_body.dart @@ -0,0 +1,49 @@ +import '../tools/em_extension.dart'; + +import 'em_file_message_body.dart'; +import 'em_chat_enums.dart'; + +/// +/// The voice message body class. +/// +class EMVoiceMessageBody extends EMFileMessageBody { + /// + /// Creates a voice message. + /// + /// Param [localPath] The local path of the voice file. + /// + /// Param [displayName] The name of the voice file. + /// + /// Param [fileSize] The size of the voice file in bytes. + /// + /// Param [duration] The voice duration in seconds. + /// + EMVoiceMessageBody({ + localPath, + this.duration = 0, + String? displayName, + int? fileSize, + }) : super( + localPath: localPath, + displayName: displayName, + fileSize: fileSize, + type: MessageType.VOICE, + ); + + /// @nodoc + EMVoiceMessageBody.fromJson({required Map map}) + : super.fromJson(map: map, type: MessageType.VOICE) { + this.duration = map.getIntValue("duration", defaultValue: 0)!; + } + + /// @nodoc + @override + Map toJson() { + final Map data = super.toJson(); + data.setValueWithOutNull("duration", duration); + return data; + } + + /// The voice duration in seconds. + late final int duration; +} diff --git a/lib/src/tools/em_extension.dart b/lib/src/tools/em_extension.dart index 25d631d8..ce462c7e 100644 --- a/lib/src/tools/em_extension.dart +++ b/lib/src/tools/em_extension.dart @@ -1,6 +1,7 @@ -// 思考: 是否要把所有格式转换的部分都放到这个extension中? import '../models/em_group_shared_file.dart'; +Type typeOf() => T; + extension MapExtension on Map { bool boolValue(String key) { if (!containsKey(key)) { @@ -35,13 +36,13 @@ extension MapExtension on Map { List? listValue(String key) { if (this.containsKey(key)) { List obj = this[key]; - if (T is String) { + if (typeOf().toString() == "String") { List strList = []; for (var item in obj) { strList.add(item); } return strList as List; - } else if (T is EMGroupSharedFile) { + } else if (typeOf().toString() == "EMGroupSharedFile") { List fileList = []; for (var item in obj) { var file = EMGroupSharedFile.fromJson(item); @@ -49,15 +50,14 @@ extension MapExtension on Map { } return fileList as List; } - } else { - return null; } + return null; } -} -extension MapWithoutNull on Map { - setValueWithOutNull(String key, T? value, - [Object Function(T object)? callback]) { + /// + /// 如果给的value是null则不设置到map中。 + void setValueWithOutNull(String key, T? value, + {Object Function(T object)? callback, T? defaultValue}) { if (value != null) { if (callback != null) { Object v = callback(value); @@ -65,6 +65,67 @@ extension MapWithoutNull on Map { } else { this[key] = value; } + } else { + if (defaultValue != null) { + this[key] = defaultValue; + } + } + } + + int? getIntValue(String key, {int? defaultValue}) { + int? ret = defaultValue; + if (this.containsKey(key)) { + dynamic value = this[key]; + if (value is int) { + ret = value; + } + } + return ret; + } + + bool? getBoolValue(String key, {bool? defaultValue}) { + bool? ret = defaultValue; + if (this.containsKey(key)) { + dynamic value = this[key]; + if (value is bool) { + ret = value; + } + } + return ret; + } + + String? getStringValue(String key, {String? defaultValue}) { + String? ret = defaultValue; + if (this.containsKey(key)) { + dynamic value = this[key]; + if (value is String) { + ret = value; + } + } + return ret; + } + + double? getDoubleValue(String key, {double? defaultValue}) { + double? ret = defaultValue; + if (this.containsKey(key)) { + dynamic value = this[key]; + if (value is double) { + ret = value; + } else if (value is int) { + ret = value.toDouble(); + } + } + return ret; + } + + Map? getMapValue(String key, {Map? defaultValue}) { + Map? ret = defaultValue; + if (this.containsKey(key)) { + Map? value = this[key]; + if (value is double) { + ret = value; + } } + return ret; } }