From d1bf1daedf945dd711df75cd157c56be1f2dca93 Mon Sep 17 00:00:00 2001 From: SL Date: Thu, 4 Jul 2024 22:34:18 +0800 Subject: [PATCH] fix: Upgrade message protocol, add message extension topping function and the ability to send expired messages --- CHANGELOG.md | 4 +- assets/202407042149.sql | 3 + assets/sql.txt | 3 +- example/lib/http.dart | 1 - lib/common/options.dart | 2 +- lib/db/channel.dart | 24 ++++-- lib/db/channel_member.dart | 37 ++++++--- lib/db/const.dart | 8 +- lib/db/conversation.dart | 69 +++++++++++++---- lib/db/message.dart | 128 ++++++++++++++++++++++--------- lib/db/reaction.dart | 13 ++-- lib/db/reminder.dart | 10 +-- lib/db/wk_db_helper.dart | 4 +- lib/entity/msg.dart | 3 + lib/manager/connect_manager.dart | 4 + lib/proto/packet.dart | 3 + lib/proto/proto.dart | 20 ++++- pubspec.yaml | 2 +- 18 files changed, 253 insertions(+), 85 deletions(-) create mode 100644 assets/202407042149.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index 22f4f22..fb78136 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -91,4 +91,6 @@ ### 1.4.5 * fix: Update send & recv message No fromChannel information added ### 1.4.6 - * fix: Update send message fromChannel information is Null \ No newline at end of file + * fix: Update send message fromChannel information is Null + ### 1.4.7 + * fix: Upgrade message protocol, add message extension topping function and the ability to send expired messages \ No newline at end of file diff --git a/assets/202407042149.sql b/assets/202407042149.sql new file mode 100644 index 0000000..a56f865 --- /dev/null +++ b/assets/202407042149.sql @@ -0,0 +1,3 @@ +ALTER TABLE 'message' add column 'expire_time' BIGINT DEFAULT 0; +ALTER TABLE 'message' add column 'expire_timestamp' BIGINT DEFAULT 0; +ALTER TABLE 'message_extra' ADD COLUMN is_pinned int DEFAULT 0; \ No newline at end of file diff --git a/assets/sql.txt b/assets/sql.txt index 8b71638..a023f41 100644 --- a/assets/sql.txt +++ b/assets/sql.txt @@ -14,4 +14,5 @@ 202211241110; 202211251048; 202302070951; -202302081049; \ No newline at end of file +202302081049; +202407042149; \ No newline at end of file diff --git a/example/lib/http.dart b/example/lib/http.dart index 9e27b7e..5feb285 100644 --- a/example/lib/http.dart +++ b/example/lib/http.dart @@ -121,7 +121,6 @@ class HttpUtils { String payload = json['payload']; try { msg.payload = jsonDecode(utf8.decode(base64Decode(payload))); - print('消息seq: ${msg.messageSeq},查询的消息${msg.payload}'); } catch (e) { // print('异常了'); } diff --git a/lib/common/options.dart b/lib/common/options.dart index 8fd1aea..d46ca81 100644 --- a/lib/common/options.dart +++ b/lib/common/options.dart @@ -3,7 +3,7 @@ import '../proto/proto.dart'; class Options { String? uid, token; String? addr; // connect address IP:PORT - int protoVersion = 0x01; // protocol version + int protoVersion = 0x04; // protocol version Function(Function(String addr) complete)? getAddr; // async get connect address Proto proto = Proto(); diff --git a/lib/db/channel.dart b/lib/db/channel.dart index 3d17c3e..bb171eb 100644 --- a/lib/db/channel.dart +++ b/lib/db/channel.dart @@ -14,7 +14,10 @@ class ChannelDB { Future query(String channelID, int channelType) async { WKChannel? channel; - List> list = await WKDBHelper.shared.getDB().query( + if (WKDBHelper.shared.getDB() == null) { + return channel; + } + List> list = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableChannel, where: "channel_id=? and channel_type=?", whereArgs: [channelID, channelType]); @@ -25,6 +28,9 @@ class ChannelDB { } insertOrUpdateList(List list) async { + if (WKDBHelper.shared.getDB() == null) { + return; + } List> addList = []; for (WKChannel channel in list) { if (channel.channelID != '') { @@ -32,7 +38,7 @@ class ChannelDB { } } if (addList.isNotEmpty) { - WKDBHelper.shared.getDB().transaction((txn) async { + WKDBHelper.shared.getDB()!.transaction((txn) async { if (addList.isNotEmpty) { for (Map value in addList) { txn.insert(WKDBConst.tableChannel, value, @@ -48,19 +54,22 @@ class ChannelDB { } insert(WKChannel channel) { - WKDBHelper.shared.getDB().insert(WKDBConst.tableChannel, getMap(channel), + WKDBHelper.shared.getDB()?.insert(WKDBConst.tableChannel, getMap(channel), conflictAlgorithm: ConflictAlgorithm.replace); } update(WKChannel channel) { - WKDBHelper.shared.getDB().update(WKDBConst.tableChannel, getMap(channel), + WKDBHelper.shared.getDB()?.update(WKDBConst.tableChannel, getMap(channel), where: "channel_id=? and channel_type=?", whereArgs: [channel.channelID, channel.channelType]); } Future isExist(String channelID, int channelType) async { bool isExit = false; - List> list = await WKDBHelper.shared.getDB().query( + if (WKDBHelper.shared.getDB() == null) { + return isExit; + } + List> list = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableChannel, where: "channel_id=? and channel_type=?", whereArgs: [channelID, channelType]); @@ -85,7 +94,10 @@ class ChannelDB { args.addAll(channelIDs); args.add(channelType); List list = []; - List> results = await WKDBHelper.shared.getDB().query( + if (WKDBHelper.shared.getDB() == null) { + return list; + } + List> results = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableChannel, where: "channel_id in (${WKDBConst.getPlaceholders(channelIDs.length)}) and channel_type=?", diff --git a/lib/db/channel_member.dart b/lib/db/channel_member.dart index cd49831..1a54ad8 100644 --- a/lib/db/channel_member.dart +++ b/lib/db/channel_member.dart @@ -19,7 +19,10 @@ class ChannelMemberDB { args.add(channelType); args.addAll(uidList); List list = []; - List> results = await WKDBHelper.shared.getDB().query( + if (WKDBHelper.shared.getDB() == null) { + return list; + } + List> results = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableChannelMember, where: "channel_id=? and channel_type=? and member_uid in (${WKDBConst.getPlaceholders(uidList.length)})", @@ -36,9 +39,12 @@ class ChannelMemberDB { String sql = "select max(version) version from ${WKDBConst.tableChannelMember} where channel_id =? and channel_type=? limit 0, 1"; int version = 0; - - List> results = - await WKDBHelper.shared.getDB().rawQuery(sql, [channelID, channelType]); + if (WKDBHelper.shared.getDB() == null) { + return version; + } + List> results = await WKDBHelper.shared + .getDB()! + .rawQuery(sql, [channelID, channelType]); if (results.isNotEmpty) { dynamic data = results[0]; version = WKDBConst.readInt(data, 'version'); @@ -51,8 +57,11 @@ class ChannelMemberDB { String sql = "select ${WKDBConst.tableChannelMember}.*,$channelCols from ${WKDBConst.tableChannelMember} left join ${WKDBConst.tableChannel} on ${WKDBConst.tableChannelMember}.member_uid = ${WKDBConst.tableChannel}.channel_id AND ${WKDBConst.tableChannel}.channel_type=1 where (${WKDBConst.tableChannelMember}.channel_id=? and ${WKDBConst.tableChannelMember}.channel_type=? and ${WKDBConst.tableChannelMember}.member_uid=?)"; WKChannelMember? channelMember; + if (WKDBHelper.shared.getDB() == null) { + return channelMember; + } List> list = await WKDBHelper.shared - .getDB() + .getDB()! .rawQuery(sql, [channelId, channelType, memberUID]); if (list.isNotEmpty) { channelMember = WKDBConst.serializeChannelMember(list[0]); @@ -65,8 +74,12 @@ class ChannelMemberDB { String sql = "select ${WKDBConst.tableChannelMember}.*,$channelCols from ${WKDBConst.tableChannelMember} LEFT JOIN ${WKDBConst.tableChannel} on ${WKDBConst.tableChannelMember}.member_uid=${WKDBConst.tableChannel}.channel_id and ${WKDBConst.tableChannel}.channel_type=1 where ${WKDBConst.tableChannelMember}.channel_id=? and ${WKDBConst.tableChannelMember}.channel_type=? and ${WKDBConst.tableChannelMember}.is_deleted=0 and ${WKDBConst.tableChannelMember}.status=1 order by ${WKDBConst.tableChannelMember}.role=1 desc,${WKDBConst.tableChannelMember}.role=2 desc,${WKDBConst.tableChannelMember}.created_at asc"; List list = []; - List> results = - await WKDBHelper.shared.getDB().rawQuery(sql, [channelId, channelType]); + if (WKDBHelper.shared.getDB() == null) { + return list; + } + List> results = await WKDBHelper.shared + .getDB()! + .rawQuery(sql, [channelId, channelType]); if (results.isNotEmpty) { for (Map data in results) { list.add(WKDBConst.serializeChannelMember(data)); @@ -83,7 +96,10 @@ class ChannelMemberDB { args.addAll(uidList); List list = []; - List> results = await WKDBHelper.shared.getDB().query( + if (WKDBHelper.shared.getDB() == null) { + return list; + } + List> results = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableChannelMember, where: "channel_id=? and channel_type=? and member_uid in (${WKDBConst.getPlaceholders(uidList.length)}) ", @@ -97,12 +113,15 @@ class ChannelMemberDB { } insertList(List allMemberList) { + if (WKDBHelper.shared.getDB() == null) { + return; + } List> insertCVList = []; for (WKChannelMember channelMember in allMemberList) { insertCVList.add(getMap(channelMember)); } if (insertCVList.isNotEmpty) { - WKDBHelper.shared.getDB().transaction((txn) async { + WKDBHelper.shared.getDB()!.transaction((txn) async { if (insertCVList.isNotEmpty) { for (Map value in insertCVList) { txn.insert(WKDBConst.tableChannelMember, value, diff --git a/lib/db/const.dart b/lib/db/const.dart index a47e6d9..5a33636 100644 --- a/lib/db/const.dart +++ b/lib/db/const.dart @@ -44,6 +44,8 @@ class WKDBConst { msg.viewed = readInt(data, 'viewed'); msg.viewedAt = readInt(data, 'viewed_at'); msg.topicID = readString(data, 'topic_id'); + msg.expireTime = readInt(data, 'expire_time'); + msg.expireTimestamp = readInt(data, 'expire_timestamp'); // 扩展表数据 msg.wkMsgExtra = serializeMsgExtra(data); msg.localExtraMap = readDynamic(data, 'extra'); @@ -76,6 +78,7 @@ class WKDBConst { extra.editedAt = readInt(data, 'edited_at'); extra.contentEdit = readString(data, 'content_edit'); extra.needUpload = readInt(data, 'need_upload'); + extra.isPinned = readInt(data, 'is_pinned'); return extra; } @@ -224,7 +227,10 @@ class WKDBConst { if (result == Null || result == null) { return 0; } - return result as int; + if (result is int) { + return int.parse(result.toString()); + } + return 0; } static String readString(dynamic data, String key) { diff --git a/lib/db/conversation.dart b/lib/db/conversation.dart index 0711035..c29a828 100644 --- a/lib/db/conversation.dart +++ b/lib/db/conversation.dart @@ -21,8 +21,11 @@ class ConversationDB { String sql = "SELECT ${WKDBConst.tableConversation}.*,$channelCols,$extraCols FROM ${WKDBConst.tableConversation} LEFT JOIN ${WKDBConst.tableChannel} ON ${WKDBConst.tableConversation}.channel_id = ${WKDBConst.tableChannel}.channel_id AND ${WKDBConst.tableConversation}.channel_type = ${WKDBConst.tableChannel}.channel_type LEFT JOIN ${WKDBConst.tableConversationExtra} ON ${WKDBConst.tableConversation}.channel_id=${WKDBConst.tableConversationExtra}.channel_id AND ${WKDBConst.tableConversation}.channel_type=${WKDBConst.tableConversationExtra}.channel_type where ${WKDBConst.tableConversation}.is_deleted=0 order by last_msg_timestamp desc"; List list = []; + if (WKDBHelper.shared.getDB() == null) { + return list; + } List> results = - await WKDBHelper.shared.getDB().rawQuery(sql); + await WKDBHelper.shared.getDB()!.rawQuery(sql); if (results.isNotEmpty) { for (Map data in results) { WKConversationMsg msg = WKDBConst.serializeCoversation(data); @@ -36,9 +39,12 @@ class ConversationDB { } Future delete(String channelID, int channelType) async { + if (WKDBHelper.shared.getDB() == null) { + return false; + } Map data = HashMap(); data['is_deleted'] = 1; - int row = await WKDBHelper.shared.getDB().update( + int row = await WKDBHelper.shared.getDB()!.update( WKDBConst.tableConversation, data, where: "channel_id=? and channel_type=?", whereArgs: [channelID, channelType]); @@ -47,18 +53,21 @@ class ConversationDB { Future insertOrUpdateWithConvMsg( WKConversationMsg conversationMsg) async { + if (WKDBHelper.shared.getDB() == null) { + return null; + } int row; WKConversationMsg? lastMsg = await queryMsgByMsgChannelId( conversationMsg.channelID, conversationMsg.channelType); if (lastMsg == null || lastMsg.channelID.isEmpty) { - row = await WKDBHelper.shared.getDB().insert( + row = await WKDBHelper.shared.getDB()!.insert( WKDBConst.tableConversation, getMap(conversationMsg, false), conflictAlgorithm: ConflictAlgorithm.replace); } else { conversationMsg.unreadCount = lastMsg.unreadCount + conversationMsg.unreadCount; - row = await WKDBHelper.shared.getDB().update( + row = await WKDBHelper.shared.getDB()!.update( WKDBConst.tableConversation, getMap(conversationMsg, false), where: "channel_id=? and channel_type=?", whereArgs: [conversationMsg.channelID, conversationMsg.channelType]); @@ -72,8 +81,10 @@ class ConversationDB { Future queryMsgByMsgChannelId( String channelId, int channelType) async { WKConversationMsg? msg; - - List> list = await WKDBHelper.shared.getDB().query( + if (WKDBHelper.shared.getDB() == null) { + return msg; + } + List> list = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableConversation, where: "channel_id=? and channel_type=?", whereArgs: [channelId, channelType]); @@ -85,11 +96,14 @@ class ConversationDB { Future getMaxVersion() async { int maxVersion = 0; + if (WKDBHelper.shared.getDB() == null) { + return maxVersion; + } String sql = "select max(version) version from ${WKDBConst.tableConversation} limit 0, 1"; List> list = - await WKDBHelper.shared.getDB().rawQuery(sql); + await WKDBHelper.shared.getDB()!.rawQuery(sql); if (list.isNotEmpty) { dynamic data = list[0]; maxVersion = WKDBConst.readInt(data, 'version'); @@ -99,11 +113,14 @@ class ConversationDB { Future getLastMsgSeqs() async { String lastMsgSeqs = ""; + if (WKDBHelper.shared.getDB() == null) { + return lastMsgSeqs; + } String sql = "select GROUP_CONCAT(channel_id||':'||channel_type||':'|| last_seq,'|') synckey from (select *,(select max(message_seq) from ${WKDBConst.tableMessage} where ${WKDBConst.tableMessage}.channel_id=${WKDBConst.tableConversation}.channel_id and ${WKDBConst.tableMessage}.channel_type=${WKDBConst.tableConversation}.channel_type limit 1) last_seq from ${WKDBConst.tableConversation}) cn where channel_id<>'' AND is_deleted=0"; List> list = - await WKDBHelper.shared.getDB().rawQuery(sql); + await WKDBHelper.shared.getDB()!.rawQuery(sql); if (list.isNotEmpty) { dynamic data = list[0]; lastMsgSeqs = WKDBConst.readString(data, 'synckey'); @@ -114,7 +131,10 @@ class ConversationDB { Future> queryWithChannelIds( List channelIds) async { List list = []; - List> results = await WKDBHelper.shared.getDB().query( + if (WKDBHelper.shared.getDB() == null) { + return list; + } + List> results = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableConversation, where: "channel_id in (${WKDBConst.getPlaceholders(channelIds.length)})", @@ -128,11 +148,14 @@ class ConversationDB { } insetMsgs(List list) async { + if (WKDBHelper.shared.getDB() == null) { + return; + } List> insertList = []; for (WKConversationMsg msg in list) { insertList.add(getMap(msg, true)); } - WKDBHelper.shared.getDB().transaction((txn) async { + WKDBHelper.shared.getDB()!.transaction((txn) async { if (insertList.isNotEmpty) { for (int i = 0; i < insertList.length; i++) { txn.insert(WKDBConst.tableConversation, insertList[i], @@ -143,6 +166,9 @@ class ConversationDB { } insertMsgList(List list) async { + if (WKDBHelper.shared.getDB() == null) { + return; + } List channelIds = []; for (var i = 0; i < list.length; i++) { if (list[i].channelID != '') { @@ -170,7 +196,7 @@ class ConversationDB { } } if (insertList.isNotEmpty || updateList.isNotEmpty) { - WKDBHelper.shared.getDB().transaction((txn) async { + WKDBHelper.shared.getDB()!.transaction((txn) async { if (insertList.isNotEmpty) { for (int i = 0; i < insertList.length; i++) { txn.insert(WKDBConst.tableConversation, insertList[i], @@ -189,16 +215,22 @@ class ConversationDB { } clearAll() { - WKDBHelper.shared.getDB().delete(WKDBConst.tableConversation); + if (WKDBHelper.shared.getDB() == null) { + return; + } + WKDBHelper.shared.getDB()!.delete(WKDBConst.tableConversation); } Future queryExtraMaxVersion() async { int maxVersion = 0; + if (WKDBHelper.shared.getDB() == null) { + return maxVersion; + } String sql = "select max(version) version from ${WKDBConst.tableConversationExtra}"; List> list = - await WKDBHelper.shared.getDB().rawQuery(sql); + await WKDBHelper.shared.getDB()!.rawQuery(sql); if (list.isNotEmpty) { dynamic data = list[0]; maxVersion = WKDBConst.readInt(data, 'version'); @@ -207,16 +239,23 @@ class ConversationDB { } Future clearAllRedDot() async { + if (WKDBHelper.shared.getDB() == null) { + return 0; + } var map = {}; + map['unread_count'] = 0; return await WKDBHelper.shared - .getDB() + .getDB()! .update(WKDBConst.tableConversation, map, where: "unread_count>0"); } Future updateWithField( dynamic map, String channelID, int channelType) async { - return await WKDBHelper.shared.getDB().update( + if (WKDBHelper.shared.getDB() == null) { + return 0; + } + return await WKDBHelper.shared.getDB()!.update( WKDBConst.tableConversation, map, where: "channel_id=? and channel_type=?", whereArgs: [channelID, channelType]); diff --git a/lib/db/message.dart b/lib/db/message.dart index 3b5855f..283623d 100644 --- a/lib/db/message.dart +++ b/lib/db/message.dart @@ -18,13 +18,16 @@ class MessageDB { static final MessageDB _instance = MessageDB._privateConstructor(); static MessageDB get shared => _instance; final String extraCols = - "IFNULL(${WKDBConst.tableMessageExtra}.readed,0) as readed,IFNULL(${WKDBConst.tableMessageExtra}.readed_count,0) as readed_count,IFNULL(${WKDBConst.tableMessageExtra}.unread_count,0) as unread_count,IFNULL(${WKDBConst.tableMessageExtra}.revoke,0) as revoke,IFNULL(${WKDBConst.tableMessageExtra}.revoker,'') as revoker,IFNULL(${WKDBConst.tableMessageExtra}.extra_version,0) as extra_version,IFNULL(${WKDBConst.tableMessageExtra}.is_mutual_deleted,0) as is_mutual_deleted,IFNULL(${WKDBConst.tableMessageExtra}.need_upload,0) as need_upload,IFNULL(${WKDBConst.tableMessageExtra}.content_edit,'') as content_edit,IFNULL(${WKDBConst.tableMessageExtra}.edited_at,0) as edited_at"; + "IFNULL(${WKDBConst.tableMessageExtra}.readed,0) as readed,IFNULL(${WKDBConst.tableMessageExtra}.readed_count,0) as readed_count,IFNULL(${WKDBConst.tableMessageExtra}.unread_count,0) as unread_count,IFNULL(${WKDBConst.tableMessageExtra}.revoke,0) as revoke,IFNULL(${WKDBConst.tableMessageExtra}.revoker,'') as revoker,IFNULL(${WKDBConst.tableMessageExtra}.extra_version,0) as extra_version,IFNULL(${WKDBConst.tableMessageExtra}.is_mutual_deleted,0) as is_mutual_deleted,IFNULL(${WKDBConst.tableMessageExtra}.need_upload,0) as need_upload,IFNULL(${WKDBConst.tableMessageExtra}.content_edit,'') as content_edit,IFNULL(${WKDBConst.tableMessageExtra}.edited_at,0) as edited_at,IFNULL(${WKDBConst.tableMessageExtra}.is_pinned,0) as is_pinned"; final String messageCols = - "${WKDBConst.tableMessage}.client_seq,${WKDBConst.tableMessage}.message_id,${WKDBConst.tableMessage}.message_seq,${WKDBConst.tableMessage}.channel_id,${WKDBConst.tableMessage}.channel_type,${WKDBConst.tableMessage}.timestamp,${WKDBConst.tableMessage}.topic_id,${WKDBConst.tableMessage}.from_uid,${WKDBConst.tableMessage}.type,${WKDBConst.tableMessage}.content,${WKDBConst.tableMessage}.status,${WKDBConst.tableMessage}.voice_status,${WKDBConst.tableMessage}.created_at,${WKDBConst.tableMessage}.updated_at,${WKDBConst.tableMessage}.searchable_word,${WKDBConst.tableMessage}.client_msg_no,${WKDBConst.tableMessage}.setting,${WKDBConst.tableMessage}.order_seq,${WKDBConst.tableMessage}.extra,${WKDBConst.tableMessage}.is_deleted,${WKDBConst.tableMessage}.flame,${WKDBConst.tableMessage}.flame_second,${WKDBConst.tableMessage}.viewed,${WKDBConst.tableMessage}.viewed_at"; + "${WKDBConst.tableMessage}.client_seq,${WKDBConst.tableMessage}.message_id,${WKDBConst.tableMessage}.message_seq,${WKDBConst.tableMessage}.channel_id,${WKDBConst.tableMessage}.channel_type,${WKDBConst.tableMessage}.timestamp,${WKDBConst.tableMessage}.topic_id,${WKDBConst.tableMessage}.from_uid,${WKDBConst.tableMessage}.type,${WKDBConst.tableMessage}.content,${WKDBConst.tableMessage}.status,${WKDBConst.tableMessage}.voice_status,${WKDBConst.tableMessage}.created_at,${WKDBConst.tableMessage}.updated_at,${WKDBConst.tableMessage}.searchable_word,${WKDBConst.tableMessage}.client_msg_no,${WKDBConst.tableMessage}.setting,${WKDBConst.tableMessage}.order_seq,${WKDBConst.tableMessage}.extra,${WKDBConst.tableMessage}.is_deleted,${WKDBConst.tableMessage}.flame,${WKDBConst.tableMessage}.flame_second,${WKDBConst.tableMessage}.viewed,${WKDBConst.tableMessage}.viewed_at,${WKDBConst.tableMessage}.expire_time,${WKDBConst.tableMessage}.expire_timestamp"; Future isExist(String clientMsgNo) async { bool isExist = false; - List> list = await WKDBHelper.shared.getDB().query( + if (WKDBHelper.shared.getDB() == null) { + return isExist; + } + List> list = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableMessage, where: "client_msg_no=?", whereArgs: [clientMsgNo]); @@ -46,25 +49,34 @@ class MessageDB { msg.clientMsgNO = WKIM.shared.messageManager.generateClientMsgNo(); } } - return await WKDBHelper.shared.getDB().insert( + return await WKDBHelper.shared.getDB()!.insert( WKDBConst.tableMessage, getMap(msg), conflictAlgorithm: ConflictAlgorithm.replace); } Future updateMsg(WKMsg msg) async { - return await WKDBHelper.shared.getDB().update( + if (WKDBHelper.shared.getDB() == null) { + return 0; + } + return await WKDBHelper.shared.getDB()!.update( WKDBConst.tableMessage, getMap(msg), where: "client_seq=?", whereArgs: [msg.clientSeq]); } Future updateMsgWithField(dynamic map, int clientSeq) async { - return await WKDBHelper.shared.getDB().update(WKDBConst.tableMessage, map, + if (WKDBHelper.shared.getDB() == null) { + return 0; + } + return await WKDBHelper.shared.getDB()!.update(WKDBConst.tableMessage, map, where: "client_seq=?", whereArgs: [clientSeq]); } Future updateMsgWithFieldAndClientMsgNo( dynamic map, String clientMsgNO) async { - return await WKDBHelper.shared.getDB().update(WKDBConst.tableMessage, map, + if (WKDBHelper.shared.getDB() == null) { + return 0; + } + return await WKDBHelper.shared.getDB()!.update(WKDBConst.tableMessage, map, where: "client_msg_no=?", whereArgs: [clientMsgNO]); } @@ -72,9 +84,11 @@ class MessageDB { WKMsg? wkMsg; String sql = "select $messageCols,$extraCols from ${WKDBConst.tableMessage} LEFT JOIN ${WKDBConst.tableMessageExtra} ON ${WKDBConst.tableMessage}.message_id=${WKDBConst.tableMessageExtra}.message_id WHERE ${WKDBConst.tableMessage}.client_msg_no=?"; - + if (WKDBHelper.shared.getDB() == null) { + return wkMsg; + } List> list = - await WKDBHelper.shared.getDB().rawQuery(sql, [clientMsgNo]); + await WKDBHelper.shared.getDB()!.rawQuery(sql, [clientMsgNo]); if (list.isNotEmpty) { wkMsg = WKDBConst.serializeWKMsg(list[0]); } @@ -89,9 +103,11 @@ class MessageDB { WKMsg? wkMsg; String sql = "select $messageCols,$extraCols from ${WKDBConst.tableMessage} LEFT JOIN ${WKDBConst.tableMessageExtra} ON ${WKDBConst.tableMessage}.message_id=${WKDBConst.tableMessageExtra}.message_id WHERE ${WKDBConst.tableMessage}.client_seq=?"; - + if (WKDBHelper.shared.getDB() == null) { + return wkMsg; + } List> list = - await WKDBHelper.shared.getDB().rawQuery(sql, [clientSeq]); + await WKDBHelper.shared.getDB()!.rawQuery(sql, [clientSeq]); if (list.isNotEmpty) { wkMsg = WKDBConst.serializeWKMsg(list[0]); } @@ -106,8 +122,11 @@ class MessageDB { String sql = "select $messageCols,$extraCols from ${WKDBConst.tableMessage} LEFT JOIN ${WKDBConst.tableMessageExtra} ON ${WKDBConst.tableMessage}.message_id=${WKDBConst.tableMessageExtra}.message_id WHERE ${WKDBConst.tableMessage}.message_id in (${WKDBConst.getPlaceholders(messageIds.length)})"; List list = []; + if (WKDBHelper.shared.getDB() == null) { + return list; + } List> results = - await WKDBHelper.shared.getDB().rawQuery(sql, messageIds); + await WKDBHelper.shared.getDB()!.rawQuery(sql, messageIds); if (results.isNotEmpty) { for (Map data in results) { list.add(WKDBConst.serializeWKMsg(data)); @@ -118,10 +137,14 @@ class MessageDB { Future queryMaxOrderSeq(String channelID, int channelType) async { int maxOrderSeq = 0; + if (WKDBHelper.shared.getDB() == null) { + return maxOrderSeq; + } String sql = "select max(order_seq) order_seq from ${WKDBConst.tableMessage} where channel_id =? and channel_type=? and type<>99 and type<>0 and is_deleted=0"; - List> list = - await WKDBHelper.shared.getDB().rawQuery(sql, [channelID, channelType]); + List> list = await WKDBHelper.shared + .getDB()! + .rawQuery(sql, [channelID, channelType]); if (list.isNotEmpty) { dynamic data = list[0]; maxOrderSeq = WKDBConst.readInt(data, 'order_seq'); @@ -133,8 +156,12 @@ class MessageDB { String sql = "SELECT max(message_seq) message_seq FROM ${WKDBConst.tableMessage} WHERE channel_id=? AND channel_type=?"; int messageSeq = 0; - List> list = - await WKDBHelper.shared.getDB().rawQuery(sql, [channelID, channelType]); + if (WKDBHelper.shared.getDB() == null) { + return messageSeq; + } + List> list = await WKDBHelper.shared + .getDB()! + .rawQuery(sql, [channelID, channelType]); if (list.isNotEmpty) { dynamic data = list[0]; messageSeq = WKDBConst.readInt(data, 'message_seq'); @@ -145,10 +172,13 @@ class MessageDB { Future getOrderSeq( String channelID, int channelType, int maxOrderSeq, int limit) async { int minOrderSeq = 0; + if (WKDBHelper.shared.getDB() == null) { + return minOrderSeq; + } String sql = "select order_seq from ${WKDBConst.tableMessage} where channel_id=? and channel_type=? and type<>99 and order_seq <=? order by order_seq desc limit ?"; List> list = await WKDBHelper.shared - .getDB() + .getDB()! .rawQuery(sql, [channelID, channelType, maxOrderSeq, limit]); if (list.isNotEmpty) { dynamic data = list[0]; @@ -195,7 +225,7 @@ class MessageDB { List replyMsgIds = []; List fromUIDs = []; List> results = - await WKDBHelper.shared.getDB().rawQuery(sql, args); + await WKDBHelper.shared.getDB()!.rawQuery(sql, args); if (results.isNotEmpty) { WKChannel? wkChannel = await ChannelDB.shared.query(channelId, channelType); @@ -502,8 +532,11 @@ class MessageDB { String sql = "select count(*) num from ${WKDBConst.tableMessage} where channel_id=? and channel_type=? and message_seq>? and message_seq> list = await WKDBHelper.shared - .getDB() + .getDB()! .rawQuery(sql, [channelID, channelType, minMessageSeq, maxMessageSeq]); if (list.isNotEmpty) { dynamic data = list[0]; @@ -523,9 +556,11 @@ class MessageDB { sql = "select message_seq from ${WKDBConst.tableMessage} where channel_id=? and channel_type=? and order_seq0 order by message_seq asc limit 1"; } - + if (WKDBHelper.shared.getDB() == null) { + return messageSeq; + } List> list = await WKDBHelper.shared - .getDB() + .getDB()! .rawQuery(sql, [channelID, channelType, oldestOrderSeq]); if (list.isNotEmpty) { dynamic data = list[0]; @@ -595,7 +630,7 @@ class MessageDB { cvList.add(getMap(wkMsg)); } if (cvList.isNotEmpty) { - WKDBHelper.shared.getDB().transaction((txn) async { + WKDBHelper.shared.getDB()!.transaction((txn) async { for (int i = 0; i < cvList.length; i++) { txn.insert(WKDBConst.tableMessage, cvList[i], conflictAlgorithm: ConflictAlgorithm.replace); @@ -607,7 +642,10 @@ class MessageDB { Future> queryWithClientMsgNos(List clientMsgNos) async { List msgs = []; - List> results = await WKDBHelper.shared.getDB().query( + if (WKDBHelper.shared.getDB() == null) { + return msgs; + } + List> results = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableMessage, where: "client_msg_no in (${WKDBConst.getPlaceholders(clientMsgNos.length)})", @@ -628,7 +666,7 @@ class MessageDB { for (int i = 0, size = list.length; i < size; i++) { insertCVList.add(getExtraMap(list[i])); } - WKDBHelper.shared.getDB().transaction((txn) async { + WKDBHelper.shared.getDB()!.transaction((txn) async { if (insertCVList.isNotEmpty) { for (int i = 0; i < insertCVList.length; i++) { txn.insert(WKDBConst.tableMessageExtra, insertCVList[i], @@ -663,7 +701,7 @@ class MessageDB { } } if (insertCVList.isNotEmpty || updateCVList.isNotEmpty) { - WKDBHelper.shared.getDB().transaction((txn) async { + WKDBHelper.shared.getDB()!.transaction((txn) async { if (insertCVList.isNotEmpty) { for (int i = 0; i < insertCVList.length; i++) { txn.insert(WKDBConst.tableMessageExtra, insertCVList[i], @@ -687,8 +725,9 @@ class MessageDB { int extraVersion = 0; String sql = "select max(extra_version) extra_version from ${WKDBConst.tableMessageExtra} where channel_id =? and channel_type=?"; - List> list = - await WKDBHelper.shared.getDB().rawQuery(sql, [channelID, channelType]); + List> list = await WKDBHelper.shared + .getDB()! + .rawQuery(sql, [channelID, channelType]); if (list.isNotEmpty) { dynamic data = list[0]; extraVersion = WKDBConst.readInt(data, 'extra_version'); @@ -701,7 +740,7 @@ class MessageDB { "select * from ${WKDBConst.tableMessageExtra} where need_upload=?"; List list = []; List> results = - await WKDBHelper.shared.getDB().rawQuery(sql, [needUpload]); + await WKDBHelper.shared.getDB()!.rawQuery(sql, [needUpload]); if (results.isNotEmpty) { for (Map data in results) { list.add(WKDBConst.serializeMsgExtra(data)); @@ -713,7 +752,10 @@ class MessageDB { Future queryMsgExtraWithMsgID(String messageID) async { WKMsgExtra? msgExtra; - List> list = await WKDBHelper.shared.getDB().query( + if (WKDBHelper.shared.getDB() == null) { + return msgExtra; + } + List> list = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableMessageExtra, where: "message_id=?", whereArgs: [messageID]); @@ -725,7 +767,10 @@ class MessageDB { Future> queryMsgExtrasWithMsgIds(List msgIds) async { List list = []; - List> results = await WKDBHelper.shared.getDB().query( + if (WKDBHelper.shared.getDB() == null) { + return list; + } + List> results = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableMessageExtra, where: "message_id in (${WKDBConst.getPlaceholders(msgIds.length)})", whereArgs: msgIds); @@ -739,10 +784,13 @@ class MessageDB { } updateSendingMsgFail() { + if (WKDBHelper.shared.getDB() == null) { + return; + } var map = {}; map['status'] = WKSendMsgResult.sendFail; WKDBHelper.shared - .getDB() + .getDB()! .update(WKDBConst.tableMessage, map, where: 'status=0'); } @@ -751,8 +799,9 @@ class MessageDB { WKMsg? wkMsg; String sql = "select * from ${WKDBConst.tableMessage} where channel_id=? and channel_type=? and is_deleted=0 and type<>0 and type<>99 order by order_seq desc limit 1"; - List> list = - await WKDBHelper.shared.getDB().rawQuery(sql, [channelID, channelType]); + List> list = await WKDBHelper.shared + .getDB()! + .rawQuery(sql, [channelID, channelType]); if (list.isNotEmpty) { dynamic data = list[0]; if (data != null) { @@ -767,17 +816,23 @@ class MessageDB { } Future deleteWithMessageIDs(List msgIds) async { + if (WKDBHelper.shared.getDB() == null) { + return 0; + } var map = {}; map['is_deleted'] = 1; - return await WKDBHelper.shared.getDB().update(WKDBConst.tableMessage, map, + return await WKDBHelper.shared.getDB()!.update(WKDBConst.tableMessage, map, where: "message_id in (${WKDBConst.getPlaceholders(msgIds.length)})", whereArgs: msgIds); } Future deleteWithChannel(String channelId, int channelType) async { + if (WKDBHelper.shared.getDB() == null) { + return 0; + } var map = {}; map['is_deleted'] = 1; - return await WKDBHelper.shared.getDB().update(WKDBConst.tableMessage, map, + return await WKDBHelper.shared.getDB()!.update(WKDBConst.tableMessage, map, where: "channel_id=? and channel_type=?", whereArgs: [channelId, channelType]); } @@ -800,6 +855,8 @@ class MessageDB { map['viewed'] = msg.viewed; map['viewed_at'] = msg.viewedAt; map['topic_id'] = msg.topicID; + map['expire_time'] = msg.expireTime; + map['expire_timestamp'] = msg.expireTimestamp; if (msg.messageContent != null) { map['searchable_word'] = msg.messageContent!.searchableWord(); } else { @@ -829,6 +886,7 @@ class MessageDB { map['edited_at'] = extra.editedAt; map['need_upload'] = extra.needUpload; map['message_id'] = extra.messageID; + map['is_pinned'] = extra.isPinned; return map; } } diff --git a/lib/db/reaction.dart b/lib/db/reaction.dart index df4c7c4..b26dfdd 100644 --- a/lib/db/reaction.dart +++ b/lib/db/reaction.dart @@ -14,8 +14,9 @@ class ReactionDB { "select max(seq) seq from ${WKDBConst.tableMessageReaction} where channel_id=? and channel_type=? limit 0, 1"; int version = 0; - List> list = - await WKDBHelper.shared.getDB().rawQuery(sql, [channelID, channelType]); + List> list = await WKDBHelper.shared + .getDB()! + .rawQuery(sql, [channelID, channelType]); if (list.isNotEmpty) { dynamic data = list[0]; if (data != null) { @@ -27,7 +28,7 @@ class ReactionDB { Future> queryWithMessageId(String messageId) async { List list = []; - List> results = await WKDBHelper.shared.getDB().query( + List> results = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableMessageReaction, where: "message_id=? and is_deleted=0", whereArgs: [messageId], @@ -43,7 +44,7 @@ class ReactionDB { Future> queryWithMessageIds( List messageIds) async { List list = []; - List> results = await WKDBHelper.shared.getDB().query( + List> results = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableMessageReaction, where: "message_id in (${WKDBConst.getPlaceholders(messageIds.length)}) and is_deleted=0", @@ -90,14 +91,14 @@ class ReactionDB { // } insertReaction(WKMsgReaction reaction) { - WKDBHelper.shared.getDB().insert( + WKDBHelper.shared.getDB()!.insert( WKDBConst.tableMessageReaction, getReactionMap(reaction), conflictAlgorithm: ConflictAlgorithm.replace); } Future isExistReaction(String uid, String messageID) async { bool isExist = false; - List> list = await WKDBHelper.shared.getDB().query( + List> list = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableMessageReaction, where: "message_id=? and uid=?", whereArgs: [messageID, uid]); diff --git a/lib/db/reminder.dart b/lib/db/reminder.dart index 16cbd3f..f318df8 100644 --- a/lib/db/reminder.dart +++ b/lib/db/reminder.dart @@ -21,7 +21,7 @@ class ReminderDB { int version = 0; List> list = - await WKDBHelper.shared.getDB().rawQuery(sql); + await WKDBHelper.shared.getDB()!.rawQuery(sql); if (list.isNotEmpty) { dynamic data = list[0]; if (data != null) { @@ -34,7 +34,7 @@ class ReminderDB { Future> queryWithChannel( String channelID, int channelType, int done) async { List list = []; - List> results = await WKDBHelper.shared.getDB().query( + List> results = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableReminders, where: "channel_id=? and channel_type=? and done=?", whereArgs: [channelID, channelType, done], @@ -82,7 +82,7 @@ class ReminderDB { } if (addList.isNotEmpty || updateList.isNotEmpty) { - WKDBHelper.shared.getDB().transaction((txn) async { + WKDBHelper.shared.getDB()!.transaction((txn) async { if (addList.isNotEmpty) { for (Map value in addList) { txn.insert(WKDBConst.tableReminders, value, @@ -118,7 +118,7 @@ class ReminderDB { Future> queryWithChannelIds(List channelIds) async { List list = []; - List> results = await WKDBHelper.shared.getDB().query( + List> results = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableReminders, where: "channel_id in (${WKDBConst.getPlaceholders(channelIds.length)})", @@ -133,7 +133,7 @@ class ReminderDB { Future> queryWithIds(List ids) async { List list = []; - List> results = await WKDBHelper.shared.getDB().query( + List> results = await WKDBHelper.shared.getDB()!.query( WKDBConst.tableReminders, where: "reminder_id in (${WKDBConst.getPlaceholders(ids.length)})", whereArgs: ids); diff --git a/lib/db/wk_db_helper.dart b/lib/db/wk_db_helper.dart index 2bf25a9..38a948a 100644 --- a/lib/db/wk_db_helper.dart +++ b/lib/db/wk_db_helper.dart @@ -61,8 +61,8 @@ class WKDBHelper { return true; } - Database getDB() { - return _database!; + Database? getDB() { + return _database; } close() { diff --git a/lib/entity/msg.dart b/lib/entity/msg.dart index 3a6f990..59d6cc0 100644 --- a/lib/entity/msg.dart +++ b/lib/entity/msg.dart @@ -30,6 +30,8 @@ class WKMsg { WKChannel? _channelInfo; WKChannelMember? _memberOfFrom; int orderSeq = 0; + int expireTime = 0; + int expireTimestamp = 0; int viewed = 0; int viewedAt = 0; String topicID = ""; @@ -89,6 +91,7 @@ class WKMsgExtra { int editedAt = 0; String contentEdit = ""; int needUpload = 0; + int isPinned = 0; WKMessageContent? messageContent; } diff --git a/lib/manager/connect_manager.dart b/lib/manager/connect_manager.dart index 0d2e56c..bfdc078 100644 --- a/lib/manager/connect_manager.dart +++ b/lib/manager/connect_manager.dart @@ -447,6 +447,10 @@ class WKConnectionManager { msg.timestamp = recvMsg.messageTime; msg.fromUID = recvMsg.fromUID; msg.clientMsgNO = recvMsg.clientMsgNO; + msg.expireTime = recvMsg.expire; + if (msg.expireTime > 0) { + msg.expireTimestamp = msg.expireTime + msg.timestamp; + } msg.status = WKSendMsgResult.sendSuccess; msg.topicID = recvMsg.topic; msg.orderSeq = await WKIM.shared.messageManager diff --git a/lib/proto/packet.dart b/lib/proto/packet.dart index a89d745..8547ee0 100644 --- a/lib/proto/packet.dart +++ b/lib/proto/packet.dart @@ -8,6 +8,7 @@ class PacketHeader { bool noPersist = false; // 是否不存储 bool syncOnce = false; // 是否只同步一次 int remainingLength = 0; + bool hasServerVersion = false; // 是否有服务端版本 } class Packet { @@ -60,6 +61,7 @@ class SendPacket extends Packet { int channelType; String? topic; String payload = ''; + int expire = 0; SendPacket({ this.clientSeq = 0, this.clientMsgNO = "", @@ -122,6 +124,7 @@ class RecvPacket extends Packet { int messageTime = 0; String topic = ""; String payload = ""; + int expire = 0; @override String toString() { return "msgkey:$msgKey,chanenlID:$channelID,channelType:$channelType,fromUID:$fromUID,clientMsgNO:$clientMsgNO,messageID:$messageID,messageSeq:$messageSeq,messageTime:$messageTime,payload:$payload"; diff --git a/lib/proto/proto.dart b/lib/proto/proto.dart index 8c82120..3e4da6d 100644 --- a/lib/proto/proto.dart +++ b/lib/proto/proto.dart @@ -1,5 +1,8 @@ +import 'dart:math'; import 'dart:typed_data'; +import 'package:wukongimfluttersdk/wkim.dart'; + import '../common/logs.dart'; import 'packet.dart'; import 'write_read.dart'; @@ -94,6 +97,12 @@ Uint8List encodeConnect(ConnectPacket packet) { decodeConnack(PacketHeader header, ReadData reader) { var p = ConnackPacket(); p.header = header; + if (header.hasServerVersion) { + var version = reader.readByte(); + Logs.debug("server protocol version: $version"); + WKIM.shared.options.protoVersion = + min(version, WKIM.shared.options.protoVersion); + } p.timeDiff = reader.readUint64().toInt(); p.reasonCode = reader.readUint8(); p.serverKey = reader.readString(); @@ -102,7 +111,7 @@ decodeConnack(PacketHeader header, ReadData reader) { } PacketHeader decodeHeader(ReadData reader) { - var b = reader.readUint8(); + var b = reader.readByte(); var header = PacketHeader(); header.noPersist = (b & 0x01) > 0; header.showUnread = ((b >> 1) & 0x01) > 0; @@ -112,6 +121,9 @@ PacketHeader decodeHeader(ReadData reader) { header.packetType != PacketType.pong) { header.remainingLength = reader.readVariableLength(); } + if (header.packetType == PacketType.connack) { + header.hasServerVersion = (b & 0x01) > 0; + } return header; } @@ -161,6 +173,9 @@ Uint8List encodeSend(SendPacket packet) { } write.writeString(packet.channelID); write.writeUint8(packet.channelType); + if (WKIM.shared.options.protoVersion >= 3) { + write.writeUint32(packet.expire); + } write.writeString(packet.encodeMsgKey()); if (packet.setting.topic == 1) { write.writeString(packet.topic == null ? "" : packet.topic!); @@ -194,6 +209,9 @@ RecvPacket decodeRecv(PacketHeader header, ReadData reader) { recv.fromUID = reader.readString(); recv.channelID = reader.readString(); recv.channelType = reader.readUint8().toInt(); + if (WKIM.shared.options.protoVersion >= 3) { + recv.expire = reader.readUint32().toInt(); + } recv.clientMsgNO = reader.readString(); if (recv.setting.stream == 1) { recv.streamNo = reader.readString(); diff --git a/pubspec.yaml b/pubspec.yaml index 631c215..6704e8f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ description: wukong IM flutter sdk # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.4.6 +version: 1.4.7 homepage: https://github.com/WuKongIM/WuKongIMFlutterSDK environment: