From 7457f182f332c84b178e74fee12867e1daa7a2f5 Mon Sep 17 00:00:00 2001 From: hrxiang Date: Wed, 18 May 2022 16:47:14 +0800 Subject: [PATCH] Upgrade --- CHANGELOG.md | 6 + android/build.gradle | 2 +- .../FlutterOpenimSdkPlugin.java | 3 + .../listener/OnOrganizationListener.java | 10 + .../flutter_openim_sdk/manager/IMManager.java | 9 + .../manager/OrganizationManager.java | 54 +++++ ios/Classes/Module/IMManager.swift | 3 + ios/Classes/Module/OrganizationManager.swift | 49 +++++ ios/Classes/SwiftFlutterOpenimSdkPlugin.swift | 4 + ios/flutter_openim_sdk.podspec | 2 +- lib/flutter_openim_sdk.dart | 3 + lib/src/enum/listener_type.dart | 1 + lib/src/listener/organization_listener.dart | 9 + lib/src/manager/im_conversation_manager.dart | 4 +- lib/src/manager/im_friendship_manager.dart | 8 +- lib/src/manager/im_group_manager.dart | 38 +++- lib/src/manager/im_manager.dart | 43 +++- lib/src/manager/im_message_manager.dart | 117 +++++++---- lib/src/manager/im_organization_manager.dart | 98 +++++++++ lib/src/models/organization_info.dart | 198 ++++++++++++++++++ pubspec.yaml | 2 +- 21 files changed, 607 insertions(+), 56 deletions(-) create mode 100644 android/src/main/java/io/openim/flutter_openim_sdk/listener/OnOrganizationListener.java create mode 100644 android/src/main/java/io/openim/flutter_openim_sdk/manager/OrganizationManager.java create mode 100644 ios/Classes/Module/OrganizationManager.swift create mode 100644 lib/src/listener/organization_listener.dart create mode 100644 lib/src/manager/im_organization_manager.dart create mode 100644 lib/src/models/organization_info.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ce6c41..273b2fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 2.0.9 + +1.Fix bug
+2.New organization fuction
+3.New uploadImage method
+ ## 2.0.8 1.Fix bug
diff --git a/android/build.gradle b/android/build.gradle index cfaf600..744d514 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -49,5 +49,5 @@ android { } } dependencies { - implementation 'io.openim:core-sdk:2.0.8.+@aar' + implementation 'io.openim:core-sdk:2.0.9.+@aar' } \ No newline at end of file diff --git a/android/src/main/java/io/openim/flutter_openim_sdk/FlutterOpenimSdkPlugin.java b/android/src/main/java/io/openim/flutter_openim_sdk/FlutterOpenimSdkPlugin.java index 918b76b..9d16d2a 100644 --- a/android/src/main/java/io/openim/flutter_openim_sdk/FlutterOpenimSdkPlugin.java +++ b/android/src/main/java/io/openim/flutter_openim_sdk/FlutterOpenimSdkPlugin.java @@ -18,6 +18,7 @@ import io.openim.flutter_openim_sdk.manager.FriendshipManager; import io.openim.flutter_openim_sdk.manager.GroupManager; import io.openim.flutter_openim_sdk.manager.IMManager; import io.openim.flutter_openim_sdk.manager.MessageManager; +import io.openim.flutter_openim_sdk.manager.OrganizationManager; import io.openim.flutter_openim_sdk.manager.SignalingManager; import io.openim.flutter_openim_sdk.manager.UserManager; import io.openim.flutter_openim_sdk.manager.WorkMomentsManager; @@ -41,6 +42,7 @@ public class FlutterOpenimSdkPlugin implements FlutterPlugin, MethodCallHandler private static GroupManager groupManager; private static SignalingManager signalingManager; private static WorkMomentsManager workMomentsManager; + private static OrganizationManager organizationManager; public FlutterOpenimSdkPlugin() { } @@ -54,6 +56,7 @@ public class FlutterOpenimSdkPlugin implements FlutterPlugin, MethodCallHandler FlutterOpenimSdkPlugin.groupManager = new GroupManager(); FlutterOpenimSdkPlugin.signalingManager = new SignalingManager(); FlutterOpenimSdkPlugin.workMomentsManager = new WorkMomentsManager(); + FlutterOpenimSdkPlugin.organizationManager = new OrganizationManager(); } @Override diff --git a/android/src/main/java/io/openim/flutter_openim_sdk/listener/OnOrganizationListener.java b/android/src/main/java/io/openim/flutter_openim_sdk/listener/OnOrganizationListener.java new file mode 100644 index 0000000..4743ab2 --- /dev/null +++ b/android/src/main/java/io/openim/flutter_openim_sdk/listener/OnOrganizationListener.java @@ -0,0 +1,10 @@ +package io.openim.flutter_openim_sdk.listener; + +import io.openim.flutter_openim_sdk.util.CommonUtil; + +public class OnOrganizationListener implements open_im_sdk_callback.OnOrganizationListener { + @Override + public void onOrganizationUpdated() { + CommonUtil.emitEvent("organizationListener", "onOrganizationUpdated", null); + } +} diff --git a/android/src/main/java/io/openim/flutter_openim_sdk/manager/IMManager.java b/android/src/main/java/io/openim/flutter_openim_sdk/manager/IMManager.java index 9db2c87..a857e7d 100644 --- a/android/src/main/java/io/openim/flutter_openim_sdk/manager/IMManager.java +++ b/android/src/main/java/io/openim/flutter_openim_sdk/manager/IMManager.java @@ -44,4 +44,13 @@ public class IMManager extends BaseManager { ); } + public void uploadImage(MethodCall methodCall, MethodChannel.Result result) { + Open_im_sdk.uploadImage( + new OnBaseListener(result, methodCall), + value(methodCall, "operationID"), + value(methodCall, "path"), + value(methodCall, "token"), + value(methodCall, "obj") + ); + } } diff --git a/android/src/main/java/io/openim/flutter_openim_sdk/manager/OrganizationManager.java b/android/src/main/java/io/openim/flutter_openim_sdk/manager/OrganizationManager.java new file mode 100644 index 0000000..a5073bc --- /dev/null +++ b/android/src/main/java/io/openim/flutter_openim_sdk/manager/OrganizationManager.java @@ -0,0 +1,54 @@ +package io.openim.flutter_openim_sdk.manager; + +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.openim.flutter_openim_sdk.listener.OnBaseListener; +import io.openim.flutter_openim_sdk.listener.OnOrganizationListener; +import open_im_sdk.Open_im_sdk; + +public class OrganizationManager extends BaseManager { + + public void setOrganizationListener(MethodCall methodCall, MethodChannel.Result result) { + Open_im_sdk.setOrganizationListener(new OnOrganizationListener()); + } + + public void getSubDepartment(MethodCall methodCall, MethodChannel.Result result) { + Open_im_sdk.getSubDepartment( + new OnBaseListener(result, methodCall), + value(methodCall, "operationID"), + value(methodCall, "departmentID"), + int2long(methodCall, "offset"), + int2long(methodCall, "count") + ); + } + + public void getDepartmentMember(MethodCall methodCall, MethodChannel.Result result) { + Open_im_sdk.getDepartmentMember( + new OnBaseListener(result, methodCall), + value(methodCall, "operationID"), + value(methodCall, "departmentID"), + int2long(methodCall, "offset"), + int2long(methodCall, "count") + ); + } + + public void getUserInDepartment(MethodCall methodCall, MethodChannel.Result result) { + Open_im_sdk.getUserInDepartment( + new OnBaseListener(result, methodCall), + value(methodCall, "operationID"), + value(methodCall, "userID") + ); + } + + public void getDepartmentMemberAndSubDepartment(MethodCall methodCall, MethodChannel.Result result) { + Open_im_sdk.getDepartmentMemberAndSubDepartment( + new OnBaseListener(result, methodCall), + value(methodCall, "operationID"), + value(methodCall, "departmentID"), + int2long(methodCall, "departmentOffset"), + int2long(methodCall, "departmentCount"), + int2long(methodCall, "memberOffset"), + int2long(methodCall, "memberCount") + ); + } +} diff --git a/ios/Classes/Module/IMManager.swift b/ios/Classes/Module/IMManager.swift index 0a11eae..57dfa8f 100644 --- a/ios/Classes/Module/IMManager.swift +++ b/ios/Classes/Module/IMManager.swift @@ -32,6 +32,9 @@ public class IMMananger: BaseServiceManager { Open_im_sdkWakeUp(BaseCallback(result: result), methodCall[string: "operationID"]) } + func uploadImage(methodCall: FlutterMethodCall, result: @escaping FlutterResult) { + Open_im_sdkUploadImage(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "path"], methodCall[string: "token"], methodCall[string: "obj"]) + } } public class ConnListener: NSObject, Open_im_sdk_callbackOnConnListenerProtocol { diff --git a/ios/Classes/Module/OrganizationManager.swift b/ios/Classes/Module/OrganizationManager.swift new file mode 100644 index 0000000..011b395 --- /dev/null +++ b/ios/Classes/Module/OrganizationManager.swift @@ -0,0 +1,49 @@ +import Foundation +import OpenIMCore + +public class OrganizationManager: BaseServiceManager { + + public override func registerHandlers() { + super.registerHandlers() + self["setOrganizationListener"] = setOrganizationListener + self["getSubDepartment"] = getSubDepartment + self["getDepartmentMember"] = getDepartmentMember + self["getUserInDepartment"] = getUserInDepartment + self["getDepartmentMemberAndSubDepartment"] = getDepartmentMemberAndSubDepartment + } + + func setOrganizationListener(methodCall: FlutterMethodCall, result: @escaping FlutterResult){ + Open_im_sdkSetOrganizationListener(OrganizationListener(channel: channel)) + callBack(result) + } + + func getSubDepartment(methodCall: FlutterMethodCall, result: @escaping FlutterResult) { + Open_im_sdkGetSubDepartment(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "departmentID"], methodCall[int: "offset"], methodCall[int: "count"]) + } + + func getDepartmentMember(methodCall: FlutterMethodCall, result: @escaping FlutterResult) { + Open_im_sdkGetDepartmentMember(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "departmentID"], methodCall[int: "offset"], methodCall[int: "count"]) + } + + func getUserInDepartment(methodCall: FlutterMethodCall, result: @escaping FlutterResult) { + Open_im_sdkGetUserInDepartment(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "userID"]) + } + + func getDepartmentMemberAndSubDepartment(methodCall: FlutterMethodCall, result: @escaping FlutterResult) { + Open_im_sdkGetDepartmentMemberAndSubDepartment(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "departmentID"], methodCall[int: "departmentOffset"], methodCall[int: "departmentCount"], methodCall[int: "memberOffset"], methodCall[int: "memberCount"]) + } +} + +public class OrganizationListener: NSObject, Open_im_sdk_callbackOnOrganizationListenerProtocol { + + private let channel:FlutterMethodChannel + + init(channel:FlutterMethodChannel) { + self.channel = channel + } + + public func onOrganizationUpdated() { + CommonUtil.emitEvent(channel: self.channel, method: "organizationListener", type: "onOrganizationUpdated", errCode: nil, errMsg: nil, data: nil) + } + +} diff --git a/ios/Classes/SwiftFlutterOpenimSdkPlugin.swift b/ios/Classes/SwiftFlutterOpenimSdkPlugin.swift index 8091c80..0e07bf7 100644 --- a/ios/Classes/SwiftFlutterOpenimSdkPlugin.swift +++ b/ios/Classes/SwiftFlutterOpenimSdkPlugin.swift @@ -10,6 +10,7 @@ public class SwiftFlutterOpenimSdkPlugin: NSObject, FlutterPlugin { let userManger: UserManager let signalingManager: SignalingManager let workMomentsManager: WorkMomentsManager + let organizationManager: OrganizationManager init(channel: FlutterMethodChannel) { self.imManager = IMMananger(channel: channel) @@ -20,6 +21,7 @@ public class SwiftFlutterOpenimSdkPlugin: NSObject, FlutterPlugin { self.userManger = UserManager(channel: channel) self.signalingManager = SignalingManager(channel: channel) self.workMomentsManager = WorkMomentsManager(channel: channel) + self.organizationManager = OrganizationManager(channel: channel) } public static func register(with registrar: FlutterPluginRegistrar) { @@ -47,6 +49,8 @@ public class SwiftFlutterOpenimSdkPlugin: NSObject, FlutterPlugin { signalingManager.handleMethod(call: call, result: result) case "workMomentsManager": workMomentsManager.handleMethod(call: call, result: result) + case "organizationManager": + organizationManager.handleMethod(call: call, result: result) default: print("Handle ManagerName Error: \(managerName) not found") } diff --git a/ios/flutter_openim_sdk.podspec b/ios/flutter_openim_sdk.podspec index 78b1729..72d1af5 100644 --- a/ios/flutter_openim_sdk.podspec +++ b/ios/flutter_openim_sdk.podspec @@ -17,7 +17,7 @@ A new Flutter project. s.dependency 'Flutter' s.platform = :ios, '8.0' - s.dependency 'OpenIMSDKCore','2.0.8' + s.dependency 'OpenIMSDKCore','2.0.9' s.static_framework = true # s.vendored_frameworks = 'Framework/*.framework' # Flutter.framework does not contain a i386 slice. diff --git a/lib/flutter_openim_sdk.dart b/lib/flutter_openim_sdk.dart index 365f4df..756a894 100644 --- a/lib/flutter_openim_sdk.dart +++ b/lib/flutter_openim_sdk.dart @@ -13,6 +13,7 @@ export 'src/listener/conversation_listener.dart'; export 'src/listener/friendship_listener.dart'; export 'src/listener/group_listener.dart'; export 'src/listener/msg_send_progress_listener.dart'; +export 'src/listener/organization_listener.dart'; export 'src/listener/signaling_listener.dart'; export 'src/listener/user_listener.dart'; export 'src/listener/workmoments_listener.dart'; @@ -22,6 +23,7 @@ export 'src/manager/im_group_manager.dart'; export 'src/manager/im_manager.dart'; export 'src/manager/im_message_manager.dart'; export 'src/manager/im_offline_push_manager.dart'; +export 'src/manager/im_organization_manager.dart'; export 'src/manager/im_signaling_manager.dart'; export 'src/manager/im_user_manager.dart'; export 'src/manager/im_workmoments_manager.dart'; @@ -29,6 +31,7 @@ export 'src/models/conversation_info.dart'; export 'src/models/group_info.dart'; export 'src/models/message.dart'; export 'src/models/notification_info.dart'; +export 'src/models/organization_info.dart'; export 'src/models/search_info.dart'; export 'src/models/signaling_info.dart'; export 'src/models/user_info.dart'; diff --git a/lib/src/enum/listener_type.dart b/lib/src/enum/listener_type.dart index 6e13237..67c3490 100644 --- a/lib/src/enum/listener_type.dart +++ b/lib/src/enum/listener_type.dart @@ -9,4 +9,5 @@ class ListenerType { static final signalingListener = 'signalingListener'; static final msgSendProgressListener = "msgSendProgressListener"; static final workMomentsListener = "workMomentsListener"; + static final organizationListener = "organizationListener"; } diff --git a/lib/src/listener/organization_listener.dart b/lib/src/listener/organization_listener.dart new file mode 100644 index 0000000..000bcd8 --- /dev/null +++ b/lib/src/listener/organization_listener.dart @@ -0,0 +1,9 @@ +class OnOrganizationListener { + Function()? onOrganizationUpdated; + + OnOrganizationListener({this.onOrganizationUpdated}); + + void organizationUpdated() { + onOrganizationUpdated?.call(); + } +} diff --git a/lib/src/manager/im_conversation_manager.dart b/lib/src/manager/im_conversation_manager.dart index 270f9be..f728689 100644 --- a/lib/src/manager/im_conversation_manager.dart +++ b/lib/src/manager/im_conversation_manager.dart @@ -130,8 +130,8 @@ class ConversationManager { // _channel.invokeMethod( // 'markSingleMessageHasRead', _buildParam({'userID': userID})); - /// Mark group chat messages as read - /// 标记群聊已读 + /// Mark group chat all messages as read + /// 标记群聊会话已读 Future markGroupMessageHasRead({ required String groupID, String? operationID, diff --git a/lib/src/manager/im_friendship_manager.dart b/lib/src/manager/im_friendship_manager.dart index 34f08ce..73b198d 100644 --- a/lib/src/manager/im_friendship_manager.dart +++ b/lib/src/manager/im_friendship_manager.dart @@ -16,6 +16,7 @@ class FriendshipManager { /// Get friend info by user id /// 查询好友信息 + /// [uidList] 好友的userID集合 Future> getFriendsInfo({ required List uidList, String? operationID, @@ -30,7 +31,9 @@ class FriendshipManager { .then((value) => Utils.toList(value, (v) => UserInfo.fromJson(v))); /// Send an friend application - /// 发送一个好友请求 + /// 发送一个好友请求,需要对方调用同意申请才能成为好友。 + /// [uid] 被邀请的用户ID + /// [reason] 说明 Future addFriend({ required String uid, String? reason, @@ -92,6 +95,8 @@ class FriendshipManager { /// Modify friend remark name /// 设置好友备注 + /// [uid] 好友的userID + /// [remark] 好友的备注 Future setFriendRemark({ required String uid, required String remark, @@ -107,6 +112,7 @@ class FriendshipManager { /// Add friends to blacklist /// 加入黑名单 + /// [uid]被加入黑名单的好友ID Future addBlacklist({ required String uid, String? operationID, diff --git a/lib/src/manager/im_group_manager.dart b/lib/src/manager/im_group_manager.dart index b1c46d2..bb04334 100644 --- a/lib/src/manager/im_group_manager.dart +++ b/lib/src/manager/im_group_manager.dart @@ -74,6 +74,10 @@ class GroupManager { /// Get the list of group members /// 分页获取组成员列表 + /// [groupId] 群ID + /// [filter] 过滤成员 1普通成员, 2群主,3管理员,0所有 + /// [offset] 开始下标 + /// [count] 总数 Future> getGroupMemberList({ required String groupId, int filter = 0, @@ -96,6 +100,10 @@ class GroupManager { /// Get the list of group members /// 分页获取组成员列表 + /// [groupId] 群ID + /// [filter] 过滤成员 1普通成员, 2群主,3管理员,0所有 + /// [offset] 开始下标 + /// [count] 总数 Future> getGroupMemberListMap({ required String groupId, int filter = 0, @@ -147,6 +155,12 @@ class GroupManager { /// Create a group /// 创建一个组 + /// [groupName] 群名 + /// [notification] 公告 + /// [introduction] 群介绍 + /// [faceUrl] 群头像 + /// [ex] 额外信息 + /// [list] 初创群成员以及其角色 Future createGroup({ String? groupName, String? notification, @@ -177,6 +191,12 @@ class GroupManager { /// Edit group information /// 编辑组资料 + /// [groupID] 被编辑的群ID + /// [groupName] 新的群名 + /// [notification] 新的公告 + /// [introduction] 新的群介绍 + /// [faceUrl] 新的群头像 + /// [ex] 新的额外信息 Future setGroupInfo({ required String groupID, String? groupName, @@ -218,7 +238,7 @@ class GroupManager { (value) => Utils.toList(value, (map) => GroupInfo.fromJson(map))); /// Apply to join the group - /// 申请加入组,需要通过管理员同意。 + /// 申请加入组,需要通过管理员/群组同意。 Future joinGroup({ required String gid, String? reason, @@ -260,8 +280,8 @@ class GroupManager { 'operationID': Utils.checkOperationID(operationID), })); - /// As the group owner or administrator, get the list of received group members' applications to join the group. - /// 作为群主或者管理员,获取收到的群成员申请进群列表。 + /// As the group owner or administrator, the group member's application to join the group received + /// 作为群主或者管理员,收到的群成员入群申请 Future> getRecvGroupApplicationList( {String? operationID}) => _channel @@ -288,6 +308,7 @@ class GroupManager { /// Accept group application /// 管理员或者群主同意某人进入某群 + /// 注:主动申请入群需要通过管理员/群组处理,被别人拉入群不需要管理员/群组处理 Future acceptGroupApplication({ required String gid, required String uid, @@ -305,6 +326,7 @@ class GroupManager { /// Refuse group application /// 管理员或者群主拒绝某人进入某群 + /// 注:主动申请入群需要通过管理员/群组处理,被别人拉入群不需要管理员/群组处理 Future refuseGroupApplication({ required String gid, required String uid, @@ -334,7 +356,9 @@ class GroupManager { })); /// Enable group mute - /// 开启群禁言 + /// 开启群禁言,所有群成员禁止发言 + /// [groupID] 将开启群禁言的组ID + /// [mute] true:开启,false:关闭 Future changeGroupMute({ required String groupID, required bool mute, @@ -350,6 +374,9 @@ class GroupManager { /// Mute group members /// 禁言群成员 + /// [groupID] 群ID + /// [userID] 将被禁言的成员ID + /// [seconds] 被禁言的时间s,设置为0则为接触禁言 Future changeGroupMemberMute({ required String groupID, required String userID, @@ -367,6 +394,9 @@ class GroupManager { /// Set group user nickname /// 设置群成员昵称 + /// [groupID] 群ID + /// [userID] 群成员的用户ID + /// [groupNickname] 群昵称 Future setGroupMemberNickname({ required String groupID, required String userID, diff --git a/lib/src/manager/im_manager.dart b/lib/src/manager/im_manager.dart index 5f594bd..1901130 100644 --- a/lib/src/manager/im_manager.dart +++ b/lib/src/manager/im_manager.dart @@ -14,11 +14,14 @@ class IMManager { // late OfflinePushManager offlinePushManager; late SignalingManager signalingManager; late WorkMomentsManager workMomentsManager; + late OrganizationManager organizationManager; late OnConnectListener _connectListener; late String uid; late UserInfo uInfo; bool isLogined = false; + String? token; + String? _objectStorage; IMManager(this._channel) { conversationManager = ConversationManager(_channel); @@ -29,6 +32,7 @@ class IMManager { // offlinePushManager = OfflinePushManager(_channel); signalingManager = SignalingManager(_channel); workMomentsManager = WorkMomentsManager(_channel); + organizationManager = OrganizationManager(_channel); _addNativeCallback(_channel); } @@ -269,6 +273,13 @@ class IMManager { workMomentsManager.listener.recvNewNotification(); break; } + } else if (call.method == ListenerType.organizationListener) { + String type = call.arguments['type']; + switch (type) { + case 'onOrganizationUpdated': + organizationManager.listener.organizationUpdated(); + break; + } } } catch (err) { print( @@ -284,6 +295,8 @@ class IMManager { /// [apiAddr] api server ip address /// [wsAddr] webSocket ip address /// [dataDir] data storage directory + /// [objectStorage] storage object: cos/minio + /// [logLevel] log level: 1-not print /// /// 初始化SDK /// @@ -291,6 +304,8 @@ class IMManager { /// [apiAddr] SDK api地址 /// [wsAddr] SDK websocket地址 /// [dataDir] SDK数据库存储目录 + /// [objectStorage] 存储对象 cos/minio + /// [logLevel] 日志 1-不打印 Future initSDK({ required int platform, required String apiAddr, @@ -301,7 +316,8 @@ class IMManager { String objectStorage = 'cos', String? operationID, }) { - _connectListener = listener; + this._connectListener = listener; + this._objectStorage = objectStorage; return _channel.invokeMethod( 'initSDK', _buildParam( @@ -324,6 +340,8 @@ class IMManager { /// Login sdk /// 登录 + /// [uid]用户id + /// [token]登录token,从业务服务器上获取 Future login({ required String uid, required String token, @@ -339,6 +357,7 @@ class IMManager { ); this.isLogined = true; this.uid = uid; + this.token = token; this.uInfo = await userManager.getSelfUserInfo(); return uInfo; } @@ -352,6 +371,7 @@ class IMManager { 'operationID': Utils.checkOperationID(operationID), })); this.isLogined = false; + this.token = null; return value; } @@ -368,12 +388,33 @@ class IMManager { Future getLoginUserInfo() async => uInfo; /// wakeup + /// 从后台回到前台立刻唤醒 Future wakeUp({String? operationID}) => _channel.invokeMethod( 'wakeUp', _buildParam({ 'operationID': Utils.checkOperationID(operationID), })); + /// upload image to server + /// 上传图片到服务器 + /// [path]图片路径 + /// [token] im token + /// [objectStorage] 存储对象 cos/minio + Future uploadImage({ + required String path, + String? token, + String? objectStorage, + String? operationID, + }) => + _channel.invokeMethod( + 'uploadImage', + _buildParam({ + 'path': path, + 'token': token ?? this.token, + 'obj': objectStorage ?? this._objectStorage, + 'operationID': Utils.checkOperationID(operationID), + })); + static Map _buildParam(Map param) { param["ManagerName"] = "imManager"; return param; diff --git a/lib/src/manager/im_message_manager.dart b/lib/src/manager/im_message_manager.dart index 59875a3..f9a895e 100644 --- a/lib/src/manager/im_message_manager.dart +++ b/lib/src/manager/im_message_manager.dart @@ -54,10 +54,12 @@ class MessageManager { .then((value) => Utils.toObj(value, (map) => Message.fromJson(map))); /// Find all history message - /// 获取聊天记录 - /// [userID]接收消息的用户id - /// [conversationID] 会话id,查询通知是可用 - /// [groupID]接收消息的组id + /// 获取聊天记录(以startMsg为节点,以前的聊天记录) + /// [userID] 接收消息的用户id + /// [conversationID] 会话id,查询通知时可用 + /// [groupID] 接收消息的组id + /// [startMsg] 从这条消息开始查询[count]条,获取的列表index==length-1为最新消息,所以获取下一页历史记录startMsg=list.first + /// [count] 一次拉取的总数 Future> getHistoryMessageList({ String? userID, String? groupID, @@ -93,7 +95,7 @@ class MessageManager { }))); /// Delete message - /// 删除消息 + /// 删除本地消息 Future deleteMessageFromLocalStorage({ required Message message, String? operationID, @@ -110,45 +112,41 @@ class MessageManager { // _channel.invokeMethod('deleteMessages', // _buildParam({"msgList": msgList.map((e) => e.toJson()).toList()})); - /// - Future insertSingleMessageToLocalStorage({ + /// 插入单聊消息到本地 + Future insertSingleMessageToLocalStorage({ String? receiverID, String? senderID, Message? message, String? operationID, }) => - _channel.invokeMethod( - 'insertSingleMessageToLocalStorage', - _buildParam({ - "message": message?.toJson(), - "receiverID": receiverID, - "senderID": senderID, - "operationID": Utils.checkOperationID(operationID), - })); + _channel + .invokeMethod( + 'insertSingleMessageToLocalStorage', + _buildParam({ + "message": message?.toJson(), + "receiverID": receiverID, + "senderID": senderID, + "operationID": Utils.checkOperationID(operationID), + })) + .then((value) => Utils.toObj(value, (map) => Message.fromJson(map))); - /// - Future insertGroupMessageToLocalStorage({ + /// 插入群聊消息到本地 + Future insertGroupMessageToLocalStorage({ String? groupID, String? senderID, Message? message, String? operationID, }) => - _channel.invokeMethod( - 'insertGroupMessageToLocalStorage', - _buildParam({ - "message": message?.toJson(), - "groupID": groupID, - "senderID": senderID, - "operationID": Utils.checkOperationID(operationID), - })); - - /// Query the message according to the message id - // Future findMessages({required List messageIDList}) => - // _channel.invokeMethod( - // 'findMessages', - // _buildParam({ - // "messageIDList": messageIDList, - // })); + _channel + .invokeMethod( + 'insertGroupMessageToLocalStorage', + _buildParam({ + "message": message?.toJson(), + "groupID": groupID, + "senderID": senderID, + "operationID": Utils.checkOperationID(operationID), + })) + .then((value) => Utils.toObj(value, (map) => Message.fromJson(map))); /// Mark c2c message as read /// 标记c2c消息已读 @@ -182,6 +180,7 @@ class MessageManager { /// Typing /// 正在输入提示 + /// [msgTip] 自定义内容 Future typingStatusUpdate({ required String userID, String? msgTip, @@ -212,6 +211,10 @@ class MessageManager { /// Create @ message /// 创建@消息 + /// [text] 输入内容 + /// [atUserIDList] 被@到的userID集合 + /// [atUserInfoList] userID跟nickname映射关系,用在界面显示时将id替换为nickname + /// [quoteMessage] 引用消息(被回复的消息) Future createTextAtMessage({ required String text, required List atUserIDList, @@ -250,6 +253,7 @@ class MessageManager { /// Create picture message /// 创建图片消息 + /// [imagePath] 路径 Future createImageMessageFromFullPath({ required String imagePath, String? operationID, @@ -273,7 +277,7 @@ class MessageManager { }) => _channel .invokeMethod( - 'createSoundMessage', + 'createSoundMessage', _buildParam({ 'soundPath': soundPath, "duration": duration, @@ -284,6 +288,8 @@ class MessageManager { /// Create sound message /// 创建语音消息 + /// [soundPath] 路径 + /// [duration] 时长s Future createSoundMessageFromFullPath({ required String soundPath, required int duration, @@ -323,6 +329,10 @@ class MessageManager { /// Create video message /// 创建视频消息 + /// [videoPath] 路径 + /// [videoType] 视频mime类型 + /// [duration] 时长s + /// [snapshotPath] 默认站位图路径 Future createVideoMessageFromFullPath({ required String videoPath, required String videoType, @@ -362,6 +372,8 @@ class MessageManager { /// Create file message /// 创建文件消息 + /// [filePath] 路径 + /// [fileName] 文件名 Future createFileMessageFromFullPath({ required String filePath, required String fileName, @@ -379,6 +391,9 @@ class MessageManager { /// Create merger message /// 创建合并消息 + /// [messageList] 被选中的消息 + /// [title] 摘要标题 + /// [summaryList] 摘要内容 Future createMergerMessage({ required List messageList, required String title, @@ -398,6 +413,7 @@ class MessageManager { /// Create forward message /// 创建转发消息 + /// [message] 被转发的消息 Future createForwardMessage({ required Message message, String? operationID, @@ -414,6 +430,9 @@ class MessageManager { /// Create location message /// 创建位置消息 + /// [latitude] 纬度 + /// [longitude] 经度 + /// [description] 自定义描述信息 Future createLocationMessage({ required double latitude, required double longitude, @@ -452,6 +471,8 @@ class MessageManager { /// Create quote message /// 创建引用消息 + /// [text] 回复的内容 + /// [quoteMsg] 被回复的消息 Future createQuoteMessage({ required String text, required Message quoteMsg, @@ -483,9 +504,11 @@ class MessageManager { .then((value) => Utils.toObj(value, (map) => Message.fromJson(map))); /// Create custom emoji message + /// [index] The position of the emoji, such as the position emoji + /// [data] Other data, such as url expressions /// 创建自定义表情消息 - /// [index] The position of the emoji, such as the position emoji(表情的位置,如位置表情) - /// [data] Other data, such as url expressions(其他数据,如url表情) + /// [index] 位置表情,根据index匹配 + /// [data] url表情,直接使用url显示 Future createFaceMessage({ int index = -1, String? data, @@ -571,7 +594,7 @@ class MessageManager { Utils.toObj(value, (map) => SearchResult.fromJson(map))); /// Delete message from local and service - /// 删除消息 + /// 删除本地跟服务器的指定的消息 Future deleteMessageFromLocalAndSvr({ required Message message, String? operationID, @@ -584,7 +607,7 @@ class MessageManager { }))); /// Delete all message from local - /// 删除所有消息 + /// 删除本地所有聊天记录 Future deleteAllMsgFromLocal({ String? operationID, }) => @@ -595,7 +618,7 @@ class MessageManager { })); /// Delete all message from service - /// 删除所有消息 + /// 删除本地跟服务器所有聊天记录 Future deleteAllMsgFromLocalAndSvr({ String? operationID, }) => @@ -607,6 +630,8 @@ class MessageManager { /// Mark conversation message as read /// 标记消息已读 + /// [conversationID] 会话ID + /// [messageIDList] 被标记的消息clientMsgID Future markMessageAsReadByConID({ required String conversationID, required List messageIDList, @@ -621,7 +646,7 @@ class MessageManager { })); /// Clear all c2c history message - /// 清空单聊消息记录 + /// 删除本地跟服务器的单聊聊天记录 Future clearC2CHistoryMessageFromLocalAndSvr({ required String uid, String? operationID, @@ -634,7 +659,7 @@ class MessageManager { })); /// Clear all group history - /// 清空组消息记录 + /// 删除本地跟服务器的群聊天记录 Future clearGroupHistoryMessageFromLocalAndSvr({ required String gid, String? operationID, @@ -647,10 +672,12 @@ class MessageManager { })); /// Find all history message - /// 获取聊天记录 - /// [userID]接收消息的用户id - /// [conversationID] 会话id - /// [groupID]接收消息的组id + /// 获取聊天记录(以startMsg为节点,新收到的聊天记录),用在全局搜索定位某一条消息,然后此条消息后新增的消息 + /// [userID] 接收消息的用户id + /// [conversationID] 会话id,查询通知时可用 + /// [groupID] 接收消息的组id + /// [startMsg] 从这条消息开始查询[count]条,获取的列表index==length-1为最新消息,所以获取下一页历史记录startMsg=list.last + /// [count] 一次拉取的总数 Future> getHistoryMessageListReverse({ String? userID, String? groupID, diff --git a/lib/src/manager/im_organization_manager.dart b/lib/src/manager/im_organization_manager.dart new file mode 100644 index 0000000..f7fbf39 --- /dev/null +++ b/lib/src/manager/im_organization_manager.dart @@ -0,0 +1,98 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_openim_sdk/flutter_openim_sdk.dart'; + +class OrganizationManager { + MethodChannel _channel; + late OnOrganizationListener listener; + + OrganizationManager(this._channel); + + /// Observe organization info changes + /// 组织架构发生变化回调 + Future setOrganizationListener(OnOrganizationListener listener) { + this.listener = listener; + return _channel.invokeMethod('setOrganizationListener', _buildParam({})); + } + + /// Query sub department + /// 获取子部门列表 + Future> getSubDept({ + required String departmentID, + int offset = 0, + int count = 40, + String? operationID, + }) => + _channel + .invokeMethod( + 'getSubDepartment', + _buildParam({ + 'departmentID': departmentID, + 'offset': offset, + 'count': count, + 'operationID': Utils.checkOperationID(operationID), + })) + .then((value) => Utils.toList(value, (v) => DeptInfo.fromJson(v))); + + /// Get member under a department + /// 获取部门下的成员列表 + Future> getDeptMember({ + required String departmentID, + int offset = 0, + int count = 40, + String? operationID, + }) => + _channel + .invokeMethod( + 'getDepartmentMember', + _buildParam({ + 'departmentID': departmentID, + 'offset': offset, + 'count': count, + 'operationID': Utils.checkOperationID(operationID), + })) + .then((value) => + Utils.toList(value, (v) => DeptMemberInfo.fromJson(v))); + + /// Get member's department + /// 获取成员所在的部门 + Future> getUserInDept({ + required String userID, + String? operationID, + }) => + _channel + .invokeMethod( + 'getUserInDepartment', + _buildParam({ + 'userID': userID, + 'operationID': Utils.checkOperationID(operationID), + })) + .then((value) => Utils.toList(value, (v) => UserInDept.fromJson(v))); + + /// Get the sub-departments and employees under the department + /// 获取部门下的子部门跟员工 + Future> getDeptMemberAndSubDept({ + required String departmentID, + int departmentOffset = 0, + int departmentCount = 40, + int memberOffset = 0, + int memberCount = 40, + String? operationID, + }) => + _channel + .invokeMethod( + 'getDepartmentMemberAndSubDepartment', + _buildParam({ + 'departmentID': departmentID, + 'departmentOffset': departmentOffset, + 'departmentCount': departmentCount, + 'memberOffset': memberOffset, + 'memberCount': memberCount, + 'operationID': Utils.checkOperationID(operationID), + })) + .then((value) => Utils.toList(value, (v) => UserInDept.fromJson(v))); + + static Map _buildParam(Map param) { + param["ManagerName"] = "organizationManager"; + return param; + } +} diff --git a/lib/src/models/organization_info.dart b/lib/src/models/organization_info.dart new file mode 100644 index 0000000..1172d9b --- /dev/null +++ b/lib/src/models/organization_info.dart @@ -0,0 +1,198 @@ +class DeptInfo { + String? departmentID; + String? faceURL; + String? name; + String? parentID; + int? order; + int? departmentType; + int? createTime; + int? subDepartmentNum; + int? memberNum; + String? ex; + String? attachedInfo; + + DeptInfo( + {this.departmentID, + this.faceURL, + this.name, + this.parentID, + this.order, + this.departmentType, + this.createTime, + this.subDepartmentNum, + this.memberNum, + this.ex, + this.attachedInfo}); + + DeptInfo.fromJson(Map json) { + departmentID = json['departmentID']; + faceURL = json['faceURL']; + name = json['name']; + parentID = json['parentID']; + order = json['order']; + departmentType = json['departmentType']; + createTime = json['createTime ']; + subDepartmentNum = json['subDepartmentNum ']; + memberNum = json['memberNum ']; + ex = json['ex ']; + attachedInfo = json['attachedInfo ']; + } + + Map toJson() { + final data = Map(); + data['departmentID'] = this.departmentID; + data['faceURL'] = this.faceURL; + data['name'] = this.name; + data['parentID'] = this.parentID; + data['order'] = this.order; + data['departmentType'] = this.departmentType; + data['createTime '] = this.createTime; + data['subDepartmentNum '] = this.subDepartmentNum; + data['memberNum '] = this.memberNum; + data['ex '] = this.ex; + data['attachedInfo '] = this.attachedInfo; + return data; + } +} + +class DeptMemberInfo { + String? userID; + String? nickname; + String? englishName; + String? faceURL; + int? gender; + String? mobile; + String? telephone; + int? birth; + String? email; + String? departmentID; + int? order; + String? position; + int? leader; + int? status; + int? createTime; + String? ex; + String? attachedInfo; + + DeptMemberInfo( + {this.userID, + this.nickname, + this.englishName, + this.faceURL, + this.gender, + this.mobile, + this.telephone, + this.birth, + this.email, + this.departmentID, + this.order, + this.position, + this.leader, + this.status, + this.createTime, + this.ex, + this.attachedInfo}); + + DeptMemberInfo.fromJson(Map json) { + userID = json['userID']; + nickname = json['nickname']; + englishName = json['englishName']; + faceURL = json['faceURL ']; + gender = json['gender ']; + mobile = json['mobile ']; + telephone = json['telephone ']; + birth = json['birth ']; + email = json['email ']; + departmentID = json['departmentID ']; + order = json['order ']; + position = json['position ']; + leader = json['leader ']; + status = json['status ']; + createTime = json['createTime ']; + ex = json['ex ']; + attachedInfo = json['attachedInfo ']; + } + + Map toJson() { + final Map data = new Map(); + data['userID'] = this.userID; + data['nickname'] = this.nickname; + data['englishName'] = this.englishName; + data['faceURL '] = this.faceURL; + data['gender '] = this.gender; + data['mobile '] = this.mobile; + data['telephone '] = this.telephone; + data['birth '] = this.birth; + data['email '] = this.email; + data['departmentID '] = this.departmentID; + data['order '] = this.order; + data['position '] = this.position; + data['leader '] = this.leader; + data['status '] = this.status; + data['createTime '] = this.createTime; + data['ex '] = this.ex; + data['attachedInfo '] = this.attachedInfo; + return data; + } +} + +class UserInDept { + DeptInfo? department; + DeptMemberInfo? member; + + UserInDept({this.department, this.member}); + + UserInDept.fromJson(Map json) { + department = json['department'] != null + ? DeptInfo.fromJson(json['department']) + : null; + member = + json['member'] != null ? DeptMemberInfo.fromJson(json['member']) : null; + } + + Map toJson() { + final data = Map(); + if (this.department != null) { + data['department'] = this.department!.toJson(); + } + if (this.member != null) { + data['member'] = this.member!.toJson(); + } + return data; + } +} + +class DeptMemberAndSubDept { + List? departmentList; + List? departmentMemberList; + + DeptMemberAndSubDept({this.departmentList, this.departmentMemberList}); + + DeptMemberAndSubDept.fromJson(Map json) { + if (json['departmentList'] != null) { + departmentList = []; + json['departmentList'].forEach((v) { + departmentList!.add(DeptInfo.fromJson(v)); + }); + } + if (json['departmentMemberList'] != null) { + departmentMemberList = []; + json['departmentMemberList'].forEach((v) { + departmentMemberList!.add(DeptMemberInfo.fromJson(v)); + }); + } + } + + Map toJson() { + final data = Map(); + if (this.departmentList != null) { + data['departmentList'] = + this.departmentList!.map((v) => v.toJson()).toList(); + } + if (this.departmentMemberList != null) { + data['departmentMemberList'] = + this.departmentMemberList!.map((v) => v.toJson()).toList(); + } + return data; + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 8ef9c08..46505b5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_openim_sdk description: An instant messaging plug-in that supports Android and IOS. And the server is also all open source. -version: 2.0.8 +version: 2.0.9 homepage: https://www.rentsoft.cn repository: https://github.com/OpenIMSDK/Open-IM-SDK-Flutter