From d61370352407bcc2ec7433a784b6a066c1403cd8 Mon Sep 17 00:00:00 2001 From: hrxiang Date: Mon, 5 Jul 2021 11:08:45 +0800 Subject: [PATCH] fix bug --- lib/src/enum/listener_type.dart | 33 ++ lib/src/enum/message_type.dart | 18 + lib/src/listener/advanced_msg_listener.dart | 15 + lib/src/listener/conversation_listener.dart | 15 + lib/src/listener/friendship_listener.dart | 19 + lib/src/listener/init_sdk_listener.dart | 21 ++ .../listener/msg_send_progress_listener.dart | 3 + lib/src/manager/im_conversation_manager.dart | 94 +++++ lib/src/manager/im_friendship_manager.dart | 112 ++++++ lib/src/manager/im_group_manager.dart | 7 + lib/src/manager/im_manager.dart | 317 ++++++++++++++++ lib/src/manager/im_message_manager.dart | 213 +++++++++++ lib/src/manager/im_offline_push_manager.dart | 7 + lib/src/manager/im_signaling_manager.dart | 7 + lib/src/models/conversation_info.dart | 77 ++++ lib/src/models/message.dart | 337 ++++++++++++++++++ lib/src/models/user_info.dart | 65 ++++ 17 files changed, 1360 insertions(+) create mode 100644 lib/src/enum/listener_type.dart create mode 100644 lib/src/enum/message_type.dart create mode 100644 lib/src/listener/advanced_msg_listener.dart create mode 100644 lib/src/listener/conversation_listener.dart create mode 100644 lib/src/listener/friendship_listener.dart create mode 100644 lib/src/listener/init_sdk_listener.dart create mode 100644 lib/src/listener/msg_send_progress_listener.dart create mode 100644 lib/src/manager/im_conversation_manager.dart create mode 100644 lib/src/manager/im_friendship_manager.dart create mode 100644 lib/src/manager/im_group_manager.dart create mode 100644 lib/src/manager/im_manager.dart create mode 100644 lib/src/manager/im_message_manager.dart create mode 100644 lib/src/manager/im_offline_push_manager.dart create mode 100644 lib/src/manager/im_signaling_manager.dart create mode 100644 lib/src/models/conversation_info.dart create mode 100644 lib/src/models/message.dart create mode 100644 lib/src/models/user_info.dart diff --git a/lib/src/enum/listener_type.dart b/lib/src/enum/listener_type.dart new file mode 100644 index 0000000..a184055 --- /dev/null +++ b/lib/src/enum/listener_type.dart @@ -0,0 +1,33 @@ + +class ListenerType { + /// + /// + static const String simpleMsgListener = 'simpleMsgListener'; + + /// + /// + static const String initSDKListener = 'initSDKListener'; + + /// + /// + static const String groupListener = 'groupListener'; + + /// + /// + static const String advancedMsgListener = 'advancedMsgListener'; + + /// + /// + static const String conversationListener = 'conversationListener'; + + /// + /// + static const String friendListener = 'friendListener'; + + /// + /// + static const String signalingListener = 'signalingListener'; + + /// + static const String msgSendProgressListener = "msgSendProgressListener"; +} diff --git a/lib/src/enum/message_type.dart b/lib/src/enum/message_type.dart new file mode 100644 index 0000000..6a10a75 --- /dev/null +++ b/lib/src/enum/message_type.dart @@ -0,0 +1,18 @@ +class MessageType { + /// + static const text = 101; + + /// + static const picture = 102; + + /// + static const voice = 103; + + /// + static const video = 104; + + /// + static const file = 105; + + static const accept_friend = 201; +} diff --git a/lib/src/listener/advanced_msg_listener.dart b/lib/src/listener/advanced_msg_listener.dart new file mode 100644 index 0000000..796e7e1 --- /dev/null +++ b/lib/src/listener/advanced_msg_listener.dart @@ -0,0 +1,15 @@ +import 'package:flutter_openim_sdk/flutter_openim_sdk.dart'; + + +class AdvancedMsgListener { + /// listener uniquely identifies + final String id; + + AdvancedMsgListener({required this.id}); + + void onRecvNewMessage(Message msg) {} + + void onRecvC2CReadReceipt(Message msg) {} + + void onRecvMessageRevoked(Message msg) {} +} diff --git a/lib/src/listener/conversation_listener.dart b/lib/src/listener/conversation_listener.dart new file mode 100644 index 0000000..42b399e --- /dev/null +++ b/lib/src/listener/conversation_listener.dart @@ -0,0 +1,15 @@ +import 'package:flutter_openim_sdk/flutter_openim_sdk.dart'; + +class ConversationListener { + void onConversationChanged(List list) {} + + void onNewConversation(List list) {} + + void onSyncServerFailed() {} + + void onSyncServerFinish() {} + + void onSyncServerStart() {} + + void onTotalUnreadMessageCountChanged(int i) {} +} diff --git a/lib/src/listener/friendship_listener.dart b/lib/src/listener/friendship_listener.dart new file mode 100644 index 0000000..3baad76 --- /dev/null +++ b/lib/src/listener/friendship_listener.dart @@ -0,0 +1,19 @@ +class FriendshipListener { + void onBlackListAdd(dynamic u) {} + + void onBlackListDeleted(dynamic u) {} + + void onFriendApplicationListAccept(dynamic u) {} + + void onFriendApplicationListAdded(dynamic u) {} + + void onFriendApplicationListDeleted(dynamic u) {} + + void onFriendApplicationListReject(dynamic u) {} + + void onFriendInfoChanged(dynamic u) {} + + void onFriendListAdded(dynamic u) {} + + void onFriendListDeleted(dynamic u) {} +} diff --git a/lib/src/listener/init_sdk_listener.dart b/lib/src/listener/init_sdk_listener.dart new file mode 100644 index 0000000..3711817 --- /dev/null +++ b/lib/src/listener/init_sdk_listener.dart @@ -0,0 +1,21 @@ +import 'package:flutter_openim_sdk/flutter_openim_sdk.dart'; + +class InitSDKListener { + /// SDK 正在连接到服务器 + void onConnecting() {} + + /// SDK 已经成功连接到服务器 + void onConnectSuccess() {} + + /// SDK 连接服务器失败 + void onConnectFailed(int? int, String? errorMsg) {} + + /// 当前用户被踢下线,此时可以 UI 提示用户,并再次调用 IMManager 的 login() 函数重新登录。 + void onKickedOffline() {} + + /// 在线时票据过期:此时您需要生成新的 userSig 并再次调用 IMManager 的 login() 函数重新登录 + void onUserSigExpired() {} + + /// 登录用户的资料发生了更新 + void onSelfInfoUpdated(UserInfo info) {} +} diff --git a/lib/src/listener/msg_send_progress_listener.dart b/lib/src/listener/msg_send_progress_listener.dart new file mode 100644 index 0000000..10fd4e4 --- /dev/null +++ b/lib/src/listener/msg_send_progress_listener.dart @@ -0,0 +1,3 @@ +class MsgSendProgressListener { + void onProgress(String msgID, int progress) {} +} diff --git a/lib/src/manager/im_conversation_manager.dart b/lib/src/manager/im_conversation_manager.dart new file mode 100644 index 0000000..2354abb --- /dev/null +++ b/lib/src/manager/im_conversation_manager.dart @@ -0,0 +1,94 @@ +import 'dart:convert'; + +import 'package:flutter/services.dart'; +import 'package:flutter_openim_sdk/flutter_openim_sdk.dart'; + +class ConversationManager { + MethodChannel _channel; + late ConversationListener conversationListener; + + ConversationManager(this._channel); + + void setConversationListener(ConversationListener listener) { + this.conversationListener = listener; + _channel.invokeMethod('setConversationListener', _buildParam({})); + } + + Future> getAllConversationList() { + return _channel + .invokeMethod('getAllConversationList', _buildParam({})) + .then((value) => _toList(value)); + } + + /// sourceID 若为单聊则为userID,若为群聊则为groupID + /// sessionType 若为单聊则为1,若为群聊则为2 + Future getSingleConversation( + {required String sourceID, required String sessionType}) { + return _channel + .invokeMethod('getOneConversation', + _buildParam({"sourceID": sourceID, "sessionType": sessionType})) + .then((value) => _toObj(value)); + } + + /// ["single_1234","group_3434"] + Future> getMultipleConversation( + {required List conversationIDList}) { + return _channel + .invokeMethod('getMultipleConversation', + _buildParam({"conversationIDList": conversationIDList})) + .then((value) => _toList(value)); + } + + void deleteConversation({required String conversationID}) { + _channel + .invokeMethod('deleteConversation', + _buildParam({"conversationID": conversationID})) + .then((value) => _printValue(value)); + } + + void setConversationDraft( + {required String conversationID, required String draftText}) { + _channel + .invokeMethod( + 'setConversationDraft', + _buildParam( + {"conversationID": conversationID, "draftText": draftText})) + .then((value) => _printValue(value)); + } + + void pinConversation( + {required String conversationID, required bool isPinned}) { + _channel + .invokeMethod( + 'pinConversation', + _buildParam( + {"conversationID": conversationID, "isPinned": isPinned})) + .then((value) => _printValue(value)); + } + + Future getTotalUnreadMsgCount() { + return _channel.invokeMethod('getTotalUnreadMsgCount', _buildParam({})); + } + + static Map _buildParam(Map param) { + param["ManagerName"] = "conversationManager"; + return param; + } + + static List _toList(String? value) { + var list = _formatJson(value); + if (null == list) return []; + return (list as List).map((e) => ConversationInfo.fromJson(e)).toList(); + } + + static ConversationInfo _toObj(String value) => + ConversationInfo.fromJson(_formatJson(value)); + + static dynamic _formatJson(value) { + return jsonDecode(_printValue(value)); + } + + static String _printValue(value) { + return value; + } +} diff --git a/lib/src/manager/im_friendship_manager.dart b/lib/src/manager/im_friendship_manager.dart new file mode 100644 index 0000000..6f61d2c --- /dev/null +++ b/lib/src/manager/im_friendship_manager.dart @@ -0,0 +1,112 @@ +import 'dart:convert'; + +import 'package:flutter/services.dart'; +import 'package:flutter_openim_sdk/flutter_openim_sdk.dart'; + +class FriendshipManager { + MethodChannel _channel; + late FriendshipListener friendshipListener; + + FriendshipManager(this._channel); + + void setFriendshipListener(FriendshipListener listener) { + this.friendshipListener = listener; + _channel.invokeMethod('setFriendListener', _buildParam({})); + } + + Future> getFriendsInfo({required List uidList}) { + return _channel + .invokeMethod('getFriendsInfo', _buildParam({"uidList": uidList})) + .then((value) => _toList(value)); + } + + Future addFriend({required String uid, required String reason}) { + return _channel.invokeMethod( + 'addFriend', _buildParam({"uid": uid, "reqMessage": reason})); + } + + Future> getFriendApplicationList() { + return _channel + .invokeMethod('getFriendApplicationList', _buildParam({})) + .then((value) => _toList(value)); + } + + Future> getFriendList() { + return _channel + .invokeMethod('getFriendList', _buildParam({})) + .then((value) => _toList(value)); + } + + Future setFriendInfo({required UserInfo info}) { + return _channel.invokeMethod('setFriendInfo', _buildParam(info.toJson())); + } + + Future addToBlackList({required String uid}) { + return _channel.invokeMethod('addToBlackList', _buildParam({"uid": uid})); + } + + Future> getBlackList() { + return _channel + .invokeMethod('getBlackList', _buildParam({})) + .then((value) => _toList(value)); + } + + Future deleteFromBlackList({required String uid}) { + return _channel.invokeMethod( + 'deleteFromBlackList', _buildParam({"uid": uid})); + } + + Future> checkFriend(List uidList) { + return _channel + .invokeMethod('checkFriend', _buildParam({'uidList': uidList})) + .then((value) => _toList(value)); + } + + Future deleteFromFriendList({required String uid}) { + return _channel.invokeMethod( + 'deleteFromFriendList', _buildParam({"uid": uid})); + } + + Future acceptFriendApplication({required String uid}) { + return _channel.invokeMethod( + 'acceptFriendApplication', _buildParam({"uid": uid})); + } + + Future refuseFriendApplication({required String uid}) { + return _channel.invokeMethod( + 'refuseFriendApplication', _buildParam({"uid": uid})); + } + + Future forceSyncFriendApplication() { + return _channel.invokeMethod('forceSyncFriendApplication', _buildParam({})); + } + + Future forceSyncFriend() { + return _channel.invokeMethod('forceSyncFriend', _buildParam({})); + } + + Future forceSyncBlackList() { + return _channel.invokeMethod('forceSyncBlackList', _buildParam({})); + } + + static Map _buildParam(Map param) { + param["ManagerName"] = "friendshipManager"; + return param; + } + + static List _toList(String? value) { + var list = _formatJson(value); + if (null == list) return []; + return (list as List).map((e) => UserInfo.fromJson(e)).toList(); + } + + static UserInfo _toObj(String value) => UserInfo.fromJson(_formatJson(value)); + + static dynamic _formatJson(value) { + return jsonDecode(_printValue(value)); + } + + static String _printValue(value) { + return value; + } +} diff --git a/lib/src/manager/im_group_manager.dart b/lib/src/manager/im_group_manager.dart new file mode 100644 index 0000000..c077212 --- /dev/null +++ b/lib/src/manager/im_group_manager.dart @@ -0,0 +1,7 @@ +import 'package:flutter/services.dart'; + +class GroupManager{ + MethodChannel _channel; + + GroupManager(this._channel); +} \ No newline at end of file diff --git a/lib/src/manager/im_manager.dart b/lib/src/manager/im_manager.dart new file mode 100644 index 0000000..24e6056 --- /dev/null +++ b/lib/src/manager/im_manager.dart @@ -0,0 +1,317 @@ +import 'dart:convert'; + +import 'package:flutter/services.dart'; +import 'package:flutter_openim_sdk/flutter_openim_sdk.dart'; + +class IMManager { + MethodChannel _channel; + late ConversationManager conversationManager; + late FriendshipManager friendshipManager; + late MessageManager messageManager; + late GroupManager groupManager; + late OfflinePushManager offlinePushManager; + late SignalingManager signalingManager; + late InitSDKListener _initSDKListener; + + IMManager(this._channel) { + conversationManager = ConversationManager(_channel); + friendshipManager = FriendshipManager(_channel); + messageManager = MessageManager(_channel); + groupManager = GroupManager(_channel); + offlinePushManager = OfflinePushManager(_channel); + signalingManager = SignalingManager(_channel); + addNativeCallback(_channel); + } + + void addNativeCallback(MethodChannel _channel) { + _channel.setMethodCallHandler((call) { + try { + if (call.method == ListenerType.initSDKListener) { + String type = call.arguments['type']; + dynamic data = call.arguments['data']; + switch (type) { + case 'onSelfInfoUpdated': + var u = UserInfo.fromJson(_formatJson(data)); + _initSDKListener.onSelfInfoUpdated(u); + break; + case 'onConnectFailed': + int? errCode = call.arguments['errCode']; + String? errMsg = call.arguments['errMsg']; + _initSDKListener.onConnectFailed(errCode, errMsg); + break; + case 'onConnecting': + _initSDKListener.onConnecting(); + break; + case 'onConnectSuccess': + _initSDKListener.onConnectSuccess(); + break; + case 'onKickedOffline': + _initSDKListener.onKickedOffline(); + break; + case 'onUserSigExpired': + _initSDKListener.onUserSigExpired(); + break; + } + } else if (call.method == ListenerType.groupListener) { + var args = call.arguments; + String type = args['type']; + Map params = args['data'] == null + ? new Map() + : new Map.from(args['data']); + + String groupID = params['groupID'] == null ? '' : params['groupID']; + String opReason = + params['opReason'] == null ? '' : params['opReason']; + bool isAgreeJoin = + params['isAgreeJoin'] == null ? false : params['isAgreeJoin']; + String customData = + params['customData'] == null ? '' : params['customData']; + + Map groupAttributeMap = + params['groupAttributeMap'] == null + ? new Map() + : new Map.from(params['groupAttributeMap']); + + List> memberListMap = + params['memberList'] == null + ? List.empty(growable: true) + : List.from(params['memberList']); + + List> groupMemberChangeInfoListMap = + params['groupMemberChangeInfoList'] == null + ? List.empty(growable: true) + : List.from(params['groupMemberChangeInfoList']); + + List> groupChangeInfoListMap = + params['groupChangeInfoList'] == null + ? List.empty(growable: true) + : List.from(params['groupChangeInfoList']); + + switch (type) { + case 'onMemberEnter': + break; + case 'onMemberLeave': + break; + case 'onMemberInvited': + break; + case 'onMemberKicked': + break; + case 'onMemberInfoChanged': + break; + case 'onGroupCreated': + break; + case 'onGroupDismissed': + break; + case 'onGroupRecycled': + break; + case 'onGroupInfoChanged': + break; + case 'onReceiveJoinApplication': + break; + case 'onApplicationProcessed': + break; + case 'onGrantAdministrator': + break; + case 'onRevokeAdministrator': + break; + case 'onQuitFromGroup': + break; + case 'onReceiveRESTCustomData': + break; + case 'onGroupAttributeChanged': + break; + } + } else if (call.method == ListenerType.advancedMsgListener) { + var type = call.arguments['type']; + var id = call.arguments['data']['id']; + var msg = + Message.fromJson(_formatJson(call.arguments['data']['message'])); + switch (type) { + case 'onRecvNewMessage': + for (var listener in messageManager.advancedMsgListeners) { + if (listener.id == id) { + listener.onRecvNewMessage(msg); + } + } + break; + case 'onRecvMessageRevoked': + for (var listener in messageManager.advancedMsgListeners) { + if (listener.id == id) { + listener.onRecvMessageRevoked(msg); + } + } + break; + case 'onRecvC2CReadReceipt': + for (var listener in messageManager.advancedMsgListeners) { + if (listener.id == id) { + listener.onRecvC2CReadReceipt(msg); + } + } + break; + } + } else if (call.method == ListenerType.msgSendProgressListener) { + String type = call.arguments['type']; + dynamic data = call.arguments['data']; + String msgID = data['clientMsgID'] ?? ''; + int progress = data['progress'] ?? 100; + switch (type) { + case 'onProgress': + messageManager.msgSendProgressListener?.onProgress( + msgID, + progress, + ); + break; + } + } else if (call.method == ListenerType.conversationListener) { + String type = call.arguments['type']; + dynamic data = call.arguments['data']; + switch (type) { + case 'onSyncServerStart': + conversationManager.conversationListener.onSyncServerStart(); + break; + case 'onSyncServerFinish': + conversationManager.conversationListener.onSyncServerFinish(); + break; + + case 'onSyncServerFailed': + conversationManager.conversationListener.onSyncServerFailed(); + break; + case 'onNewConversation': + List list = List.empty(growable: true); + if (null != data) { + list = (_formatJson(data) as List) + .map((e) => ConversationInfo.fromJson(e)) + .toList(); + } + conversationManager.conversationListener.onNewConversation(list); + break; + case 'onConversationChanged': + List list = List.empty(growable: true); + if (null != data) { + list = (_formatJson(data) as List) + .map((e) => ConversationInfo.fromJson(e)) + .toList(); + } + conversationManager.conversationListener + .onConversationChanged(list); + break; + case 'onTotalUnreadMessageCountChanged': + conversationManager.conversationListener + .onTotalUnreadMessageCountChanged(data ?? 0); + break; + } + } else if (call.method == ListenerType.friendListener) { + String type = call.arguments['type']; + dynamic data = call.arguments['data']; + switch (type) { + case 'onBlackListAdd': + friendshipManager.friendshipListener.onBlackListAdd(data); + break; + case 'onBlackListDeleted': + friendshipManager.friendshipListener.onBlackListDeleted(data); + break; + case 'onFriendApplicationListAccept': + friendshipManager.friendshipListener + .onFriendApplicationListAccept(data); + break; + case 'onFriendApplicationListAdded': + friendshipManager.friendshipListener + .onFriendApplicationListAdded(data); + break; + case 'onFriendApplicationListDeleted': + friendshipManager.friendshipListener + .onFriendApplicationListDeleted(data); + break; + case 'onFriendApplicationListReject': + friendshipManager.friendshipListener + .onFriendApplicationListReject(data); + break; + case 'onFriendInfoChanged': + friendshipManager.friendshipListener.onFriendInfoChanged(data); + break; + case 'onFriendListAdded': + friendshipManager.friendshipListener.onFriendListAdded(data); + break; + case 'onFriendListDeleted': + friendshipManager.friendshipListener.onFriendListDeleted(data); + break; + } + } + } catch (err) { + print( + "回调失败了,数据类型异常。$err ${call.method} ${call.arguments['type']} ${call.arguments['data']}"); + } + return Future.value(null); + }); + } + + Future initSDK({ + required int platform, + required String ipApi, + required String ipWs, + required String dbPath, + required InitSDKListener listener, + }) { + _initSDKListener = listener; + return _channel.invokeMethod( + 'initSDK', + _buildParam( + {"platform": platform, "ipApi": ipApi, "ipWs": ipWs, "dbDir": dbPath}, + ), + ); + } + + Future unInitSDK() { + return _channel.invokeMethod('unInitSDK', _buildParam({})); + } + + Future login({required String uid, required String token}) { + return _channel.invokeMethod( + 'login', + _buildParam({'uid': uid, 'token': token}), + ); + } + + Future logout() { + return _channel.invokeMethod('logout', _buildParam({})); + } + + Future getLoginStatus() { + return _channel.invokeMethod('getLoginStatus', _buildParam({})); + } + + Future getLoginUid() { + return _channel.invokeMethod('getLoginUid', _buildParam({})); + } + + Future setSelfInfo(UserInfo info) { + return _channel.invokeMethod('setSelfInfo', _buildParam(info.toJson())); + // .then((value) => UserInfo.fromJson(value)); + } + + Future> getUsersInfo(List uidList) { + return _channel + .invokeMethod('getUsersInfo', _buildParam({'uidList': uidList})) + .then((value) => _toList(value)); + } + + Future forceSyncLoginUerInfo(List uidList) { + return _channel.invokeMethod('forceSyncLoginUerInfo', _buildParam({})); + } + + static Map _buildParam(Map param) { + param["ManagerName"] = "imManager"; + return param; + } + + static List _toList(String value) => + (_formatJson(value) as List).map((e) => UserInfo.fromJson(e)).toList(); + + static dynamic _formatJson(value) { + return jsonDecode(_printValue(value)); + } + + static String _printValue(value) { + return value; + } +} diff --git a/lib/src/manager/im_message_manager.dart b/lib/src/manager/im_message_manager.dart new file mode 100644 index 0000000..72bab02 --- /dev/null +++ b/lib/src/manager/im_message_manager.dart @@ -0,0 +1,213 @@ +import 'dart:convert'; + +import 'package:flutter/services.dart'; +import 'package:flutter_openim_sdk/flutter_openim_sdk.dart'; + +class MessageManager { + MethodChannel _channel; + List advancedMsgListeners = List.empty(growable: true); + MsgSendProgressListener? msgSendProgressListener; + + MessageManager(this._channel); + + void addAdvancedMsgListener(AdvancedMsgListener listener) { + advancedMsgListeners.add(listener); + _channel.invokeMethod( + 'addAdvancedMsgListener', _buildParam({'id': listener.id})); + } + + void removeAdvancedMsgListener(AdvancedMsgListener listener) { + advancedMsgListeners.remove(listener); + _channel.invokeMethod( + 'removeAdvancedMsgListener', _buildParam({'id': listener.id})); + } + + void setMsgSendProgressListener(MsgSendProgressListener listener) { + msgSendProgressListener = listener; + } + + /*Future */ + Future sendMessage({ + required Message message, + String? receiver, + String? groupID, + required bool onlineUserOnly, + }) { + return _channel.invokeMethod( + 'sendMessage', + _buildParam({ + 'message': message.toJson(), + 'receiver': receiver ?? '', + 'groupID': groupID ?? '', + 'onlineUserOnly': onlineUserOnly, + })) + /*.then((value) => _toObj(value))*/; + } + + Future> getHistoryMessageList({ + String? userID, + Message? startMsg, + String? groupID, + int? count, + }) { + return _channel + .invokeMethod( + 'getHistoryMessageList', + _buildParam({ + 'userID': userID ?? '', + 'startMsg': startMsg?.toJson() /*?? {}*/, + 'groupID': groupID ?? '', + 'count': count ?? 10, + })) + .then((value) => _toList(value)); + } + + void revokeMessage({required Message message}) { + _channel.invokeMethod('revokeMessage', _buildParam(message.toJson())); + } + + Future deleteMessageFromLocalStorage({required Message message}) { + return _channel.invokeMethod( + 'deleteMessageFromLocalStorage', _buildParam(message.toJson())); + } + + void deleteMessages({required List msgList}) { + _channel.invokeMethod('deleteMessages', + _buildParam({"msgList": msgList.map((e) => e.toJson()).toList()})); + } + + void insertSingleMessageToLocalStorage({ + String? userID, + Message? message, + String? sender, + }) { + _channel.invokeMethod( + 'insertSingleMessageToLocalStorage', + _buildParam({ + "userID": userID, + "message": message?.toJson(), + "sender": sender, + })); + } + + void findMessages({required List messageIDList}) { + _channel.invokeMethod( + 'findMessages', + _buildParam({ + "messageIDList": messageIDList, + })); + } + + Future markSingleMessageHasRead({required String userID}) { + return _channel.invokeMethod( + 'markSingleMessageHasRead', _buildParam({'userID': userID})); + } + + Future createTextMessage({required String text}) { + return _channel + .invokeMethod('createTextMessage', _buildParam({'text': text})) + .then((value) => _toObj(value)); + } + + Future createTextAtMessage({ + required String text, + required List atUserList, + }) { + return _channel + .invokeMethod( + 'createTextAtMessage', + _buildParam({ + 'text': text, + 'atUserList': atUserList, + }), + ) + .then((value) => _toObj(value)); + } + + Future createImageMessage({required String imagePath}) { + return _channel + .invokeMethod( + 'createImageMessage', + _buildParam({'imagePath': imagePath}), + ) + .then((value) => _toObj(value)); + } + + Future createSoundMessage( + {required String soundPath, required int duration}) { + return _channel + .invokeMethod( + 'createSoundMessage', + _buildParam({'soundPath': soundPath, "duration": duration}), + ) + .then((value) => _toObj(value)); + } + + Future createVideoMessage({ + required String videoPath, + required String videoType, + required int duration, + required String snapshotPath, + }) { + return _channel + .invokeMethod( + 'createVideoMessage', + _buildParam({ + 'videoPath': videoPath, + 'videoType': videoType, + 'duration': duration, + 'snapshotPath': snapshotPath, + })) + .then((value) => _toObj(value)); + } + + Future createFileMessage( + {required String filePath, required String fileName}) { + return _channel + .invokeMethod('createFileMessage', + _buildParam({'filePath': filePath, 'fileName': fileName})) + .then((value) => _toObj(value)); + } + + Future createMergerMessage( + {required List messageList, + required String title, + required List summaryList}) { + return _channel + .invokeMethod( + 'createMergerMessage', + _buildParam({ + 'messageList': messageList.map((e) => e.toJson()).toList(), + 'title': title, + 'summaryList': summaryList, + })) + .then((value) => _toObj(value)); + } + + Future createForwardMessage({required List messageList}) { + return _channel + .invokeMethod( + 'createForwardMessage', + _buildParam( + {'message': messageList.map((e) => e.toJson()).toList()})) + .then((value) => _toObj(value)); + } + + static Map _buildParam(Map param) { + param["ManagerName"] = "messageManager"; + return param; + } + + static List _toList(String value) => + (_formatJson(value) as List).map((e) => Message.fromJson(e)).toList(); + + static Message _toObj(String value) => Message.fromJson(_formatJson(value)); + + static dynamic _formatJson(value) { + return jsonDecode(_printValue(value)); + } + + static String _printValue(value) { + return value; + } +} diff --git a/lib/src/manager/im_offline_push_manager.dart b/lib/src/manager/im_offline_push_manager.dart new file mode 100644 index 0000000..c6c8256 --- /dev/null +++ b/lib/src/manager/im_offline_push_manager.dart @@ -0,0 +1,7 @@ +import 'package:flutter/services.dart'; + +class OfflinePushManager{ + MethodChannel _channel; + + OfflinePushManager(this._channel); +} \ No newline at end of file diff --git a/lib/src/manager/im_signaling_manager.dart b/lib/src/manager/im_signaling_manager.dart new file mode 100644 index 0000000..adaa4c0 --- /dev/null +++ b/lib/src/manager/im_signaling_manager.dart @@ -0,0 +1,7 @@ +import 'package:flutter/services.dart'; + +class SignalingManager { + MethodChannel _channel; + + SignalingManager(this._channel); +} diff --git a/lib/src/models/conversation_info.dart b/lib/src/models/conversation_info.dart new file mode 100644 index 0000000..fe125fa --- /dev/null +++ b/lib/src/models/conversation_info.dart @@ -0,0 +1,77 @@ +import 'dart:convert'; + +import 'package:flutter_openim_sdk/flutter_openim_sdk.dart'; + +class ConversationInfo { + String conversationID; + int? conversationType; + String? userID; + String? groupID; + String? showName; + String? faceUrl; + int? recvMsgOpt; + int? unreadCount; + Message? latestMsg; + int? latestMsgSendTime; + String? draftText; + int? draftTimestamp; + dynamic isPinned; + + ConversationInfo( + {required this.conversationID, + this.conversationType, + this.userID, + this.groupID, + this.showName, + this.faceUrl, + this.recvMsgOpt, + this.unreadCount, + this.latestMsg, + this.latestMsgSendTime, + this.draftText, + this.draftTimestamp, + this.isPinned}); + + ConversationInfo.fromJson(Map json) + : conversationID = json['conversationID'] { + // conversationID = json['conversationID']; + conversationType = json['conversationType']; + userID = json['userID']; + groupID = json['groupID']; + showName = json['showName']; + faceUrl = json['faceUrl']; + recvMsgOpt = json['recvMsgOpt']; + unreadCount = json['unreadCount']; + // latestMsg = json['latestMsg']; + // if (null != json['latestMsg']) { + if (json['latestMsg'] is String) { + latestMsg = Message.fromJson(jsonDecode(json['latestMsg'])); + } else if (json['latestMsg'] is Map) { + latestMsg = Message.fromJson(json['latestMsg']); + } + // } + + latestMsgSendTime = json['latestMsgSendTime']; + draftText = json['draftText']; + draftTimestamp = json['draftTimestamp']; + isPinned = json['isPinned']; + } + + Map toJson() { + final Map data = new Map(); + data['conversationID'] = this.conversationID; + data['conversationType'] = this.conversationType; + data['userID'] = this.userID; + data['groupID'] = this.groupID; + data['showName'] = this.showName; + data['faceUrl'] = this.faceUrl; + data['recvMsgOpt'] = this.recvMsgOpt; + data['unreadCount'] = this.unreadCount; + data['latestMsg'] = this.latestMsg?.toJson(); + data['latestMsgSendTime'] = this.latestMsgSendTime; + data['draftText'] = this.draftText; + data['draftTimestamp'] = this.draftTimestamp; + data['isPinned'] = this.isPinned; + return data; + } +} diff --git a/lib/src/models/message.dart b/lib/src/models/message.dart new file mode 100644 index 0000000..d99fa1c --- /dev/null +++ b/lib/src/models/message.dart @@ -0,0 +1,337 @@ +class Message { + String? clientMsgID; + String? serverMsgID; + int? createTime; + int? sendTime; + String? sendID; + String? recvID; + int? msgFrom; + int? contentType; + int? platformID; + List? forceList; + String? senderNickName; + String? senderFaceUrl; + String? groupID; + String? content; + int? seq; + bool? isRead; + int? status; + String? remark; + dynamic ext; + int? sessionType; + PictureElem? pictureElem; + SoundElem? soundElem; + VideoElem? videoElem; + FileElem? fileElem; + + Message( + {this.clientMsgID, + this.serverMsgID, + this.createTime, + this.sendTime, + this.sendID, + this.recvID, + this.msgFrom, + this.contentType, + this.platformID, + this.forceList, + this.senderNickName, + this.senderFaceUrl, + this.groupID, + this.content, + this.seq, + this.isRead, + this.status, + this.remark, + this.ext, + this.sessionType, + this.pictureElem, + this.soundElem, + this.videoElem, + this.fileElem}); + + Message.fromJson(Map json) + /* : clientMsgID = json['clientMsgID']*/ { + clientMsgID = json['clientMsgID']; + serverMsgID = json['serverMsgID']; + createTime = json['createTime']; + sendTime = json['sendTime']; + sendID = json['sendID']; + recvID = json['RecvID']; + msgFrom = json['msgFrom']; + contentType = json['contentType']; + platformID = json['platformID']; + forceList = json['forceList']; + senderNickName = json['senderNickName']; + senderFaceUrl = json['senderFaceUrl']; + groupID = json['groupID']; + content = json['content']; + seq = json['seq']; + isRead = json['isRead']; + status = json['status']; + remark = json['remark']; + ext = json['ext']; + sessionType = json['sessionType']; + pictureElem = json['pictureElem'] != null + ? new PictureElem.fromJson(json['pictureElem']) + : null; + soundElem = json['soundElem'] != null + ? new SoundElem.fromJson(json['soundElem']) + : null; + videoElem = json['videoElem'] != null + ? new VideoElem.fromJson(json['videoElem']) + : null; + fileElem = json['fileElem'] != null + ? new FileElem.fromJson(json['fileElem']) + : null; + } + + Map toJson() { + final Map data = new Map(); + data['clientMsgID'] = this.clientMsgID; + data['serverMsgID'] = this.serverMsgID; + data['createTime'] = this.createTime; + data['sendTime'] = this.sendTime; + data['sendID'] = this.sendID; + data['RecvID'] = this.recvID; + data['msgFrom'] = this.msgFrom; + data['contentType'] = this.contentType; + data['platformID'] = this.platformID; + data['forceList'] = this.forceList; + data['senderNickName'] = this.senderNickName; + data['senderFaceUrl'] = this.senderFaceUrl; + data['groupID'] = this.groupID; + data['content'] = this.content; + data['seq'] = this.seq; + data['isRead'] = this.isRead; + data['status'] = this.status; + data['remark'] = this.remark; + data['ext'] = this.ext; + data['sessionType'] = this.sessionType; + if (this.pictureElem != null) { + data['pictureElem'] = this.pictureElem!.toJson(); + } + if (this.soundElem != null) { + data['soundElem'] = this.soundElem!.toJson(); + } + if (this.videoElem != null) { + data['videoElem'] = this.videoElem!.toJson(); + } + if (this.fileElem != null) { + data['fileElem'] = this.fileElem!.toJson(); + } + return data; + } + + @override + bool operator ==(Object other) { + // TODO: implement == + if (other is Message) { + return other._id == _id; + } + return super == other; + } + + @override + // TODO: implement hashCode + int get hashCode => super.hashCode; + + String? get _id => + clientMsgID == null || clientMsgID!.isEmpty ? serverMsgID : clientMsgID; +} + +class PictureElem { + String? sourcePath; + PictureInfo? sourcePicture; + PictureInfo? bigPicture; + PictureInfo? snapshotPicture; + + PictureElem( + {this.sourcePath, + this.sourcePicture, + this.bigPicture, + this.snapshotPicture}); + + PictureElem.fromJson(Map json) { + sourcePath = json['sourcePath']; + sourcePicture = json['sourcePicture'] != null + ? new PictureInfo.fromJson(json['sourcePicture']) + : null; + bigPicture = json['bigPicture'] != null + ? new PictureInfo.fromJson(json['bigPicture']) + : null; + snapshotPicture = json['snapshotPicture'] != null + ? new PictureInfo.fromJson(json['snapshotPicture']) + : null; + } + + Map toJson() { + final Map data = new Map(); + data['sourcePath'] = this.sourcePath; + if (this.sourcePicture != null) { + data['sourcePicture'] = this.sourcePicture?.toJson(); + } + if (this.bigPicture != null) { + data['bigPicture'] = this.bigPicture?.toJson(); + } + if (this.snapshotPicture != null) { + data['snapshotPicture'] = this.snapshotPicture?.toJson(); + } + return data; + } +} + +class PictureInfo { + String? uuID; + String? type; + int? size; + int? width; + int? height; + String? url; + + PictureInfo( + {this.uuID, this.type, this.size, this.width, this.height, this.url}); + + PictureInfo.fromJson(Map json) { + uuID = json['uuID']; + type = json['type']; + size = json['size']; + width = json['width']; + height = json['height']; + url = json['url']; + } + + Map toJson() { + final Map data = new Map(); + data['uuID'] = this.uuID; + data['type'] = this.type; + data['size'] = this.size; + data['width'] = this.width; + data['height'] = this.height; + data['url'] = this.url; + return data; + } +} + +class SoundElem { + String? uuID; + String? soundPath; + String? sourceUrl; + int? dataSize; + int? duration; + + SoundElem( + {this.uuID, + this.soundPath, + this.sourceUrl, + this.dataSize, + this.duration}); + + SoundElem.fromJson(Map json) { + uuID = json['uuID']; + soundPath = json['soundPath']; + sourceUrl = json['sourceUrl']; + dataSize = json['dataSize']; + duration = json['duration']; + } + + Map toJson() { + final Map data = new Map(); + data['uuID'] = this.uuID; + data['soundPath'] = this.soundPath; + data['sourceUrl'] = this.sourceUrl; + data['dataSize'] = this.dataSize; + data['duration'] = this.duration; + return data; + } +} + +class VideoElem { + String? videoPath; + String? videoUUID; + String? videoUrl; + String? videoType; + int? videoSize; + int? duration; + String? snapshotPath; + String? snapshotUUID; + int? snapshotSize; + String? snapshotUrl; + int? snapshotWidth; + int? snapshotHeight; + + VideoElem( + {this.videoPath, + this.videoUUID, + this.videoUrl, + this.videoType, + this.videoSize, + this.duration, + this.snapshotPath, + this.snapshotUUID, + this.snapshotSize, + this.snapshotUrl, + this.snapshotWidth, + this.snapshotHeight}); + + VideoElem.fromJson(Map json) { + videoPath = json['videoPath']; + videoUUID = json['videoUUID']; + videoUrl = json['videoUrl']; + videoType = json['videoType']; + videoSize = json['videoSize']; + duration = json['duration']; + snapshotPath = json['snapshotPath']; + snapshotUUID = json['snapshotUUID']; + snapshotSize = json['snapshotSize']; + snapshotUrl = json['snapshotUrl']; + snapshotWidth = json['snapshotWidth']; + snapshotHeight = json['snapshotHeight']; + } + + Map toJson() { + final Map data = new Map(); + data['videoPath'] = this.videoPath; + data['videoUUID'] = this.videoUUID; + data['videoUrl'] = this.videoUrl; + data['videoType'] = this.videoType; + data['videoSize'] = this.videoSize; + data['duration'] = this.duration; + data['snapshotPath'] = this.snapshotPath; + data['snapshotUUID'] = this.snapshotUUID; + data['snapshotSize'] = this.snapshotSize; + data['snapshotUrl'] = this.snapshotUrl; + data['snapshotWidth'] = this.snapshotWidth; + data['snapshotHeight'] = this.snapshotHeight; + return data; + } +} + +class FileElem { + String? filePath; + String? uuID; + String? sourceUrl; + String? fileName; + int? fileSize; + + FileElem( + {this.filePath, this.uuID, this.sourceUrl, this.fileName, this.fileSize}); + + FileElem.fromJson(Map json) { + filePath = json['filePath']; + uuID = json['uuID']; + sourceUrl = json['sourceUrl']; + fileName = json['fileName']; + fileSize = json['fileSize']; + } + + Map toJson() { + final Map data = new Map(); + data['filePath'] = this.filePath; + data['uuID'] = this.uuID; + data['sourceUrl'] = this.sourceUrl; + data['fileName'] = this.fileName; + data['fileSize'] = this.fileSize; + return data; + } +} diff --git a/lib/src/models/user_info.dart b/lib/src/models/user_info.dart new file mode 100644 index 0000000..f87b953 --- /dev/null +++ b/lib/src/models/user_info.dart @@ -0,0 +1,65 @@ +class UserInfo { + String uid; + String? name; + String? icon; + int? gender; // 0 未知,1 男,2 女 + String? mobile; + String? birth; + String? email; + String? ex; + String? comment; + int? isInBlackList; // 0 不在黑名单,1 在黑名单 + String? reqMessage; + String? applyTime; + int? flag; // //0请求添加好友,1同意添加好友,-1拒绝添加好友 + + UserInfo( + {required this.uid, + this.name, + this.icon, + this.gender, + this.mobile, + this.birth, + this.email, + this.ex, + this.comment, + this.isInBlackList, + this.reqMessage, + this.applyTime, + this.flag}); + + UserInfo.fromJson(Map json) : uid = json['uid'] { + name = json['name']; + icon = json['icon']; + gender = json['gender']; + mobile = json['mobile']; + birth = json['birth']; + email = json['email']; + ex = json['ex']; + comment = json['comment']; + isInBlackList = json['isInBlackList']; + reqMessage = json['reqMessage']; + applyTime = json['applyTime']; + flag = json['flag']; + } + + Map toJson() { + final Map data = new Map(); + data['uid'] = this.uid; + data['name'] = this.name; + data['icon'] = this.icon; + data['gender'] = this.gender; + data['mobile'] = this.mobile; + data['birth'] = this.birth; + data['email'] = this.email; + data['ex'] = this.ex; + data['comment'] = this.comment; + data['isInBlackList'] = this.isInBlackList; + data['reqMessage'] = this.reqMessage; + data['applyTime'] = this.applyTime; + data['flag'] = this.flag; + return data; + } + + String get nickname => comment ?? name ?? uid; +}