tencent_cloud_chat_uikit source code update to version 3.1.0+2
This commit is contained in:
parent
5700746752
commit
e7c38ef149
24
README_ZH.md
24
README_ZH.md
|
|
@ -113,16 +113,16 @@ _coreInstance.login(
|
||||||
全部场景码清单如下:
|
全部场景码清单如下:
|
||||||
|
|
||||||
| 场景码 `infoCode` | 推荐提示语 `infoRecommendText` | 场景描述 |
|
| 场景码 `infoCode` | 推荐提示语 `infoRecommendText` | 场景描述 |
|
||||||
| ----------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
|------------------| ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||||
| 6660101 | 好友申请已发送 | 用户申请添加其他用户为联系人 |
|
| 6660101(3.0.1废弃)| 好友申请已发送 | 用户申请添加其他用户为联系人 |
|
||||||
| 6660102 | 该用户已是好友 | 用户申请添加其他已是好友的用户为好友时,触发 `onTapAlreadyFriendsItem` 回调 |
|
| 6660102(3.0.1废弃)| 该用户已是好友 | 用户申请添加其他已是好友的用户为好友时,触发 `onTapAlreadyFriendsItem` 回调 |
|
||||||
| 6660201 | 群申请已发送 | 用户申请加入需要管理员审批的群聊 |
|
| 6660201 | 群申请已发送 | 用户申请加入需要管理员审批的群聊 |
|
||||||
| 6660202 | 您已是群成员 | 用户申请加群时,判断用户已经是当前群成员,触发 `onTapExistGroup` 回调 |
|
| 6660202 | 您已是群成员 | 用户申请加群时,判断用户已经是当前群成员,触发 `onTapExistGroup` 回调 |
|
||||||
| 6660401 | 无法定位到原消息 | 当用户需要跳转至@消息或者是引用消息时,在消息列表中查不到目标消息 |
|
| 6660401(3.0.1废弃)| 无法定位到原消息 | 当用户需要跳转至@消息或者是引用消息时,在消息列表中查不到目标消息 |
|
||||||
| 6660402 | 视频保存成功 | 用户在消息列表,点开视频消息后,选择保存视频 |
|
| 6660402 | 视频保存成功 | 用户在消息列表,点开视频消息后,选择保存视频 |
|
||||||
| 6660403 | 视频保存失败 | 用户在消息列表,点开视频消息后,选择保存视频 |
|
| 6660403 | 视频保存失败 | 用户在消息列表,点开视频消息后,选择保存视频 |
|
||||||
| 6660404 | 说话时间太短 | 用户发送了过短的语音消息 |
|
| 6660404 | 说话时间太短 | 用户发送了过短的语音消息 |
|
||||||
| 6660405 | 发送失败,视频不能大于 100MB | 用户试图发送大于 100MB 的视频 |
|
| 6660405(3.0.1废弃)| 发送失败,视频不能大于 100MB | 用户试图发送大于 100MB 的视频 |
|
||||||
| 6660406 | 图片保存成功 | 用户在消息列表,点开图片大图后,选择保存图片 |
|
| 6660406 | 图片保存成功 | 用户在消息列表,点开图片大图后,选择保存图片 |
|
||||||
| 6660407 | 图片保存失败 | 用户在消息列表,点开图片大图后,选择保存图片 |
|
| 6660407 | 图片保存失败 | 用户在消息列表,点开图片大图后,选择保存图片 |
|
||||||
| 6660408 | 已复制 | 用户在弹窗内选择复制文字消息 |
|
| 6660408 | 已复制 | 用户在弹窗内选择复制文字消息 |
|
||||||
|
|
@ -135,14 +135,14 @@ _coreInstance.login(
|
||||||
| 6661002 | 无网络连接,无法查看群成员 | 当用户试图在无网络环境下,修改群资料 |
|
| 6661002 | 无网络连接,无法查看群成员 | 当用户试图在无网络环境下,修改群资料 |
|
||||||
| 6661003 | 成功取消管理员身份 | 用户将群内其他用户移除管理员 |
|
| 6661003 | 成功取消管理员身份 | 用户将群内其他用户移除管理员 |
|
||||||
| 6661201 | 无网络连接,无法修改 | 当用户试图在无网络环境下,修改自己或联系人的资料 |
|
| 6661201 | 无网络连接,无法修改 | 当用户试图在无网络环境下,修改自己或联系人的资料 |
|
||||||
| 6661202 | 好友添加成功 | 在资料页添加其他用户为好友,并自动添加成功,无需验证 |
|
| 6661202(3.0.1废弃)| 好友添加成功 | 在资料页添加其他用户为好友,并自动添加成功,无需验证 |
|
||||||
| 6661203 | 好友申请已发出 | 在资料页添加其他用户为好友,对方设置需要验证 |
|
| 6661203(3.0.1废弃)| 好友申请已发出 | 在资料页添加其他用户为好友,对方设置需要验证 |
|
||||||
| 6661204 | 当前用户在黑名单 | 在资料页添加其他用户为好友,对方在自己的黑名单内 |
|
| 6661204(3.0.1废弃)| 当前用户在黑名单 | 在资料页添加其他用户为好友,对方在自己的黑名单内 |
|
||||||
| 6661205 | 好友添加失败 | 在资料页添加其他用户为好友,添加失败,可能是由于对方禁止加好友 |
|
| 6661205(3.0.1废弃)| 好友添加失败 | 在资料页添加其他用户为好友,添加失败,可能是由于对方禁止加好友 |
|
||||||
| 6661206 | 好友删除成功 | 在资料页删除其他用户为好友,成功 |
|
| 6661206(3.0.1废弃)| 好友删除成功 | 在资料页删除其他用户为好友,成功 |
|
||||||
| 6661207 | 好友删除失败 | 在资料页删除其他用户为好友,失败 |
|
| 6661207(3.0.1废弃)| 好友删除失败 | 在资料页删除其他用户为好友,失败 |
|
||||||
| 6661401 | 输入不能为空 | 当用户在录入信息时,输入了空字符串 |
|
| 6661401 | 输入不能为空 | 当用户在录入信息时,输入了空字符串 |
|
||||||
| 6661402 | 请传入离开群组生命周期函数,提供返回首页或其他页面的导航方法 | 用户退出群或解散群时,为提供返回首页办法 |
|
| 6661402(3.0.1废弃)| 请传入离开群组生命周期函数,提供返回首页或其他页面的导航方法 | 用户退出群或解散群时,为提供返回首页办法 |
|
||||||
| 6661403 | 设备存储空间不足,建议清理,以获得更好使用体验 | 在login成功后,会自动检测设备存储空间,如果不足1GB,会提示存储空间不足 |
|
| 6661403 | 设备存储空间不足,建议清理,以获得更好使用体验 | 在login成功后,会自动检测设备存储空间,如果不足1GB,会提示存储空间不足 |
|
||||||
|
|
||||||
## TIMUIKitConversation
|
## TIMUIKitConversation
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
final TUIChatGlobalModel globalModel = serviceLocator<TUIChatGlobalModel>();
|
final TUIChatGlobalModel globalModel = serviceLocator<TUIChatGlobalModel>();
|
||||||
final TUIChatModelTools tools = serviceLocator<TUIChatModelTools>();
|
final TUIChatModelTools tools = serviceLocator<TUIChatModelTools>();
|
||||||
final TUISelfInfoViewModel selfModel = serviceLocator<TUISelfInfoViewModel>();
|
final TUISelfInfoViewModel selfModel = serviceLocator<TUISelfInfoViewModel>();
|
||||||
final TUIConversationViewModel conversationViewModel = serviceLocator<TUIConversationViewModel>();
|
final TUIConversationViewModel conversationViewModel =
|
||||||
|
serviceLocator<TUIConversationViewModel>();
|
||||||
final _uuid = const Uuid();
|
final _uuid = const Uuid();
|
||||||
|
|
||||||
ChatLifeCycle? lifeCycle;
|
ChatLifeCycle? lifeCycle;
|
||||||
|
|
@ -135,7 +136,8 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
|
|
||||||
List<V2TimMessage> currentHistoryMsgList = getOriginMessageList();
|
List<V2TimMessage> currentHistoryMsgList = getOriginMessageList();
|
||||||
for (var v2TimMessage in currentHistoryMsgList) {
|
for (var v2TimMessage in currentHistoryMsgList) {
|
||||||
if (_selectedPositions.containsKey(v2TimMessage.msgID) && _selectedPositions[v2TimMessage.msgID]!) {
|
if (_selectedPositions.containsKey(v2TimMessage.msgID) &&
|
||||||
|
_selectedPositions[v2TimMessage.msgID]!) {
|
||||||
selectList.add(v2TimMessage);
|
selectList.add(v2TimMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -368,7 +370,6 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
? haveMoreLatestData = false
|
? haveMoreLatestData = false
|
||||||
: tempHaveMoreData = false;
|
: tempHaveMoreData = false;
|
||||||
|
|
||||||
|
|
||||||
// 获取当前聊天对话的历史消息列表
|
// 获取当前聊天对话的历史消息列表
|
||||||
final currentRecordList = globalModel.messageListMap[conversationID];
|
final currentRecordList = globalModel.messageListMap[conversationID];
|
||||||
|
|
||||||
|
|
@ -478,7 +479,10 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
|
|
||||||
_getMsgReadReceipt(List<V2TimMessage> message) async {
|
_getMsgReadReceipt(List<V2TimMessage> message) async {
|
||||||
final msgID = message
|
final msgID = message
|
||||||
.where((e) => (e.isSelf ?? true) && (e.needReadReceipt ?? false) && (e.status == MessageStatus.V2TIM_MSG_STATUS_SEND_SUCC))
|
.where((e) =>
|
||||||
|
(e.isSelf ?? true) &&
|
||||||
|
(e.needReadReceipt ?? false) &&
|
||||||
|
(e.status == MessageStatus.V2TIM_MSG_STATUS_SEND_SUCC))
|
||||||
.map((e) => e.msgID ?? '')
|
.map((e) => e.msgID ?? '')
|
||||||
.toList();
|
.toList();
|
||||||
if (msgID.isNotEmpty) {
|
if (msgID.isNotEmpty) {
|
||||||
|
|
@ -588,10 +592,10 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _notify(){
|
void _notify() {
|
||||||
try{
|
try {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}catch(e){
|
} catch (e) {
|
||||||
debugPrint(e.toString());
|
debugPrint(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -920,8 +924,8 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
|
|
||||||
_repliedMessage = null;
|
_repliedMessage = null;
|
||||||
final sendMsgRes = await _messageService.sendMessage(
|
final sendMsgRes = await _messageService.sendMessage(
|
||||||
cloudCustomData:
|
cloudCustomData: TencentUtils.checkString(
|
||||||
TencentUtils.checkString(messageInfoWithSender?.cloudCustomData) ??
|
messageInfoWithSender?.cloudCustomData) ??
|
||||||
json.encode(cloudCustomData),
|
json.encode(cloudCustomData),
|
||||||
id: textMessageInfo.id as String,
|
id: textMessageInfo.id as String,
|
||||||
offlinePushInfo: tools.buildMessagePushInfo(
|
offlinePushInfo: tools.buildMessagePushInfo(
|
||||||
|
|
@ -1149,9 +1153,11 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
for (var conversation in conversationList) {
|
for (var conversation in conversationList) {
|
||||||
final convID = conversation.groupID ?? conversation.userID ?? "";
|
final convID = conversation.groupID ?? conversation.userID ?? "";
|
||||||
final convType = conversation.type;
|
final convType = conversation.type;
|
||||||
List<V2TimMessage> currentHistoryMsgList = globalModel.messageListMap[conversationID] ?? [];
|
List<V2TimMessage> currentHistoryMsgList =
|
||||||
|
globalModel.messageListMap[conversationID] ?? [];
|
||||||
for (var message in selectedMessages) {
|
for (var message in selectedMessages) {
|
||||||
final forwardMessageInfo = await _messageService.createForwardMessage(msgID: message.msgID!);
|
final forwardMessageInfo =
|
||||||
|
await _messageService.createForwardMessage(msgID: message.msgID!);
|
||||||
final messageInfo = forwardMessageInfo!.messageInfo;
|
final messageInfo = forwardMessageInfo!.messageInfo;
|
||||||
if (messageInfo != null) {
|
if (messageInfo != null) {
|
||||||
tools.setUserInfoForMessage(messageInfo, forwardMessageInfo.id);
|
tools.setUserInfoForMessage(messageInfo, forwardMessageInfo.id);
|
||||||
|
|
@ -1159,11 +1165,9 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
addSendingMessageID(messageInfo.id);
|
addSendingMessageID(messageInfo.id);
|
||||||
// 如果转发的会话是当前会话,则直接添加到当前会话的消息列表中
|
// 如果转发的会话是当前会话,则直接添加到当前会话的消息列表中
|
||||||
if (convID == conversationID) {
|
if (convID == conversationID) {
|
||||||
if (globalModel.getMessageListPosition(convID) != HistoryMessagePosition.notShowLatest) {
|
if (globalModel.getMessageListPosition(convID) !=
|
||||||
currentHistoryMsgList = [
|
HistoryMessagePosition.notShowLatest) {
|
||||||
messageInfo,
|
currentHistoryMsgList = [messageInfo, ...currentHistoryMsgList];
|
||||||
...currentHistoryMsgList
|
|
||||||
];
|
|
||||||
globalModel.setMessageList(conversationID, currentHistoryMsgList);
|
globalModel.setMessageList(conversationID, currentHistoryMsgList);
|
||||||
_notify();
|
_notify();
|
||||||
}
|
}
|
||||||
|
|
@ -1198,7 +1202,8 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
for (var conversation in conversationList) {
|
for (var conversation in conversationList) {
|
||||||
final convID = conversation.groupID ?? conversation.userID ?? "";
|
final convID = conversation.groupID ?? conversation.userID ?? "";
|
||||||
final convType = conversation.type;
|
final convType = conversation.type;
|
||||||
List<V2TimMessage> currentHistoryMsgList = globalModel.messageListMap[conversationID] ?? [];
|
List<V2TimMessage> currentHistoryMsgList =
|
||||||
|
globalModel.messageListMap[conversationID] ?? [];
|
||||||
final mergerMessageInfo = await _messageService.createMergerMessage(
|
final mergerMessageInfo = await _messageService.createMergerMessage(
|
||||||
msgIDList: msgIDList,
|
msgIDList: msgIDList,
|
||||||
title: title,
|
title: title,
|
||||||
|
|
@ -1211,11 +1216,9 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
addSendingMessageID(messageInfo.id);
|
addSendingMessageID(messageInfo.id);
|
||||||
// 如果转发的会话是当前会话,则直接添加到当前会话的消息列表中
|
// 如果转发的会话是当前会话,则直接添加到当前会话的消息列表中
|
||||||
if (convID == conversationID) {
|
if (convID == conversationID) {
|
||||||
if (globalModel.getMessageListPosition(convID) != HistoryMessagePosition.notShowLatest) {
|
if (globalModel.getMessageListPosition(convID) !=
|
||||||
currentHistoryMsgList = [
|
HistoryMessagePosition.notShowLatest) {
|
||||||
messageInfo,
|
currentHistoryMsgList = [messageInfo, ...currentHistoryMsgList];
|
||||||
...currentHistoryMsgList
|
|
||||||
];
|
|
||||||
globalModel.setMessageList(conversationID, currentHistoryMsgList);
|
globalModel.setMessageList(conversationID, currentHistoryMsgList);
|
||||||
_notify();
|
_notify();
|
||||||
}
|
}
|
||||||
|
|
@ -1244,16 +1247,14 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentHistoryMsgList.removeWhere((element) => element.msgID == message.msgID);
|
currentHistoryMsgList
|
||||||
|
.removeWhere((element) => element.msgID == message.msgID);
|
||||||
message.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
|
message.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
|
||||||
addSendingMessageID(message.msgID);
|
addSendingMessageID(message.msgID);
|
||||||
globalModel.setMessageList(convID, currentHistoryMsgList);
|
globalModel.setMessageList(convID, currentHistoryMsgList);
|
||||||
if (globalModel.getMessageListPosition(conversationID) !=
|
if (globalModel.getMessageListPosition(conversationID) !=
|
||||||
HistoryMessagePosition.notShowLatest) {
|
HistoryMessagePosition.notShowLatest) {
|
||||||
currentHistoryMsgList = [
|
currentHistoryMsgList = [message, ...currentHistoryMsgList];
|
||||||
message,
|
|
||||||
...currentHistoryMsgList
|
|
||||||
];
|
|
||||||
globalModel.setMessageList(conversationID, currentHistoryMsgList);
|
globalModel.setMessageList(conversationID, currentHistoryMsgList);
|
||||||
_notify();
|
_notify();
|
||||||
}
|
}
|
||||||
|
|
@ -1426,7 +1427,8 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
for (var msgID in msgIDs) {
|
for (var msgID in msgIDs) {
|
||||||
messageList.removeWhere((element) => element.msgID == msgID);
|
messageList.removeWhere((element) => element.msgID == msgID);
|
||||||
}
|
}
|
||||||
globalModel.setMessageList(conversationID, messageList, isDeleteMsg: true);
|
globalModel.setMessageList(conversationID, messageList,
|
||||||
|
isDeleteMsg: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1495,7 +1497,6 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
return _sendingMessageIDMap[id];
|
return _sendingMessageIDMap[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
print("sending test, hasDelayedRenderSendingStatus false:${id}");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// ignore_for_file: unnecessary_getters_setters
|
// ignore_for_file: unnecessary_getters_setters
|
||||||
|
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/conversation_life_cycle.dart';
|
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/conversation_life_cycle.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
|
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
|
||||||
|
|
@ -11,7 +12,8 @@ import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
|
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
|
||||||
|
|
||||||
List<T> removeDuplicates<T>(List<T> list, bool Function(T first, T second) isEqual) {
|
List<T> removeDuplicates<T>(
|
||||||
|
List<T> list, bool Function(T first, T second) isEqual) {
|
||||||
List<T> output = [];
|
List<T> output = [];
|
||||||
for (var i = 0; i < list.length; i++) {
|
for (var i = 0; i < list.length; i++) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
@ -32,10 +34,14 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
static const String conversationC2CPrefix = "c2c_";
|
static const String conversationC2CPrefix = "c2c_";
|
||||||
static const String conversationGroupPrefix = "group_";
|
static const String conversationGroupPrefix = "group_";
|
||||||
|
|
||||||
final TUISelfInfoViewModel selfInfoViewModel = serviceLocator<TUISelfInfoViewModel>();
|
final TUISelfInfoViewModel selfInfoViewModel =
|
||||||
final ConversationService _conversationService = serviceLocator<ConversationService>();
|
serviceLocator<TUISelfInfoViewModel>();
|
||||||
final FriendshipServices _friendshipServices = serviceLocator<FriendshipServices>();
|
final ConversationService _conversationService =
|
||||||
final TUIChatGlobalModel _chatGlobalModel = serviceLocator<TUIChatGlobalModel>();
|
serviceLocator<ConversationService>();
|
||||||
|
final FriendshipServices _friendshipServices =
|
||||||
|
serviceLocator<FriendshipServices>();
|
||||||
|
final TUIChatGlobalModel _chatGlobalModel =
|
||||||
|
serviceLocator<TUIChatGlobalModel>();
|
||||||
final MessageService _messageService = serviceLocator<MessageService>();
|
final MessageService _messageService = serviceLocator<MessageService>();
|
||||||
late V2TimConversationListener _conversationListener;
|
late V2TimConversationListener _conversationListener;
|
||||||
List<V2TimConversation?> _conversationList = [];
|
List<V2TimConversation?> _conversationList = [];
|
||||||
|
|
@ -45,7 +51,8 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
bool _haveMoreData = true;
|
bool _haveMoreData = true;
|
||||||
int _totalUnReadCount = 0;
|
int _totalUnReadCount = 0;
|
||||||
String? _scrollToConversation;
|
String? _scrollToConversation;
|
||||||
final TUIChatGlobalModel globalChatModel = serviceLocator<TUIChatGlobalModel>();
|
final TUIChatGlobalModel globalChatModel =
|
||||||
|
serviceLocator<TUIChatGlobalModel>();
|
||||||
|
|
||||||
String _nextSeq = "0";
|
String _nextSeq = "0";
|
||||||
ConversationLifeCycle? _lifeCycle;
|
ConversationLifeCycle? _lifeCycle;
|
||||||
|
|
@ -54,10 +61,13 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
if (PlatformUtils().isWeb) {
|
if (PlatformUtils().isWeb) {
|
||||||
try {
|
try {
|
||||||
_conversationList.sort((a, b) {
|
_conversationList.sort((a, b) {
|
||||||
return b!.lastMessage!.timestamp!.compareTo(a!.lastMessage!.timestamp!);
|
return b!.lastMessage!.timestamp!
|
||||||
|
.compareTo(a!.lastMessage!.timestamp!);
|
||||||
});
|
});
|
||||||
|
|
||||||
final pinnedConversation = _conversationList.where((element) => element?.isPinned == true).toList();
|
final pinnedConversation = _conversationList
|
||||||
|
.where((element) => element?.isPinned == true)
|
||||||
|
.toList();
|
||||||
_conversationList.removeWhere((element) => element?.isPinned == true);
|
_conversationList.removeWhere((element) => element?.isPinned == true);
|
||||||
_conversationList = [...pinnedConversation, ..._conversationList];
|
_conversationList = [...pinnedConversation, ..._conversationList];
|
||||||
// ignore: empty_catches
|
// ignore: empty_catches
|
||||||
|
|
@ -69,7 +79,8 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
V2TimConversation? getConversation(String conversationID) {
|
V2TimConversation? getConversation(String conversationID) {
|
||||||
return _conversationList.firstWhere((element) => element?.conversationID == conversationID);
|
return _conversationList.firstWhereOrNull(
|
||||||
|
(element) => element?.conversationID == conversationID);
|
||||||
}
|
}
|
||||||
|
|
||||||
String? get scrollToConversation => _scrollToConversation;
|
String? get scrollToConversation => _scrollToConversation;
|
||||||
|
|
@ -116,7 +127,8 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
TUIConversationViewModel() {
|
TUIConversationViewModel() {
|
||||||
_conversationListener = V2TimConversationListener(onConversationChanged: (conversationList) {
|
_conversationListener =
|
||||||
|
V2TimConversationListener(onConversationChanged: (conversationList) {
|
||||||
_onConversationListChanged(conversationList);
|
_onConversationListChanged(conversationList);
|
||||||
}, onNewConversation: (conversationList) {
|
}, onNewConversation: (conversationList) {
|
||||||
_addNewConversation(conversationList);
|
_addNewConversation(conversationList);
|
||||||
|
|
@ -129,7 +141,7 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
if (!PlatformUtils().isWeb) {
|
if (!PlatformUtils().isWeb) {
|
||||||
loadInitConversation();
|
loadInitConversation();
|
||||||
}
|
}
|
||||||
}, onConversationDeleted:(List<String> conversationIDList) {
|
}, onConversationDeleted: (List<String> conversationIDList) {
|
||||||
_onConversationDeleted(conversationIDList);
|
_onConversationDeleted(conversationIDList);
|
||||||
for (var conversationID in conversationIDList) {
|
for (var conversationID in conversationIDList) {
|
||||||
String resultID = "";
|
String resultID = "";
|
||||||
|
|
@ -162,7 +174,8 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
Future<void> loadData({required int count}) async {
|
Future<void> loadData({required int count}) async {
|
||||||
_haveMoreData = true;
|
_haveMoreData = true;
|
||||||
final isRefresh = _nextSeq == "0";
|
final isRefresh = _nextSeq == "0";
|
||||||
final conversationResult = await _conversationService.getConversationList(nextSeq: _nextSeq, count: count);
|
final conversationResult = await _conversationService.getConversationList(
|
||||||
|
nextSeq: _nextSeq, count: count);
|
||||||
_nextSeq = conversationResult?.nextSeq ?? "";
|
_nextSeq = conversationResult?.nextSeq ?? "";
|
||||||
final conversationList = conversationResult?.conversationList;
|
final conversationList = conversationResult?.conversationList;
|
||||||
if (conversationList != null) {
|
if (conversationList != null) {
|
||||||
|
|
@ -175,8 +188,12 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
} else {
|
} else {
|
||||||
combinedConversationList = [..._conversationList, ...conversationList];
|
combinedConversationList = [..._conversationList, ...conversationList];
|
||||||
}
|
}
|
||||||
final List<V2TimConversation?> finalConversationList = await _lifeCycle?.conversationListWillMount(combinedConversationList) ?? combinedConversationList;
|
final List<V2TimConversation?> finalConversationList = await _lifeCycle
|
||||||
_conversationList = removeDuplicates<V2TimConversation?>(finalConversationList, (item1, item2) => item1?.conversationID == item2?.conversationID);
|
?.conversationListWillMount(combinedConversationList) ??
|
||||||
|
combinedConversationList;
|
||||||
|
_conversationList = removeDuplicates<V2TimConversation?>(
|
||||||
|
finalConversationList,
|
||||||
|
(item1, item2) => item1?.conversationID == item2?.conversationID);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
_totalUnReadCount = await _conversationService.getTotalUnreadCount();
|
_totalUnReadCount = await _conversationService.getTotalUnreadCount();
|
||||||
|
|
@ -193,11 +210,15 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
required String conversationID,
|
required String conversationID,
|
||||||
required bool isPinned,
|
required bool isPinned,
|
||||||
}) {
|
}) {
|
||||||
return _conversationService.pinConversation(conversationID: conversationID, isPinned: isPinned);
|
return _conversationService.pinConversation(
|
||||||
|
conversationID: conversationID, isPinned: isPinned);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<V2TimCallback?> clearHistoryMessage({required String convID, required int convType}) async {
|
Future<V2TimCallback?> clearHistoryMessage(
|
||||||
if (_lifeCycle?.shouldClearHistoricalMessageForConversation != null && await _lifeCycle!.shouldClearHistoricalMessageForConversation(convID) == false) {
|
{required String convID, required int convType}) async {
|
||||||
|
if (_lifeCycle?.shouldClearHistoricalMessageForConversation != null &&
|
||||||
|
await _lifeCycle!.shouldClearHistoricalMessageForConversation(convID) ==
|
||||||
|
false) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -211,17 +232,22 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
searchFriends(String searchKey) async {
|
searchFriends(String searchKey) async {
|
||||||
final res = await _friendshipServices.searchFriends(searchParam: V2TimFriendSearchParam(keywordList: [searchKey]));
|
final res = await _friendshipServices.searchFriends(
|
||||||
|
searchParam: V2TimFriendSearchParam(keywordList: [searchKey]));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<V2TimCallback?> deleteConversation({required String conversationID}) async {
|
Future<V2TimCallback?> deleteConversation(
|
||||||
if (_lifeCycle?.shouldDeleteConversation != null && await _lifeCycle!.shouldDeleteConversation(conversationID) == false) {
|
{required String conversationID}) async {
|
||||||
|
if (_lifeCycle?.shouldDeleteConversation != null &&
|
||||||
|
await _lifeCycle!.shouldDeleteConversation(conversationID) == false) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final res = await _conversationService.deleteConversation(conversationID: conversationID);
|
final res = await _conversationService.deleteConversation(
|
||||||
|
conversationID: conversationID);
|
||||||
if (res.code == 0) {
|
if (res.code == 0) {
|
||||||
_conversationList.removeWhere((element) => element?.conversationID == conversationID);
|
_conversationList
|
||||||
|
.removeWhere((element) => element?.conversationID == conversationID);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -229,9 +255,11 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
|
|
||||||
_onConversationListChanged(List<V2TimConversation> list) {
|
_onConversationListChanged(List<V2TimConversation> list) {
|
||||||
for (int element = 0; element < list.length; element++) {
|
for (int element = 0; element < list.length; element++) {
|
||||||
int index = _conversationList.indexWhere((item) => item!.conversationID == list[element].conversationID);
|
int index = _conversationList.indexWhere(
|
||||||
|
(item) => item!.conversationID == list[element].conversationID);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
_conversationList.setAll(index, [list[element]] as List<V2TimConversation?>);
|
_conversationList.setAll(
|
||||||
|
index, [list[element]] as List<V2TimConversation?>);
|
||||||
} else {
|
} else {
|
||||||
_conversationList.add(list[element]);
|
_conversationList.add(list[element]);
|
||||||
}
|
}
|
||||||
|
|
@ -242,10 +270,13 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
|
|
||||||
_onConversationDeleted(List<String> list) {
|
_onConversationDeleted(List<String> list) {
|
||||||
for (int i = 0; i < list.length; i++) {
|
for (int i = 0; i < list.length; i++) {
|
||||||
int index = _conversationList.indexWhere((item) => item!.conversationID == list[i]);
|
int index = _conversationList
|
||||||
|
.indexWhere((item) => item!.conversationID == list[i]);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
_conversationList.removeAt(index);
|
_conversationList.removeAt(index);
|
||||||
_conversationList = removeDuplicates<V2TimConversation?>(_conversationList, (item1, item2) => item1?.conversationID == item2?.conversationID);
|
_conversationList = removeDuplicates<V2TimConversation?>(
|
||||||
|
_conversationList,
|
||||||
|
(item1, item2) => item1?.conversationID == item2?.conversationID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
@ -253,16 +284,19 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
|
|
||||||
_addNewConversation(List<V2TimConversation> list) {
|
_addNewConversation(List<V2TimConversation> list) {
|
||||||
_conversationList.addAll(list);
|
_conversationList.addAll(list);
|
||||||
_conversationList = removeDuplicates<V2TimConversation?>(_conversationList, (item1, item2) => item1?.conversationID == item2?.conversationID);
|
_conversationList = removeDuplicates<V2TimConversation?>(_conversationList,
|
||||||
|
(item1, item2) => item1?.conversationID == item2?.conversationID);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
setConversationListener() {
|
setConversationListener() {
|
||||||
_conversationService.addConversationListener(listener: _conversationListener);
|
_conversationService.addConversationListener(
|
||||||
|
listener: _conversationListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeConversationListener() {
|
removeConversationListener() {
|
||||||
_conversationService.removeConversationListener(listener: _conversationListener);
|
_conversationService.removeConversationListener(
|
||||||
|
listener: _conversationListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<V2TimCallback> setConversationDraft({
|
Future<V2TimCallback> setConversationDraft({
|
||||||
|
|
@ -272,19 +306,25 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
String? groupID,
|
String? groupID,
|
||||||
bool isAllowWeb = true,
|
bool isAllowWeb = true,
|
||||||
}) async {
|
}) async {
|
||||||
assert(!isTopic || (groupID != null && groupID.isNotEmpty), "When 'isTopic' is true, 'groupID' must not be null or empty.");
|
assert(!isTopic || (groupID != null && groupID.isNotEmpty),
|
||||||
|
"When 'isTopic' is true, 'groupID' must not be null or empty.");
|
||||||
if (PlatformUtils().isWeb && isAllowWeb) {
|
if (PlatformUtils().isWeb && isAllowWeb) {
|
||||||
webDraftMap[conversationID] = draftText ?? "";
|
webDraftMap[conversationID] = draftText ?? "";
|
||||||
return V2TimCallback(code: 0, desc: "");
|
return V2TimCallback(code: 0, desc: "");
|
||||||
} else {
|
} else {
|
||||||
if (isTopic) {
|
if (isTopic) {
|
||||||
final topicInfoList = await TencentImSDKPlugin.v2TIMManager.getGroupManager().getTopicInfoList(groupID: groupID!, topicIDList: [conversationID]);
|
final topicInfoList = await TencentImSDKPlugin.v2TIMManager
|
||||||
|
.getGroupManager()
|
||||||
|
.getTopicInfoList(groupID: groupID!, topicIDList: [conversationID]);
|
||||||
final topicInfo = topicInfoList.data?.first.topicInfo;
|
final topicInfo = topicInfoList.data?.first.topicInfo;
|
||||||
topicInfo?.draftText = draftText;
|
topicInfo?.draftText = draftText;
|
||||||
final res = await TencentImSDKPlugin.v2TIMManager.getGroupManager().setTopicInfo(groupID: groupID, topicInfo: topicInfo!);
|
final res = await TencentImSDKPlugin.v2TIMManager
|
||||||
|
.getGroupManager()
|
||||||
|
.setTopicInfo(groupID: groupID, topicInfo: topicInfo!);
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
return _conversationService.setConversationDraft(conversationID: conversationID, draftText: draftText);
|
return _conversationService.setConversationDraft(
|
||||||
|
conversationID: conversationID, draftText: draftText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
import 'package:flutter_slidable_plus_plus/flutter_slidable_plus_plus.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
|
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/block_list_life_cycle.dart';
|
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/block_list_life_cycle.dart';
|
||||||
|
|
@ -88,7 +88,8 @@ class _TIMUIKitBlackListState extends TIMUIKitState<TIMUIKitBlackList> {
|
||||||
child: Text(
|
child: Text(
|
||||||
showName,
|
showName,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: theme.black, fontSize: isDesktopScreen ? 14 : 18),
|
color: theme.black,
|
||||||
|
fontSize: isDesktopScreen ? 14 : 18),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
if (isDesktopScreen)
|
if (isDesktopScreen)
|
||||||
|
|
@ -132,7 +133,6 @@ class _TIMUIKitBlackListState extends TIMUIKitState<TIMUIKitBlackList> {
|
||||||
return widget.itemBuilder ?? _itemBuilder;
|
return widget.itemBuilder ?? _itemBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,8 @@ typedef MessageRowBuilder = Widget? Function(
|
||||||
Function onScrollToIndexBegin,
|
Function onScrollToIndexBegin,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef MessageNickNameBuilder = Widget Function(BuildContext context, V2TimMessage message, TUIChatSeparateViewModel model);
|
typedef MessageNickNameBuilder = Widget Function(
|
||||||
|
BuildContext context, V2TimMessage message, TUIChatSeparateViewModel model);
|
||||||
|
|
||||||
typedef MessageItemContent = Widget? Function(
|
typedef MessageItemContent = Widget? Function(
|
||||||
V2TimMessage message,
|
V2TimMessage message,
|
||||||
|
|
@ -71,7 +72,8 @@ class MessageHoverControlItem {
|
||||||
Widget icon;
|
Widget icon;
|
||||||
ValueChanged<TapDownDetails> onClick;
|
ValueChanged<TapDownDetails> onClick;
|
||||||
|
|
||||||
MessageHoverControlItem({required this.name, required this.icon, required this.onClick});
|
MessageHoverControlItem(
|
||||||
|
{required this.name, required this.icon, required this.onClick});
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageItemBuilder {
|
class MessageItemBuilder {
|
||||||
|
|
@ -139,7 +141,11 @@ class MessageToolTipItem {
|
||||||
final String iconImageAsset;
|
final String iconImageAsset;
|
||||||
final VoidCallback onClick;
|
final VoidCallback onClick;
|
||||||
|
|
||||||
MessageToolTipItem({required this.label, required this.id, required this.iconImageAsset, required this.onClick});
|
MessageToolTipItem(
|
||||||
|
{required this.label,
|
||||||
|
required this.id,
|
||||||
|
required this.iconImageAsset,
|
||||||
|
required this.onClick});
|
||||||
}
|
}
|
||||||
|
|
||||||
class ToolTipsConfig {
|
class ToolTipsConfig {
|
||||||
|
|
@ -165,10 +171,12 @@ class ToolTipsConfig {
|
||||||
bool showTranslation;
|
bool showTranslation;
|
||||||
|
|
||||||
/// A builder for additional custom items. We recommend using `additionalMessageToolTips` instead of this field since version 2.0, as you only need to provide the data rather than the whole widget. This makes usage easier and you don't need to worry about the UI display.
|
/// A builder for additional custom items. We recommend using `additionalMessageToolTips` instead of this field since version 2.0, as you only need to provide the data rather than the whole widget. This makes usage easier and you don't need to worry about the UI display.
|
||||||
final Widget? Function(V2TimMessage message, Function() closeTooltip, [Key? key, BuildContext? context])? additionalItemBuilder;
|
final Widget? Function(V2TimMessage message, Function() closeTooltip,
|
||||||
|
[Key? key, BuildContext? context])? additionalItemBuilder;
|
||||||
|
|
||||||
/// A list of additional message tooltip menu items, provided with the data only. We recommend using this field instead of the previous `additionalItemBuilder`.
|
/// A list of additional message tooltip menu items, provided with the data only. We recommend using this field instead of the previous `additionalItemBuilder`.
|
||||||
List<MessageToolTipItem> Function(V2TimMessage message, Function() closeTooltip)? additionalMessageToolTips;
|
List<MessageToolTipItem> Function(
|
||||||
|
V2TimMessage message, Function() closeTooltip)? additionalMessageToolTips;
|
||||||
|
|
||||||
ToolTipsConfig(
|
ToolTipsConfig(
|
||||||
{this.showDeleteMessage = true,
|
{this.showDeleteMessage = true,
|
||||||
|
|
@ -179,7 +187,8 @@ class ToolTipsConfig {
|
||||||
this.showCopyMessage = true,
|
this.showCopyMessage = true,
|
||||||
this.showForwardMessage = true,
|
this.showForwardMessage = true,
|
||||||
this.additionalMessageToolTips,
|
this.additionalMessageToolTips,
|
||||||
@Deprecated("Please use `additionalMessageToolTips` instead. You are now only expected to specify the data, rather than providing a whole widget. This makes usage easier, as you no longer need to worry about the UI display.")
|
@Deprecated(
|
||||||
|
"Please use `additionalMessageToolTips` instead. You are now only expected to specify the data, rather than providing a whole widget. This makes usage easier, as you no longer need to worry about the UI display.")
|
||||||
this.additionalItemBuilder});
|
this.additionalItemBuilder});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -188,10 +197,12 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
|
||||||
final V2TimMessage message;
|
final V2TimMessage message;
|
||||||
|
|
||||||
/// tap remote user avatar callback function
|
/// tap remote user avatar callback function
|
||||||
final void Function(String userID, TapDownDetails tapDetails)? onTapForOthersPortrait;
|
final void Function(String userID, TapDownDetails tapDetails)?
|
||||||
|
onTapForOthersPortrait;
|
||||||
|
|
||||||
/// secondary tap remote user avatar callback function
|
/// secondary tap remote user avatar callback function
|
||||||
final void Function(String userID, TapDownDetails tapDetails)? onSecondaryTapForOthersPortrait;
|
final void Function(String userID, TapDownDetails tapDetails)?
|
||||||
|
onSecondaryTapForOthersPortrait;
|
||||||
|
|
||||||
/// the function use for reply message, when click replied message can scroll to it.
|
/// the function use for reply message, when click replied message can scroll to it.
|
||||||
final Function? onScrollToIndex;
|
final Function? onScrollToIndex;
|
||||||
|
|
@ -200,7 +211,8 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
|
||||||
final Function? onScrollToIndexBegin;
|
final Function? onScrollToIndexBegin;
|
||||||
|
|
||||||
/// the callback for long press event, except myself avatar
|
/// the callback for long press event, except myself avatar
|
||||||
final Function(String? userId, String? nickName)? onLongPressForOthersHeadPortrait;
|
final Function(String? userId, String? nickName)?
|
||||||
|
onLongPressForOthersHeadPortrait;
|
||||||
|
|
||||||
/// message item builder, works for customize all message types and row layout.
|
/// message item builder, works for customize all message types and row layout.
|
||||||
final MessageItemBuilder? messageItemBuilder;
|
final MessageItemBuilder? messageItemBuilder;
|
||||||
|
|
@ -220,7 +232,8 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
|
||||||
/// Auto mention user when send reply message
|
/// Auto mention user when send reply message
|
||||||
final bool allowAtUserWhenReply;
|
final bool allowAtUserWhenReply;
|
||||||
|
|
||||||
@Deprecated("Nickname will not show in one-to-one chat, if you tend to control it in group chat, please use `isShowSelfNameInGroup` and `isShowOthersNameInGroup` from `config: TIMUIKitChatConfig` instead")
|
@Deprecated(
|
||||||
|
"Nickname will not show in one-to-one chat, if you tend to control it in group chat, please use `isShowSelfNameInGroup` and `isShowOthersNameInGroup` from `config: TIMUIKitChatConfig` instead")
|
||||||
|
|
||||||
/// allow show user nick name
|
/// allow show user nick name
|
||||||
final bool showNickName;
|
final bool showNickName;
|
||||||
|
|
@ -241,16 +254,19 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
|
||||||
final EdgeInsetsGeometry? textPadding;
|
final EdgeInsetsGeometry? textPadding;
|
||||||
|
|
||||||
/// avatar builder
|
/// avatar builder
|
||||||
final Widget Function(BuildContext context, V2TimMessage message)? userAvatarBuilder;
|
final Widget Function(BuildContext context, V2TimMessage message)?
|
||||||
|
userAvatarBuilder;
|
||||||
|
|
||||||
/// theme info for message and avatar
|
/// theme info for message and avatar
|
||||||
final MessageThemeData? themeData;
|
final MessageThemeData? themeData;
|
||||||
|
|
||||||
/// builder for nick name row
|
/// builder for nick name row
|
||||||
final Widget Function(BuildContext context, V2TimMessage message)? topRowBuilder;
|
final Widget Function(BuildContext context, V2TimMessage message)?
|
||||||
|
topRowBuilder;
|
||||||
|
|
||||||
/// builder for bottom raw which under message content
|
/// builder for bottom raw which under message content
|
||||||
final Widget Function(BuildContext context, V2TimMessage message)? bottomRowBuilder;
|
final Widget Function(BuildContext context, V2TimMessage message)?
|
||||||
|
bottomRowBuilder;
|
||||||
|
|
||||||
// open MessageReaction
|
// open MessageReaction
|
||||||
final bool? isUseMessageReaction;
|
final bool? isUseMessageReaction;
|
||||||
|
|
@ -271,7 +287,9 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
|
||||||
const TIMUIKitHistoryMessageListItem(
|
const TIMUIKitHistoryMessageListItem(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
required this.message,
|
required this.message,
|
||||||
@Deprecated("Nickname will not show in one-to-one chat, if you tend to control it in group chat, please use `isShowSelfNameInGroup` and `isShowOthersNameInGroup` from `config: TIMUIKitChatConfig` instead") this.showNickName = false,
|
@Deprecated(
|
||||||
|
"Nickname will not show in one-to-one chat, if you tend to control it in group chat, please use `isShowSelfNameInGroup` and `isShowOthersNameInGroup` from `config: TIMUIKitChatConfig` instead")
|
||||||
|
this.showNickName = false,
|
||||||
this.onScrollToIndex,
|
this.onScrollToIndex,
|
||||||
this.onScrollToIndexBegin,
|
this.onScrollToIndexBegin,
|
||||||
this.onTapForOthersPortrait,
|
this.onTapForOthersPortrait,
|
||||||
|
|
@ -308,7 +326,9 @@ class TipsActionItem extends TIMUIKitStatelessWidget {
|
||||||
final String icon;
|
final String icon;
|
||||||
final String? package;
|
final String? package;
|
||||||
|
|
||||||
TipsActionItem({Key? key, required this.label, required this.icon, this.package}) : super(key: key);
|
TipsActionItem(
|
||||||
|
{Key? key, required this.label, required this.icon, this.package})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
|
|
@ -336,13 +356,16 @@ class TipsActionItem extends TIMUIKitStatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistoryMessageListItem> with SingleTickerProviderStateMixin {
|
class _TIMUIKItHistoryMessageListItemState
|
||||||
|
extends TIMUIKitState<TIMUIKitHistoryMessageListItem>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
SuperTooltip? tooltip;
|
SuperTooltip? tooltip;
|
||||||
late AnimationController _animationController;
|
late AnimationController _animationController;
|
||||||
|
|
||||||
// ignore: unused_field
|
// ignore: unused_field
|
||||||
final MessageService _messageService = serviceLocator<MessageService>();
|
final MessageService _messageService = serviceLocator<MessageService>();
|
||||||
final TUISelfInfoViewModel selfInfoModel = serviceLocator<TUISelfInfoViewModel>();
|
final TUISelfInfoViewModel selfInfoModel =
|
||||||
|
serviceLocator<TUISelfInfoViewModel>();
|
||||||
final TUIThemeViewModel themeModel = serviceLocator<TUIThemeViewModel>();
|
final TUIThemeViewModel themeModel = serviceLocator<TUIThemeViewModel>();
|
||||||
|
|
||||||
// bool isChecked = false;
|
// bool isChecked = false;
|
||||||
|
|
@ -353,7 +376,9 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_animationController = AnimationController(duration: const Duration(seconds: 1), vsync: this)..repeat();
|
_animationController =
|
||||||
|
AnimationController(duration: const Duration(seconds: 1), vsync: this)
|
||||||
|
..repeat();
|
||||||
}
|
}
|
||||||
|
|
||||||
closeTooltip() {
|
closeTooltip() {
|
||||||
|
|
@ -361,10 +386,15 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isReplyMessage(V2TimMessage message) {
|
bool isReplyMessage(V2TimMessage message) {
|
||||||
final hasCustomData = message.cloudCustomData != null && message.cloudCustomData != "";
|
final hasCustomData =
|
||||||
|
message.cloudCustomData != null && message.cloudCustomData != "";
|
||||||
if (hasCustomData) {
|
if (hasCustomData) {
|
||||||
try {
|
try {
|
||||||
final CloudCustomData messageCloudCustomData = CloudCustomData.fromJson(json.decode(TencentUtils.checkString(message.cloudCustomData) != null ? message.cloudCustomData! : "{}"));
|
final CloudCustomData messageCloudCustomData = CloudCustomData.fromJson(
|
||||||
|
json.decode(
|
||||||
|
TencentUtils.checkString(message.cloudCustomData) != null
|
||||||
|
? message.cloudCustomData!
|
||||||
|
: "{}"));
|
||||||
if (messageCloudCustomData.messageReply != null) {
|
if (messageCloudCustomData.messageReply != null) {
|
||||||
MessageRepliedData.fromJson(messageCloudCustomData.messageReply!);
|
MessageRepliedData.fromJson(messageCloudCustomData.messageReply!);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -377,7 +407,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
(bool isRevoke, bool isRevokeByAdmin) isRevokeMessage(V2TimMessage message, TUIChatSeparateViewModel model) {
|
(bool isRevoke, bool isRevokeByAdmin) isRevokeMessage(
|
||||||
|
V2TimMessage message, TUIChatSeparateViewModel model) {
|
||||||
if (message.status == 6) {
|
if (message.status == 6) {
|
||||||
return (true, false);
|
return (true, false);
|
||||||
} else if (model.chatConfig.isGroupAdminRecallEnabled) {
|
} else if (model.chatConfig.isGroupAdminRecallEnabled) {
|
||||||
|
|
@ -393,9 +424,11 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
return (false, false);
|
return (false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _messageItemBuilder(V2TimMessage messageItem, TUIChatSeparateViewModel model) {
|
Widget _messageItemBuilder(
|
||||||
|
V2TimMessage messageItem, TUIChatSeparateViewModel model) {
|
||||||
final msgType = messageItem.elemType;
|
final msgType = messageItem.elemType;
|
||||||
final isShowJump = (model.jumpMsgID == messageItem.msgID) && (messageItem.msgID?.isNotEmpty ?? false);
|
final isShowJump = (model.jumpMsgID == messageItem.msgID) &&
|
||||||
|
(messageItem.msgID?.isNotEmpty ?? false);
|
||||||
final MessageItemBuilder? messageItemBuilder = widget.messageItemBuilder;
|
final MessageItemBuilder? messageItemBuilder = widget.messageItemBuilder;
|
||||||
final isFromSelf = messageItem.isSelf ?? true;
|
final isFromSelf = messageItem.isSelf ?? true;
|
||||||
void clearJump() {
|
void clearJump() {
|
||||||
|
|
@ -406,7 +439,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
|
|
||||||
switch (msgType) {
|
switch (msgType) {
|
||||||
case MessageElemType.V2TIM_ELEM_TYPE_CUSTOM:
|
case MessageElemType.V2TIM_ELEM_TYPE_CUSTOM:
|
||||||
final customWidget = messageItemBuilder?.customMessageItemBuilder != null
|
final customWidget =
|
||||||
|
messageItemBuilder?.customMessageItemBuilder != null
|
||||||
? messageItemBuilder!.customMessageItemBuilder!(
|
? messageItemBuilder!.customMessageItemBuilder!(
|
||||||
messageItem,
|
messageItem,
|
||||||
isShowJump,
|
isShowJump,
|
||||||
|
|
@ -450,7 +484,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
);
|
);
|
||||||
case MessageElemType.V2TIM_ELEM_TYPE_TEXT:
|
case MessageElemType.V2TIM_ELEM_TYPE_TEXT:
|
||||||
if (isReplyMessage(messageItem)) {
|
if (isReplyMessage(messageItem)) {
|
||||||
final customWidget = messageItemBuilder?.textReplyMessageItemBuilder != null
|
final customWidget =
|
||||||
|
messageItemBuilder?.textReplyMessageItemBuilder != null
|
||||||
? messageItemBuilder!.textReplyMessageItemBuilder!(
|
? messageItemBuilder!.textReplyMessageItemBuilder!(
|
||||||
messageItem,
|
messageItem,
|
||||||
isShowJump,
|
isShowJump,
|
||||||
|
|
@ -532,7 +567,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
isShowMessageReaction: widget.isUseMessageReaction,
|
isShowMessageReaction: widget.isUseMessageReaction,
|
||||||
);
|
);
|
||||||
case MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS:
|
case MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS:
|
||||||
final customWidget = messageItemBuilder?.groupTipsMessageItemBuilder != null
|
final customWidget =
|
||||||
|
messageItemBuilder?.groupTipsMessageItemBuilder != null
|
||||||
? messageItemBuilder!.groupTipsMessageItemBuilder!(
|
? messageItemBuilder!.groupTipsMessageItemBuilder!(
|
||||||
messageItem,
|
messageItem,
|
||||||
isShowJump,
|
isShowJump,
|
||||||
|
|
@ -574,7 +610,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
isShowMessageReaction: widget.isUseMessageReaction,
|
isShowMessageReaction: widget.isUseMessageReaction,
|
||||||
);
|
);
|
||||||
case MessageElemType.V2TIM_ELEM_TYPE_LOCATION:
|
case MessageElemType.V2TIM_ELEM_TYPE_LOCATION:
|
||||||
final customWidget = messageItemBuilder?.locationMessageItemBuilder != null
|
final customWidget =
|
||||||
|
messageItemBuilder?.locationMessageItemBuilder != null
|
||||||
? messageItemBuilder!.locationMessageItemBuilder!(
|
? messageItemBuilder!.locationMessageItemBuilder!(
|
||||||
messageItem,
|
messageItem,
|
||||||
isShowJump,
|
isShowJump,
|
||||||
|
|
@ -583,7 +620,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
: null;
|
: null;
|
||||||
return customWidget ?? Text(TIM_t("[位置]"));
|
return customWidget ?? Text(TIM_t("[位置]"));
|
||||||
case MessageElemType.V2TIM_ELEM_TYPE_MERGER:
|
case MessageElemType.V2TIM_ELEM_TYPE_MERGER:
|
||||||
final customWidget = messageItemBuilder?.mergerMessageItemBuilder != null
|
final customWidget =
|
||||||
|
messageItemBuilder?.mergerMessageItemBuilder != null
|
||||||
? messageItemBuilder!.mergerMessageItemBuilder!(
|
? messageItemBuilder!.mergerMessageItemBuilder!(
|
||||||
messageItem,
|
messageItem,
|
||||||
isShowJump,
|
isShowJump,
|
||||||
|
|
@ -608,7 +646,11 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
|
|
||||||
Widget _groupTipsMessageBuilder(TUIChatSeparateViewModel model) {
|
Widget _groupTipsMessageBuilder(TUIChatSeparateViewModel model) {
|
||||||
final messageItem = widget.message;
|
final messageItem = widget.message;
|
||||||
return Container(padding: const EdgeInsets.only(bottom: 20), child: TIMUIKitGroupTipsElem(groupTipsElem: messageItem.groupTipsElem!, groupMemberList: model.groupMemberList ?? []));
|
return Container(
|
||||||
|
padding: const EdgeInsets.only(bottom: 20),
|
||||||
|
child: TIMUIKitGroupTipsElem(
|
||||||
|
groupTipsElem: messageItem.groupTipsElem!,
|
||||||
|
groupMemberList: model.groupMemberList ?? []));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _selfRevokeEditMessageBuilder(theme, TUIChatSeparateViewModel model) {
|
Widget _selfRevokeEditMessageBuilder(theme, TUIChatSeparateViewModel model) {
|
||||||
|
|
@ -624,7 +666,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
text: TIM_t("重新编辑"),
|
text: TIM_t("重新编辑"),
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () {
|
..onTap = () {
|
||||||
widget.textFieldController?.setTextField(widget.message.textElem?.text ?? "");
|
widget.textFieldController
|
||||||
|
?.setTextField(widget.message.textElem?.text ?? "");
|
||||||
},
|
},
|
||||||
style: TextStyle(color: theme.primaryColor),
|
style: TextStyle(color: theme.primaryColor),
|
||||||
)
|
)
|
||||||
|
|
@ -641,12 +684,15 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _timeDividerBuilder(theme, int timeStamp, TUIChatSeparateViewModel model) {
|
Widget _timeDividerBuilder(
|
||||||
|
theme, int timeStamp, TUIChatSeparateViewModel model) {
|
||||||
return Container(
|
return Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
margin: const EdgeInsets.symmetric(vertical: 20),
|
margin: const EdgeInsets.symmetric(vertical: 20),
|
||||||
child: Text(
|
child: Text(
|
||||||
model.chatConfig.timeDividerConfig?.timestampParser != null ? (model.chatConfig.timeDividerConfig?.timestampParser!(timeStamp))! : TimeAgo().getTimeForMessage(timeStamp),
|
model.chatConfig.timeDividerConfig?.timestampParser != null
|
||||||
|
? (model.chatConfig.timeDividerConfig?.timestampParser!(timeStamp))!
|
||||||
|
: TimeAgo().getTimeForMessage(timeStamp),
|
||||||
style: widget.themeData?.timelineTextStyle ??
|
style: widget.themeData?.timelineTextStyle ??
|
||||||
TextStyle(
|
TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
|
@ -670,7 +716,10 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
width: 100,
|
width: 100,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(colors: [const Color(0x00C0E1FF), theme.primaryColor ?? CommonColor.lightPrimaryColor]),
|
gradient: LinearGradient(colors: [
|
||||||
|
const Color(0x00C0E1FF),
|
||||||
|
theme.primaryColor ?? CommonColor.lightPrimaryColor
|
||||||
|
]),
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -702,7 +751,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isRevocable(int timestamp) => (DateTime.now().millisecondsSinceEpoch / 1000).ceil() - timestamp < 120;
|
bool isRevocable(int timestamp) =>
|
||||||
|
(DateTime.now().millisecondsSinceEpoch / 1000).ceil() - timestamp < 120;
|
||||||
|
|
||||||
// TODO : 继续看这里
|
// TODO : 继续看这里
|
||||||
|
|
||||||
|
|
@ -723,21 +773,38 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
|
|
||||||
final screenHeight = MediaQuery.of(context).size.height;
|
final screenHeight = MediaQuery.of(context).size.height;
|
||||||
final screenWidth = MediaQuery.of(context).size.width;
|
final screenWidth = MediaQuery.of(context).size.width;
|
||||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
final isDesktopScreen =
|
||||||
final isLongMessage = context.size!.height + 350 > screenHeight && !(isDesktopScreen);
|
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||||
final tapDetails = (isDesktopScreen || isLongMessage) ? (details ?? _tapDetails) : details;
|
final isLongMessage =
|
||||||
|
context.size!.height + 350 > screenHeight && !(isDesktopScreen);
|
||||||
|
final tapDetails =
|
||||||
|
(isDesktopScreen || isLongMessage) ? (details ?? _tapDetails) : details;
|
||||||
final isSelf = message.isSelf ?? true;
|
final isSelf = message.isSelf ?? true;
|
||||||
|
|
||||||
final targetWidth = min(MediaQuery.of(context).size.width * 0.84, 350).toDouble();
|
final targetWidth =
|
||||||
final double dx = !isSelf ? min(tapDetails?.globalPosition.dx ?? targetWidth, screenWidth - targetWidth) : max(tapDetails?.globalPosition.dx ?? targetWidth, targetWidth).toDouble();
|
min(MediaQuery.of(context).size.width * 0.84, 350).toDouble();
|
||||||
final double dy = min(tapDetails?.globalPosition.dy ?? MediaQuery.of(context).size.height, MediaQuery.of(context).size.height - 320).toDouble();
|
final double dx = !isSelf
|
||||||
|
? min(tapDetails?.globalPosition.dx ?? targetWidth,
|
||||||
|
screenWidth - targetWidth)
|
||||||
|
: max(tapDetails?.globalPosition.dx ?? targetWidth, targetWidth)
|
||||||
|
.toDouble();
|
||||||
|
final double dy = min(
|
||||||
|
tapDetails?.globalPosition.dy ?? MediaQuery.of(context).size.height,
|
||||||
|
MediaQuery.of(context).size.height - 320)
|
||||||
|
.toDouble();
|
||||||
final finalTapDetail = tapDetails != null
|
final finalTapDetail = tapDetails != null
|
||||||
? TapDownDetails(
|
? TapDownDetails(
|
||||||
globalPosition: Offset(dx, dy),
|
globalPosition: Offset(dx, dy),
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
initTools(context: c, model: model, isShowMoreSticker: isShowMoreSticker, details: finalTapDetail, theme: theme, isFromWideToolTip: isFromWideTooltip);
|
initTools(
|
||||||
|
context: c,
|
||||||
|
model: model,
|
||||||
|
isShowMoreSticker: isShowMoreSticker,
|
||||||
|
details: finalTapDetail,
|
||||||
|
theme: theme,
|
||||||
|
isFromWideToolTip: isFromWideTooltip);
|
||||||
tooltip!.show(c, targetCenter: finalTapDetail?.globalPosition);
|
tooltip!.show(c, targetCenter: finalTapDetail?.globalPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -750,15 +817,26 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<V2TimValueCallback<V2TimMessageChangeInfo>> _modifySticker(int sticker) async {
|
Future<V2TimValueCallback<V2TimMessageChangeInfo>> _modifySticker(
|
||||||
|
int sticker) async {
|
||||||
return await Future.delayed(const Duration(milliseconds: 50), () async {
|
return await Future.delayed(const Duration(milliseconds: 50), () async {
|
||||||
return await MessageReactionUtils.clickOnSticker(widget.message, sticker);
|
return await MessageReactionUtils.clickOnSticker(widget.message, sticker);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
initTools({BuildContext? context, bool isLongMessage = false, required TUIChatSeparateViewModel model, TUITheme? theme, bool? isShowMoreSticker, TapDownDetails? details, bool? isFromWideToolTip}) {
|
initTools(
|
||||||
final isUseMessageReaction = widget.message.elemType == 2 ? false : model.chatConfig.isUseMessageReaction;
|
{BuildContext? context,
|
||||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
bool isLongMessage = false,
|
||||||
|
required TUIChatSeparateViewModel model,
|
||||||
|
TUITheme? theme,
|
||||||
|
bool? isShowMoreSticker,
|
||||||
|
TapDownDetails? details,
|
||||||
|
bool? isFromWideToolTip}) {
|
||||||
|
final isUseMessageReaction = widget.message.elemType == 2
|
||||||
|
? false
|
||||||
|
: model.chatConfig.isUseMessageReaction;
|
||||||
|
final isDesktopScreen =
|
||||||
|
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||||
final isSelf = widget.message.isSelf ?? true;
|
final isSelf = widget.message.isSelf ?? true;
|
||||||
double arrowTipDistance = 30;
|
double arrowTipDistance = 30;
|
||||||
double arrowBaseWidth = 10;
|
double arrowBaseWidth = 10;
|
||||||
|
|
@ -767,7 +845,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
TooltipDirection popupDirection = TooltipDirection.up;
|
TooltipDirection popupDirection = TooltipDirection.up;
|
||||||
double? left;
|
double? left;
|
||||||
double? right;
|
double? right;
|
||||||
SelectEmojiPanelPosition selectEmojiPanelPosition = SelectEmojiPanelPosition.down;
|
SelectEmojiPanelPosition selectEmojiPanelPosition =
|
||||||
|
SelectEmojiPanelPosition.down;
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
RenderBox? box = _key.currentContext?.findRenderObject() as RenderBox?;
|
RenderBox? box = _key.currentContext?.findRenderObject() as RenderBox?;
|
||||||
if (details != null && box != null) {
|
if (details != null && box != null) {
|
||||||
|
|
@ -790,7 +869,9 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
Offset offset = box.localToGlobal(Offset.zero);
|
Offset offset = box.localToGlobal(Offset.zero);
|
||||||
double boxWidth = box.size.width;
|
double boxWidth = box.size.width;
|
||||||
if (isSelf) {
|
if (isSelf) {
|
||||||
right = screenWidth - offset.dx - ((isUseMessageReaction) ? boxWidth : (boxWidth / 1.3));
|
right = screenWidth -
|
||||||
|
offset.dx -
|
||||||
|
((isUseMessageReaction) ? boxWidth : (boxWidth / 1.3));
|
||||||
} else {
|
} else {
|
||||||
left = offset.dx;
|
left = offset.dx;
|
||||||
}
|
}
|
||||||
|
|
@ -802,7 +883,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
popupDirection = TooltipDirection.down;
|
popupDirection = TooltipDirection.down;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
arrowTipDistance = (context.size!.height / 2).roundToDouble() + (isLongMessage ? -120 : 10);
|
arrowTipDistance = (context.size!.height / 2).roundToDouble() +
|
||||||
|
(isLongMessage ? -120 : 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -812,7 +894,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
widget.toolTipsConfig?.showReplyMessage = false;
|
widget.toolTipsConfig?.showReplyMessage = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget.message.status != MessageStatus.V2TIM_MSG_STATUS_SEND_FAIL && !(widget.message.hasRiskContent ?? false)) {
|
if (widget.message.status != MessageStatus.V2TIM_MSG_STATUS_SEND_FAIL &&
|
||||||
|
!(widget.message.hasRiskContent ?? false)) {
|
||||||
widget.toolTipsConfig?.showForwardMessage = true;
|
widget.toolTipsConfig?.showForwardMessage = true;
|
||||||
} else {
|
} else {
|
||||||
widget.toolTipsConfig?.showForwardMessage = false;
|
widget.toolTipsConfig?.showForwardMessage = false;
|
||||||
|
|
@ -835,7 +918,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
showCloseButton: ShowCloseButton.none,
|
showCloseButton: ShowCloseButton.none,
|
||||||
touchThroughAreaShape: ClipAreaShape.rectangle,
|
touchThroughAreaShape: ClipAreaShape.rectangle,
|
||||||
content: TIMUIKitMessageTooltip(
|
content: TIMUIKitMessageTooltip(
|
||||||
iSUseDefaultHoverBar: model.chatConfig.isUseMessageHoverBarOnDesktop && widget.customMessageHoverBarOnDesktop == null,
|
iSUseDefaultHoverBar: model.chatConfig.isUseMessageHoverBarOnDesktop &&
|
||||||
|
widget.customMessageHoverBarOnDesktop == null,
|
||||||
model: model,
|
model: model,
|
||||||
groupMemberInfo: widget.groupMemberInfo,
|
groupMemberInfo: widget.groupMemberInfo,
|
||||||
isShowMoreSticker: isShowMoreSticker ?? false,
|
isShowMoreSticker: isShowMoreSticker ?? false,
|
||||||
|
|
@ -843,7 +927,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
isUseMessageReaction: isUseMessageReaction,
|
isUseMessageReaction: isUseMessageReaction,
|
||||||
message: widget.message,
|
message: widget.message,
|
||||||
allowAtUserWhenReply: widget.allowAtUserWhenReply,
|
allowAtUserWhenReply: widget.allowAtUserWhenReply,
|
||||||
onLongPressForOthersHeadPortrait: widget.onLongPressForOthersHeadPortrait,
|
onLongPressForOthersHeadPortrait:
|
||||||
|
widget.onLongPressForOthersHeadPortrait,
|
||||||
selectEmojiPanelPosition: selectEmojiPanelPosition,
|
selectEmojiPanelPosition: selectEmojiPanelPosition,
|
||||||
onCloseTooltip: () => tooltip?.close(),
|
onCloseTooltip: () => tooltip?.close(),
|
||||||
onSelectSticker: (int value) {
|
onSelectSticker: (int value) {
|
||||||
|
|
@ -854,7 +939,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _getMessageItemBuilder(V2TimMessage message, int? messageStatues, TUIChatSeparateViewModel model) {
|
Widget _getMessageItemBuilder(V2TimMessage message, int? messageStatues,
|
||||||
|
TUIChatSeparateViewModel model) {
|
||||||
final messageBuilder = _messageItemBuilder;
|
final messageBuilder = _messageItemBuilder;
|
||||||
|
|
||||||
return messageBuilder(widget.message, model);
|
return messageBuilder(widget.message, model);
|
||||||
|
|
@ -896,7 +982,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MessageHoverControlItem> getWideMessageHoverControlBar(TUIChatSeparateViewModel model, TUITheme theme) {
|
List<MessageHoverControlItem> getWideMessageHoverControlBar(
|
||||||
|
TUIChatSeparateViewModel model, TUITheme theme) {
|
||||||
return [
|
return [
|
||||||
if (widget.isUseMessageReaction ?? false)
|
if (widget.isUseMessageReaction ?? false)
|
||||||
MessageHoverControlItem(
|
MessageHoverControlItem(
|
||||||
|
|
@ -907,7 +994,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
color: hexToColor("8f959e"),
|
color: hexToColor("8f959e"),
|
||||||
),
|
),
|
||||||
onClick: (details) {
|
onClick: (details) {
|
||||||
_onOpenToolTip(context, widget.message, model, theme, details, true, true);
|
_onOpenToolTip(
|
||||||
|
context, widget.message, model, theme, details, true, true);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (widget.toolTipsConfig?.showReplyMessage ?? true)
|
if (widget.toolTipsConfig?.showReplyMessage ?? true)
|
||||||
|
|
@ -921,14 +1009,21 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
onClick: (_) {
|
onClick: (_) {
|
||||||
model.repliedMessage = widget.message;
|
model.repliedMessage = widget.message;
|
||||||
final isSelf = widget.message.isSelf ?? true;
|
final isSelf = widget.message.isSelf ?? true;
|
||||||
final isGroup = TencentUtils.checkString(widget.message.groupID) != null;
|
final isGroup =
|
||||||
final isAtWhenReply = !isSelf && isGroup && widget.allowAtUserWhenReply && widget.onLongPressForOthersHeadPortrait != null;
|
TencentUtils.checkString(widget.message.groupID) != null;
|
||||||
|
final isAtWhenReply = !isSelf &&
|
||||||
|
isGroup &&
|
||||||
|
widget.allowAtUserWhenReply &&
|
||||||
|
widget.onLongPressForOthersHeadPortrait != null;
|
||||||
|
|
||||||
/// If replying to a self message, do not add a at tag, only requestFocus.
|
/// If replying to a self message, do not add a at tag, only requestFocus.
|
||||||
widget.onLongPressForOthersHeadPortrait!(!isAtWhenReply ? null : widget.message.sender, !isAtWhenReply ? null : widget.message.nickName);
|
widget.onLongPressForOthersHeadPortrait!(
|
||||||
|
!isAtWhenReply ? null : widget.message.sender,
|
||||||
|
!isAtWhenReply ? null : widget.message.nickName);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if ((widget.toolTipsConfig?.showForwardMessage ?? true) && !model.isVoteMessage(widget.message))
|
if ((widget.toolTipsConfig?.showForwardMessage ?? true) &&
|
||||||
|
!model.isVoteMessage(widget.message))
|
||||||
MessageHoverControlItem(
|
MessageHoverControlItem(
|
||||||
name: TIM_t("转发"),
|
name: TIM_t("转发"),
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
|
|
@ -968,7 +1063,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
color: hexToColor("8f959e"),
|
color: hexToColor("8f959e"),
|
||||||
),
|
),
|
||||||
onClick: (details) {
|
onClick: (details) {
|
||||||
_onOpenToolTip(context, widget.message, model, theme, details, true, false);
|
_onOpenToolTip(
|
||||||
|
context, widget.message, model, theme, details, true, false);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
...?model.chatConfig.additionalDesktopMessageHoverBarItem
|
...?model.chatConfig.additionalDesktopMessageHoverBarItem
|
||||||
|
|
@ -978,17 +1074,37 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
_onMsgSendFailIconTap(V2TimMessage message, TUIChatSeparateViewModel model) {
|
_onMsgSendFailIconTap(V2TimMessage message, TUIChatSeparateViewModel model) {
|
||||||
final convID = model.conversationID;
|
final convID = model.conversationID;
|
||||||
final convType = model.conversationType;
|
final convType = model.conversationType;
|
||||||
MessageUtils.handleMessageError(model.reSendFailMessage(message: message, convType: convType ?? ConvType.c2c, convID: convID), context);
|
MessageUtils.handleMessageError(
|
||||||
|
model.reSendFailMessage(
|
||||||
|
message: message,
|
||||||
|
convType: convType ?? ConvType.c2c,
|
||||||
|
convID: convID),
|
||||||
|
context);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget renderHoverTipAndReadStatus(TUIChatSeparateViewModel model, bool isSelf, V2TimMessage message, bool isPeerRead, TUITheme theme, bool isDownloadWaiting) {
|
Widget renderHoverTipAndReadStatus(
|
||||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
TUIChatSeparateViewModel model,
|
||||||
final customHoverBar = widget.customMessageHoverBarOnDesktop != null ? widget.customMessageHoverBarOnDesktop!(message) : null;
|
bool isSelf,
|
||||||
final wideHoverTipList = (model.chatConfig.isUseMessageHoverBarOnDesktop && customHoverBar == null) ? getWideMessageHoverControlBar(model, theme) : [];
|
V2TimMessage message,
|
||||||
final lastItemName = wideHoverTipList.isNotEmpty ? wideHoverTipList.last.name : "";
|
bool isPeerRead,
|
||||||
|
TUITheme theme,
|
||||||
|
bool isDownloadWaiting) {
|
||||||
|
final isDesktopScreen =
|
||||||
|
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||||
|
final customHoverBar = widget.customMessageHoverBarOnDesktop != null
|
||||||
|
? widget.customMessageHoverBarOnDesktop!(message)
|
||||||
|
: null;
|
||||||
|
final wideHoverTipList = (model.chatConfig.isUseMessageHoverBarOnDesktop &&
|
||||||
|
customHoverBar == null)
|
||||||
|
? getWideMessageHoverControlBar(model, theme)
|
||||||
|
: [];
|
||||||
|
final lastItemName =
|
||||||
|
wideHoverTipList.isNotEmpty ? wideHoverTipList.last.name : "";
|
||||||
|
|
||||||
|
// 满足条件延迟 1 秒渲染,否则立即渲染
|
||||||
Future<void> _conditionalDelay() async {
|
Future<void> _conditionalDelay() async {
|
||||||
if (!(model.hasDelayedRenderSendingStatus(message.id ?? message.msgID!) ?? true)) {
|
if (!(model.hasDelayedRenderSendingStatus(message.id ?? message.msgID!) ??
|
||||||
|
true)) {
|
||||||
model.setDelayedRenderSendingStatus(message.id ?? message.msgID!);
|
model.setDelayedRenderSendingStatus(message.id ?? message.msgID!);
|
||||||
await Future.delayed(const Duration(seconds: 1));
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
}
|
}
|
||||||
|
|
@ -999,9 +1115,14 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
if (isDesktopScreen && isShowWideToolTip && customHoverBar == null && !((widget.message.elemType == 6 && isDownloadWaiting)))
|
if (isDesktopScreen &&
|
||||||
|
isShowWideToolTip &&
|
||||||
|
customHoverBar == null &&
|
||||||
|
!((widget.message.elemType == 6 && isDownloadWaiting)))
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(4), border: Border.all(color: hexToColor("d9dde0"), width: 1)),
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
border: Border.all(color: hexToColor("d9dde0"), width: 1)),
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 4),
|
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: wideHoverTipList
|
children: wideHoverTipList
|
||||||
|
|
@ -1033,12 +1154,17 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
.toList(),
|
.toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (isDesktopScreen && isShowWideToolTip && customHoverBar != null) customHoverBar,
|
if (isDesktopScreen && isShowWideToolTip && customHoverBar != null)
|
||||||
if (!isDesktopScreen || (model.chatConfig.isUseMessageHoverBarOnDesktop && customHoverBar == null && !isShowWideToolTip))
|
customHoverBar,
|
||||||
|
if (!isDesktopScreen ||
|
||||||
|
(model.chatConfig.isUseMessageHoverBarOnDesktop &&
|
||||||
|
customHoverBar == null &&
|
||||||
|
!isShowWideToolTip))
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
if (isSelf && message.status == MessageStatus.V2TIM_MSG_STATUS_SEND_FAIL)
|
if (isSelf &&
|
||||||
|
message.status == MessageStatus.V2TIM_MSG_STATUS_SEND_FAIL)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.only(bottom: 3),
|
padding: const EdgeInsets.only(bottom: 3),
|
||||||
margin: const EdgeInsets.only(right: 6),
|
margin: const EdgeInsets.only(right: 6),
|
||||||
|
|
@ -1069,7 +1195,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (model.chatConfig.isShowReadingStatus &&
|
if (model.chatConfig.isShowReadingStatus &&
|
||||||
isSelf && message.status == MessageStatus.V2TIM_MSG_STATUS_SEND_SUCC &&
|
isSelf &&
|
||||||
|
message.status == MessageStatus.V2TIM_MSG_STATUS_SEND_SUCC &&
|
||||||
(message.needReadReceipt ?? false) &&
|
(message.needReadReceipt ?? false) &&
|
||||||
!model.isVoteMessage(widget.message))
|
!model.isVoteMessage(widget.message))
|
||||||
TIMUIKitMessageReadReceipt(
|
TIMUIKitMessageReadReceipt(
|
||||||
|
|
@ -1082,13 +1209,16 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
final TUIChatSeparateViewModel model = Provider.of<TUIChatSeparateViewModel>(context);
|
final TUIChatSeparateViewModel model =
|
||||||
final isDownloadWaiting = context.select<TUIChatGlobalModel, bool>((value) => value.isWaiting(widget.message.msgID ?? ""));
|
Provider.of<TUIChatSeparateViewModel>(context);
|
||||||
|
final isDownloadWaiting = context.select<TUIChatGlobalModel, bool>(
|
||||||
|
(value) => value.isWaiting(widget.message.msgID ?? ""));
|
||||||
final TUITheme theme = value.theme;
|
final TUITheme theme = value.theme;
|
||||||
final message = widget.message;
|
final message = widget.message;
|
||||||
final msgType = message.elemType;
|
final msgType = message.elemType;
|
||||||
final isSelf = message.isSelf ?? true;
|
final isSelf = message.isSelf ?? true;
|
||||||
final isGroupTipsMsg = msgType == MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS;
|
final isGroupTipsMsg =
|
||||||
|
msgType == MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS;
|
||||||
|
|
||||||
final revokeStatus = isRevokeMessage(message, model);
|
final revokeStatus = isRevokeMessage(message, model);
|
||||||
final isRevokedMsg = revokeStatus.$1;
|
final isRevokedMsg = revokeStatus.$1;
|
||||||
|
|
@ -1098,10 +1228,14 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
final isLatestDivider = msgType == 101;
|
final isLatestDivider = msgType == 101;
|
||||||
final isPeerRead = message.isPeerRead ?? false;
|
final isPeerRead = message.isPeerRead ?? false;
|
||||||
final isGroupMessage = model.conversationType == ConvType.group;
|
final isGroupMessage = model.conversationType == ConvType.group;
|
||||||
final bool isRevokeEditable = widget.message.elemType == MessageElemType.V2TIM_ELEM_TYPE_TEXT;
|
final bool isRevokeEditable =
|
||||||
final isShowNickNameForSelf = isGroupMessage && model.chatConfig.isShowSelfNameInGroup;
|
widget.message.elemType == MessageElemType.V2TIM_ELEM_TYPE_TEXT;
|
||||||
final isShowNickNameForOthers = isGroupMessage && model.chatConfig.isShowOthersNameInGroup;
|
final isShowNickNameForSelf =
|
||||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
isGroupMessage && model.chatConfig.isShowSelfNameInGroup;
|
||||||
|
final isShowNickNameForOthers =
|
||||||
|
isGroupMessage && model.chatConfig.isShowOthersNameInGroup;
|
||||||
|
final isDesktopScreen =
|
||||||
|
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||||
if (isTimeDivider) {
|
if (isTimeDivider) {
|
||||||
return _timeDividerBuilder(theme, message.timestamp ?? 0, model);
|
return _timeDividerBuilder(theme, message.timestamp ?? 0, model);
|
||||||
}
|
}
|
||||||
|
|
@ -1116,7 +1250,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
|
|
||||||
if (isGroupTipsMsg) {
|
if (isGroupTipsMsg) {
|
||||||
if (widget.messageItemBuilder?.groupTipsMessageItemBuilder != null) {
|
if (widget.messageItemBuilder?.groupTipsMessageItemBuilder != null) {
|
||||||
final groupTipsMessage = widget.messageItemBuilder!.groupTipsMessageItemBuilder!(
|
final groupTipsMessage =
|
||||||
|
widget.messageItemBuilder!.groupTipsMessageItemBuilder!(
|
||||||
message,
|
message,
|
||||||
(model.jumpMsgID == message.msgID),
|
(model.jumpMsgID == message.msgID),
|
||||||
clearJump,
|
clearJump,
|
||||||
|
|
@ -1127,8 +1262,16 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRevokedMsg) {
|
if (isRevokedMsg) {
|
||||||
final displayName = isAdminRevoke ? TIM_t("管理员") : (isSelf ? TIM_t("您") : TencentUtils.checkString(message.nickName) ?? TencentUtils.checkString(message.sender) ?? message.userID);
|
final displayName = isAdminRevoke
|
||||||
return isSelf && isRevokeEditable && isRevocable(message.timestamp!) ? _selfRevokeEditMessageBuilder(theme, model) : _revokedMessageBuilder(theme, displayName ?? "");
|
? TIM_t("管理员")
|
||||||
|
: (isSelf
|
||||||
|
? TIM_t("您")
|
||||||
|
: TencentUtils.checkString(message.nickName) ??
|
||||||
|
TencentUtils.checkString(message.sender) ??
|
||||||
|
message.userID);
|
||||||
|
return isSelf && isRevokeEditable && isRevocable(message.timestamp!)
|
||||||
|
? _selfRevokeEditMessageBuilder(theme, model)
|
||||||
|
: _revokedMessageBuilder(theme, displayName ?? "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用自定义行
|
// 使用自定义行
|
||||||
|
|
@ -1157,7 +1300,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
},
|
},
|
||||||
child: LayoutBuilder(
|
child: LayoutBuilder(
|
||||||
builder: (context, constraints) => Container(
|
builder: (context, constraints) => Container(
|
||||||
padding: EdgeInsets.only(left: isSelf ? 0 : 16, right: isSelf ? 16 : 0),
|
padding:
|
||||||
|
EdgeInsets.only(left: isSelf ? 0 : 16, right: isSelf ? 16 : 0),
|
||||||
margin: widget.padding ?? const EdgeInsets.only(bottom: 20),
|
margin: widget.padding ?? const EdgeInsets.only(bottom: 20),
|
||||||
child: Row(
|
child: Row(
|
||||||
key: _key,
|
key: _key,
|
||||||
|
|
@ -1166,7 +1310,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
children: [
|
children: [
|
||||||
if (model.isMultiSelect)
|
if (model.isMultiSelect)
|
||||||
Container(
|
Container(
|
||||||
margin: EdgeInsets.only(right: 12, top: 10, left: isSelf ? 16 : 0),
|
margin: EdgeInsets.only(
|
||||||
|
right: 12, top: 10, left: isSelf ? 16 : 0),
|
||||||
child: CheckBoxButton(
|
child: CheckBoxButton(
|
||||||
isChecked: model.getSelectedMessageList().contains(message),
|
isChecked: model.getSelectedMessageList().contains(message),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
|
@ -1177,14 +1322,16 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
Expanded(
|
Expanded(
|
||||||
child: MouseRegion(
|
child: MouseRegion(
|
||||||
onEnter: (_) {
|
onEnter: (_) {
|
||||||
if (isDesktopScreen && model.chatConfig.isUseMessageHoverBarOnDesktop) {
|
if (isDesktopScreen &&
|
||||||
|
model.chatConfig.isUseMessageHoverBarOnDesktop) {
|
||||||
setState(() {
|
setState(() {
|
||||||
isShowWideToolTip = true;
|
isShowWideToolTip = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onExit: (_) {
|
onExit: (_) {
|
||||||
if (isDesktopScreen && model.chatConfig.isUseMessageHoverBarOnDesktop) {
|
if (isDesktopScreen &&
|
||||||
|
model.chatConfig.isUseMessageHoverBarOnDesktop) {
|
||||||
Tooltip.dismissAllToolTips();
|
Tooltip.dismissAllToolTips();
|
||||||
Future.delayed(const Duration(milliseconds: 100), () {
|
Future.delayed(const Duration(milliseconds: 100), () {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|
@ -1194,10 +1341,13 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
behavior: model.isMultiSelect ? HitTestBehavior.translucent : null,
|
behavior: model.isMultiSelect
|
||||||
|
? HitTestBehavior.translucent
|
||||||
|
: null,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (model.isMultiSelect) {
|
if (model.isMultiSelect) {
|
||||||
final checked = model.getSelectedMessageList().contains(message);
|
final checked =
|
||||||
|
model.getSelectedMessageList().contains(message);
|
||||||
model.setMessageItemChecked(message, !checked);
|
model.setMessageItemChecked(message, !checked);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1205,59 +1355,81 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: isSelf ? MainAxisAlignment.end : MainAxisAlignment.start,
|
mainAxisAlignment: isSelf
|
||||||
|
? MainAxisAlignment.end
|
||||||
|
: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (!isSelf && widget.showAvatar)
|
if (!isSelf && widget.showAvatar)
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
if (widget.onLongPressForOthersHeadPortrait != null) {}
|
if (widget.onLongPressForOthersHeadPortrait !=
|
||||||
|
null) {}
|
||||||
if (model.chatConfig.isAllowLongPressAvatarToAt) {
|
if (model.chatConfig.isAllowLongPressAvatarToAt) {
|
||||||
widget.onLongPressForOthersHeadPortrait!(message.sender, message.nickName);
|
widget.onLongPressForOthersHeadPortrait!(
|
||||||
|
message.sender, message.nickName);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onTapDown: isDesktopScreen
|
onTapDown: isDesktopScreen
|
||||||
? (details) {
|
? (details) {
|
||||||
if (widget.onTapForOthersPortrait != null && widget.allowAvatarTap) {
|
if (widget.onTapForOthersPortrait != null &&
|
||||||
widget.onTapForOthersPortrait!(message.sender ?? "", details);
|
widget.allowAvatarTap) {
|
||||||
|
widget.onTapForOthersPortrait!(
|
||||||
|
message.sender ?? "", details);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
onTap: isDesktopScreen
|
onTap: isDesktopScreen
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
if (widget.onTapForOthersPortrait != null && widget.allowAvatarTap) {
|
if (widget.onTapForOthersPortrait != null &&
|
||||||
widget.onTapForOthersPortrait!(message.sender ?? "", TapDownDetails());
|
widget.allowAvatarTap) {
|
||||||
|
widget.onTapForOthersPortrait!(
|
||||||
|
message.sender ?? "",
|
||||||
|
TapDownDetails());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSecondaryTap: isDesktopScreen
|
onSecondaryTap: isDesktopScreen
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
if (widget.onSecondaryTapForOthersPortrait != null && widget.allowAvatarTap) {
|
if (widget.onSecondaryTapForOthersPortrait !=
|
||||||
widget.onSecondaryTapForOthersPortrait!(message.sender ?? "", TapDownDetails());
|
null &&
|
||||||
|
widget.allowAvatarTap) {
|
||||||
|
widget.onSecondaryTapForOthersPortrait!(
|
||||||
|
message.sender ?? "",
|
||||||
|
TapDownDetails());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSecondaryTapDown: isDesktopScreen
|
onSecondaryTapDown: isDesktopScreen
|
||||||
? (details) {
|
? (details) {
|
||||||
if (widget.onSecondaryTapForOthersPortrait != null && widget.allowAvatarTap) {
|
if (widget.onSecondaryTapForOthersPortrait !=
|
||||||
widget.onSecondaryTapForOthersPortrait!(message.sender ?? "", details);
|
null &&
|
||||||
|
widget.allowAvatarTap) {
|
||||||
|
widget.onSecondaryTapForOthersPortrait!(
|
||||||
|
message.sender ?? "", details);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
child: widget.userAvatarBuilder != null
|
child: widget.userAvatarBuilder != null
|
||||||
? widget.userAvatarBuilder!(context, message)
|
? widget.userAvatarBuilder!(context, message)
|
||||||
: Container(
|
: Container(
|
||||||
margin: (isSelf && isShowNickNameForSelf) || (!isSelf && isShowNickNameForOthers) ? const EdgeInsets.only(top: 2) : null,
|
margin: (isSelf && isShowNickNameForSelf) ||
|
||||||
|
(!isSelf && isShowNickNameForOthers)
|
||||||
|
? const EdgeInsets.only(top: 2)
|
||||||
|
: null,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 40,
|
width: 40,
|
||||||
height: 40,
|
height: 40,
|
||||||
child: Avatar(
|
child: Avatar(
|
||||||
faceUrl: message.faceUrl ?? "",
|
faceUrl: message.faceUrl ?? "",
|
||||||
showName: MessageUtils.getDisplayName(message),
|
showName: MessageUtils.getDisplayName(
|
||||||
|
message),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (isSelf && widget.message.elemType == 6 && isDownloadWaiting)
|
if (isSelf &&
|
||||||
|
widget.message.elemType == 6 &&
|
||||||
|
isDownloadWaiting)
|
||||||
Container(
|
Container(
|
||||||
margin: const EdgeInsets.only(top: 46, right: 10),
|
margin: const EdgeInsets.only(top: 46, right: 10),
|
||||||
child: LoadingAnimationWidget.threeArchedCircle(
|
child: LoadingAnimationWidget.threeArchedCircle(
|
||||||
|
|
@ -1266,52 +1438,96 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
margin: widget.showAvatar ? (isSelf ? const EdgeInsets.only(right: 13) : const EdgeInsets.only(left: 13)) : null,
|
margin: widget.showAvatar
|
||||||
|
? (isSelf
|
||||||
|
? const EdgeInsets.only(right: 13)
|
||||||
|
: const EdgeInsets.only(left: 13))
|
||||||
|
: null,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: isSelf ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
crossAxisAlignment: isSelf
|
||||||
|
? CrossAxisAlignment.end
|
||||||
|
: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if ((isSelf && isShowNickNameForSelf) || (!isSelf && isShowNickNameForOthers))
|
if ((isSelf && isShowNickNameForSelf) ||
|
||||||
|
(!isSelf && isShowNickNameForOthers))
|
||||||
widget.topRowBuilder != null
|
widget.topRowBuilder != null
|
||||||
? widget.topRowBuilder!(context, message)
|
? widget.topRowBuilder!(context, message)
|
||||||
: Container(
|
: Container(
|
||||||
// margin: const EdgeInsets.only(bottom: 4),
|
// margin: const EdgeInsets.only(bottom: 4),
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width / 1.7),
|
constraints: BoxConstraints(
|
||||||
|
maxWidth: MediaQuery.of(context)
|
||||||
|
.size
|
||||||
|
.width /
|
||||||
|
1.7),
|
||||||
child: Text(
|
child: Text(
|
||||||
MessageUtils.getDisplayName(message),
|
MessageUtils.getDisplayName(message),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: widget.themeData?.nickNameTextStyle ?? TextStyle(fontSize: 12, color: theme.weakTextColor),
|
style: widget.themeData
|
||||||
|
?.nickNameTextStyle ??
|
||||||
|
TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: theme.weakTextColor),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
if (isSelf) renderHoverTipAndReadStatus(model, isSelf, message, isPeerRead, theme, isDownloadWaiting),
|
if (isSelf)
|
||||||
|
renderHoverTipAndReadStatus(
|
||||||
|
model,
|
||||||
|
isSelf,
|
||||||
|
message,
|
||||||
|
isPeerRead,
|
||||||
|
theme,
|
||||||
|
isDownloadWaiting),
|
||||||
Container(
|
Container(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxWidth: constraints.maxWidth * 0.77,
|
maxWidth: constraints.maxWidth * 0.77,
|
||||||
),
|
),
|
||||||
child: Builder(builder: (context) {
|
child: Builder(builder: (context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
child: IgnorePointer(ignoring: model.isMultiSelect, child: _getMessageItemBuilder(message, message.status, model)),
|
child: IgnorePointer(
|
||||||
|
ignoring: model.isMultiSelect,
|
||||||
|
child: _getMessageItemBuilder(
|
||||||
|
message,
|
||||||
|
message.status,
|
||||||
|
model)),
|
||||||
onSecondaryTapDown: (details) {
|
onSecondaryTapDown: (details) {
|
||||||
if (widget.onLongPress != null) {
|
if (widget.onLongPress != null) {
|
||||||
widget.onLongPress!(context, message);
|
widget.onLongPress!(
|
||||||
|
context, message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!PlatformUtils().isMobile) {
|
if (!PlatformUtils().isMobile) {
|
||||||
if (widget.allowLongPress) {
|
if (widget.allowLongPress) {
|
||||||
_onOpenToolTip(context, message, model, theme, details, false, false);
|
_onOpenToolTip(
|
||||||
|
context,
|
||||||
|
message,
|
||||||
|
model,
|
||||||
|
theme,
|
||||||
|
details,
|
||||||
|
false,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
if (widget.onLongPress != null) {
|
if (widget.onLongPress != null) {
|
||||||
widget.onLongPress!(context, message);
|
widget.onLongPress!(
|
||||||
|
context, message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (widget.allowLongPress && !isDesktopScreen) {
|
if (widget.allowLongPress &&
|
||||||
_onOpenToolTip(context, message, model, theme, null, false, false);
|
!isDesktopScreen) {
|
||||||
|
_onOpenToolTip(
|
||||||
|
context,
|
||||||
|
message,
|
||||||
|
model,
|
||||||
|
theme,
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onTapDown: (details) {
|
onTapDown: (details) {
|
||||||
|
|
@ -1320,24 +1536,46 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
if (!isSelf && message.elemType == MessageElemType.V2TIM_ELEM_TYPE_SOUND && message.localCustomInt != null && message.localCustomInt != HistoryMessageDartConstant.read)
|
if (!isSelf &&
|
||||||
Padding(padding: const EdgeInsets.only(left: 5, bottom: 12), child: Icon(Icons.circle, color: theme.cautionColor, size: 10)),
|
message.elemType ==
|
||||||
if (!isSelf) renderHoverTipAndReadStatus(model, isSelf, message, isPeerRead, theme, isDownloadWaiting),
|
MessageElemType
|
||||||
|
.V2TIM_ELEM_TYPE_SOUND &&
|
||||||
|
message.localCustomInt != null &&
|
||||||
|
message.localCustomInt !=
|
||||||
|
HistoryMessageDartConstant.read)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 5, bottom: 12),
|
||||||
|
child: Icon(Icons.circle,
|
||||||
|
color: theme.cautionColor,
|
||||||
|
size: 10)),
|
||||||
|
if (!isSelf)
|
||||||
|
renderHoverTipAndReadStatus(
|
||||||
|
model,
|
||||||
|
isSelf,
|
||||||
|
message,
|
||||||
|
isPeerRead,
|
||||||
|
theme,
|
||||||
|
isDownloadWaiting),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
TIMUIKitTextTranslationElem(
|
TIMUIKitTextTranslationElem(
|
||||||
message: message,
|
message: message,
|
||||||
isUseDefaultEmoji: widget.isUseDefaultEmoji,
|
isUseDefaultEmoji: widget.isUseDefaultEmoji,
|
||||||
customEmojiStickerList: widget.customEmojiStickerList,
|
customEmojiStickerList:
|
||||||
|
widget.customEmojiStickerList,
|
||||||
isFromSelf: message.isSelf ?? true,
|
isFromSelf: message.isSelf ?? true,
|
||||||
isShowJump: false,
|
isShowJump: false,
|
||||||
clearJump: () {},
|
clearJump: () {},
|
||||||
chatModel: model),
|
chatModel: model),
|
||||||
if (widget.bottomRowBuilder != null) widget.bottomRowBuilder!(context, message)
|
if (widget.bottomRowBuilder != null)
|
||||||
|
widget.bottomRowBuilder!(context, message)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!isSelf && widget.message.elemType == 6 && isDownloadWaiting)
|
if (!isSelf &&
|
||||||
|
widget.message.elemType == 6 &&
|
||||||
|
isDownloadWaiting)
|
||||||
Container(
|
Container(
|
||||||
margin: const EdgeInsets.only(top: 46, left: 10),
|
margin: const EdgeInsets.only(top: 46, left: 10),
|
||||||
child: LoadingAnimationWidget.threeArchedCircle(
|
child: LoadingAnimationWidget.threeArchedCircle(
|
||||||
|
|
@ -1353,11 +1591,17 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
||||||
height: 40,
|
height: 40,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTapDown: (details) {
|
onTapDown: (details) {
|
||||||
if (widget.onTapForOthersPortrait != null && widget.allowAvatarTap) {
|
if (widget.onTapForOthersPortrait !=
|
||||||
widget.onTapForOthersPortrait!(message.sender ?? "", details);
|
null &&
|
||||||
|
widget.allowAvatarTap) {
|
||||||
|
widget.onTapForOthersPortrait!(
|
||||||
|
message.sender ?? "", details);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Avatar(faceUrl: message.faceUrl ?? "", showName: MessageUtils.getDisplayName(message)),
|
child: Avatar(
|
||||||
|
faceUrl: message.faceUrl ?? "",
|
||||||
|
showName: MessageUtils.getDisplayName(
|
||||||
|
message)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:image_clipboard/image_clipboard.dart';
|
|
||||||
import 'package:open_file/open_file.dart';
|
import 'package:open_file/open_file.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart';
|
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart';
|
||||||
|
|
@ -196,13 +195,15 @@ class TIMUIKitMessageTooltipState
|
||||||
bool showTranslation = true;
|
bool showTranslation = true;
|
||||||
if (widget.message.localCustomData != null) {
|
if (widget.message.localCustomData != null) {
|
||||||
final LocalCustomDataModel localCustomData = LocalCustomDataModel.fromMap(
|
final LocalCustomDataModel localCustomData = LocalCustomDataModel.fromMap(
|
||||||
json.decode(TencentUtils.checkString(widget.message.localCustomData) ?? "{}"));
|
json.decode(
|
||||||
if (localCustomData.translatedText != null && localCustomData.translatedText != "") {
|
TencentUtils.checkString(widget.message.localCustomData) ??
|
||||||
|
"{}"));
|
||||||
|
if (localCustomData.translatedText != null &&
|
||||||
|
localCustomData.translatedText != "") {
|
||||||
showTranslation = false;
|
showTranslation = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final dynamicQuote =
|
final dynamicQuote =
|
||||||
model.chatConfig.isAtWhenReplyDynamic?.call(widget.message);
|
model.chatConfig.isAtWhenReplyDynamic?.call(widget.message);
|
||||||
|
|
||||||
|
|
@ -405,12 +406,6 @@ class TIMUIKitMessageTooltipState
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> copyImageToClipboard(String imagePath) async {
|
|
||||||
ImageClipboard().copyImage(imagePath);
|
|
||||||
// final DesktopClipboard desktopClipboard = DesktopClipboard();
|
|
||||||
// desktopClipboard.copyImage(imagePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onTap(String operation, TUIChatSeparateViewModel model) async {
|
_onTap(String operation, TUIChatSeparateViewModel model) async {
|
||||||
final messageItem = widget.message;
|
final messageItem = widget.message;
|
||||||
final msgID = messageItem.msgID as String;
|
final msgID = messageItem.msgID as String;
|
||||||
|
|
@ -494,13 +489,6 @@ class TIMUIKitMessageTooltipState
|
||||||
infoCode: 6660408));
|
infoCode: 6660408));
|
||||||
// ignore: empty_catches
|
// ignore: empty_catches
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
} else if (widget.message.elemType ==
|
|
||||||
MessageElemType.V2TIM_ELEM_TYPE_IMAGE) {
|
|
||||||
final savePath = (TencentUtils.checkString(
|
|
||||||
widget.message.imageElem!.imageList?[0]?.localUrl) ??
|
|
||||||
TencentUtils.checkString(widget.message.imageElem?.path) ??
|
|
||||||
"");
|
|
||||||
copyImageToClipboard(savePath);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "replyMessage":
|
case "replyMessage":
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import 'package:crypto/crypto.dart';
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:image_gallery_saver/image_gallery_saver.dart';
|
import 'package:image_gallery_saver_plus/image_gallery_saver_plus.dart';
|
||||||
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
||||||
import 'package:open_file/open_file.dart';
|
import 'package:open_file/open_file.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
@ -172,7 +172,8 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
|
||||||
if (model.getMessageProgress(widget.message.msgID) == 100) {
|
if (model.getMessageProgress(widget.message.msgID) == 100) {
|
||||||
String savePath;
|
String savePath;
|
||||||
if (widget.message.imageElem!.path != null &&
|
if (widget.message.imageElem!.path != null &&
|
||||||
widget.message.imageElem!.path != '' && File(widget.message.imageElem!.path!).existsSync()) {
|
widget.message.imageElem!.path != '' &&
|
||||||
|
File(widget.message.imageElem!.path!).existsSync()) {
|
||||||
savePath = widget.message.imageElem!.path!;
|
savePath = widget.message.imageElem!.path!;
|
||||||
} else {
|
} else {
|
||||||
savePath = model.getFileMessageLocation(widget.message.msgID);
|
savePath = model.getFileMessageLocation(widget.message.msgID);
|
||||||
|
|
@ -593,7 +594,6 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
|
||||||
|
|
||||||
Widget? _renderImage(dynamic heroTag, TUITheme theme,
|
Widget? _renderImage(dynamic heroTag, TUITheme theme,
|
||||||
{V2TimImage? originalImg, V2TimImage? smallImg}) {
|
{V2TimImage? originalImg, V2TimImage? smallImg}) {
|
||||||
|
|
||||||
double positionRadio = 1.0;
|
double positionRadio = 1.0;
|
||||||
if (smallImg?.width != null &&
|
if (smallImg?.width != null &&
|
||||||
smallImg?.height != null &&
|
smallImg?.height != null &&
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_easyrefresh/easy_refresh.dart';
|
import 'package:flutter_easyrefresh/easy_refresh.dart';
|
||||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
import 'package:flutter_slidable_plus_plus/flutter_slidable_plus_plus.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:scroll_to_index/scroll_to_index.dart';
|
import 'package:scroll_to_index/scroll_to_index.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||||
|
|
@ -22,11 +22,15 @@ import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitConversation/tim_uikit
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/widgets/customize_ball_pulse_header.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/widgets/customize_ball_pulse_header.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/widgets/wide_popup.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/widgets/wide_popup.dart';
|
||||||
|
|
||||||
typedef ConversationItemBuilder = Widget Function(V2TimConversation conversationItem, [V2TimUserStatus? onlineStatus]);
|
typedef ConversationItemBuilder = Widget Function(
|
||||||
|
V2TimConversation conversationItem,
|
||||||
|
[V2TimUserStatus? onlineStatus]);
|
||||||
|
|
||||||
typedef ConversationItemSlideBuilder = List<ConversationItemSlidePanel> Function(V2TimConversation conversationItem);
|
typedef ConversationItemSlideBuilder = List<ConversationItemSlidePanel>
|
||||||
|
Function(V2TimConversation conversationItem);
|
||||||
|
|
||||||
typedef ConversationItemSecondaryMenuBuilder = Widget Function(V2TimConversation conversationItem, VoidCallback onClose);
|
typedef ConversationItemSecondaryMenuBuilder = Widget Function(
|
||||||
|
V2TimConversation conversationItem, VoidCallback onClose);
|
||||||
|
|
||||||
class TIMUIKitConversation extends StatefulWidget {
|
class TIMUIKitConversation extends StatefulWidget {
|
||||||
/// the callback after clicking conversation item
|
/// the callback after clicking conversation item
|
||||||
|
|
@ -140,11 +144,14 @@ class ConversationItemSlidePanel extends TIMUIKitStatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
final TUIConversationViewModel model = serviceLocator<TUIConversationViewModel>();
|
final TUIConversationViewModel model =
|
||||||
|
serviceLocator<TUIConversationViewModel>();
|
||||||
late TIMUIKitConversationController _timuiKitConversationController;
|
late TIMUIKitConversationController _timuiKitConversationController;
|
||||||
final TUIThemeViewModel themeViewModel = serviceLocator<TUIThemeViewModel>();
|
final TUIThemeViewModel themeViewModel = serviceLocator<TUIThemeViewModel>();
|
||||||
final TUIFriendShipViewModel friendShipViewModel = serviceLocator<TUIFriendShipViewModel>();
|
final TUIFriendShipViewModel friendShipViewModel =
|
||||||
final TUIGroupListenerModel groupListenerModel = serviceLocator<TUIGroupListenerModel>();
|
serviceLocator<TUIFriendShipViewModel>();
|
||||||
|
final TUIGroupListenerModel groupListenerModel =
|
||||||
|
serviceLocator<TUIGroupListenerModel>();
|
||||||
late AutoScrollController _autoScrollController;
|
late AutoScrollController _autoScrollController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -168,21 +175,30 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
}
|
}
|
||||||
|
|
||||||
_clearHistory(V2TimConversation conversationItem) {
|
_clearHistory(V2TimConversation conversationItem) {
|
||||||
_timuiKitConversationController.clearHistoryMessage(conversation: conversationItem);
|
_timuiKitConversationController.clearHistoryMessage(
|
||||||
|
conversation: conversationItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
_pinConversation(V2TimConversation conversation) {
|
_pinConversation(V2TimConversation conversation) {
|
||||||
_timuiKitConversationController.pinConversation(conversationID: conversation.conversationID, isPinned: !conversation.isPinned!);
|
_timuiKitConversationController.pinConversation(
|
||||||
|
conversationID: conversation.conversationID,
|
||||||
|
isPinned: !conversation.isPinned!);
|
||||||
}
|
}
|
||||||
|
|
||||||
_deleteConversation(V2TimConversation conversation) {
|
_deleteConversation(V2TimConversation conversation) {
|
||||||
_timuiKitConversationController.deleteConversation(conversationID: conversation.conversationID);
|
_timuiKitConversationController.deleteConversation(
|
||||||
|
conversationID: conversation.conversationID);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<V2TimConversation?> getFilteredConversation() {
|
List<V2TimConversation?> getFilteredConversation() {
|
||||||
List<V2TimConversation?> filteredConversationList = model.conversationList.where((element) => (element?.groupID != null || element?.userID != null)).toList();
|
List<V2TimConversation?> filteredConversationList = model.conversationList
|
||||||
|
.where(
|
||||||
|
(element) => (element?.groupID != null || element?.userID != null))
|
||||||
|
.toList();
|
||||||
if (widget.conversationCollector != null) {
|
if (widget.conversationCollector != null) {
|
||||||
filteredConversationList = filteredConversationList.where(widget.conversationCollector!).toList();
|
filteredConversationList = filteredConversationList
|
||||||
|
.where(widget.conversationCollector!)
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
return filteredConversationList;
|
return filteredConversationList;
|
||||||
}
|
}
|
||||||
|
|
@ -208,7 +224,8 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _defaultSecondaryMenu(V2TimConversation conversationItem, VoidCallback onClose) {
|
Widget _defaultSecondaryMenu(
|
||||||
|
V2TimConversation conversationItem, VoidCallback onClose) {
|
||||||
return TUIKitColumnMenu(data: [
|
return TUIKitColumnMenu(data: [
|
||||||
if (!PlatformUtils().isWeb)
|
if (!PlatformUtils().isWeb)
|
||||||
ColumnMenuItem(
|
ColumnMenuItem(
|
||||||
|
|
@ -220,7 +237,11 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
}),
|
}),
|
||||||
ColumnMenuItem(
|
ColumnMenuItem(
|
||||||
label: conversationItem.isPinned! ? TIM_t("取消置顶") : TIM_t("置顶"),
|
label: conversationItem.isPinned! ? TIM_t("取消置顶") : TIM_t("置顶"),
|
||||||
icon: Icon(conversationItem.isPinned! ? Icons.vertical_align_bottom : Icons.vertical_align_top, size: 16),
|
icon: Icon(
|
||||||
|
conversationItem.isPinned!
|
||||||
|
? Icons.vertical_align_bottom
|
||||||
|
: Icons.vertical_align_top,
|
||||||
|
size: 16),
|
||||||
onClick: () {
|
onClick: () {
|
||||||
onClose();
|
onClose();
|
||||||
_pinConversation(conversationItem);
|
_pinConversation(conversationItem);
|
||||||
|
|
@ -245,7 +266,8 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
onPressed: (context) {
|
onPressed: (context) {
|
||||||
_clearHistory(conversationItem);
|
_clearHistory(conversationItem);
|
||||||
},
|
},
|
||||||
backgroundColor: theme.conversationItemSliderClearBgColor ?? CommonColor.primaryColor,
|
backgroundColor: theme.conversationItemSliderClearBgColor ??
|
||||||
|
CommonColor.primaryColor,
|
||||||
foregroundColor: theme.conversationItemSliderTextColor,
|
foregroundColor: theme.conversationItemSliderTextColor,
|
||||||
label: TIM_t("清除"),
|
label: TIM_t("清除"),
|
||||||
spacing: 0,
|
spacing: 0,
|
||||||
|
|
@ -255,7 +277,8 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
onPressed: (context) {
|
onPressed: (context) {
|
||||||
_pinConversation(conversationItem);
|
_pinConversation(conversationItem);
|
||||||
},
|
},
|
||||||
backgroundColor: theme.conversationItemSliderPinBgColor ?? CommonColor.infoColor,
|
backgroundColor:
|
||||||
|
theme.conversationItemSliderPinBgColor ?? CommonColor.infoColor,
|
||||||
foregroundColor: theme.conversationItemSliderTextColor,
|
foregroundColor: theme.conversationItemSliderTextColor,
|
||||||
label: conversationItem.isPinned! ? TIM_t("取消置顶") : TIM_t("置顶"),
|
label: conversationItem.isPinned! ? TIM_t("取消置顶") : TIM_t("置顶"),
|
||||||
),
|
),
|
||||||
|
|
@ -263,14 +286,16 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
onPressed: (context) {
|
onPressed: (context) {
|
||||||
_deleteConversation(conversationItem);
|
_deleteConversation(conversationItem);
|
||||||
},
|
},
|
||||||
backgroundColor: theme.conversationItemSliderDeleteBgColor ?? Colors.red,
|
backgroundColor:
|
||||||
|
theme.conversationItemSliderDeleteBgColor ?? Colors.red,
|
||||||
foregroundColor: theme.conversationItemSliderTextColor,
|
foregroundColor: theme.conversationItemSliderTextColor,
|
||||||
label: TIM_t("删除"),
|
label: TIM_t("删除"),
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _getSecondaryMenu(V2TimConversation conversation, VoidCallback onClose) {
|
Widget _getSecondaryMenu(
|
||||||
|
V2TimConversation conversation, VoidCallback onClose) {
|
||||||
if (widget.itemSecondaryMenuBuilder != null) {
|
if (widget.itemSecondaryMenuBuilder != null) {
|
||||||
return widget.itemSecondaryMenuBuilder!(conversation, onClose);
|
return widget.itemSecondaryMenuBuilder!(conversation, onClose);
|
||||||
}
|
}
|
||||||
|
|
@ -289,19 +314,23 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
@override
|
@override
|
||||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
final theme = value.theme;
|
final theme = value.theme;
|
||||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
final isDesktopScreen =
|
||||||
|
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
ChangeNotifierProvider.value(value: model),
|
ChangeNotifierProvider.value(value: model),
|
||||||
ChangeNotifierProvider.value(value: friendShipViewModel),
|
ChangeNotifierProvider.value(value: friendShipViewModel),
|
||||||
ChangeNotifierProvider.value(value: groupListenerModel)],
|
ChangeNotifierProvider.value(value: groupListenerModel)
|
||||||
|
],
|
||||||
builder: (BuildContext context, Widget? w) {
|
builder: (BuildContext context, Widget? w) {
|
||||||
final _model = Provider.of<TUIConversationViewModel>(context);
|
final _model = Provider.of<TUIConversationViewModel>(context);
|
||||||
bool haveMoreData = _model.haveMoreData;
|
bool haveMoreData = _model.haveMoreData;
|
||||||
final _friendShipViewModel = Provider.of<TUIFriendShipViewModel>(context);
|
final _friendShipViewModel =
|
||||||
|
Provider.of<TUIFriendShipViewModel>(context);
|
||||||
_model.lifeCycle = widget.lifeCycle;
|
_model.lifeCycle = widget.lifeCycle;
|
||||||
|
|
||||||
final TUIGroupListenerModel groupListenerModel = Provider.of<TUIGroupListenerModel>(context, listen: true);
|
final TUIGroupListenerModel groupListenerModel =
|
||||||
|
Provider.of<TUIGroupListenerModel>(context, listen: true);
|
||||||
final NeedUpdate? needUpdate = groupListenerModel.needUpdate;
|
final NeedUpdate? needUpdate = groupListenerModel.needUpdate;
|
||||||
if (needUpdate != null) {
|
if (needUpdate != null) {
|
||||||
groupListenerModel.needUpdate = null;
|
groupListenerModel.needUpdate = null;
|
||||||
|
|
@ -313,12 +342,14 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
} else if (needUpdate.updateType == UpdateType.kickedFromGroup) {
|
} else if (needUpdate.updateType == UpdateType.kickedFromGroup) {
|
||||||
onTIMCallback(TIMCallback(
|
onTIMCallback(TIMCallback(
|
||||||
type: TIMCallbackType.INFO,
|
type: TIMCallbackType.INFO,
|
||||||
infoRecommendText: "${TIM_t("您已被踢出")}${needUpdate!.extraData}",
|
infoRecommendText:
|
||||||
|
"${TIM_t("您已被踢出")}${needUpdate!.extraData}",
|
||||||
infoCode: 6661402));
|
infoCode: 6661402));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<V2TimConversation?> filteredConversationList = getFilteredConversation();
|
List<V2TimConversation?> filteredConversationList =
|
||||||
|
getFilteredConversation();
|
||||||
|
|
||||||
if (TencentUtils.checkString(_model.scrollToConversation) != null) {
|
if (TencentUtils.checkString(_model.scrollToConversation) != null) {
|
||||||
_onScrollToConversation(_model.scrollToConversation!);
|
_onScrollToConversation(_model.scrollToConversation!);
|
||||||
|
|
@ -340,15 +371,21 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
|
|
||||||
final conversationItem = filteredConversationList[index];
|
final conversationItem = filteredConversationList[index];
|
||||||
|
|
||||||
final V2TimUserStatus? onlineStatus = _friendShipViewModel.userStatusList.firstWhere((item) => item.userID == conversationItem?.userID, orElse: () => V2TimUserStatus(statusType: 0));
|
final V2TimUserStatus? onlineStatus =
|
||||||
|
_friendShipViewModel.userStatusList.firstWhere(
|
||||||
|
(item) => item.userID == conversationItem?.userID,
|
||||||
|
orElse: () => V2TimUserStatus(statusType: 0));
|
||||||
|
|
||||||
if (widget.itemBuilder != null) {
|
if (widget.itemBuilder != null) {
|
||||||
return widget.itemBuilder!(conversationItem!, onlineStatus);
|
return widget.itemBuilder!(
|
||||||
|
conversationItem!, onlineStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
final slideChildren = _getSlideBuilder()(conversationItem!);
|
final slideChildren =
|
||||||
|
_getSlideBuilder()(conversationItem!);
|
||||||
|
|
||||||
final isCurrent = conversationItem.conversationID == model.selectedConversation?.conversationID;
|
final isCurrent = conversationItem.conversationID ==
|
||||||
|
model.selectedConversation?.conversationID;
|
||||||
|
|
||||||
final isPined = conversationItem.isPinned ?? false;
|
final isPined = conversationItem.isPinned ?? false;
|
||||||
|
|
||||||
|
|
@ -365,14 +402,21 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
lastMessageBuilder: widget.lastMessageBuilder,
|
lastMessageBuilder: widget.lastMessageBuilder,
|
||||||
faceUrl: conversationItem.faceUrl ?? "",
|
faceUrl: conversationItem.faceUrl ?? "",
|
||||||
nickName: conversationItem.showName ?? "",
|
nickName: conversationItem.showName ?? "",
|
||||||
isDisturb: (conversationItem.groupType == "Meeting" ? false : conversationItem
|
isDisturb:
|
||||||
.recvOpt != 0),
|
(conversationItem.groupType == "Meeting"
|
||||||
|
? false
|
||||||
|
: conversationItem.recvOpt != 0),
|
||||||
lastMsg: conversationItem.lastMessage,
|
lastMsg: conversationItem.lastMessage,
|
||||||
isPined: isPined,
|
isPined: isPined,
|
||||||
groupAtInfoList: conversationItem.groupAtInfoList ?? [],
|
groupAtInfoList:
|
||||||
|
conversationItem.groupAtInfoList ?? [],
|
||||||
unreadCount: conversationItem.unreadCount ?? 0,
|
unreadCount: conversationItem.unreadCount ?? 0,
|
||||||
draftText: conversationItem.draftText,
|
draftText: conversationItem.draftText,
|
||||||
onlineStatus: (widget.isShowOnlineStatus && conversationItem.userID != null && conversationItem.userID!.isNotEmpty) ? onlineStatus : null,
|
onlineStatus: (widget.isShowOnlineStatus &&
|
||||||
|
conversationItem.userID != null &&
|
||||||
|
conversationItem.userID!.isNotEmpty)
|
||||||
|
? onlineStatus
|
||||||
|
: null,
|
||||||
draftTimestamp: conversationItem.draftTimestamp,
|
draftTimestamp: conversationItem.draftTimestamp,
|
||||||
convType: conversationItem.type),
|
convType: conversationItem.type),
|
||||||
onTap: () => onTapConvItem(conversationItem),
|
onTap: () => onTapConvItem(conversationItem),
|
||||||
|
|
@ -389,12 +433,23 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onSecondaryTapDown: (details) {
|
onSecondaryTapDown: (details) {
|
||||||
TUIKitWidePopup.showPopupWindow(
|
TUIKitWidePopup.showPopupWindow(
|
||||||
operationKey: TUIKitWideModalOperationKey.conversationSecondaryMenu,
|
operationKey: TUIKitWideModalOperationKey
|
||||||
|
.conversationSecondaryMenu,
|
||||||
isDarkBackground: false,
|
isDarkBackground: false,
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(4)),
|
||||||
context: context,
|
context: context,
|
||||||
offset: Offset(min(details.globalPosition.dx, MediaQuery.of(context).size.width - 80), min(details.globalPosition.dy, MediaQuery.of(context).size.height - 130)),
|
offset: Offset(
|
||||||
child: (onClose) => _getSecondaryMenu(conversationItem, onClose));
|
min(
|
||||||
|
details.globalPosition.dx,
|
||||||
|
MediaQuery.of(context).size.width -
|
||||||
|
80),
|
||||||
|
min(
|
||||||
|
details.globalPosition.dy,
|
||||||
|
MediaQuery.of(context).size.height -
|
||||||
|
130)),
|
||||||
|
child: (onClose) => _getSecondaryMenu(
|
||||||
|
conversationItem, onClose));
|
||||||
},
|
},
|
||||||
child: conversationLineItem(),
|
child: conversationLineItem(),
|
||||||
),
|
),
|
||||||
|
|
@ -403,10 +458,19 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
key: ValueKey(conversationItem.conversationID),
|
key: ValueKey(conversationItem.conversationID),
|
||||||
controller: _autoScrollController,
|
controller: _autoScrollController,
|
||||||
index: index,
|
index: index,
|
||||||
child: Slidable(groupTag: 'conversation-list', child: conversationLineItem(), endActionPane: ActionPane(extentRatio: slideChildren.length > 2 ? 0.77 : 0.5, motion: const DrawerMotion(), children: slideChildren)),
|
child: Slidable(
|
||||||
|
groupTag: 'conversation-list',
|
||||||
|
child: conversationLineItem(),
|
||||||
|
endActionPane: ActionPane(
|
||||||
|
extentRatio:
|
||||||
|
slideChildren.length > 2 ? 0.77 : 0.5,
|
||||||
|
motion: const DrawerMotion(),
|
||||||
|
children: slideChildren)),
|
||||||
));
|
));
|
||||||
})
|
})
|
||||||
: (widget.emptyBuilder != null ? widget.emptyBuilder!() : Container());
|
: (widget.emptyBuilder != null
|
||||||
|
? widget.emptyBuilder!()
|
||||||
|
: Container());
|
||||||
}
|
}
|
||||||
|
|
||||||
return TUIKitScreenUtils.getDeviceWidget(
|
return TUIKitScreenUtils.getDeviceWidget(
|
||||||
|
|
@ -420,7 +484,9 @@ class _TIMUIKitConversationState extends TIMUIKitState<TIMUIKitConversation> {
|
||||||
child: conversationList(),
|
child: conversationList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
desktopWidget: Scrollbar(controller: _autoScrollController, child: conversationList()));
|
desktopWidget: Scrollbar(
|
||||||
|
controller: _autoScrollController,
|
||||||
|
child: conversationList()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
import 'package:flutter_slidable_plus_plus/flutter_slidable_plus_plus.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
|
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
|
||||||
|
|
@ -26,23 +26,34 @@ class GroupProfileGroupManage extends StatefulWidget {
|
||||||
State<StatefulWidget> createState() => GroupProfileGroupManageState();
|
State<StatefulWidget> createState() => GroupProfileGroupManageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class GroupProfileGroupManageState extends TIMUIKitState<GroupProfileGroupManage> {
|
class GroupProfileGroupManageState
|
||||||
|
extends TIMUIKitState<GroupProfileGroupManage> {
|
||||||
bool isShowManageBox = false;
|
bool isShowManageBox = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
final TUITheme theme = value.theme;
|
final TUITheme theme = value.theme;
|
||||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
final isDesktopScreen =
|
||||||
|
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||||
final model = Provider.of<TUIGroupProfileModel>(context);
|
final model = Provider.of<TUIGroupProfileModel>(context);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
decoration: BoxDecoration(color: Colors.white, border: isDesktopScreen ? null : Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))),
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: isDesktopScreen
|
||||||
|
? null
|
||||||
|
: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: theme.weakDividerColor ??
|
||||||
|
CommonColor.weakDividerColor))),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
final isDesktopScreen =
|
||||||
|
TUIKitScreenUtils.getFormFactor(context) ==
|
||||||
|
DeviceType.Desktop;
|
||||||
if (!isDesktopScreen) {
|
if (!isDesktopScreen) {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
|
|
@ -61,12 +72,15 @@ class GroupProfileGroupManageState extends TIMUIKitState<GroupProfileGroupManage
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
TIM_t("群管理"),
|
TIM_t("群管理"),
|
||||||
style: TextStyle(fontSize: isDesktopScreen ? 14 : 16, color: theme.darkTextColor),
|
style: TextStyle(
|
||||||
|
fontSize: isDesktopScreen ? 14 : 16,
|
||||||
|
color: theme.darkTextColor),
|
||||||
),
|
),
|
||||||
AnimatedRotation(
|
AnimatedRotation(
|
||||||
turns: isShowManageBox ? 0.25 : 0,
|
turns: isShowManageBox ? 0.25 : 0,
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
child: Icon(Icons.keyboard_arrow_right, color: theme.weakTextColor),
|
child: Icon(Icons.keyboard_arrow_right,
|
||||||
|
color: theme.weakTextColor),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -94,7 +108,8 @@ class GroupProfileGroupManagePage extends StatefulWidget {
|
||||||
State<StatefulWidget> createState() => _GroupProfileGroupManagePageState();
|
State<StatefulWidget> createState() => _GroupProfileGroupManagePageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GroupProfileGroupManagePageState extends TIMUIKitState<GroupProfileGroupManagePage> {
|
class _GroupProfileGroupManagePageState
|
||||||
|
extends TIMUIKitState<GroupProfileGroupManagePage> {
|
||||||
int? serverTime;
|
int? serverTime;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -113,20 +128,38 @@ class _GroupProfileGroupManagePageState extends TIMUIKitState<GroupProfileGroupM
|
||||||
@override
|
@override
|
||||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [ChangeNotifierProvider.value(value: widget.model), ChangeNotifierProvider.value(value: serviceLocator<TUIThemeViewModel>())],
|
providers: [
|
||||||
|
ChangeNotifierProvider.value(value: widget.model),
|
||||||
|
ChangeNotifierProvider.value(
|
||||||
|
value: serviceLocator<TUIThemeViewModel>())
|
||||||
|
],
|
||||||
builder: (context, w) {
|
builder: (context, w) {
|
||||||
final memberList = Provider.of<TUIGroupProfileModel>(context).groupMemberList;
|
final memberList =
|
||||||
|
Provider.of<TUIGroupProfileModel>(context).groupMemberList;
|
||||||
final theme = Provider.of<TUIThemeViewModel>(context).theme;
|
final theme = Provider.of<TUIThemeViewModel>(context).theme;
|
||||||
final isAllMuted = widget.model.groupInfo?.isAllMuted ?? false;
|
final isAllMuted = widget.model.groupInfo?.isAllMuted ?? false;
|
||||||
final bool isAllowMuteMember = (widget.model.groupInfo?.groupType ?? "") != GroupType.Work;
|
final bool isAllowMuteMember =
|
||||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
(widget.model.groupInfo?.groupType ?? "") != GroupType.Work;
|
||||||
|
final isDesktopScreen =
|
||||||
|
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||||
|
|
||||||
Widget managePage() {
|
Widget managePage() {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.only(top: 12, left: isDesktopScreen ? 0 : 16, bottom: isDesktopScreen ? 0 : 12, right: isDesktopScreen ? 0 : 12),
|
padding: EdgeInsets.only(
|
||||||
decoration: BoxDecoration(color: Colors.white, border: isDesktopScreen ? null : Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))),
|
top: 12,
|
||||||
|
left: isDesktopScreen ? 0 : 16,
|
||||||
|
bottom: isDesktopScreen ? 0 : 12,
|
||||||
|
right: isDesktopScreen ? 0 : 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: isDesktopScreen
|
||||||
|
? null
|
||||||
|
: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: theme.weakDividerColor ??
|
||||||
|
CommonColor.weakDividerColor))),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: isDesktopScreen
|
onTap: isDesktopScreen
|
||||||
? null
|
? null
|
||||||
|
|
@ -134,7 +167,8 @@ class _GroupProfileGroupManagePageState extends TIMUIKitState<GroupProfileGroupM
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => GroupProfileSetManagerPage(
|
builder: (context) =>
|
||||||
|
GroupProfileSetManagerPage(
|
||||||
model: widget.model,
|
model: widget.model,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
@ -143,12 +177,22 @@ class _GroupProfileGroupManagePageState extends TIMUIKitState<GroupProfileGroupM
|
||||||
? Row(
|
? Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(TIM_t("群管理员"), style: TextStyle(fontSize: 14, color: theme.darkTextColor)),
|
Text(TIM_t("群管理员"),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: theme.darkTextColor)),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: Row(
|
: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [Text(TIM_t("设置管理员"), style: TextStyle(fontSize: isDesktopScreen ? 14 : 16, color: theme.darkTextColor)), Icon(Icons.keyboard_arrow_right, color: theme.weakTextColor)],
|
children: [
|
||||||
|
Text(TIM_t("设置管理员"),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: isDesktopScreen ? 14 : 16,
|
||||||
|
color: theme.darkTextColor)),
|
||||||
|
Icon(Icons.keyboard_arrow_right,
|
||||||
|
color: theme.weakTextColor)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -158,14 +202,21 @@ class _GroupProfileGroupManagePageState extends TIMUIKitState<GroupProfileGroupM
|
||||||
),
|
),
|
||||||
if (!isDesktopScreen)
|
if (!isDesktopScreen)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.only(top: 12, left: 16, bottom: 12, right: 12),
|
padding: const EdgeInsets.only(
|
||||||
decoration: BoxDecoration(color: Colors.white, border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))),
|
top: 12, left: 16, bottom: 12, right: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: theme.weakDividerColor ??
|
||||||
|
CommonColor.weakDividerColor))),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
TIM_t("全员禁言"),
|
TIM_t("全员禁言"),
|
||||||
style: TextStyle(fontSize: 16, color: theme.darkTextColor),
|
style: TextStyle(
|
||||||
|
fontSize: 16, color: theme.darkTextColor),
|
||||||
),
|
),
|
||||||
CupertinoSwitch(
|
CupertinoSwitch(
|
||||||
value: isAllMuted,
|
value: isAllMuted,
|
||||||
|
|
@ -180,7 +231,9 @@ class _GroupProfileGroupManagePageState extends TIMUIKitState<GroupProfileGroupM
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(TIM_t("禁言"), style: TextStyle(fontSize: 14, color: theme.darkTextColor)),
|
Text(TIM_t("禁言"),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14, color: theme.darkTextColor)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDesktopScreen)
|
if (isDesktopScreen)
|
||||||
|
|
@ -200,12 +253,14 @@ class _GroupProfileGroupManagePageState extends TIMUIKitState<GroupProfileGroupM
|
||||||
),
|
),
|
||||||
if (!isDesktopScreen)
|
if (!isDesktopScreen)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10, horizontal: 16),
|
||||||
color: theme.weakBackgroundColor,
|
color: theme.weakBackgroundColor,
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
TIM_t("全员禁言开启后,只允许群主和管理员发言。"),
|
TIM_t("全员禁言开启后,只允许群主和管理员发言。"),
|
||||||
style: TextStyle(fontSize: 12, color: theme.weakTextColor),
|
style:
|
||||||
|
TextStyle(fontSize: 12, color: theme.weakTextColor),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!isAllMuted && isAllowMuteMember)
|
if (!isAllMuted && isAllowMuteMember)
|
||||||
|
|
@ -221,7 +276,14 @@ class _GroupProfileGroupManagePageState extends TIMUIKitState<GroupProfileGroupM
|
||||||
: const EdgeInsets.only(
|
: const EdgeInsets.only(
|
||||||
bottom: 4,
|
bottom: 4,
|
||||||
),
|
),
|
||||||
decoration: isDesktopScreen ? null : BoxDecoration(color: Colors.white, border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))),
|
decoration: isDesktopScreen
|
||||||
|
? null
|
||||||
|
: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: theme.weakDividerColor ??
|
||||||
|
CommonColor.weakDividerColor))),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
|
|
@ -242,15 +304,21 @@ class _GroupProfileGroupManagePageState extends TIMUIKitState<GroupProfileGroupM
|
||||||
key: groupProfileAddAdminKey,
|
key: groupProfileAddAdminKey,
|
||||||
appbarTitle: TIM_t("设置禁言"),
|
appbarTitle: TIM_t("设置禁言"),
|
||||||
memberList: memberList.where((element) {
|
memberList: memberList.where((element) {
|
||||||
final isMute = (serverTime != null ? (element?.muteUntil ?? 0) > serverTime! : false);
|
final isMute = (serverTime != null
|
||||||
final isMember = element!.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER;
|
? (element?.muteUntil ?? 0) > serverTime!
|
||||||
|
: false);
|
||||||
|
final isMember = element!.role ==
|
||||||
|
GroupMemberRoleType
|
||||||
|
.V2TIM_GROUP_MEMBER_ROLE_MEMBER;
|
||||||
return !isMute && isMember;
|
return !isMute && isMember;
|
||||||
}).toList(),
|
}).toList(),
|
||||||
selectCompletedHandler: (context, selectedMember) async {
|
selectCompletedHandler:
|
||||||
|
(context, selectedMember) async {
|
||||||
if (selectedMember.isNotEmpty) {
|
if (selectedMember.isNotEmpty) {
|
||||||
for (var member in selectedMember) {
|
for (var member in selectedMember) {
|
||||||
final userID = member!.userID;
|
final userID = member!.userID;
|
||||||
widget.model.muteGroupMember(userID, true, serverTime);
|
widget.model
|
||||||
|
.muteGroupMember(userID, true, serverTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -269,29 +337,48 @@ class _GroupProfileGroupManagePageState extends TIMUIKitState<GroupProfileGroupM
|
||||||
},
|
},
|
||||||
child: (onClose) => muteMember());
|
child: (onClose) => muteMember());
|
||||||
} else {
|
} else {
|
||||||
Navigator.push(context, MaterialPageRoute(builder: (context) => muteMember()));
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => muteMember()));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (!isAllMuted && isAllowMuteMember)
|
if (!isAllMuted && isAllowMuteMember)
|
||||||
...memberList
|
...memberList
|
||||||
.where((element) => (serverTime != null ? (element?.muteUntil ?? 0) > serverTime! : false))
|
.where((element) => (serverTime != null
|
||||||
|
? (element?.muteUntil ?? 0) > serverTime!
|
||||||
|
: false))
|
||||||
.map((e) => Container(
|
.map((e) => Container(
|
||||||
padding: isDesktopScreen ? const EdgeInsets.only(left: 16) : null,
|
padding: isDesktopScreen
|
||||||
|
? const EdgeInsets.only(left: 16)
|
||||||
|
: null,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onSecondaryTapDown: (details) {
|
onSecondaryTapDown: (details) {
|
||||||
TUIKitWidePopup.showPopupWindow(
|
TUIKitWidePopup.showPopupWindow(
|
||||||
operationKey: TUIKitWideModalOperationKey.setUnmute,
|
operationKey:
|
||||||
|
TUIKitWideModalOperationKey.setUnmute,
|
||||||
isDarkBackground: false,
|
isDarkBackground: false,
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(4)),
|
||||||
context: context,
|
context: context,
|
||||||
offset: Offset(min(details.globalPosition.dx, MediaQuery.of(context).size.width - 80), details.globalPosition.dy),
|
offset: Offset(
|
||||||
|
min(
|
||||||
|
details.globalPosition.dx,
|
||||||
|
MediaQuery.of(context).size.width -
|
||||||
|
80),
|
||||||
|
details.globalPosition.dy),
|
||||||
child: (onClose) => TUIKitColumnMenu(data: [
|
child: (onClose) => TUIKitColumnMenu(data: [
|
||||||
ColumnMenuItem(
|
ColumnMenuItem(
|
||||||
label: TIM_t("删除"),
|
label: TIM_t("删除"),
|
||||||
icon: const Icon(Icons.remove_circle_outline, size: 16),
|
icon: const Icon(
|
||||||
|
Icons.remove_circle_outline,
|
||||||
|
size: 16),
|
||||||
onClick: () {
|
onClick: () {
|
||||||
widget.model.muteGroupMember(e.userID, false, serverTime);
|
widget.model.muteGroupMember(
|
||||||
|
e.userID,
|
||||||
|
false,
|
||||||
|
serverTime);
|
||||||
onClose();
|
onClose();
|
||||||
}),
|
}),
|
||||||
]));
|
]));
|
||||||
|
|
@ -299,13 +386,17 @@ class _GroupProfileGroupManagePageState extends TIMUIKitState<GroupProfileGroupM
|
||||||
child: _buildListItem(
|
child: _buildListItem(
|
||||||
context,
|
context,
|
||||||
e!,
|
e!,
|
||||||
ActionPane(motion: const DrawerMotion(), children: [
|
ActionPane(
|
||||||
|
motion: const DrawerMotion(),
|
||||||
|
children: [
|
||||||
SlidableAction(
|
SlidableAction(
|
||||||
onPressed: (_) {
|
onPressed: (_) {
|
||||||
widget.model.muteGroupMember(e.userID, false, serverTime);
|
widget.model.muteGroupMember(
|
||||||
|
e.userID, false, serverTime);
|
||||||
},
|
},
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: theme.cautionColor ?? CommonColor.cautionColor,
|
backgroundColor: theme.cautionColor ??
|
||||||
|
CommonColor.cautionColor,
|
||||||
autoClose: true,
|
autoClose: true,
|
||||||
label: TIM_t("删除"),
|
label: TIM_t("删除"),
|
||||||
)
|
)
|
||||||
|
|
@ -324,7 +415,8 @@ class _GroupProfileGroupManagePageState extends TIMUIKitState<GroupProfileGroupM
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(
|
title: Text(
|
||||||
TIM_t("群管理"),
|
TIM_t("群管理"),
|
||||||
style: TextStyle(color: theme.appbarTextColor, fontSize: 17),
|
style:
|
||||||
|
TextStyle(color: theme.appbarTextColor, fontSize: 17),
|
||||||
),
|
),
|
||||||
backgroundColor: theme.appbarBgColor ?? theme.primaryColor,
|
backgroundColor: theme.appbarBgColor ?? theme.primaryColor,
|
||||||
shadowColor: theme.weakDividerColor,
|
shadowColor: theme.weakDividerColor,
|
||||||
|
|
@ -369,9 +461,11 @@ _getShowName(V2TimGroupMemberFullInfo? item) {
|
||||||
: userID;
|
: userID;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildListItem(BuildContext context, V2TimGroupMemberFullInfo memberInfo, ActionPane? endActionPane) {
|
Widget _buildListItem(BuildContext context, V2TimGroupMemberFullInfo memberInfo,
|
||||||
|
ActionPane? endActionPane) {
|
||||||
final theme = Provider.of<TUIThemeViewModel>(context).theme;
|
final theme = Provider.of<TUIThemeViewModel>(context).theme;
|
||||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
final isDesktopScreen =
|
||||||
|
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||||
|
|
||||||
Widget nameItem() {
|
Widget nameItem() {
|
||||||
return Container(
|
return Container(
|
||||||
|
|
@ -390,42 +484,67 @@ Widget _buildListItem(BuildContext context, V2TimGroupMemberFullInfo memberInfo,
|
||||||
),
|
),
|
||||||
title: Row(
|
title: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(_getShowName(memberInfo), style: TextStyle(fontSize: isDesktopScreen ? 14 : 16)),
|
Text(_getShowName(memberInfo),
|
||||||
|
style: TextStyle(fontSize: isDesktopScreen ? 14 : 16)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: () {},
|
onTap: () {},
|
||||||
),
|
),
|
||||||
if (!isDesktopScreen) Divider(thickness: 1, indent: 74, endIndent: 0, color: theme.weakDividerColor, height: 0)
|
if (!isDesktopScreen)
|
||||||
|
Divider(
|
||||||
|
thickness: 1,
|
||||||
|
indent: 74,
|
||||||
|
endIndent: 0,
|
||||||
|
color: theme.weakDividerColor,
|
||||||
|
height: 0)
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TUIKitScreenUtils.getDeviceWidget(context: context, desktopWidget: nameItem(), defaultWidget: SingleChildScrollView(child: Slidable(endActionPane: endActionPane, child: nameItem())));
|
return TUIKitScreenUtils.getDeviceWidget(
|
||||||
|
context: context,
|
||||||
|
desktopWidget: nameItem(),
|
||||||
|
defaultWidget: SingleChildScrollView(
|
||||||
|
child: Slidable(endActionPane: endActionPane, child: nameItem())));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 选择管理员
|
/// 选择管理员
|
||||||
class GroupProfileSetManagerPage extends StatefulWidget {
|
class GroupProfileSetManagerPage extends StatefulWidget {
|
||||||
final TUIGroupProfileModel model;
|
final TUIGroupProfileModel model;
|
||||||
|
|
||||||
const GroupProfileSetManagerPage({Key? key, required this.model}) : super(key: key);
|
const GroupProfileSetManagerPage({Key? key, required this.model})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() => _GroupProfileSetManagerPageState();
|
State<StatefulWidget> createState() => _GroupProfileSetManagerPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GroupProfileSetManagerPageState extends TIMUIKitState<GroupProfileSetManagerPage> {
|
class _GroupProfileSetManagerPageState
|
||||||
List<V2TimGroupMemberFullInfo?> _getAdminMemberList(List<V2TimGroupMemberFullInfo?> memberList) {
|
extends TIMUIKitState<GroupProfileSetManagerPage> {
|
||||||
return memberList.where((member) => member?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN).toList();
|
List<V2TimGroupMemberFullInfo?> _getAdminMemberList(
|
||||||
|
List<V2TimGroupMemberFullInfo?> memberList) {
|
||||||
|
return memberList
|
||||||
|
.where((member) =>
|
||||||
|
member?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN)
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<V2TimGroupMemberFullInfo?> _getOwnerList(List<V2TimGroupMemberFullInfo?> memberList) {
|
List<V2TimGroupMemberFullInfo?> _getOwnerList(
|
||||||
return memberList.where((member) => member?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER).toList();
|
List<V2TimGroupMemberFullInfo?> memberList) {
|
||||||
|
return memberList
|
||||||
|
.where((member) =>
|
||||||
|
member?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER)
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
_removeAdmin(BuildContext context, V2TimGroupMemberFullInfo memberFullInfo) async {
|
_removeAdmin(
|
||||||
|
BuildContext context, V2TimGroupMemberFullInfo memberFullInfo) async {
|
||||||
final res = await widget.model.setMemberToNormal(memberFullInfo.userID);
|
final res = await widget.model.setMemberToNormal(memberFullInfo.userID);
|
||||||
if (res.code == 0) {
|
if (res.code == 0) {
|
||||||
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("成功取消管理员身份"), infoCode: 6661003));
|
onTIMCallback(TIMCallback(
|
||||||
|
type: TIMCallbackType.INFO,
|
||||||
|
infoRecommendText: TIM_t("成功取消管理员身份"),
|
||||||
|
infoCode: 6661003));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -441,7 +560,8 @@ class _GroupProfileSetManagerPageState extends TIMUIKitState<GroupProfileSetMana
|
||||||
final adminList = _getAdminMemberList(memberList);
|
final adminList = _getAdminMemberList(memberList);
|
||||||
final ownerList = _getOwnerList(memberList);
|
final ownerList = _getOwnerList(memberList);
|
||||||
final String option2 = adminList.length.toString();
|
final String option2 = adminList.length.toString();
|
||||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
final isDesktopScreen =
|
||||||
|
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
|
||||||
|
|
||||||
Widget adminPage() {
|
Widget adminPage() {
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
|
|
@ -451,7 +571,8 @@ class _GroupProfileSetManagerPageState extends TIMUIKitState<GroupProfileSetMana
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
color: theme.weakDividerColor,
|
color: theme.weakDividerColor,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16),
|
padding:
|
||||||
|
const EdgeInsets.symmetric(vertical: 6, horizontal: 16),
|
||||||
child: Text(
|
child: Text(
|
||||||
TIM_t("群主"),
|
TIM_t("群主"),
|
||||||
style: TextStyle(fontSize: 14, color: theme.weakTextColor),
|
style: TextStyle(fontSize: 14, color: theme.weakTextColor),
|
||||||
|
|
@ -469,7 +590,9 @@ class _GroupProfileSetManagerPageState extends TIMUIKitState<GroupProfileSetMana
|
||||||
...ownerList
|
...ownerList
|
||||||
.map(
|
.map(
|
||||||
(e) => Container(
|
(e) => Container(
|
||||||
padding: isDesktopScreen ? const EdgeInsets.only(left: 16) : null,
|
padding: isDesktopScreen
|
||||||
|
? const EdgeInsets.only(left: 16)
|
||||||
|
: null,
|
||||||
child: _buildListItem(context, e!, null),
|
child: _buildListItem(context, e!, null),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -478,9 +601,11 @@ class _GroupProfileSetManagerPageState extends TIMUIKitState<GroupProfileSetMana
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
color: theme.weakDividerColor,
|
color: theme.weakDividerColor,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16),
|
padding:
|
||||||
|
const EdgeInsets.symmetric(vertical: 6, horizontal: 16),
|
||||||
child: Text(
|
child: Text(
|
||||||
TIM_t_para("管理员 ({{option2}}/10)", "管理员 ($option2/10)")(option2: option2),
|
TIM_t_para("管理员 ({{option2}}/10)", "管理员 ($option2/10)")(
|
||||||
|
option2: option2),
|
||||||
style: TextStyle(fontSize: 14, color: theme.weakTextColor),
|
style: TextStyle(fontSize: 14, color: theme.weakTextColor),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -489,7 +614,8 @@ class _GroupProfileSetManagerPageState extends TIMUIKitState<GroupProfileSetMana
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
padding: const EdgeInsets.only(top: 10, bottom: 4, left: 16),
|
padding: const EdgeInsets.only(top: 10, bottom: 4, left: 16),
|
||||||
child: Text(
|
child: Text(
|
||||||
TIM_t_para("管理员 ({{option2}}/10)", "管理员 ($option2/10)")(option2: option2),
|
TIM_t_para("管理员 ({{option2}}/10)", "管理员 ($option2/10)")(
|
||||||
|
option2: option2),
|
||||||
style: TextStyle(fontSize: 14, color: theme.primaryColor),
|
style: TextStyle(fontSize: 14, color: theme.primaryColor),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -501,7 +627,14 @@ class _GroupProfileSetManagerPageState extends TIMUIKitState<GroupProfileSetMana
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
vertical: 12,
|
vertical: 12,
|
||||||
),
|
),
|
||||||
decoration: isDesktopScreen ? null : BoxDecoration(color: Colors.white, border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))),
|
decoration: isDesktopScreen
|
||||||
|
? null
|
||||||
|
: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: theme.weakDividerColor ??
|
||||||
|
CommonColor.weakDividerColor))),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
|
|
@ -529,9 +662,15 @@ class _GroupProfileSetManagerPageState extends TIMUIKitState<GroupProfileSetMana
|
||||||
},
|
},
|
||||||
child: (onClose) => GroupProfileAddAdmin(
|
child: (onClose) => GroupProfileAddAdmin(
|
||||||
key: groupProfileAddAdminKey,
|
key: groupProfileAddAdminKey,
|
||||||
memberList: memberList.where((element) => element?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER).toList(),
|
memberList: memberList
|
||||||
|
.where((element) =>
|
||||||
|
element?.role ==
|
||||||
|
GroupMemberRoleType
|
||||||
|
.V2TIM_GROUP_MEMBER_ROLE_MEMBER)
|
||||||
|
.toList(),
|
||||||
appbarTitle: TIM_t("设置管理员"),
|
appbarTitle: TIM_t("设置管理员"),
|
||||||
selectCompletedHandler: (context, selectedMember) async {
|
selectCompletedHandler:
|
||||||
|
(context, selectedMember) async {
|
||||||
if (selectedMember.isNotEmpty) {
|
if (selectedMember.isNotEmpty) {
|
||||||
for (var member in selectedMember) {
|
for (var member in selectedMember) {
|
||||||
final userID = member!.userID;
|
final userID = member!.userID;
|
||||||
|
|
@ -546,9 +685,15 @@ class _GroupProfileSetManagerPageState extends TIMUIKitState<GroupProfileSetMana
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => GroupProfileAddAdmin(
|
builder: (context) => GroupProfileAddAdmin(
|
||||||
key: groupProfileAddAdminKey,
|
key: groupProfileAddAdminKey,
|
||||||
memberList: memberList.where((element) => element?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER).toList(),
|
memberList: memberList
|
||||||
|
.where((element) =>
|
||||||
|
element?.role ==
|
||||||
|
GroupMemberRoleType
|
||||||
|
.V2TIM_GROUP_MEMBER_ROLE_MEMBER)
|
||||||
|
.toList(),
|
||||||
appbarTitle: TIM_t("设置管理员"),
|
appbarTitle: TIM_t("设置管理员"),
|
||||||
selectCompletedHandler: (context, selectedMember) async {
|
selectCompletedHandler:
|
||||||
|
(context, selectedMember) async {
|
||||||
if (selectedMember.isNotEmpty) {
|
if (selectedMember.isNotEmpty) {
|
||||||
for (var member in selectedMember) {
|
for (var member in selectedMember) {
|
||||||
final userID = member!.userID;
|
final userID = member!.userID;
|
||||||
|
|
@ -564,15 +709,22 @@ class _GroupProfileSetManagerPageState extends TIMUIKitState<GroupProfileSetMana
|
||||||
.map((e) => GestureDetector(
|
.map((e) => GestureDetector(
|
||||||
onSecondaryTapDown: (details) {
|
onSecondaryTapDown: (details) {
|
||||||
TUIKitWidePopup.showPopupWindow(
|
TUIKitWidePopup.showPopupWindow(
|
||||||
operationKey: TUIKitWideModalOperationKey.deleteAdmin,
|
operationKey:
|
||||||
|
TUIKitWideModalOperationKey.deleteAdmin,
|
||||||
isDarkBackground: false,
|
isDarkBackground: false,
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
borderRadius:
|
||||||
|
const BorderRadius.all(Radius.circular(4)),
|
||||||
context: context,
|
context: context,
|
||||||
offset: Offset(min(details.globalPosition.dx, MediaQuery.of(context).size.width - 80), details.globalPosition.dy),
|
offset: Offset(
|
||||||
|
min(details.globalPosition.dx,
|
||||||
|
MediaQuery.of(context).size.width - 80),
|
||||||
|
details.globalPosition.dy),
|
||||||
child: (onClose) => TUIKitColumnMenu(data: [
|
child: (onClose) => TUIKitColumnMenu(data: [
|
||||||
ColumnMenuItem(
|
ColumnMenuItem(
|
||||||
label: TIM_t("删除"),
|
label: TIM_t("删除"),
|
||||||
icon: const Icon(Icons.remove_circle_outline, size: 16),
|
icon: const Icon(
|
||||||
|
Icons.remove_circle_outline,
|
||||||
|
size: 16),
|
||||||
onClick: () {
|
onClick: () {
|
||||||
_removeAdmin(context, e);
|
_removeAdmin(context, e);
|
||||||
onClose();
|
onClose();
|
||||||
|
|
@ -580,17 +732,22 @@ class _GroupProfileSetManagerPageState extends TIMUIKitState<GroupProfileSetMana
|
||||||
]));
|
]));
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: isDesktopScreen ? const EdgeInsets.only(left: 16) : null,
|
padding: isDesktopScreen
|
||||||
|
? const EdgeInsets.only(left: 16)
|
||||||
|
: null,
|
||||||
child: _buildListItem(
|
child: _buildListItem(
|
||||||
context,
|
context,
|
||||||
e!,
|
e!,
|
||||||
ActionPane(motion: const DrawerMotion(), children: [
|
ActionPane(
|
||||||
|
motion: const DrawerMotion(),
|
||||||
|
children: [
|
||||||
SlidableAction(
|
SlidableAction(
|
||||||
onPressed: (_) {
|
onPressed: (_) {
|
||||||
_removeAdmin(context, e);
|
_removeAdmin(context, e);
|
||||||
},
|
},
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: theme.cautionColor ?? CommonColor.cautionColor,
|
backgroundColor: theme.cautionColor ??
|
||||||
|
CommonColor.cautionColor,
|
||||||
autoClose: true,
|
autoClose: true,
|
||||||
label: TIM_t("删除"),
|
label: TIM_t("删除"),
|
||||||
)
|
)
|
||||||
|
|
@ -628,9 +785,16 @@ class _GroupProfileSetManagerPageState extends TIMUIKitState<GroupProfileSetMana
|
||||||
class GroupProfileAddAdmin extends StatefulWidget {
|
class GroupProfileAddAdmin extends StatefulWidget {
|
||||||
final List<V2TimGroupMemberFullInfo?> memberList;
|
final List<V2TimGroupMemberFullInfo?> memberList;
|
||||||
final String appbarTitle;
|
final String appbarTitle;
|
||||||
final void Function(BuildContext context, List<V2TimGroupMemberFullInfo?> selectedMemberList)? selectCompletedHandler;
|
final void Function(BuildContext context,
|
||||||
|
List<V2TimGroupMemberFullInfo?> selectedMemberList)?
|
||||||
|
selectCompletedHandler;
|
||||||
|
|
||||||
const GroupProfileAddAdmin({Key? key, required this.memberList, this.selectCompletedHandler, required this.appbarTitle}) : super(key: key);
|
const GroupProfileAddAdmin(
|
||||||
|
{Key? key,
|
||||||
|
required this.memberList,
|
||||||
|
this.selectCompletedHandler,
|
||||||
|
required this.appbarTitle})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() => _GroupProfileAddAdminState();
|
State<StatefulWidget> createState() => _GroupProfileAddAdminState();
|
||||||
|
|
@ -664,8 +828,14 @@ class _GroupProfileAddAdminState extends TIMUIKitState<GroupProfileAddAdmin> {
|
||||||
),
|
),
|
||||||
...widget.memberList
|
...widget.memberList
|
||||||
.map((e) => Container(
|
.map((e) => Container(
|
||||||
decoration: BoxDecoration(color: Colors.white, border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))),
|
decoration: BoxDecoration(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
color: Colors.white,
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: theme.weakDividerColor ??
|
||||||
|
CommonColor.weakDividerColor))),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10, horizontal: 16),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
final isChecked = selectedMemberList.contains(e);
|
final isChecked = selectedMemberList.contains(e);
|
||||||
|
|
@ -697,7 +867,8 @@ class _GroupProfileAddAdminState extends TIMUIKitState<GroupProfileAddAdmin> {
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 10,
|
width: 10,
|
||||||
),
|
),
|
||||||
Text(_getShowName(e), style: const TextStyle(fontSize: 16))
|
Text(_getShowName(e),
|
||||||
|
style: const TextStyle(fontSize: 16))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import 'package:azlistview_all_platforms/azlistview_all_platforms.dart';
|
import 'package:azlistview_all_platforms/azlistview_all_platforms.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
import 'package:flutter_slidable_plus_plus/flutter_slidable_plus_plus.dart';
|
||||||
import 'package:lpinyin/lpinyin.dart';
|
import 'package:lpinyin/lpinyin.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||||
|
|
@ -24,9 +24,12 @@ class GroupProfileMemberList extends StatefulWidget {
|
||||||
|
|
||||||
// when the @ need filter some group types
|
// when the @ need filter some group types
|
||||||
final String? groupType;
|
final String? groupType;
|
||||||
final Function(List<V2TimGroupMemberFullInfo> selectedMember)? onSelectedMemberChange;
|
final Function(List<V2TimGroupMemberFullInfo> selectedMember)?
|
||||||
|
onSelectedMemberChange;
|
||||||
// notice: onTapMemberItem and onSelectedMemberChange use together will triger together
|
// notice: onTapMemberItem and onSelectedMemberChange use together will triger together
|
||||||
final Function(V2TimGroupMemberFullInfo memberInfo, TapDownDetails? tapDetails)? onTapMemberItem;
|
final Function(
|
||||||
|
V2TimGroupMemberFullInfo memberInfo, TapDownDetails? tapDetails)?
|
||||||
|
onTapMemberItem;
|
||||||
// When sliding to the bottom bar callBack
|
// When sliding to the bottom bar callBack
|
||||||
final Function()? touchBottomCallBack;
|
final Function()? touchBottomCallBack;
|
||||||
|
|
||||||
|
|
@ -53,7 +56,8 @@ class GroupProfileMemberList extends StatefulWidget {
|
||||||
State<StatefulWidget> createState() => _GroupProfileMemberListState();
|
State<StatefulWidget> createState() => _GroupProfileMemberListState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GroupProfileMemberListState extends TIMUIKitState<GroupProfileMemberList> {
|
class _GroupProfileMemberListState
|
||||||
|
extends TIMUIKitState<GroupProfileMemberList> {
|
||||||
List<V2TimGroupMemberFullInfo> selectedMemberList = [];
|
List<V2TimGroupMemberFullInfo> selectedMemberList = [];
|
||||||
|
|
||||||
_getShowName(V2TimGroupMemberFullInfo? item) {
|
_getShowName(V2TimGroupMemberFullInfo? item) {
|
||||||
|
|
@ -70,12 +74,14 @@ class _GroupProfileMemberListState extends TIMUIKitState<GroupProfileMemberList>
|
||||||
: userID;
|
: userID;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ISuspensionBeanImpl> _getShowList(List<V2TimGroupMemberFullInfo?> memberList) {
|
List<ISuspensionBeanImpl> _getShowList(
|
||||||
|
List<V2TimGroupMemberFullInfo?> memberList) {
|
||||||
final List<ISuspensionBeanImpl> showList = List.empty(growable: true);
|
final List<ISuspensionBeanImpl> showList = List.empty(growable: true);
|
||||||
for (var i = 0; i < memberList.length; i++) {
|
for (var i = 0; i < memberList.length; i++) {
|
||||||
final item = memberList[i];
|
final item = memberList[i];
|
||||||
final showName = _getShowName(item);
|
final showName = _getShowName(item);
|
||||||
if (item?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER || item?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN) {
|
if (item?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER ||
|
||||||
|
item?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN) {
|
||||||
showList.add(ISuspensionBeanImpl(memberInfo: item, tagIndex: "@"));
|
showList.add(ISuspensionBeanImpl(memberInfo: item, tagIndex: "@"));
|
||||||
} else {
|
} else {
|
||||||
String pinyin = PinyinHelper.getPinyinE(showName);
|
String pinyin = PinyinHelper.getPinyinE(showName);
|
||||||
|
|
@ -94,17 +100,26 @@ class _GroupProfileMemberListState extends TIMUIKitState<GroupProfileMemberList>
|
||||||
if (widget.canAtAll) {
|
if (widget.canAtAll) {
|
||||||
final canAtGroupType = ["Work", "Public", "Meeting"];
|
final canAtGroupType = ["Work", "Public", "Meeting"];
|
||||||
if (canAtGroupType.contains(widget.groupType)) {
|
if (canAtGroupType.contains(widget.groupType)) {
|
||||||
showList.insert(0, ISuspensionBeanImpl(memberInfo: V2TimGroupMemberFullInfo(userID: GroupProfileMemberList.AT_ALL_USER_ID, nickName: TIM_t("所有人")), tagIndex: ""));
|
showList.insert(
|
||||||
|
0,
|
||||||
|
ISuspensionBeanImpl(
|
||||||
|
memberInfo: V2TimGroupMemberFullInfo(
|
||||||
|
userID: GroupProfileMemberList.AT_ALL_USER_ID,
|
||||||
|
nickName: TIM_t("所有人")),
|
||||||
|
tagIndex: ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return showList;
|
return showList;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildListItem(BuildContext context, V2TimGroupMemberFullInfo memberInfo) {
|
Widget _buildListItem(
|
||||||
|
BuildContext context, V2TimGroupMemberFullInfo memberInfo) {
|
||||||
final theme = Provider.of<TUIThemeViewModel>(context).theme;
|
final theme = Provider.of<TUIThemeViewModel>(context).theme;
|
||||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor() == DeviceType.Desktop;
|
final isDesktopScreen =
|
||||||
final isGroupMember = memberInfo.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER;
|
TUIKitScreenUtils.getFormFactor() == DeviceType.Desktop;
|
||||||
|
final isGroupMember =
|
||||||
|
memberInfo.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER;
|
||||||
return Container(
|
return Container(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
child: Slidable(
|
child: Slidable(
|
||||||
|
|
@ -117,7 +132,8 @@ class _GroupProfileMemberListState extends TIMUIKitState<GroupProfileMemberList>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: theme.cautionColor ?? CommonColor.cautionColor,
|
backgroundColor:
|
||||||
|
theme.cautionColor ?? CommonColor.cautionColor,
|
||||||
autoClose: true,
|
autoClose: true,
|
||||||
label: TIM_t("删除"),
|
label: TIM_t("删除"),
|
||||||
)
|
)
|
||||||
|
|
@ -134,21 +150,28 @@ class _GroupProfileMemberListState extends TIMUIKitState<GroupProfileMemberList>
|
||||||
child: CheckBoxButton(
|
child: CheckBoxButton(
|
||||||
onChanged: (isChecked) {
|
onChanged: (isChecked) {
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
if (widget.maxSelectNum != null && selectedMemberList.length >= widget.maxSelectNum!) {
|
if (widget.maxSelectNum != null &&
|
||||||
|
selectedMemberList.length >=
|
||||||
|
widget.maxSelectNum!) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
selectedMemberList.add(memberInfo);
|
selectedMemberList.add(memberInfo);
|
||||||
} else {
|
} else {
|
||||||
selectedMemberList.removeWhere((element) => element.userID == memberInfo.userID);
|
selectedMemberList.removeWhere((element) =>
|
||||||
|
element.userID == memberInfo.userID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget.onSelectedMemberChange != null) {
|
if (widget.onSelectedMemberChange != null) {
|
||||||
widget.onSelectedMemberChange!(selectedMemberList);
|
widget.onSelectedMemberChange!(
|
||||||
|
selectedMemberList);
|
||||||
}
|
}
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
isChecked: selectedMemberList.where((element) => element.userID == memberInfo.userID).toList().isNotEmpty
|
isChecked: selectedMemberList
|
||||||
),
|
.where((element) =>
|
||||||
|
element.userID == memberInfo.userID)
|
||||||
|
.toList()
|
||||||
|
.isNotEmpty),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
width: isDesktopScreen ? 30 : 36,
|
width: isDesktopScreen ? 30 : 36,
|
||||||
|
|
@ -160,8 +183,10 @@ class _GroupProfileMemberListState extends TIMUIKitState<GroupProfileMemberList>
|
||||||
type: 1,
|
type: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(_getShowName(memberInfo), style: TextStyle(fontSize: isDesktopScreen ? 14 : 16)),
|
Text(_getShowName(memberInfo),
|
||||||
memberInfo.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER
|
style: TextStyle(fontSize: isDesktopScreen ? 14 : 16)),
|
||||||
|
memberInfo.role ==
|
||||||
|
GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER
|
||||||
? Container(
|
? Container(
|
||||||
margin: const EdgeInsets.only(left: 5),
|
margin: const EdgeInsets.only(left: 5),
|
||||||
child: Text(TIM_t("群主"),
|
child: Text(TIM_t("群主"),
|
||||||
|
|
@ -171,11 +196,17 @@ class _GroupProfileMemberListState extends TIMUIKitState<GroupProfileMemberList>
|
||||||
)),
|
)),
|
||||||
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
|
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: theme.ownerColor ?? CommonColor.ownerColor, width: 1),
|
border: Border.all(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(4.0)),
|
color: theme.ownerColor ??
|
||||||
|
CommonColor.ownerColor,
|
||||||
|
width: 1),
|
||||||
|
borderRadius:
|
||||||
|
const BorderRadius.all(Radius.circular(4.0)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: memberInfo.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN
|
: memberInfo.role ==
|
||||||
|
GroupMemberRoleType
|
||||||
|
.V2TIM_GROUP_MEMBER_ROLE_ADMIN
|
||||||
? Container(
|
? Container(
|
||||||
margin: const EdgeInsets.only(left: 5),
|
margin: const EdgeInsets.only(left: 5),
|
||||||
child: Text(TIM_t("管理员"),
|
child: Text(TIM_t("管理员"),
|
||||||
|
|
@ -185,8 +216,12 @@ class _GroupProfileMemberListState extends TIMUIKitState<GroupProfileMemberList>
|
||||||
)),
|
)),
|
||||||
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
|
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: theme.adminColor ?? CommonColor.adminColor, width: 1),
|
border: Border.all(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(4.0)),
|
color: theme.adminColor ??
|
||||||
|
CommonColor.adminColor,
|
||||||
|
width: 1),
|
||||||
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(4.0)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Container()
|
: Container()
|
||||||
|
|
@ -201,7 +236,8 @@ class _GroupProfileMemberListState extends TIMUIKitState<GroupProfileMemberList>
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
selectedMemberList.remove(memberInfo);
|
selectedMemberList.remove(memberInfo);
|
||||||
} else {
|
} else {
|
||||||
if (widget.maxSelectNum != null && selectedMemberList.length >= widget.maxSelectNum!) {
|
if (widget.maxSelectNum != null &&
|
||||||
|
selectedMemberList.length >= widget.maxSelectNum!) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
selectedMemberList.add(memberInfo);
|
selectedMemberList.add(memberInfo);
|
||||||
|
|
@ -213,11 +249,17 @@ class _GroupProfileMemberListState extends TIMUIKitState<GroupProfileMemberList>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Divider(thickness: 1, indent: 74, endIndent: 0, color: theme.weakBackgroundColor, height: 0)
|
Divider(
|
||||||
|
thickness: 1,
|
||||||
|
indent: 74,
|
||||||
|
endIndent: 0,
|
||||||
|
color: theme.weakBackgroundColor,
|
||||||
|
height: 0)
|
||||||
])));
|
])));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Widget getSusItem(BuildContext context, TUITheme theme, String tag, {double susHeight = 40}) {
|
static Widget getSusItem(BuildContext context, TUITheme theme, String tag,
|
||||||
|
{double susHeight = 40}) {
|
||||||
if (tag == '@') {
|
if (tag == '@') {
|
||||||
tag = TIM_t("群主、管理员");
|
tag = TIM_t("群主、管理员");
|
||||||
}
|
}
|
||||||
|
|
@ -242,9 +284,11 @@ class _GroupProfileMemberListState extends TIMUIKitState<GroupProfileMemberList>
|
||||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
final TUITheme theme = value.theme;
|
final TUITheme theme = value.theme;
|
||||||
|
|
||||||
final isDesktopScreen = TUIKitScreenUtils.getFormFactor() == DeviceType.Desktop;
|
final isDesktopScreen =
|
||||||
|
TUIKitScreenUtils.getFormFactor() == DeviceType.Desktop;
|
||||||
|
|
||||||
final throteFunction = OptimizeUtils.throttle((ScrollNotification notification) {
|
final throteFunction =
|
||||||
|
OptimizeUtils.throttle((ScrollNotification notification) {
|
||||||
final pixels = notification.metrics.pixels;
|
final pixels = notification.metrics.pixels;
|
||||||
// 总像素高度
|
// 总像素高度
|
||||||
final maxScrollExtent = notification.metrics.maxScrollExtent;
|
final maxScrollExtent = notification.metrics.maxScrollExtent;
|
||||||
|
|
@ -272,15 +316,19 @@ class _GroupProfileMemberListState extends TIMUIKitState<GroupProfileMemberList>
|
||||||
child: Text(TIM_t("暂无群成员")),
|
child: Text(TIM_t("暂无群成员")),
|
||||||
)
|
)
|
||||||
: Container(
|
: Container(
|
||||||
padding: isDesktopScreen ? const EdgeInsets.symmetric(horizontal: 16) : null,
|
padding: isDesktopScreen
|
||||||
|
? const EdgeInsets.symmetric(horizontal: 16)
|
||||||
|
: null,
|
||||||
child: AZListViewContainer(
|
child: AZListViewContainer(
|
||||||
memberList: showList,
|
memberList: showList,
|
||||||
susItemBuilder: (context, index) {
|
susItemBuilder: (context, index) {
|
||||||
final model = showList[index];
|
final model = showList[index];
|
||||||
return getSusItem(context, theme, model.getSuspensionTag());
|
return getSusItem(
|
||||||
|
context, theme, model.getSuspensionTag());
|
||||||
},
|
},
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final memberInfo = showList[index].memberInfo as V2TimGroupMemberFullInfo;
|
final memberInfo = showList[index].memberInfo
|
||||||
|
as V2TimGroupMemberFullInfo;
|
||||||
|
|
||||||
return _buildListItem(context, memberInfo);
|
return _buildListItem(context, memberInfo);
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:extended_image/extended_image.dart';
|
import 'package:extended_image/extended_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:image_gallery_saver/image_gallery_saver.dart';
|
import 'package:image_gallery_saver_plus/image_gallery_saver_plus.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
|
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
|
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
|
||||||
|
|
@ -21,7 +21,12 @@ import 'package:universal_html/html.dart' as html;
|
||||||
import 'package:video_player/video_player.dart';
|
import 'package:video_player/video_player.dart';
|
||||||
|
|
||||||
class VideoScreen extends StatefulWidget {
|
class VideoScreen extends StatefulWidget {
|
||||||
const VideoScreen({required this.message, required this.heroTag, required this.videoElement, Key? key}) : super(key: key);
|
const VideoScreen(
|
||||||
|
{required this.message,
|
||||||
|
required this.heroTag,
|
||||||
|
required this.videoElement,
|
||||||
|
Key? key})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
final V2TimMessage message;
|
final V2TimMessage message;
|
||||||
final dynamic heroTag;
|
final dynamic heroTag;
|
||||||
|
|
@ -34,7 +39,8 @@ class VideoScreen extends StatefulWidget {
|
||||||
class _VideoScreenState extends TIMUIKitState<VideoScreen> {
|
class _VideoScreenState extends TIMUIKitState<VideoScreen> {
|
||||||
late VideoPlayerController videoPlayerController;
|
late VideoPlayerController videoPlayerController;
|
||||||
late ChewieController chewieController;
|
late ChewieController chewieController;
|
||||||
GlobalKey<ExtendedImageSlidePageState> slidePagekey = GlobalKey<ExtendedImageSlidePageState>();
|
GlobalKey<ExtendedImageSlidePageState> slidePagekey =
|
||||||
|
GlobalKey<ExtendedImageSlidePageState>();
|
||||||
final TUIChatGlobalModel model = serviceLocator<TUIChatGlobalModel>();
|
final TUIChatGlobalModel model = serviceLocator<TUIChatGlobalModel>();
|
||||||
bool isInit = false;
|
bool isInit = false;
|
||||||
|
|
||||||
|
|
@ -64,7 +70,8 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
|
||||||
xhr.open('get', videoUrl);
|
xhr.open('get', videoUrl);
|
||||||
xhr.responseType = 'arraybuffer';
|
xhr.responseType = 'arraybuffer';
|
||||||
xhr.onLoad.listen((event) {
|
xhr.onLoad.listen((event) {
|
||||||
final a = html.AnchorElement(href: html.Url.createObjectUrl(html.Blob([xhr.response])));
|
final a = html.AnchorElement(
|
||||||
|
href: html.Url.createObjectUrl(html.Blob([xhr.response])));
|
||||||
a.download = '${md5.convert(utf8.encode(videoUrl)).toString()}$suffix';
|
a.download = '${md5.convert(utf8.encode(videoUrl)).toString()}$suffix';
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
|
|
@ -110,7 +117,8 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
|
||||||
}
|
}
|
||||||
if (model.getMessageProgress(widget.message.msgID) == 100) {
|
if (model.getMessageProgress(widget.message.msgID) == 100) {
|
||||||
String savePath;
|
String savePath;
|
||||||
if (widget.message.videoElem!.localVideoUrl != null && widget.message.videoElem!.localVideoUrl != '') {
|
if (widget.message.videoElem!.localVideoUrl != null &&
|
||||||
|
widget.message.videoElem!.localVideoUrl != '') {
|
||||||
savePath = widget.message.videoElem!.localVideoUrl!;
|
savePath = widget.message.videoElem!.localVideoUrl!;
|
||||||
} else {
|
} else {
|
||||||
savePath = model.getFileMessageLocation(widget.message.msgID);
|
savePath = model.getFileMessageLocation(widget.message.msgID);
|
||||||
|
|
@ -120,35 +128,62 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
|
||||||
var result = await ImageGallerySaver.saveFile(savePath);
|
var result = await ImageGallerySaver.saveFile(savePath);
|
||||||
if (PlatformUtils().isIOS) {
|
if (PlatformUtils().isIOS) {
|
||||||
if (result['isSuccess']) {
|
if (result['isSuccess']) {
|
||||||
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存成功"), infoCode: 6660402));
|
onTIMCallback(TIMCallback(
|
||||||
|
type: TIMCallbackType.INFO,
|
||||||
|
infoRecommendText: TIM_t("视频保存成功"),
|
||||||
|
infoCode: 6660402));
|
||||||
} else {
|
} else {
|
||||||
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存失败"), infoCode: 6660403));
|
onTIMCallback(TIMCallback(
|
||||||
|
type: TIMCallbackType.INFO,
|
||||||
|
infoRecommendText: TIM_t("视频保存失败"),
|
||||||
|
infoCode: 6660403));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存成功"), infoCode: 6660402));
|
onTIMCallback(TIMCallback(
|
||||||
|
type: TIMCallbackType.INFO,
|
||||||
|
infoRecommendText: TIM_t("视频保存成功"),
|
||||||
|
infoCode: 6660402));
|
||||||
} else {
|
} else {
|
||||||
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存失败"), infoCode: 6660403));
|
onTIMCallback(TIMCallback(
|
||||||
|
type: TIMCallbackType.INFO,
|
||||||
|
infoRecommendText: TIM_t("视频保存失败"),
|
||||||
|
infoCode: 6660403));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("the message is downloading"), infoCode: -1));
|
onTIMCallback(TIMCallback(
|
||||||
|
type: TIMCallbackType.INFO,
|
||||||
|
infoRecommendText: TIM_t("the message is downloading"),
|
||||||
|
infoCode: -1));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var result = await ImageGallerySaver.saveFile(savePath);
|
var result = await ImageGallerySaver.saveFile(savePath);
|
||||||
if (PlatformUtils().isIOS) {
|
if (PlatformUtils().isIOS) {
|
||||||
if (result['isSuccess']) {
|
if (result['isSuccess']) {
|
||||||
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存成功"), infoCode: 6660402));
|
onTIMCallback(TIMCallback(
|
||||||
|
type: TIMCallbackType.INFO,
|
||||||
|
infoRecommendText: TIM_t("视频保存成功"),
|
||||||
|
infoCode: 6660402));
|
||||||
} else {
|
} else {
|
||||||
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存失败"), infoCode: 6660403));
|
onTIMCallback(TIMCallback(
|
||||||
|
type: TIMCallbackType.INFO,
|
||||||
|
infoRecommendText: TIM_t("视频保存失败"),
|
||||||
|
infoCode: 6660403));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存成功"), infoCode: 6660402));
|
onTIMCallback(TIMCallback(
|
||||||
|
type: TIMCallbackType.INFO,
|
||||||
|
infoRecommendText: TIM_t("视频保存成功"),
|
||||||
|
infoCode: 6660402));
|
||||||
} else {
|
} else {
|
||||||
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存失败"), infoCode: 6660403));
|
onTIMCallback(TIMCallback(
|
||||||
|
type: TIMCallbackType.INFO,
|
||||||
|
infoRecommendText: TIM_t("视频保存失败"),
|
||||||
|
infoCode: 6660403));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -162,7 +197,9 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
|
||||||
isAsset: true,
|
isAsset: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (widget.videoElement.videoPath != '' && widget.videoElement.videoPath != null && File(widget.videoElement.videoPath!).existsSync()) {
|
if (widget.videoElement.videoPath != '' &&
|
||||||
|
widget.videoElement.videoPath != null &&
|
||||||
|
File(widget.videoElement.videoPath!).existsSync()) {
|
||||||
File f = File(widget.videoElement.videoPath!);
|
File f = File(widget.videoElement.videoPath!);
|
||||||
if (f.existsSync()) {
|
if (f.existsSync()) {
|
||||||
return await _saveNetworkVideo(
|
return await _saveNetworkVideo(
|
||||||
|
|
@ -172,7 +209,8 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (widget.videoElement.localVideoUrl != '' && widget.videoElement.localVideoUrl != null) {
|
if (widget.videoElement.localVideoUrl != '' &&
|
||||||
|
widget.videoElement.localVideoUrl != null) {
|
||||||
File f = File(widget.videoElement.localVideoUrl!);
|
File f = File(widget.videoElement.localVideoUrl!);
|
||||||
if (f.existsSync()) {
|
if (f.existsSync()) {
|
||||||
return await _saveNetworkVideo(
|
return await _saveNetworkVideo(
|
||||||
|
|
@ -211,7 +249,8 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
|
||||||
|
|
||||||
setVideoPlayerController() async {
|
setVideoPlayerController() async {
|
||||||
if (!PlatformUtils().isWeb) {
|
if (!PlatformUtils().isWeb) {
|
||||||
if (TencentUtils.checkString(widget.message.msgID) != null && widget.videoElement.localVideoUrl == null) {
|
if (TencentUtils.checkString(widget.message.msgID) != null &&
|
||||||
|
widget.videoElement.localVideoUrl == null) {
|
||||||
String savePath = model.getFileMessageLocation(widget.message.msgID);
|
String savePath = model.getFileMessageLocation(widget.message.msgID);
|
||||||
File f = File(savePath);
|
File f = File(savePath);
|
||||||
if (f.existsSync()) {
|
if (f.existsSync()) {
|
||||||
|
|
@ -221,20 +260,26 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoPlayerController player = PlatformUtils().isWeb
|
VideoPlayerController player = PlatformUtils().isWeb
|
||||||
? ((TencentUtils.checkString(widget.videoElement.videoPath) != null) || widget.message.status == MessageStatus.V2TIM_MSG_STATUS_SENDING
|
? ((TencentUtils.checkString(widget.videoElement.videoPath) != null) ||
|
||||||
|
widget.message.status == MessageStatus.V2TIM_MSG_STATUS_SENDING
|
||||||
? VideoPlayerController.networkUrl(
|
? VideoPlayerController.networkUrl(
|
||||||
Uri.parse(widget.videoElement.videoPath!),
|
Uri.parse(widget.videoElement.videoPath!),
|
||||||
)
|
)
|
||||||
: (TencentUtils.checkString(widget.videoElement.localVideoUrl) == null)
|
: (TencentUtils.checkString(widget.videoElement.localVideoUrl) ==
|
||||||
|
null)
|
||||||
? VideoPlayerController.networkUrl(
|
? VideoPlayerController.networkUrl(
|
||||||
Uri.parse(widget.videoElement.videoUrl!),
|
Uri.parse(widget.videoElement.videoUrl!),
|
||||||
)
|
)
|
||||||
: VideoPlayerController.networkUrl(
|
: VideoPlayerController.networkUrl(
|
||||||
Uri.parse(widget.videoElement.localVideoUrl!),
|
Uri.parse(widget.videoElement.localVideoUrl!),
|
||||||
))
|
))
|
||||||
: ((TencentUtils.checkString(widget.videoElement.videoPath) != null || widget.message.status == MessageStatus.V2TIM_MSG_STATUS_SENDING) && File(widget.videoElement.videoPath!).existsSync())
|
: ((TencentUtils.checkString(widget.videoElement.videoPath) != null ||
|
||||||
|
widget.message.status ==
|
||||||
|
MessageStatus.V2TIM_MSG_STATUS_SENDING) &&
|
||||||
|
File(widget.videoElement.videoPath!).existsSync())
|
||||||
? VideoPlayerController.file(File(widget.videoElement.videoPath!))
|
? VideoPlayerController.file(File(widget.videoElement.videoPath!))
|
||||||
: (TencentUtils.checkString(widget.videoElement.localVideoUrl) == null)
|
: (TencentUtils.checkString(widget.videoElement.localVideoUrl) ==
|
||||||
|
null)
|
||||||
? VideoPlayerController.networkUrl(
|
? VideoPlayerController.networkUrl(
|
||||||
Uri.parse(widget.videoElement.videoUrl!),
|
Uri.parse(widget.videoElement.videoUrl!),
|
||||||
)
|
)
|
||||||
|
|
@ -264,7 +309,8 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
didUpdateWidget(oldWidget) {
|
didUpdateWidget(oldWidget) {
|
||||||
if (oldWidget.videoElement.videoUrl != widget.videoElement.videoUrl || oldWidget.videoElement.videoPath != widget.videoElement.videoPath) {
|
if (oldWidget.videoElement.videoUrl != widget.videoElement.videoUrl ||
|
||||||
|
oldWidget.videoElement.videoPath != widget.videoElement.videoPath) {
|
||||||
setVideoPlayerController();
|
setVideoPlayerController();
|
||||||
}
|
}
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
|
|
@ -299,8 +345,10 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
|
||||||
return Colors.black;
|
return Colors.black;
|
||||||
}
|
}
|
||||||
double opacity = 0.0;
|
double opacity = 0.0;
|
||||||
opacity = offset.distance / (Offset(size.width, size.height).distance / 2.0);
|
opacity = offset.distance /
|
||||||
return Colors.black.withOpacity(min(1.0, max(1.0 - opacity, 0.0)));
|
(Offset(size.width, size.height).distance / 2.0);
|
||||||
|
return Colors.black
|
||||||
|
.withOpacity(min(1.0, max(1.0 - opacity, 0.0)));
|
||||||
},
|
},
|
||||||
slideType: SlideType.onlyImage,
|
slideType: SlideType.onlyImage,
|
||||||
slideEndHandler: (
|
slideEndHandler: (
|
||||||
|
|
@ -322,13 +370,22 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
|
||||||
? Chewie(
|
? Chewie(
|
||||||
controller: chewieController,
|
controller: chewieController,
|
||||||
)
|
)
|
||||||
: const Center(child: CircularProgressIndicator(color: Colors.white))),
|
: const Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: Colors.white))),
|
||||||
heroBuilderForSlidingPage: (Widget result) {
|
heroBuilderForSlidingPage: (Widget result) {
|
||||||
return Hero(
|
return Hero(
|
||||||
tag: widget.heroTag,
|
tag: widget.heroTag,
|
||||||
child: result,
|
child: result,
|
||||||
flightShuttleBuilder: (BuildContext flightContext, Animation<double> animation, HeroFlightDirection flightDirection, BuildContext fromHeroContext, BuildContext toHeroContext) {
|
flightShuttleBuilder: (BuildContext flightContext,
|
||||||
final Hero hero = (flightDirection == HeroFlightDirection.pop ? fromHeroContext.widget : toHeroContext.widget) as Hero;
|
Animation<double> animation,
|
||||||
|
HeroFlightDirection flightDirection,
|
||||||
|
BuildContext fromHeroContext,
|
||||||
|
BuildContext toHeroContext) {
|
||||||
|
final Hero hero =
|
||||||
|
(flightDirection == HeroFlightDirection.pop
|
||||||
|
? fromHeroContext.widget
|
||||||
|
: toHeroContext.widget) as Hero;
|
||||||
|
|
||||||
return hero.child;
|
return hero.child;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
11
pubspec.yaml
11
pubspec.yaml
|
|
@ -1,6 +1,6 @@
|
||||||
name: tencent_cloud_chat_uikit
|
name: tencent_cloud_chat_uikit
|
||||||
description: A powerful chat UI component library and business logic for Tencent Cloud Chat, creating seamless in-app chat modules for delightful user experiences.
|
description: A powerful chat UI component library and business logic for Tencent Cloud Chat, creating seamless in-app chat modules for delightful user experiences.
|
||||||
version: 3.1.0
|
version: 3.1.0+2
|
||||||
homepage: https://trtc.io/products/chat?utm_source=gfs&utm_medium=link&utm_campaign=%E6%B8%A0%E9%81%93&_channel_track_key=k6WgfCKn
|
homepage: https://trtc.io/products/chat?utm_source=gfs&utm_medium=link&utm_campaign=%E6%B8%A0%E9%81%93&_channel_track_key=k6WgfCKn
|
||||||
repository: https://github.com/TencentCloud/chat-uikit-flutter
|
repository: https://github.com/TencentCloud/chat-uikit-flutter
|
||||||
documentation: https://comm.qq.com/im/doc/flutter/en/TUIKit/readme.html
|
documentation: https://comm.qq.com/im/doc/flutter/en/TUIKit/readme.html
|
||||||
|
|
@ -30,12 +30,12 @@ dependencies:
|
||||||
tencent_super_tooltip: ^0.0.1
|
tencent_super_tooltip: ^0.0.1
|
||||||
video_player: ^2.9.0
|
video_player: ^2.9.0
|
||||||
chewie: ^1.8.5
|
chewie: ^1.8.5
|
||||||
flutter_slidable: ^3.0.1
|
flutter_slidable_plus_plus: ^0.1.0
|
||||||
flutter_plugin_record_plus: ^0.0.17
|
flutter_plugin_record_plus: ^0.0.19
|
||||||
azlistview_all_platforms: ^2.1.2
|
azlistview_all_platforms: ^2.1.2
|
||||||
lpinyin: ^2.0.3
|
lpinyin: ^2.0.3
|
||||||
transparent_image: ^2.0.0
|
transparent_image: ^2.0.0
|
||||||
image_gallery_saver: ^2.0.1
|
image_gallery_saver_plus: ^3.0.5
|
||||||
path_provider: ^2.0.8
|
path_provider: ^2.0.8
|
||||||
cached_network_image: ^3.3.0
|
cached_network_image: ^3.3.0
|
||||||
shared_preferences: ^2.0.13
|
shared_preferences: ^2.0.13
|
||||||
|
|
@ -57,7 +57,7 @@ dependencies:
|
||||||
http: ^1.0.0
|
http: ^1.0.0
|
||||||
crypto: ^3.0.2
|
crypto: ^3.0.2
|
||||||
collection: ^1.15.0
|
collection: ^1.15.0
|
||||||
flutter_image_compress: ^1.1.3
|
flutter_image_compress: ^2.3.0
|
||||||
uuid: ^3.0.6
|
uuid: ^3.0.6
|
||||||
open_file: ^3.3.2
|
open_file: ^3.3.2
|
||||||
tencent_keyboard_visibility: ^1.0.1
|
tencent_keyboard_visibility: ^1.0.1
|
||||||
|
|
@ -75,7 +75,6 @@ dependencies:
|
||||||
just_audio: ^0.9.34
|
just_audio: ^0.9.34
|
||||||
markdown: ^7.1.0
|
markdown: ^7.1.0
|
||||||
logger: ^2.0.1
|
logger: ^2.0.1
|
||||||
image_clipboard: ^1.0.0+2
|
|
||||||
visibility_detector: ^0.4.0+2
|
visibility_detector: ^0.4.0+2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue