mirror of
https://github.com/WuKongIM/WuKongIMFlutterSDK
synced 2025-05-24 02:42:20 +00:00
fix:新增修改频道头像方法,优化example
This commit is contained in:
parent
c0bb596c6a
commit
66fb59ac67
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -1,3 +1,4 @@
|
||||
{
|
||||
"DockerRun.DisableDockerrc": true
|
||||
"DockerRun.DisableDockerrc": true,
|
||||
"java.compile.nullAnalysis.mode": "automatic"
|
||||
}
|
||||
|
@ -125,4 +125,6 @@
|
||||
### 1.6.2
|
||||
* fix: 修改数据库解码错误数据导致oom
|
||||
### 1.6.3
|
||||
* fix: 优化在未收到服务端心跳消息时主动断开重连
|
||||
* fix: 优化在未收到服务端心跳消息时主动断开重连
|
||||
### 1.6.4
|
||||
* fix: 新增监听头像改变事件
|
@ -13,125 +13,126 @@ class HttpUtils {
|
||||
// static String apiURL = "https://api.githubim.com";
|
||||
static String apiURL = "http://62.234.8.38:7090/v1";
|
||||
// static String apiURL = "http://175.27.245.108:15001";
|
||||
static getAvatarUrl(String uid) {
|
||||
|
||||
static Dio? _dio;
|
||||
|
||||
/// Get Dio instance with trust all certificates configuration
|
||||
static Dio get dio {
|
||||
if (_dio == null) {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) => true; // Trust all certificates
|
||||
|
||||
_dio = Dio(BaseOptions(
|
||||
baseUrl: apiURL,
|
||||
// 允许所有状态码,避免自动抛出异常
|
||||
validateStatus: (status) => true,
|
||||
));
|
||||
(_dio!.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
|
||||
(client) => httpClient;
|
||||
}
|
||||
return _dio!;
|
||||
}
|
||||
|
||||
static String getAvatarUrl(String uid) {
|
||||
return "$apiURL/users/$uid/avatar";
|
||||
}
|
||||
|
||||
static getGroupAvatarUrl(String gid) {
|
||||
static String getGroupAvatarUrl(String gid) {
|
||||
return "$apiURL/groups/$gid/avatar";
|
||||
}
|
||||
|
||||
static Future<int> login(String uid, String token) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
final response = await dio.post("$apiURL/user/login", data: {
|
||||
'uid': uid,
|
||||
'token': token,
|
||||
'device_flag': 0,
|
||||
'device_level': 1
|
||||
});
|
||||
try {
|
||||
final response = await dio.post("/user/login", data: {
|
||||
'uid': uid,
|
||||
'token': token,
|
||||
'device_flag': 0,
|
||||
'device_level': 1
|
||||
});
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
UserInfo.name = response.data['name'];
|
||||
}
|
||||
return response.statusCode ?? HttpStatus.badRequest;
|
||||
} catch (e) {
|
||||
print('获取用户信息失败');
|
||||
print('Login error: $e');
|
||||
return HttpStatus.internalServerError;
|
||||
}
|
||||
|
||||
return response.statusCode!;
|
||||
}
|
||||
|
||||
static Future<String> getIP(String uid) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
String ip = '';
|
||||
try {
|
||||
final response = await dio.get('$apiURL/users/$uid/route');
|
||||
final response = await dio.get('/users/$uid/route');
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
ip = response.data['tcp_addr'];
|
||||
return response.data['tcp_addr'] ?? '';
|
||||
}
|
||||
} catch (e) {
|
||||
ip = '';
|
||||
print('Get IP error: $e');
|
||||
}
|
||||
|
||||
return ip;
|
||||
return '';
|
||||
}
|
||||
|
||||
static syncConversation(String lastSsgSeqs, int msgCount, int version,
|
||||
static Future<void> syncConversation(String lastSsgSeqs, int msgCount, int version,
|
||||
Function(WKSyncConversation) back) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
|
||||
final response = await dio.post('$apiURL/conversation/sync', data: {
|
||||
"login_uid": UserInfo.uid, // 当前登录用户uid
|
||||
"version": version, // 当前客户端的会话最大版本号(从保存的结果里取最大的version,如果本地没有数据则传0),
|
||||
"last_msg_seqs":
|
||||
lastSsgSeqs, // 客户端所有频道会话的最后一条消息序列号拼接出来的同步串 格式: channelID:channelType:last_msg_seq|channelID:channelType:last_msg_seq (此字段非必填,如果不填就获取全量数据,填写了获取增量数据,看你自己的需求。)
|
||||
"msg_count": 10, // 每个会话获取最大的消息数量,一般为app点进去第一屏的数据
|
||||
"device_uuid": UserInfo.uid,
|
||||
});
|
||||
// print(response.data);
|
||||
WKSyncConversation conversation = WKSyncConversation();
|
||||
conversation.conversations = [];
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
try {
|
||||
var list = response.data['conversations'];
|
||||
// var list = jsonDecode(response.data);
|
||||
for (int i = 0; i < list.length; i++) {
|
||||
var json = list[i];
|
||||
WKSyncConvMsg convMsg = WKSyncConvMsg();
|
||||
convMsg.channelID = json['channel_id'];
|
||||
convMsg.channelType = json['channel_type'];
|
||||
convMsg.unread = json['unread'] ?? 0;
|
||||
convMsg.timestamp = json['timestamp'];
|
||||
convMsg.lastMsgSeq = json['last_msg_seq'];
|
||||
convMsg.lastClientMsgNO = json['last_client_msg_no'];
|
||||
convMsg.version = json['version'];
|
||||
var msgListJson = json['recents'] as List<dynamic>;
|
||||
List<WKSyncMsg> msgList = [];
|
||||
if (msgListJson.isNotEmpty) {
|
||||
for (int j = 0; j < msgListJson.length; j++) {
|
||||
var msgJson = msgListJson[j];
|
||||
msgList.add(getWKSyncMsg(msgJson));
|
||||
}
|
||||
}
|
||||
|
||||
convMsg.recents = msgList;
|
||||
conversation.conversations!.add(convMsg);
|
||||
}
|
||||
} catch (e) {
|
||||
print('同步最近会话错误');
|
||||
try {
|
||||
// 检查是否已登录
|
||||
if (UserInfo.uid.isEmpty) {
|
||||
print('请先登录');
|
||||
back(WKSyncConversation()..conversations = []);
|
||||
return;
|
||||
}
|
||||
|
||||
final response = await dio.post('/conversation/sync', data: {
|
||||
"login_uid": UserInfo.uid,
|
||||
"version": version,
|
||||
"last_msg_seqs": lastSsgSeqs,
|
||||
"msg_count": msgCount,
|
||||
"device_uuid": UserInfo.uid,
|
||||
});
|
||||
|
||||
WKSyncConversation conversation = WKSyncConversation();
|
||||
conversation.conversations = [];
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
try {
|
||||
var list = response.data['conversations'];
|
||||
for (int i = 0; i < list.length; i++) {
|
||||
var json = list[i];
|
||||
WKSyncConvMsg convMsg = WKSyncConvMsg();
|
||||
convMsg.channelID = json['channel_id'];
|
||||
convMsg.channelType = json['channel_type'];
|
||||
convMsg.unread = json['unread'] ?? 0;
|
||||
convMsg.timestamp = json['timestamp'];
|
||||
convMsg.lastMsgSeq = json['last_msg_seq'];
|
||||
convMsg.lastClientMsgNO = json['last_client_msg_no'];
|
||||
convMsg.version = json['version'];
|
||||
var msgListJson = json['recents'] as List<dynamic>;
|
||||
List<WKSyncMsg> msgList = [];
|
||||
if (msgListJson.isNotEmpty) {
|
||||
for (int j = 0; j < msgListJson.length; j++) {
|
||||
var msgJson = msgListJson[j];
|
||||
msgList.add(getWKSyncMsg(msgJson));
|
||||
}
|
||||
}
|
||||
|
||||
convMsg.recents = msgList;
|
||||
conversation.conversations!.add(convMsg);
|
||||
}
|
||||
} catch (e) {
|
||||
print('解析会话数据错误: $e');
|
||||
}
|
||||
} else {
|
||||
print('同步会话失败: HTTP ${response.statusCode}');
|
||||
if (response.data != null && response.data is Map) {
|
||||
print('错误信息: ${response.data['message'] ?? response.data}');
|
||||
}
|
||||
}
|
||||
back(conversation);
|
||||
} catch (e) {
|
||||
print('同步会话错误: $e');
|
||||
back(WKSyncConversation()..conversations = []);
|
||||
}
|
||||
back(conversation);
|
||||
}
|
||||
|
||||
static syncChannelMsg(
|
||||
@ -142,42 +143,37 @@ class HttpUtils {
|
||||
int limit,
|
||||
int pullMode,
|
||||
Function(WKSyncChannelMsg) back) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
final response = await dio.post('$apiURL/message/channel/sync', data: {
|
||||
"login_uid": UserInfo.uid, // 当前登录用户uid
|
||||
"channel_id": channelID, // 频道ID
|
||||
"channel_type": channelType, // 频道类型
|
||||
"start_message_seq": startMsgSeq, // 开始消息列号(结果包含start_message_seq的消息)
|
||||
"end_message_seq": endMsgSeq, // 结束消息列号(结果不包含end_message_seq的消息)
|
||||
"limit": limit, // 消息数量限制
|
||||
"pull_mode": pullMode // 拉取模式 0:向下拉取 1:向上拉取
|
||||
});
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
var data = response.data;
|
||||
WKSyncChannelMsg msg = WKSyncChannelMsg();
|
||||
msg.startMessageSeq = data['start_message_seq'];
|
||||
msg.endMessageSeq = data['end_message_seq'];
|
||||
msg.more = data['more'];
|
||||
var messages = data['messages'];
|
||||
try {
|
||||
final response = await dio.post('/message/channel/sync', data: {
|
||||
"login_uid": UserInfo.uid,
|
||||
"channel_id": channelID,
|
||||
"channel_type": channelType,
|
||||
"start_message_seq": startMsgSeq,
|
||||
"end_message_seq": endMsgSeq,
|
||||
"limit": limit,
|
||||
"pull_mode": pullMode
|
||||
});
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
var data = response.data;
|
||||
WKSyncChannelMsg msg = WKSyncChannelMsg();
|
||||
msg.startMessageSeq = data['start_message_seq'];
|
||||
msg.endMessageSeq = data['end_message_seq'];
|
||||
msg.more = data['more'];
|
||||
var messages = data['messages'];
|
||||
|
||||
List<WKSyncMsg> msgList = [];
|
||||
for (int i = 0; i < messages.length; i++) {
|
||||
dynamic json = messages[i];
|
||||
msgList.add(getWKSyncMsg(json));
|
||||
List<WKSyncMsg> msgList = [];
|
||||
for (int i = 0; i < messages.length; i++) {
|
||||
dynamic json = messages[i];
|
||||
msgList.add(getWKSyncMsg(json));
|
||||
}
|
||||
print('同步channel消息数量:${msgList.length}');
|
||||
msg.messages = msgList;
|
||||
back(msg);
|
||||
}
|
||||
print('同步channel消息数量:${msgList.length}');
|
||||
msg.messages = msgList;
|
||||
back(msg);
|
||||
} catch (e) {
|
||||
print('Sync channel message error: $e');
|
||||
back(WKSyncChannelMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,71 +217,90 @@ class HttpUtils {
|
||||
return extra;
|
||||
}
|
||||
|
||||
static getGroupInfo(String groupId) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
final response = await dio.get('$apiURL/groups/$groupId');
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
var json = response.data;
|
||||
var channel = WKChannel(groupId, WKChannelType.group);
|
||||
channel.channelName = json['name'];
|
||||
channel.avatar = json['avatar'];
|
||||
WKIM.shared.channelManager.addOrUpdateChannel(channel);
|
||||
} else {
|
||||
print('获取群信息失败');
|
||||
static Future<void> getGroupInfo(String groupId) async {
|
||||
try {
|
||||
// 检查群ID是否有效
|
||||
if (groupId.isEmpty) {
|
||||
print('群ID不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否已登录
|
||||
if (UserInfo.uid.isEmpty) {
|
||||
print('请先登录');
|
||||
return;
|
||||
}
|
||||
|
||||
final response = await dio.get('/groups/$groupId');
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
var json = response.data;
|
||||
var channel = WKChannel(groupId, WKChannelType.group);
|
||||
channel.channelName = json['name'];
|
||||
channel.avatar = json['avatar'];
|
||||
WKIM.shared.channelManager.addOrUpdateChannel(channel);
|
||||
} else {
|
||||
print('获取群信息失败: HTTP ${response.statusCode}');
|
||||
// 如果服务器返回了错误消息,打印出来
|
||||
if (response.data != null && response.data is Map) {
|
||||
print('错误信息: ${response.data['message'] ?? response.data}');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('获取群信息错误: $e');
|
||||
}
|
||||
}
|
||||
|
||||
static getUserInfo(String uid) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
static Future<void> getUserInfo(String uid) async {
|
||||
try {
|
||||
final response = await dio.get('$apiURL/users/$uid');
|
||||
// 检查UID是否有效
|
||||
if (uid.isEmpty) {
|
||||
print('用户ID不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否已登录
|
||||
if (UserInfo.uid.isEmpty) {
|
||||
print('请先登录');
|
||||
return;
|
||||
}
|
||||
|
||||
final response = await dio.get('/users/$uid');
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
var json = response.data;
|
||||
var channel = WKChannel(uid, WKChannelType.personal);
|
||||
channel.channelName = json['name'];
|
||||
channel.avatar = json['avatar'];
|
||||
WKIM.shared.channelManager.addOrUpdateChannel(channel);
|
||||
} else {
|
||||
print('获取用户信息失败: HTTP ${response.statusCode}');
|
||||
// 如果服务器返回了错误消息,打印出来
|
||||
if (response.data != null && response.data is Map) {
|
||||
print('错误信息: ${response.data['message'] ?? response.data}');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('获取用户信息失败$e');
|
||||
print('获取用户信息错误: $e');
|
||||
}
|
||||
}
|
||||
|
||||
static revokeMsg(String clientMsgNo, String channelId, int channelType,
|
||||
static Future<bool> revokeMsg(String clientMsgNo, String channelId, int channelType,
|
||||
int msgSeq, String msgId) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
try {
|
||||
final response = await dio.post('$apiURL/message/revoke', data: {
|
||||
// 检查必要参数
|
||||
if (clientMsgNo.isEmpty || channelId.isEmpty || msgId.isEmpty) {
|
||||
print('撤回消息需提供完整的消息信息');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否已登录
|
||||
if (UserInfo.uid.isEmpty) {
|
||||
print('请先登录');
|
||||
return false;
|
||||
}
|
||||
|
||||
final response = await dio.post('/message/revoke', data: {
|
||||
'login_uid': UserInfo.uid,
|
||||
'channel_id': channelId,
|
||||
'channel_type': channelType,
|
||||
@ -293,57 +308,66 @@ class HttpUtils {
|
||||
'message_seq': msgSeq,
|
||||
'message_id': msgId,
|
||||
});
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
print('撤回消息成功');
|
||||
print('消息撤回成功');
|
||||
return true;
|
||||
} else {
|
||||
print('撤回消息失败: HTTP ${response.statusCode}');
|
||||
if (response.data != null && response.data is Map) {
|
||||
print('错误信息: ${response.data['message'] ?? response.data}');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
print('获取用户信息失败$e');
|
||||
print('撤回消息错误: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static deleteMsg(String clientMsgNo, String channelId, int channelType,
|
||||
static Future<bool> deleteMsg(String clientMsgNo, String channelId, int channelType,
|
||||
int msgSeq, String msgId) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
try {
|
||||
final response = await dio.post('$apiURL/message/delete', data: {
|
||||
// 检查必要参数
|
||||
if (clientMsgNo.isEmpty || channelId.isEmpty || msgId.isEmpty) {
|
||||
print('删除消息需提供完整的消息信息');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否已登录
|
||||
if (UserInfo.uid.isEmpty) {
|
||||
print('请先登录');
|
||||
return false;
|
||||
}
|
||||
|
||||
final response = await dio.post('/message/delete', data: {
|
||||
'login_uid': UserInfo.uid,
|
||||
'channel_id': channelId,
|
||||
'channel_type': channelType,
|
||||
'message_seq': msgSeq,
|
||||
'message_id': msgId,
|
||||
});
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
WKIM.shared.messageManager.deleteWithClientMsgNo(clientMsgNo);
|
||||
print('消息删除成功');
|
||||
return true;
|
||||
} else {
|
||||
print('删除消息失败: HTTP ${response.statusCode}');
|
||||
if (response.data != null && response.data is Map) {
|
||||
print('错误信息: ${response.data['message'] ?? response.data}');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
print('删除消息失败$e');
|
||||
print('删除消息错误: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static syncMsgExtra(String channelId, int channelType, int version) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
static Future<void> syncMsgExtra(String channelId, int channelType, int version) async {
|
||||
try {
|
||||
final response = await dio.post('$apiURL/message/extra/sync', data: {
|
||||
final response = await dio.post('/message/extra/sync', data: {
|
||||
'login_uid': UserInfo.uid,
|
||||
'channel_id': channelId,
|
||||
'channel_type': channelType,
|
||||
@ -351,6 +375,7 @@ class HttpUtils {
|
||||
'limit': 100,
|
||||
'extra_version': version,
|
||||
});
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
var arrJson = response.data;
|
||||
if (arrJson != null && arrJson.length > 0) {
|
||||
@ -371,122 +396,73 @@ class HttpUtils {
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('同步消息扩展失败$e');
|
||||
print('Sync message extra error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 清空红点
|
||||
static clearUnread(String channelId, int channelType) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
static Future<void> clearUnread(String channelId, int channelType) async {
|
||||
try {
|
||||
final response = await dio.put('$apiURL/conversation/clearUnread', data: {
|
||||
final response = await dio.put('/conversation/clearUnread', data: {
|
||||
'login_uid': UserInfo.uid,
|
||||
'channel_id': channelId,
|
||||
'channel_type': channelType,
|
||||
'unread': 0,
|
||||
});
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
print('清空红点成功');
|
||||
print('Unread count cleared successfully');
|
||||
}
|
||||
} catch (e) {
|
||||
print('清空红点失败$e');
|
||||
print('Clear unread count error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 清除频道消息
|
||||
static clearChannelMsg(String channelId, int channelType) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
static Future<void> clearChannelMsg(String channelId, int channelType) async {
|
||||
try {
|
||||
int maxSeq = await WKIM.shared.messageManager
|
||||
.getMaxMessageSeq(channelId, channelType);
|
||||
final response = await dio.post('$apiURL/message/offset', data: {
|
||||
|
||||
final response = await dio.post('/message/offset', data: {
|
||||
'login_uid': UserInfo.uid,
|
||||
'channel_id': channelId,
|
||||
'channel_type': channelType,
|
||||
'message_seq': maxSeq
|
||||
});
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
WKIM.shared.messageManager.clearWithChannel(channelId, channelType);
|
||||
}
|
||||
} catch (e) {
|
||||
print('清除频道消息失败$e');
|
||||
print('Clear channel message error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 创建群
|
||||
static Future<bool> createGroup(String groupNo) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
try {
|
||||
final response = await dio.post('$apiURL/group/create', data: {
|
||||
final response = await dio.post('/group/create', data: {
|
||||
'login_uid': UserInfo.uid,
|
||||
'group_no': groupNo,
|
||||
});
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return response.statusCode == HttpStatus.ok;
|
||||
} catch (e) {
|
||||
print('创建群失败$e');
|
||||
print('Create group error: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 修改群名称
|
||||
static Future<bool> updateGroupName(String groupNo, String groupName) async {
|
||||
final httpClient = HttpClient();
|
||||
httpClient.badCertificateCallback =
|
||||
(X509Certificate cert, String host, int port) {
|
||||
// 信任所有证书
|
||||
return true;
|
||||
};
|
||||
final dio = Dio();
|
||||
dio.httpClientAdapter = DefaultHttpClientAdapter()
|
||||
..onHttpClientCreate = (client) {
|
||||
return httpClient;
|
||||
};
|
||||
try {
|
||||
final response = await dio.put('$apiURL/groups/$groupNo', data: {
|
||||
final response = await dio.put('/groups/$groupNo', data: {
|
||||
'login_uid': UserInfo.uid,
|
||||
'name': groupName,
|
||||
});
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return response.statusCode == HttpStatus.ok;
|
||||
} catch (e) {
|
||||
print('修改群名称失败$e');
|
||||
print('Update group name error: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +81,10 @@ class ListViewShowDataState extends State<ListViewShowData> {
|
||||
for (var i = 0; i < msgList.length; i++) {
|
||||
msgList[i].msg.unreadCount = 0;
|
||||
}
|
||||
|
||||
// 清除红点后也重新排序,保持列表排序的一致性
|
||||
_sortMessagesByTimestamp();
|
||||
|
||||
setState(() {});
|
||||
});
|
||||
WKIM.shared.conversationManager
|
||||
@ -107,6 +111,9 @@ class ListViewShowDataState extends State<ListViewShowData> {
|
||||
if (list.isNotEmpty) {
|
||||
msgList.addAll(list);
|
||||
}
|
||||
|
||||
_sortMessagesByTimestamp();
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
@ -120,6 +127,10 @@ class ListViewShowDataState extends State<ListViewShowData> {
|
||||
msgList[i].msg.setWkChannel(channel);
|
||||
msgList[i].channelAvatar = "${HttpUtils.apiURL}/${channel.avatar}";
|
||||
msgList[i].channelName = channel.channelName;
|
||||
|
||||
// 刷新频道信息后重新排序(虽然时间戳没变,但保持一致性)
|
||||
_sortMessagesByTimestamp();
|
||||
|
||||
setState(() {});
|
||||
break;
|
||||
}
|
||||
@ -127,6 +138,11 @@ class ListViewShowDataState extends State<ListViewShowData> {
|
||||
});
|
||||
}
|
||||
|
||||
/// 对会话列表按时间戳排序,最新的会话排在前面
|
||||
void _sortMessagesByTimestamp() {
|
||||
msgList.sort((a, b) => b.msg.lastMsgTimestamp.compareTo(a.msg.lastMsgTimestamp));
|
||||
}
|
||||
|
||||
void _getDataList() {
|
||||
Future<List<WKUIConversationMsg>> list =
|
||||
WKIM.shared.conversationManager.getAll();
|
||||
@ -134,7 +150,8 @@ class ListViewShowDataState extends State<ListViewShowData> {
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
msgList.add(UIConversation(result[i]));
|
||||
}
|
||||
|
||||
|
||||
_sortMessagesByTimestamp();
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
@ -315,7 +332,7 @@ class ListViewShowDataState extends State<ListViewShowData> {
|
||||
style: const TextStyle(color: Colors.black, fontSize: 16),
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -4,13 +4,17 @@ import '../db/channel.dart';
|
||||
import '../entity/channel.dart';
|
||||
|
||||
class WKChannelManager {
|
||||
WKChannelManager._privateConstructor();
|
||||
WKChannelManager._privateConstructor() {
|
||||
_refreshChannelMap = HashMap<String, Function(WKChannel)>();
|
||||
_refreshChannelAvatarMap = HashMap<String, Function(WKChannel)>();
|
||||
}
|
||||
static final WKChannelManager _instance =
|
||||
WKChannelManager._privateConstructor();
|
||||
static WKChannelManager get shared => _instance;
|
||||
|
||||
final List<WKChannel> _list = [];
|
||||
HashMap<String, Function(WKChannel)>? _refeshChannelMap;
|
||||
late final HashMap<String, Function(WKChannel)> _refreshChannelMap;
|
||||
late final HashMap<String, Function(WKChannel)> _refreshChannelAvatarMap;
|
||||
Function(String channelID, int channelType, Function(WKChannel) back)?
|
||||
_getChannelInfoBack;
|
||||
|
||||
@ -70,6 +74,21 @@ class WKChannelManager {
|
||||
.searchWithChannelTypeAndFollow(searchKey, channelType, follow);
|
||||
}
|
||||
|
||||
// 修改头像
|
||||
updateAvatarCacheKey(
|
||||
String channelID, int channelType, String avatarCacheKey) async {
|
||||
WKChannel? channel = await getChannel(channelID, channelType);
|
||||
if (channel == null) {
|
||||
return;
|
||||
}
|
||||
channel.avatarCacheKey = avatarCacheKey;
|
||||
_updateChannel(channel);
|
||||
ChannelDB.shared.saveOrUpdate(channel);
|
||||
_refreshChannelAvatarMap.forEach((key, back) {
|
||||
back(channel);
|
||||
});
|
||||
}
|
||||
|
||||
addOrUpdateChannel(WKChannel channel) {
|
||||
_updateChannel(channel);
|
||||
_setRefresh(channel);
|
||||
@ -115,25 +134,28 @@ class WKChannelManager {
|
||||
}
|
||||
|
||||
_setRefresh(WKChannel liMChannel) {
|
||||
if (_refeshChannelMap != null) {
|
||||
_refeshChannelMap!.forEach((key, back) {
|
||||
back(liMChannel);
|
||||
});
|
||||
}
|
||||
_refreshChannelMap.forEach((key, back) {
|
||||
back(liMChannel);
|
||||
});
|
||||
}
|
||||
|
||||
addOnRefreshListener(String key, Function(WKChannel) back) {
|
||||
_refeshChannelMap ??= HashMap();
|
||||
_refeshChannelMap![key] = back;
|
||||
_refreshChannelMap[key] = back;
|
||||
}
|
||||
|
||||
removeOnRefreshListener(String key) {
|
||||
if (_refeshChannelMap != null) {
|
||||
_refeshChannelMap!.remove(key);
|
||||
}
|
||||
_refreshChannelMap.remove(key);
|
||||
}
|
||||
|
||||
addOnGetChannelListener(Function(String, int, Function(WKChannel)) back) {
|
||||
_getChannelInfoBack = back;
|
||||
}
|
||||
|
||||
addOnRefreshAvatarListener(String key, Function(WKChannel) back) {
|
||||
_refreshChannelAvatarMap[key] = back;
|
||||
}
|
||||
|
||||
removeOnRefreshAvatarListener(String key) {
|
||||
_refreshChannelAvatarMap.remove(key);
|
||||
}
|
||||
}
|
||||
|
@ -5,14 +5,18 @@ import 'package:wukongimfluttersdk/db/channel_member.dart';
|
||||
import '../entity/channel_member.dart';
|
||||
|
||||
class WKChannelMemberManager {
|
||||
WKChannelMemberManager._privateConstructor();
|
||||
WKChannelMemberManager._privateConstructor() {
|
||||
_newMembersBack = HashMap<String, Function(List<WKChannelMember>)>();
|
||||
_refreshMembersBack = HashMap<String, Function(WKChannelMember, bool)>();
|
||||
_deleteMembersBack = HashMap<String, Function(List<WKChannelMember>)>();
|
||||
}
|
||||
static final WKChannelMemberManager _instance =
|
||||
WKChannelMemberManager._privateConstructor();
|
||||
static WKChannelMemberManager get shared => _instance;
|
||||
|
||||
HashMap<String, Function(List<WKChannelMember>)>? _newMembersBack;
|
||||
HashMap<String, Function(WKChannelMember, bool)>? _refreshMembersBack;
|
||||
HashMap<String, Function(List<WKChannelMember>)>? _deleteMembersBack;
|
||||
late final HashMap<String, Function(List<WKChannelMember>)> _newMembersBack;
|
||||
late final HashMap<String, Function(WKChannelMember, bool)> _refreshMembersBack;
|
||||
late final HashMap<String, Function(List<WKChannelMember>)> _deleteMembersBack;
|
||||
|
||||
Future<int> getMaxVersion(String channelID, int channelType) async {
|
||||
return ChannelMemberDB.shared.getMaxVersion(channelID, channelType);
|
||||
@ -29,8 +33,9 @@ class WKChannelMemberManager {
|
||||
.queryWithUID(channelID, channelType, memberUID);
|
||||
}
|
||||
|
||||
saveOrUpdateList(List<WKChannelMember> list) async {
|
||||
Future<void> saveOrUpdateList(List<WKChannelMember> list) async {
|
||||
if (list.isEmpty) return;
|
||||
|
||||
String channelID = list[0].channelID;
|
||||
int channelType = list[0].channelType;
|
||||
|
||||
@ -40,7 +45,9 @@ class WKChannelMemberManager {
|
||||
|
||||
List<WKChannelMember> existList = [];
|
||||
List<String> uidList = [];
|
||||
|
||||
for (WKChannelMember channelMember in list) {
|
||||
// 分批处理,每200个UID查询一次数据库
|
||||
if (uidList.length == 200) {
|
||||
List<WKChannelMember> tempList = await ChannelMemberDB.shared
|
||||
.queryWithUIDs(
|
||||
@ -54,16 +61,16 @@ class WKChannelMemberManager {
|
||||
uidList.add(channelMember.memberUID);
|
||||
}
|
||||
|
||||
// 处理剩余的UID
|
||||
if (uidList.isNotEmpty) {
|
||||
List<WKChannelMember> tempList = await ChannelMemberDB.shared
|
||||
.queryWithUIDs(channelID, channelType, uidList);
|
||||
if (tempList.isNotEmpty) {
|
||||
existList.addAll(tempList);
|
||||
}
|
||||
|
||||
uidList.clear();
|
||||
}
|
||||
|
||||
// 分类处理成员:新增、更新或删除
|
||||
for (WKChannelMember channelMember in list) {
|
||||
bool isNewMember = true;
|
||||
for (int i = 0, size = existList.length; i < size; i++) {
|
||||
@ -86,77 +93,62 @@ class WKChannelMemberManager {
|
||||
}
|
||||
}
|
||||
|
||||
// 先保存或修改成员
|
||||
ChannelMemberDB.shared.insertList(list);
|
||||
// 保存或修改成员
|
||||
await ChannelMemberDB.shared.insertList(list);
|
||||
|
||||
// 触发回调通知
|
||||
if (addList.isNotEmpty) {
|
||||
setOnNewChannelMember(addList);
|
||||
_notifyNewChannelMembers(addList);
|
||||
}
|
||||
if (deleteList.isNotEmpty) {
|
||||
setDeleteChannelMember(deleteList);
|
||||
_notifyDeleteChannelMembers(deleteList);
|
||||
}
|
||||
|
||||
if (updateList.isNotEmpty) {
|
||||
for (int i = 0, size = updateList.length; i < size; i++) {
|
||||
setRefreshChannelMember(updateList[i], i == updateList.length - 1);
|
||||
_notifyRefreshChannelMember(updateList[i], i == updateList.length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setRefreshChannelMember(WKChannelMember member, bool isEnd) {
|
||||
if (_refreshMembersBack != null) {
|
||||
_refreshMembersBack!.forEach((key, back) {
|
||||
back(member, isEnd);
|
||||
});
|
||||
}
|
||||
void _notifyRefreshChannelMember(WKChannelMember member, bool isEnd) {
|
||||
_refreshMembersBack.forEach((key, back) {
|
||||
back(member, isEnd);
|
||||
});
|
||||
}
|
||||
|
||||
addOnRefreshMemberListener(String key, Function(WKChannelMember, bool) back) {
|
||||
_refreshMembersBack ??= HashMap();
|
||||
_refreshMembersBack![key] = back;
|
||||
void addOnRefreshMemberListener(String key, Function(WKChannelMember, bool) back) {
|
||||
_refreshMembersBack[key] = back;
|
||||
}
|
||||
|
||||
removeRefreshMemberListener(String key) {
|
||||
if (_refreshMembersBack != null) {
|
||||
_refreshMembersBack!.remove(key);
|
||||
}
|
||||
void removeRefreshMemberListener(String key) {
|
||||
_refreshMembersBack.remove(key);
|
||||
}
|
||||
|
||||
setDeleteChannelMember(List<WKChannelMember> list) {
|
||||
if (_deleteMembersBack != null) {
|
||||
_deleteMembersBack!.forEach((key, back) {
|
||||
back(list);
|
||||
});
|
||||
}
|
||||
void _notifyDeleteChannelMembers(List<WKChannelMember> list) {
|
||||
_deleteMembersBack.forEach((key, back) {
|
||||
back(list);
|
||||
});
|
||||
}
|
||||
|
||||
addOnDeleteMemberListener(String key, Function(List<WKChannelMember>) back) {
|
||||
_deleteMembersBack ??= HashMap();
|
||||
_deleteMembersBack![key] = back;
|
||||
void addOnDeleteMemberListener(String key, Function(List<WKChannelMember>) back) {
|
||||
_deleteMembersBack[key] = back;
|
||||
}
|
||||
|
||||
removeDeleteMemberListener(String key) {
|
||||
if (_deleteMembersBack != null) {
|
||||
_deleteMembersBack!.remove(key);
|
||||
}
|
||||
void removeDeleteMemberListener(String key) {
|
||||
_deleteMembersBack.remove(key);
|
||||
}
|
||||
|
||||
setOnNewChannelMember(List<WKChannelMember> list) {
|
||||
if (_newMembersBack != null) {
|
||||
_newMembersBack!.forEach((key, back) {
|
||||
back(list);
|
||||
});
|
||||
}
|
||||
void _notifyNewChannelMembers(List<WKChannelMember> list) {
|
||||
_newMembersBack.forEach((key, back) {
|
||||
back(list);
|
||||
});
|
||||
}
|
||||
|
||||
addOnNewMemberListener(String key, Function(List<WKChannelMember>) back) {
|
||||
_newMembersBack ??= HashMap();
|
||||
_newMembersBack![key] = back;
|
||||
void addOnNewMemberListener(String key, Function(List<WKChannelMember>) back) {
|
||||
_newMembersBack[key] = back;
|
||||
}
|
||||
|
||||
removeNewMemberListener(String key) {
|
||||
if (_newMembersBack != null) {
|
||||
_newMembersBack!.remove(key);
|
||||
}
|
||||
void removeNewMemberListener(String key) {
|
||||
_newMembersBack.remove(key);
|
||||
}
|
||||
}
|
||||
|
@ -4,43 +4,55 @@ import 'package:wukongimfluttersdk/db/const.dart';
|
||||
|
||||
import '../entity/cmd.dart';
|
||||
|
||||
/// 命令管理器,处理和分发命令
|
||||
class WKCMDManager {
|
||||
WKCMDManager._privateConstructor();
|
||||
WKCMDManager._privateConstructor() {
|
||||
_cmdListeners = HashMap<String, Function(WKCMD)>();
|
||||
}
|
||||
static final WKCMDManager _instance = WKCMDManager._privateConstructor();
|
||||
static WKCMDManager get shared => _instance;
|
||||
|
||||
HashMap<String, Function(WKCMD)>? _cmdback;
|
||||
handleCMD(dynamic json) {
|
||||
/// 命令监听器集合
|
||||
late final HashMap<String, Function(WKCMD)> _cmdListeners;
|
||||
|
||||
/// 处理从服务器接收的命令
|
||||
void handleCMD(dynamic json) {
|
||||
// 解析命令
|
||||
String cmd = WKDBConst.readString(json, 'cmd');
|
||||
dynamic param = json['param'];
|
||||
|
||||
// 补充频道信息(如果缺失)
|
||||
if (param != null && param is Map) {
|
||||
if (!param.containsKey('channel_id')) {
|
||||
param['channel_id'] = json['channel_id'];
|
||||
param['channel_type'] = json['channel_type'];
|
||||
}
|
||||
}
|
||||
|
||||
// 创建命令对象并分发
|
||||
WKCMD wkcmd = WKCMD();
|
||||
wkcmd.cmd = cmd;
|
||||
wkcmd.param = param;
|
||||
pushCMD(wkcmd);
|
||||
_notifyListeners(wkcmd);
|
||||
}
|
||||
|
||||
pushCMD(WKCMD wkcmd) {
|
||||
if (_cmdback != null) {
|
||||
_cmdback!.forEach((key, back) {
|
||||
back(wkcmd);
|
||||
});
|
||||
}
|
||||
/// 分发命令到所有监听器
|
||||
void _notifyListeners(WKCMD wkcmd) {
|
||||
_cmdListeners.forEach((key, listener) {
|
||||
listener(wkcmd);
|
||||
});
|
||||
}
|
||||
|
||||
addOnCmdListener(String key, Function(WKCMD) back) {
|
||||
_cmdback ??= HashMap();
|
||||
_cmdback![key] = back;
|
||||
/// 添加命令监听器
|
||||
/// [key] 监听器唯一标识
|
||||
/// [listener] 命令回调函数
|
||||
void addOnCmdListener(String key, Function(WKCMD) listener) {
|
||||
_cmdListeners[key] = listener;
|
||||
}
|
||||
|
||||
removeCmdListener(String key) {
|
||||
if (_cmdback != null) {
|
||||
_cmdback!.remove(key);
|
||||
}
|
||||
/// 移除命令监听器
|
||||
/// [key] 监听器唯一标识
|
||||
void removeCmdListener(String key) {
|
||||
_cmdListeners.remove(key);
|
||||
}
|
||||
}
|
||||
|
@ -315,6 +315,7 @@ class WKConnectionManager {
|
||||
}
|
||||
} else if (packet.header.packetType == PacketType.sendack) {
|
||||
var sendack = packet as SendAckPacket;
|
||||
Logs.debug('发送结果:${sendack.reasonCode}');
|
||||
WKIM.shared.messageManager.updateSendResult(sendack.messageID,
|
||||
sendack.clientSeq, sendack.messageSeq, sendack.reasonCode);
|
||||
if (_sendingMsgMap.containsKey(sendack.clientSeq)) {
|
||||
|
@ -9,37 +9,54 @@ import '../db/conversation.dart';
|
||||
import '../entity/conversation.dart';
|
||||
import '../type/const.dart';
|
||||
|
||||
/// 会话管理器,负责管理和维护会话数据
|
||||
class WKConversationManager {
|
||||
WKConversationManager._privateConstructor();
|
||||
WKConversationManager._privateConstructor() {
|
||||
_refreshMsgMap = HashMap<String, Function(WKUIConversationMsg, bool)>();
|
||||
_refreshMsgListMap = HashMap<String, Function(List<WKUIConversationMsg>)>();
|
||||
_deleteMsgMap = HashMap<String, Function(String, int)>();
|
||||
_clearAllRedDotMap = HashMap<String, Function()>();
|
||||
}
|
||||
|
||||
static final WKConversationManager _instance =
|
||||
WKConversationManager._privateConstructor();
|
||||
static WKConversationManager get shared => _instance;
|
||||
|
||||
HashMap<String, Function(WKUIConversationMsg, bool)>? _refeshMsgMap;
|
||||
HashMap<String, Function(List<WKUIConversationMsg>)>? _refreshMsgListMap;
|
||||
HashMap<String, Function(String, int)>? _deleteMsgMap;
|
||||
HashMap<String, Function()>? _clearAllRedDotMap;
|
||||
/// 单个会话刷新监听器
|
||||
late final HashMap<String, Function(WKUIConversationMsg, bool)> _refreshMsgMap;
|
||||
|
||||
/// 会话列表刷新监听器
|
||||
late final HashMap<String, Function(List<WKUIConversationMsg>)> _refreshMsgListMap;
|
||||
|
||||
/// 会话删除监听器
|
||||
late final HashMap<String, Function(String, int)> _deleteMsgMap;
|
||||
|
||||
/// 清除所有红点监听器
|
||||
late final HashMap<String, Function()> _clearAllRedDotMap;
|
||||
|
||||
/// 同步会话回调
|
||||
Function(String lastSsgSeqs, int msgCount, int version,
|
||||
Function(WKSyncConversation))? _syncConersationBack;
|
||||
Function(WKSyncConversation))? _syncConversationBack;
|
||||
|
||||
/// 获取所有会话
|
||||
Future<List<WKUIConversationMsg>> getAll() async {
|
||||
return await ConversationDB.shared.queryAll();
|
||||
}
|
||||
|
||||
/// 删除指定频道的会话
|
||||
Future<bool> deleteMsg(String channelID, int channelType) async {
|
||||
bool result = await ConversationDB.shared.delete(channelID, channelType);
|
||||
if (result) {
|
||||
_setDeleteMsg(channelID, channelType);
|
||||
_notifyDeleteMsg(channelID, channelType);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// 根据消息保存会话
|
||||
Future<WKUIConversationMsg?> saveWithLiMMsg(WKMsg msg, int redDot) async {
|
||||
WKConversationMsg wkConversationMsg = WKConversationMsg();
|
||||
if (msg.channelType == WKChannelType.communityTopic &&
|
||||
msg.channelID != '') {
|
||||
msg.channelID.isNotEmpty) {
|
||||
if (msg.channelID.contains("@")) {
|
||||
var str = msg.channelID.split("@");
|
||||
wkConversationMsg.parentChannelID = str[0];
|
||||
@ -57,14 +74,17 @@ class WKConversationManager {
|
||||
return uiMsg;
|
||||
}
|
||||
|
||||
/// 获取所有未读消息总数
|
||||
Future<int> getAllUnreadCount() async {
|
||||
return ConversationDB.shared.queryAllUnreadCount();
|
||||
}
|
||||
|
||||
/// 获取扩展信息的最大版本号
|
||||
Future<int> getExtraMaxVersion() async {
|
||||
return ConversationDB.shared.queryExtraMaxVersion();
|
||||
}
|
||||
|
||||
/// 获取指定频道的会话
|
||||
Future<WKUIConversationMsg?> getWithChannel(
|
||||
String channelID, int channelType) async {
|
||||
var msg = await ConversationDB.shared
|
||||
@ -75,165 +95,172 @@ class WKConversationManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
clearAll() {
|
||||
ConversationDB.shared.clearAll();
|
||||
/// 清除所有会话
|
||||
Future<void> clearAll() async {
|
||||
await ConversationDB.shared.clearAll();
|
||||
}
|
||||
|
||||
clearAllRedDot() async {
|
||||
/// 清除所有会话的未读数
|
||||
Future<void> clearAllRedDot() async {
|
||||
int row = await ConversationDB.shared.clearAllRedDot();
|
||||
if (row > 0) {
|
||||
_setClearAllRedDot();
|
||||
_notifyClearAllRedDot();
|
||||
}
|
||||
}
|
||||
|
||||
updateRedDot(String channelID, int channelType, int redDot) async {
|
||||
/// 更新指定频道的未读数
|
||||
Future<void> updateRedDot(String channelID, int channelType, int redDot) async {
|
||||
var map = <String, Object>{};
|
||||
map['unread_count'] = redDot;
|
||||
var result = await ConversationDB.shared
|
||||
.updateWithField(map, channelID, channelType);
|
||||
if (result > 0) {
|
||||
_refreshMsg(channelID, channelType);
|
||||
await _refreshChannelMsg(channelID, channelType);
|
||||
}
|
||||
}
|
||||
|
||||
_refreshMsg(String channelID, int channelType) async {
|
||||
/// 刷新指定频道的会话
|
||||
Future<void> _refreshChannelMsg(String channelID, int channelType) async {
|
||||
var msg = await ConversationDB.shared
|
||||
.queryMsgByMsgChannelId(channelID, channelType);
|
||||
if (msg != null) {
|
||||
var uiMsg = ConversationDB.shared.getUIMsg(msg);
|
||||
List<WKUIConversationMsg> uiMsgs = [];
|
||||
uiMsgs.add(uiMsg);
|
||||
List<WKUIConversationMsg> uiMsgs = [uiMsg];
|
||||
setRefreshUIMsgs(uiMsgs);
|
||||
}
|
||||
}
|
||||
|
||||
addOnClearAllRedDotListener(String key, Function() back) {
|
||||
_clearAllRedDotMap ??= HashMap();
|
||||
_clearAllRedDotMap![key] = back;
|
||||
/// 添加清除所有红点监听器
|
||||
void addOnClearAllRedDotListener(String key, Function() listener) {
|
||||
_clearAllRedDotMap[key] = listener;
|
||||
}
|
||||
|
||||
removeClearAllRedDotListener(String key) {
|
||||
if (_clearAllRedDotMap != null) {
|
||||
_clearAllRedDotMap!.remove(key);
|
||||
}
|
||||
/// 移除清除所有红点监听器
|
||||
void removeClearAllRedDotListener(String key) {
|
||||
_clearAllRedDotMap.remove(key);
|
||||
}
|
||||
|
||||
_setClearAllRedDot() {
|
||||
if (_clearAllRedDotMap != null) {
|
||||
_clearAllRedDotMap!.forEach((key, back) {
|
||||
back();
|
||||
});
|
||||
}
|
||||
/// 通知清除所有红点
|
||||
void _notifyClearAllRedDot() {
|
||||
_clearAllRedDotMap.forEach((_, listener) {
|
||||
listener();
|
||||
});
|
||||
}
|
||||
|
||||
addOnDeleteMsgListener(String key, Function(String, int) back) {
|
||||
_deleteMsgMap ??= HashMap();
|
||||
_deleteMsgMap![key] = back;
|
||||
/// 添加会话删除监听器
|
||||
void addOnDeleteMsgListener(String key, Function(String, int) listener) {
|
||||
_deleteMsgMap[key] = listener;
|
||||
}
|
||||
|
||||
removeDeleteMsgListener(String key) {
|
||||
if (_deleteMsgMap != null) {
|
||||
_deleteMsgMap!.remove(key);
|
||||
}
|
||||
/// 移除会话删除监听器
|
||||
void removeDeleteMsgListener(String key) {
|
||||
_deleteMsgMap.remove(key);
|
||||
}
|
||||
|
||||
_setDeleteMsg(String channelID, int channelType) {
|
||||
if (_deleteMsgMap != null) {
|
||||
_deleteMsgMap!.forEach((key, back) {
|
||||
back(channelID, channelType);
|
||||
});
|
||||
}
|
||||
/// 通知会话已删除
|
||||
void _notifyDeleteMsg(String channelID, int channelType) {
|
||||
_deleteMsgMap.forEach((_, listener) {
|
||||
listener(channelID, channelType);
|
||||
});
|
||||
}
|
||||
|
||||
_setRefreshMsg(WKUIConversationMsg msg, bool isEnd) {
|
||||
if (_refeshMsgMap != null) {
|
||||
_refeshMsgMap!.forEach((key, back) {
|
||||
back(msg, isEnd);
|
||||
});
|
||||
}
|
||||
/// 通知刷新单个会话
|
||||
void _notifyRefreshMsg(WKUIConversationMsg msg, bool isEnd) {
|
||||
_refreshMsgMap.forEach((_, listener) {
|
||||
listener(msg, isEnd);
|
||||
});
|
||||
}
|
||||
|
||||
@Deprecated("Please replace with `addOnRefreshMsgListListener` method")
|
||||
addOnRefreshMsgListener(
|
||||
String key, Function(WKUIConversationMsg, bool) back) {
|
||||
_refeshMsgMap ??= HashMap();
|
||||
_refeshMsgMap![key] = back;
|
||||
/// 添加会话刷新监听器(已废弃)
|
||||
@Deprecated("请使用 addOnRefreshMsgListListener 方法替代")
|
||||
void addOnRefreshMsgListener(
|
||||
String key, Function(WKUIConversationMsg, bool) listener) {
|
||||
_refreshMsgMap[key] = listener;
|
||||
}
|
||||
|
||||
removeOnRefreshMsg(String key) {
|
||||
if (_refeshMsgMap != null) {
|
||||
_refeshMsgMap!.remove(key);
|
||||
}
|
||||
/// 移除会话刷新监听器
|
||||
void removeOnRefreshMsg(String key) {
|
||||
_refreshMsgMap.remove(key);
|
||||
}
|
||||
|
||||
setRefreshUIMsgs(List<WKUIConversationMsg> msgs) {
|
||||
_setRefreshMsgList(msgs);
|
||||
/// 刷新会话UI列表
|
||||
void setRefreshUIMsgs(List<WKUIConversationMsg> msgs) {
|
||||
_notifyRefreshMsgList(msgs);
|
||||
for (int i = 0, size = msgs.length; i < size; i++) {
|
||||
_setRefreshMsg(msgs[i], i == msgs.length - 1);
|
||||
_notifyRefreshMsg(msgs[i], i == msgs.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
_setRefreshMsgList(List<WKUIConversationMsg> msgs) {
|
||||
if (_refreshMsgListMap != null) {
|
||||
_refreshMsgListMap!.forEach((key, back) {
|
||||
back(msgs);
|
||||
});
|
||||
}
|
||||
/// 通知刷新会话列表
|
||||
void _notifyRefreshMsgList(List<WKUIConversationMsg> msgs) {
|
||||
_refreshMsgListMap.forEach((_, listener) {
|
||||
listener(msgs);
|
||||
});
|
||||
}
|
||||
|
||||
addOnRefreshMsgListListener(
|
||||
String key, Function(List<WKUIConversationMsg>) back) {
|
||||
_refreshMsgListMap ??= HashMap();
|
||||
_refreshMsgListMap![key] = back;
|
||||
/// 添加会话列表刷新监听器
|
||||
void addOnRefreshMsgListListener(
|
||||
String key, Function(List<WKUIConversationMsg>) listener) {
|
||||
_refreshMsgListMap[key] = listener;
|
||||
}
|
||||
|
||||
removeOnRefreshMsgListListener(String key) {
|
||||
if (_refreshMsgListMap != null) {
|
||||
_refreshMsgListMap!.remove(key);
|
||||
}
|
||||
/// 移除会话列表刷新监听器
|
||||
void removeOnRefreshMsgListListener(String key) {
|
||||
_refreshMsgListMap.remove(key);
|
||||
}
|
||||
|
||||
addOnSyncConversationListener(
|
||||
/// 添加同步会话监听器
|
||||
void addOnSyncConversationListener(
|
||||
Function(String lastSsgSeqs, int msgCount, int version,
|
||||
Function(WKSyncConversation))
|
||||
back) {
|
||||
_syncConersationBack = back;
|
||||
listener) {
|
||||
_syncConversationBack = listener;
|
||||
}
|
||||
|
||||
setSyncConversation(Function() back) async {
|
||||
/// 触发同步会话操作
|
||||
Future<void> setSyncConversation(Function() callback) async {
|
||||
WKIM.shared.connectionManager.setConnectionStatus(WKConnectStatus.syncMsg);
|
||||
if (_syncConersationBack != null) {
|
||||
if (_syncConversationBack != null) {
|
||||
int version = await ConversationDB.shared.getMaxVersion();
|
||||
String lastMsgSeqStr = await ConversationDB.shared.getLastMsgSeqs();
|
||||
_syncConersationBack!(lastMsgSeqStr, 200, version, (msgs) {
|
||||
_saveSyncCoversation(msgs);
|
||||
back();
|
||||
_syncConversationBack!(lastMsgSeqStr, 200, version, (msgs) {
|
||||
_saveSyncConversation(msgs);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_saveSyncCoversation(WKSyncConversation? syncChat) {
|
||||
/// 保存同步的会话数据
|
||||
void _saveSyncConversation(WKSyncConversation? syncChat) {
|
||||
if (syncChat == null ||
|
||||
syncChat.conversations == null ||
|
||||
syncChat.conversations!.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化数据集合
|
||||
List<WKConversationMsg> conversationMsgList = [];
|
||||
List<WKMsg> msgList = [];
|
||||
List<WKMsgReaction> msgReactionList = [];
|
||||
List<WKMsgExtra> msgExtraList = [];
|
||||
List<WKUIConversationMsg> uiMsgList = [];
|
||||
|
||||
// 处理同步的会话数据
|
||||
if (syncChat.conversations != null && syncChat.conversations!.isNotEmpty) {
|
||||
for (int i = 0, size = syncChat.conversations!.length; i < size; i++) {
|
||||
WKConversationMsg conversationMsg = WKConversationMsg();
|
||||
|
||||
int channelType = syncChat.conversations![i].channelType;
|
||||
String channelID = syncChat.conversations![i].channelID;
|
||||
|
||||
// 处理社区主题频道
|
||||
if (channelType == WKChannelType.communityTopic) {
|
||||
var str = channelID.split("@");
|
||||
conversationMsg.parentChannelID = str[0];
|
||||
conversationMsg.parentChannelType = WKChannelType.community;
|
||||
}
|
||||
|
||||
// 设置会话属性
|
||||
conversationMsg.channelID = syncChat.conversations![i].channelID;
|
||||
conversationMsg.channelType = syncChat.conversations![i].channelType;
|
||||
conversationMsg.lastMsgSeq = syncChat.conversations![i].lastMsgSeq;
|
||||
@ -242,57 +269,74 @@ class WKConversationManager {
|
||||
conversationMsg.lastMsgTimestamp = syncChat.conversations![i].timestamp;
|
||||
conversationMsg.unreadCount = syncChat.conversations![i].unread;
|
||||
conversationMsg.version = syncChat.conversations![i].version;
|
||||
|
||||
WKUIConversationMsg uiMsg =
|
||||
ConversationDB.shared.getUIMsg(conversationMsg);
|
||||
//聊天消息对象
|
||||
|
||||
// 处理最近消息
|
||||
if (syncChat.conversations![i].recents != null &&
|
||||
syncChat.conversations![i].recents!.isNotEmpty) {
|
||||
for (WKSyncMsg wkSyncRecent in syncChat.conversations![i].recents!) {
|
||||
WKMsg msg = wkSyncRecent.getWKMsg();
|
||||
|
||||
// 处理反应列表
|
||||
if (msg.reactionList != null && msg.reactionList!.isNotEmpty) {
|
||||
msgReactionList.addAll(msg.reactionList!);
|
||||
}
|
||||
//判断会话列表的fromUID
|
||||
|
||||
// 判断会话列表的fromUID
|
||||
if (conversationMsg.lastClientMsgNO == msg.clientMsgNO) {
|
||||
conversationMsg.isDeleted = msg.isDeleted;
|
||||
uiMsg.isDeleted = conversationMsg.isDeleted;
|
||||
uiMsg.setWkMsg(msg);
|
||||
}
|
||||
|
||||
// 处理消息扩展信息
|
||||
if (wkSyncRecent.messageExtra != null) {
|
||||
WKMsgExtra extra = WKIM.shared.messageManager
|
||||
.wkSyncExtraMsg2WKMsgExtra(msg.channelID, msg.channelType,
|
||||
wkSyncRecent.messageExtra!);
|
||||
msgExtraList.add(extra);
|
||||
}
|
||||
|
||||
msgList.add(msg);
|
||||
}
|
||||
}
|
||||
|
||||
conversationMsgList.add(conversationMsg);
|
||||
uiMsgList.add(uiMsg);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存各类数据到数据库
|
||||
if (msgExtraList.isNotEmpty) {
|
||||
MessageDB.shared.insertMsgExtras(msgExtraList);
|
||||
// MessageDB.shared.insertOrUpdateMsgExtras(msgExtraList);
|
||||
}
|
||||
|
||||
if (msgList.isNotEmpty) {
|
||||
MessageDB.shared.insertMsgList(msgList);
|
||||
}
|
||||
|
||||
if (conversationMsgList.isNotEmpty) {
|
||||
// ConversationDB.shared.insertMsgList(conversationMsgList);
|
||||
ConversationDB.shared.insetMsgs(conversationMsgList);
|
||||
}
|
||||
|
||||
if (msgReactionList.isNotEmpty) {
|
||||
ReactionDB.shared.insertOrUpdateReactionList(msgReactionList);
|
||||
}
|
||||
|
||||
// 消息少于20条时,按顺序推送新消息
|
||||
if (msgList.isNotEmpty && msgList.length < 20) {
|
||||
msgList.sort((a, b) => a.messageSeq.compareTo(b.messageSeq));
|
||||
WKIM.shared.messageManager.pushNewMsg(msgList);
|
||||
}
|
||||
|
||||
// 刷新会话UI
|
||||
if (uiMsgList.isNotEmpty) {
|
||||
setRefreshUIMsgs(uiMsgList);
|
||||
}
|
||||
|
||||
// 处理命令
|
||||
if (syncChat.cmds != null && syncChat.cmds!.isNotEmpty) {
|
||||
for (int i = 0, size = syncChat.cmds!.length; i < size; i++) {
|
||||
dynamic json = <String, dynamic>{};
|
||||
|
@ -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.6.3
|
||||
version: 1.6.4
|
||||
homepage: https://github.com/WuKongIM/WuKongIMFlutterSDK
|
||||
|
||||
environment:
|
||||
|
Loading…
x
Reference in New Issue
Block a user