feat: Upgrade to 2.1.1 pre-release
This commit is contained in:
parent
be65bea65e
commit
2f001240cd
|
|
@ -1139,7 +1139,7 @@ packages:
|
||||||
path: ".."
|
path: ".."
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "2.1.0+1"
|
version: "2.1.0+2"
|
||||||
tencent_cloud_uikit_core:
|
tencent_cloud_uikit_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 8.9 KiB |
|
|
@ -1,5 +1,7 @@
|
||||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<circle cx="8" cy="8" r="7.5" stroke="#232832"/>
|
<g opacity="0.795169">
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 5C5.55228 5 6 5.44772 6 6C6 6.55228 5.55228 7 5 7C4.44772 7 4 6.55228 4 6C4 5.44772 4.44772 5 5 5Z" fill="#232832"/>
|
<circle cx="8" cy="8" r="7.5" stroke="#232832"/>
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 5C11.5523 5 12 5.44772 12 6C12 6.55228 11.5523 7 11 7C10.4477 7 10 6.55228 10 6C10 5.44772 10.4477 5 11 5Z" fill="#232832"/>
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 5C5.55228 5 6 5.44772 6 6C6 6.55228 5.55228 7 5 7C4.44772 7 4 6.55228 4 6C4 5.44772 4.44772 5 5 5Z" fill="#232832"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 5C11.5523 5 12 5.44772 12 6C12 6.55228 11.5523 7 11 7C10.4477 7 10 6.55228 10 6C10 5.44772 10.4477 5 11 5Z" fill="#232832"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 499 B After Width: | Height: | Size: 559 B |
|
|
@ -20,6 +20,7 @@ import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.
|
||||||
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
|
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/constants/history_message_constant.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/constants/history_message_constant.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/tim_uikit_cloud_custom_data.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
enum LoadDirection { previous, latest }
|
enum LoadDirection { previous, latest }
|
||||||
|
|
@ -53,7 +54,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
bool showC2cMessageEditStatus = true;
|
bool showC2cMessageEditStatus = true;
|
||||||
TIMUIKitChatConfig chatConfig = const TIMUIKitChatConfig();
|
TIMUIKitChatConfig chatConfig = const TIMUIKitChatConfig();
|
||||||
ValueChanged<String>? setInputField;
|
ValueChanged<String>? setInputField;
|
||||||
String Function(V2TimMessage message)? abstractMessageBuilder;
|
String? Function(V2TimMessage message)? abstractMessageBuilder;
|
||||||
Function(String userID, TapDownDetails tapDetails)? onTapAvatar;
|
Function(String userID, TapDownDetails tapDetails)? onTapAvatar;
|
||||||
V2TimGroupMemberFullInfo? _currentChatUserInfo;
|
V2TimGroupMemberFullInfo? _currentChatUserInfo;
|
||||||
V2TimGroupInfo? _groupInfo;
|
V2TimGroupInfo? _groupInfo;
|
||||||
|
|
@ -228,7 +229,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
globalModel.setChatConfig(chatConfig);
|
globalModel.setChatConfig(chatConfig);
|
||||||
globalModel.clearRecivedNewMessageCount();
|
globalModel.clearRecivedNewMessageCount();
|
||||||
_isInit = true;
|
_isInit = true;
|
||||||
Future.delayed(const Duration(milliseconds: 300), (){
|
Future.delayed(const Duration(milliseconds: 300), () {
|
||||||
markMessageAsRead();
|
markMessageAsRead();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -809,7 +810,25 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getAbstractMessage(V2TimMessage message) {
|
String _getMessageAbstract(V2TimMessage message){
|
||||||
|
final messageAbstract = RepliedMessageAbstract(
|
||||||
|
summary: TIM_t(_getMessageSummary(message)),
|
||||||
|
elemType: message.elemType,
|
||||||
|
msgID: message.msgID,
|
||||||
|
timestamp: message.timestamp,
|
||||||
|
seq: message.seq
|
||||||
|
);
|
||||||
|
return jsonEncode(messageAbstract.toJson());
|
||||||
|
}
|
||||||
|
|
||||||
|
String _getMessageSummary(V2TimMessage message) {
|
||||||
|
final String? customAbstractMessage = abstractMessageBuilder != null
|
||||||
|
? abstractMessageBuilder!(message)
|
||||||
|
: null;
|
||||||
|
if (customAbstractMessage != null) {
|
||||||
|
return customAbstractMessage;
|
||||||
|
}
|
||||||
|
|
||||||
final elemType = message.elemType;
|
final elemType = message.elemType;
|
||||||
switch (elemType) {
|
switch (elemType) {
|
||||||
case MessageElemType.V2TIM_ELEM_TYPE_FACE:
|
case MessageElemType.V2TIM_ELEM_TYPE_FACE:
|
||||||
|
|
@ -831,7 +850,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
case MessageElemType.V2TIM_ELEM_TYPE_SOUND:
|
case MessageElemType.V2TIM_ELEM_TYPE_SOUND:
|
||||||
return "[语音消息]";
|
return "[语音消息]";
|
||||||
case MessageElemType.V2TIM_ELEM_TYPE_TEXT:
|
case MessageElemType.V2TIM_ELEM_TYPE_TEXT:
|
||||||
return "[文本消息]";
|
return message.textElem?.text ?? "[文本消息]";
|
||||||
case MessageElemType.V2TIM_ELEM_TYPE_VIDEO:
|
case MessageElemType.V2TIM_ELEM_TYPE_VIDEO:
|
||||||
return "[视频消息]";
|
return "[视频消息]";
|
||||||
default:
|
default:
|
||||||
|
|
@ -869,7 +888,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
final cloudCustomData = {
|
final cloudCustomData = {
|
||||||
"messageReply": {
|
"messageReply": {
|
||||||
"messageID": _repliedMessage!.msgID,
|
"messageID": _repliedMessage!.msgID,
|
||||||
"messageAbstract": _getAbstractMessage(_repliedMessage!),
|
"messageAbstract": _getMessageAbstract(_repliedMessage!),
|
||||||
"messageSender": hasNickName
|
"messageSender": hasNickName
|
||||||
? _repliedMessage!.nickName
|
? _repliedMessage!.nickName
|
||||||
: _repliedMessage?.sender,
|
: _repliedMessage?.sender,
|
||||||
|
|
@ -893,9 +912,10 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
];
|
];
|
||||||
globalModel.setMessageList(conversationID, currentHistoryMsgList);
|
globalModel.setMessageList(conversationID, currentHistoryMsgList);
|
||||||
|
|
||||||
final sendMsgRes = await _messageService.sendReplyMessage(
|
_repliedMessage = null;
|
||||||
|
final sendMsgRes = await _messageService.sendMessage(
|
||||||
|
cloudCustomData: json.encode(cloudCustomData),
|
||||||
id: textMessageInfo.id as String,
|
id: textMessageInfo.id as String,
|
||||||
replyMessage: _repliedMessage!,
|
|
||||||
offlinePushInfo: tools.buildMessagePushInfo(
|
offlinePushInfo: tools.buildMessagePushInfo(
|
||||||
messageInfoWithSender, convID, convType),
|
messageInfoWithSender, convID, convType),
|
||||||
needReadReceipt: chatConfig.isShowGroupReadingStatus &&
|
needReadReceipt: chatConfig.isShowGroupReadingStatus &&
|
||||||
|
|
@ -908,7 +928,6 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
|
||||||
.contains(oldGroupType))),
|
.contains(oldGroupType))),
|
||||||
groupID: groupID,
|
groupID: groupID,
|
||||||
receiver: receiver);
|
receiver: receiver);
|
||||||
_repliedMessage = null;
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
globalModel.updateMessage(sendMsgRes, convID,
|
globalModel.updateMessage(sendMsgRes, convID,
|
||||||
messageInfoWithSender.id ?? "", convType, groupType, setInputField);
|
messageInfoWithSender.id ?? "", convType, groupType, setInputField);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
|
||||||
import 'package:tencent_im_base/tencent_im_base.dart';
|
import 'package:tencent_im_base/tencent_im_base.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';
|
||||||
|
|
@ -42,6 +43,7 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
late V2TimConversationListener _conversationListener;
|
late V2TimConversationListener _conversationListener;
|
||||||
List<V2TimConversation?> _conversationList = [];
|
List<V2TimConversation?> _conversationList = [];
|
||||||
static V2TimConversation? _selectedConversation;
|
static V2TimConversation? _selectedConversation;
|
||||||
|
Map<String, String> webDraftMap = {};
|
||||||
|
|
||||||
bool _haveMoreData = true;
|
bool _haveMoreData = true;
|
||||||
int _totalUnReadCount = 0;
|
int _totalUnReadCount = 0;
|
||||||
|
|
@ -65,9 +67,8 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
.toList();
|
.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
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
_conversationList.sort((a, b) => b!.orderkey!.compareTo(a!.orderkey!));
|
_conversationList.sort((a, b) => b!.orderkey!.compareTo(a!.orderkey!));
|
||||||
}
|
}
|
||||||
|
|
@ -259,10 +260,46 @@ class TUIConversationViewModel extends ChangeNotifier {
|
||||||
listener: _conversationListener);
|
listener: _conversationListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<V2TimCallback> setConversationDraft(
|
Future<V2TimCallback> setConversationDraft({
|
||||||
{required String conversationID, String? draftText}) async {
|
required String conversationID,
|
||||||
return _conversationService.setConversationDraft(
|
String? draftText,
|
||||||
conversationID: conversationID, draftText: draftText);
|
bool isTopic = false,
|
||||||
|
String? groupID,
|
||||||
|
bool isAllowWeb = true,
|
||||||
|
}) async {
|
||||||
|
assert(!isTopic || (groupID != null && groupID.isNotEmpty),
|
||||||
|
"When 'isTopic' is true, 'groupID' must not be null or empty.");
|
||||||
|
if (PlatformUtils().isWeb && isAllowWeb) {
|
||||||
|
webDraftMap[conversationID] = draftText ?? "";
|
||||||
|
return V2TimCallback(code: 0, desc: "");
|
||||||
|
} else {
|
||||||
|
if (isTopic) {
|
||||||
|
final topicInfoList = await TencentImSDKPlugin.v2TIMManager
|
||||||
|
.getGroupManager()
|
||||||
|
.getTopicInfoList(groupID: groupID!, topicIDList: [conversationID]);
|
||||||
|
final topicInfo = topicInfoList.data?.first.topicInfo;
|
||||||
|
topicInfo?.draftText = draftText;
|
||||||
|
final res = await TencentImSDKPlugin.v2TIMManager
|
||||||
|
.getGroupManager()
|
||||||
|
.setTopicInfo(groupID: groupID, topicInfo: topicInfo!);
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
return _conversationService.setConversationDraft(
|
||||||
|
conversationID: conversationID, draftText: draftText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearWebDraft({
|
||||||
|
required String conversationID,
|
||||||
|
}) {
|
||||||
|
webDraftMap[conversationID] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String? getWebDraft({
|
||||||
|
required String conversationID,
|
||||||
|
}) {
|
||||||
|
return TencentUtils.checkString(webDraftMap[conversationID]);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearData() {
|
clearData() {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
||||||
import 'package:tencent_im_base/tencent_im_base.dart';
|
import 'package:tencent_im_base/tencent_im_base.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/data_services/core/tim_uikit_config.dart';
|
import 'package:tencent_cloud_chat_uikit/data_services/core/tim_uikit_config.dart';
|
||||||
|
|
||||||
|
|
@ -92,4 +93,6 @@ abstract class CoreServices {
|
||||||
setDarkTheme();
|
setDarkTheme();
|
||||||
|
|
||||||
setLightTheme();
|
setLightTheme();
|
||||||
|
|
||||||
|
setDeviceType(DeviceType deviceType);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_setting_model.dart';
|
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_setting_model.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
||||||
import 'package:tencent_im_base/tencent_im_base.dart';
|
import 'package:tencent_im_base/tencent_im_base.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/business_logic/listener_model/tui_group_listener_model.dart';
|
import 'package:tencent_cloud_chat_uikit/business_logic/listener_model/tui_group_listener_model.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';
|
||||||
|
|
@ -74,22 +75,28 @@ class CoreServicesImpl implements CoreServices {
|
||||||
@override
|
@override
|
||||||
Future<bool?> init(
|
Future<bool?> init(
|
||||||
{
|
{
|
||||||
|
|
||||||
/// Callback from TUIKit invoke, includes IM SDK API error, notify information, Flutter error.
|
/// Callback from TUIKit invoke, includes IM SDK API error, notify information, Flutter error.
|
||||||
ValueChanged<TIMCallback>? onTUIKitCallbackListener,
|
ValueChanged<TIMCallback>? onTUIKitCallbackListener,
|
||||||
required int sdkAppID,
|
required int sdkAppID,
|
||||||
required LogLevelEnum loglevel,
|
required LogLevelEnum loglevel,
|
||||||
required V2TimSDKListener listener,
|
required V2TimSDKListener listener,
|
||||||
LanguageEnum? language,
|
LanguageEnum? language,
|
||||||
String? extraLanguage,
|
String? extraLanguage,
|
||||||
TIMUIKitConfig? config,
|
TIMUIKitConfig? config,
|
||||||
|
|
||||||
|
/// Specify the current device platform, mobile or desktop, based on your needs.
|
||||||
|
/// TUIKit will automatically determine the platform if no specification is provided. DeviceType? platform,
|
||||||
|
DeviceType? platform,
|
||||||
VoidCallback? onWebLoginSuccess}) async {
|
VoidCallback? onWebLoginSuccess}) async {
|
||||||
|
if (platform != null) {
|
||||||
|
TUIKitScreenUtils.deviceType = platform;
|
||||||
|
}
|
||||||
addIdentifier();
|
addIdentifier();
|
||||||
if(extraLanguage != null){
|
if (extraLanguage != null) {
|
||||||
Future.delayed(const Duration(milliseconds: 1), () {
|
Future.delayed(const Duration(milliseconds: 1), () {
|
||||||
I18nUtils(null, extraLanguage);
|
I18nUtils(null, extraLanguage);
|
||||||
});
|
});
|
||||||
}else if (language != null) {
|
} else if (language != null) {
|
||||||
Future.delayed(const Duration(milliseconds: 1), () {
|
Future.delayed(const Duration(milliseconds: 1), () {
|
||||||
I18nUtils(null, languageEnumToString[language]);
|
I18nUtils(null, languageEnumToString[language]);
|
||||||
});
|
});
|
||||||
|
|
@ -139,11 +146,11 @@ class CoreServicesImpl implements CoreServices {
|
||||||
required String userId,
|
required String userId,
|
||||||
}) async {
|
}) async {
|
||||||
_userID = userId;
|
_userID = userId;
|
||||||
if(extraLanguage != null){
|
if (extraLanguage != null) {
|
||||||
Future.delayed(const Duration(milliseconds: 1), () {
|
Future.delayed(const Duration(milliseconds: 1), () {
|
||||||
I18nUtils(null, extraLanguage);
|
I18nUtils(null, extraLanguage);
|
||||||
});
|
});
|
||||||
}else if (language != null) {
|
} else if (language != null) {
|
||||||
Future.delayed(const Duration(milliseconds: 1), () {
|
Future.delayed(const Duration(milliseconds: 1), () {
|
||||||
I18nUtils(null, languageEnumToString[language]);
|
I18nUtils(null, languageEnumToString[language]);
|
||||||
});
|
});
|
||||||
|
|
@ -246,9 +253,8 @@ class CoreServicesImpl implements CoreServices {
|
||||||
}
|
}
|
||||||
|
|
||||||
tuiFriendShipViewModel.userStatusList = currentUserStatusList;
|
tuiFriendShipViewModel.userStatusList = currentUserStatusList;
|
||||||
// ignore: empty_catches
|
// ignore: empty_catches
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -398,4 +404,9 @@ class CoreServicesImpl implements CoreServices {
|
||||||
.doBackground(unreadCount: totalCount ?? 0);
|
.doBackground(unreadCount: totalCount ?? 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
setDeviceType(DeviceType deviceType) {
|
||||||
|
TUIKitScreenUtils.deviceType = deviceType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,8 +138,8 @@ class TIMUIKitChatController {
|
||||||
assert((groupID == null) != (userID == null));
|
assert((groupID == null) != (userID == null));
|
||||||
assert(groupID != null || convType != ConvType.group);
|
assert(groupID != null || convType != ConvType.group);
|
||||||
assert(userID != null || convType != ConvType.c2c);
|
assert(userID != null || convType != ConvType.c2c);
|
||||||
if (isNavigateToMessageListBottom) {
|
if (isNavigateToMessageListBottom && scrollController != null) {
|
||||||
scrollController?.animateTo(
|
scrollController!.animateTo(
|
||||||
scrollController!.position.minScrollExtent,
|
scrollController!.position.minScrollExtent,
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
curve: Curves.ease,
|
curve: Curves.ease,
|
||||||
|
|
@ -159,7 +159,7 @@ class TIMUIKitChatController {
|
||||||
offlinePushInfo: offlinePushInfo);
|
offlinePushInfo: offlinePushInfo);
|
||||||
} else if (model != null) {
|
} else if (model != null) {
|
||||||
/// Sends a message to the current conversation specified on `TIMUIKitChat`. 发送到 `TIMUIKitChat` 中指定的当前对话。
|
/// Sends a message to the current conversation specified on `TIMUIKitChat`. 发送到 `TIMUIKitChat` 中指定的当前对话。
|
||||||
if (isNavigateToMessageListBottom) {
|
if (isNavigateToMessageListBottom && scrollController != null) {
|
||||||
scrollController?.animateTo(
|
scrollController?.animateTo(
|
||||||
scrollController!.position.minScrollExtent,
|
scrollController!.position.minScrollExtent,
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,9 @@ class TUIKitScreenUtils {
|
||||||
|
|
||||||
final diagonalInInches =
|
final diagonalInInches =
|
||||||
sqrt(pow(screenWidth, 2) + pow(screenHeight, 2)) / 96.0;
|
sqrt(pow(screenWidth, 2) + pow(screenHeight, 2)) / 96.0;
|
||||||
|
print("diagonalInInches $diagonalInInches");
|
||||||
|
|
||||||
deviceType = diagonalInInches < 8.0 ? DeviceType.Mobile : DeviceType.Desktop;
|
deviceType = diagonalInInches < 11.0 ? DeviceType.Mobile : DeviceType.Desktop;
|
||||||
return deviceType ?? DeviceType.Mobile;
|
return deviceType ?? DeviceType.Mobile;
|
||||||
}else{
|
}else{
|
||||||
if(context != null){
|
if(context != null){
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -351,7 +351,9 @@ class TIMUIKitMessageTooltipState
|
||||||
children: [
|
children: [
|
||||||
Image.asset(
|
Image.asset(
|
||||||
item.iconImageAsset,
|
item.iconImageAsset,
|
||||||
package: 'tencent_cloud_chat_uikit',
|
package: defaultTipsIds.contains(item.id)
|
||||||
|
? 'tencent_cloud_chat_uikit'
|
||||||
|
: null,
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_model_tools.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/utils/common_utils.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/utils/common_utils.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/DefaultSpecialTextSpanBuilder.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/DefaultSpecialTextSpanBuilder.dart';
|
||||||
|
|
@ -57,7 +58,7 @@ class TIMUIKitReplyElem extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
|
class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
|
||||||
MessageRepliedData? repliedMessage;
|
MessageRepliedData? repliedMessage = null;
|
||||||
V2TimMessage? rawMessage;
|
V2TimMessage? rawMessage;
|
||||||
bool isShowJumpState = false;
|
bool isShowJumpState = false;
|
||||||
bool isShining = false;
|
bool isShining = false;
|
||||||
|
|
@ -81,10 +82,32 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
|
||||||
}
|
}
|
||||||
|
|
||||||
_getMessageByMessageID() async {
|
_getMessageByMessageID() async {
|
||||||
final cloudCustomData = _getRepliedMessage();
|
final MessageRepliedData? cloudCustomData = _getRepliedMessage();
|
||||||
if (cloudCustomData != null) {
|
if (cloudCustomData != null) {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
repliedMessage = cloudCustomData;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
final messageID = cloudCustomData.messageID;
|
final messageID = cloudCustomData.messageID;
|
||||||
final message = await widget.chatModel.findMessage(messageID);
|
V2TimMessage? message = await widget.chatModel.findMessage(messageID);
|
||||||
|
if (message == null) {
|
||||||
|
try {
|
||||||
|
final RepliedMessageAbstract repliedMessageAbstract =
|
||||||
|
RepliedMessageAbstract.fromJson(
|
||||||
|
jsonDecode(cloudCustomData.messageAbstract));
|
||||||
|
if (repliedMessageAbstract.isNotEmpty) {
|
||||||
|
message = V2TimMessage(
|
||||||
|
elemType: 0,
|
||||||
|
seq: repliedMessageAbstract.seq,
|
||||||
|
timestamp: repliedMessageAbstract.timestamp,
|
||||||
|
msgID: repliedMessageAbstract.msgID);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|
@ -93,36 +116,53 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mounted) {
|
|
||||||
setState(() {
|
|
||||||
repliedMessage = cloudCustomData;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _defaultRawMessageText(String text, TUITheme? theme) {
|
Widget _defaultRawMessageText(String text, TUITheme? theme) {
|
||||||
return Text(text,
|
return Text(text,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: theme?.weakTextColor,
|
color: theme?.weakTextColor,
|
||||||
fontWeight: FontWeight.w400));
|
fontWeight: FontWeight.w400));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_renderMessageSummary(TUITheme? theme) {
|
||||||
|
try {
|
||||||
|
final RepliedMessageAbstract repliedMessageAbstract =
|
||||||
|
RepliedMessageAbstract.fromJson(
|
||||||
|
jsonDecode(repliedMessage?.messageAbstract ?? ""));
|
||||||
|
if (TencentUtils.checkString(repliedMessageAbstract.summary) != null) {
|
||||||
|
return _defaultRawMessageText(repliedMessageAbstract.summary!, theme);
|
||||||
|
}
|
||||||
|
return _defaultRawMessageText(
|
||||||
|
repliedMessage?.messageAbstract ?? TIM_t("[未知消息]"), theme);
|
||||||
|
} catch (e) {
|
||||||
|
return _defaultRawMessageText(
|
||||||
|
repliedMessage?.messageAbstract ?? TIM_t("[未知消息]"), theme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_rawMessageBuilder(V2TimMessage? message, TUITheme? theme) {
|
_rawMessageBuilder(V2TimMessage? message, TUITheme? theme) {
|
||||||
if (repliedMessage == null) {
|
if (repliedMessage == null) {
|
||||||
return const SizedBox(width: 0, height: 12);
|
return const SizedBox(width: 0, height: 12);
|
||||||
}
|
}
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
if (repliedMessage?.messageAbstract != null) {
|
if (repliedMessage?.messageAbstract != null) {
|
||||||
return _defaultRawMessageText(repliedMessage!.messageAbstract, theme);
|
_renderMessageSummary(theme);
|
||||||
}
|
}
|
||||||
return const SizedBox(width: 0, height: 12);
|
return const SizedBox(width: 0, height: 12);
|
||||||
}
|
}
|
||||||
final messageType = message.elemType;
|
final messageType = message.elemType;
|
||||||
final isSelf = message.isSelf ?? true;
|
final isSelf = message.isSelf ?? true;
|
||||||
if (widget.chatModel.abstractMessageBuilder != null) {
|
final customAbstractMessage =
|
||||||
|
widget.chatModel.abstractMessageBuilder != null
|
||||||
|
? widget.chatModel.abstractMessageBuilder!(message)
|
||||||
|
: null;
|
||||||
|
if (customAbstractMessage != null) {
|
||||||
return _defaultRawMessageText(
|
return _defaultRawMessageText(
|
||||||
widget.chatModel.abstractMessageBuilder!(message),
|
customAbstractMessage,
|
||||||
theme,
|
theme,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -173,7 +213,7 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
|
||||||
messageID: message.msgID ?? "",
|
messageID: message.msgID ?? "",
|
||||||
isSelf: isSelf);
|
isSelf: isSelf);
|
||||||
default:
|
default:
|
||||||
return _defaultRawMessageText(TIM_t("[未知消息]"), theme);
|
return _renderMessageSummary(theme);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,8 @@ class TIMUIKitInputTextField extends StatefulWidget {
|
||||||
|
|
||||||
final String? groupType;
|
final String? groupType;
|
||||||
|
|
||||||
|
final String? groupID;
|
||||||
|
|
||||||
const TIMUIKitInputTextField(
|
const TIMUIKitInputTextField(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
required this.conversationID,
|
required this.conversationID,
|
||||||
|
|
@ -113,7 +115,8 @@ class TIMUIKitInputTextField extends StatefulWidget {
|
||||||
required this.model,
|
required this.model,
|
||||||
required this.currentConversation,
|
required this.currentConversation,
|
||||||
this.groupType,
|
this.groupType,
|
||||||
this.atMemberPanelScroll})
|
this.atMemberPanelScroll,
|
||||||
|
this.groupID})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -166,21 +169,22 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
||||||
return text.replaceAll(RegExp(r'\ufeff'), "");
|
return text.replaceAll(RegExp(r'\ufeff'), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSetDraftText([String? id, ConvType? convType]) async {
|
Future handleSetDraftText([String? id, ConvType? convType]) async {
|
||||||
|
String text = textEditingController.text;
|
||||||
String convID = id ?? widget.conversationID;
|
String convID = id ?? widget.conversationID;
|
||||||
String conversationID = convID.contains("@TOPIC#")
|
final isTopic = convID.contains("@TOPIC#");
|
||||||
|
String conversationID = isTopic
|
||||||
? convID
|
? convID
|
||||||
: ((convType ?? widget.conversationType) == ConvType.c2c
|
: ((convType ?? widget.conversationType) == ConvType.c2c
|
||||||
? "c2c_$convID"
|
? "c2c_$convID"
|
||||||
: "group_$convID");
|
: "group_$convID");
|
||||||
String text = textEditingController.text;
|
String draftText = _filterU200b(text);
|
||||||
String? draftText = _filterU200b(text);
|
return await conversationModel.setConversationDraft(
|
||||||
|
groupID: widget.groupID,
|
||||||
if (draftText.isEmpty) {
|
isTopic: isTopic,
|
||||||
draftText = "";
|
isAllowWeb: widget.model.chatConfig.isUseDraftOnWeb,
|
||||||
}
|
conversationID: conversationID,
|
||||||
await conversationModel.setConversationDraft(
|
draftText: draftText);
|
||||||
conversationID: conversationID, draftText: draftText);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backSpaceText() {
|
backSpaceText() {
|
||||||
|
|
@ -189,11 +193,9 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
||||||
|
|
||||||
if (originalText == zeroWidthSpace) {
|
if (originalText == zeroWidthSpace) {
|
||||||
_handleSoftKeyBoardDelete();
|
_handleSoftKeyBoardDelete();
|
||||||
// _addDeleteTag();
|
|
||||||
} else {
|
} else {
|
||||||
text = originalText.characters.skipLast(1);
|
text = originalText.characters.skipLast(1);
|
||||||
textEditingController.text = text;
|
textEditingController.text = text;
|
||||||
// handleSetDraftText();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,6 +204,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
||||||
lastText = "";
|
lastText = "";
|
||||||
final text = textEditingController.text.trim();
|
final text = textEditingController.text.trim();
|
||||||
final convType = widget.conversationType;
|
final convType = widget.conversationType;
|
||||||
|
conversationModel.clearWebDraft(conversationID: widget.conversationID);
|
||||||
if (text.isNotEmpty && text != zeroWidthSpace) {
|
if (text.isNotEmpty && text != zeroWidthSpace) {
|
||||||
if (widget.model.repliedMessage != null) {
|
if (widget.model.repliedMessage != null) {
|
||||||
MessageUtils.handleMessageError(
|
MessageUtils.handleMessageError(
|
||||||
|
|
@ -259,6 +262,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmitted() async {
|
onSubmitted() async {
|
||||||
|
conversationModel.clearWebDraft(conversationID: widget.conversationID);
|
||||||
lastText = "";
|
lastText = "";
|
||||||
final text = textEditingController.text.trim();
|
final text = textEditingController.text.trim();
|
||||||
final convType = widget.conversationType;
|
final convType = widget.conversationType;
|
||||||
|
|
@ -417,6 +421,22 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
||||||
mentionedMembersMap = map;
|
mentionedMembersMap = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateMentionedMap() {
|
||||||
|
Map<String, V2TimGroupMemberFullInfo> map = {};
|
||||||
|
Iterable<Match> matches = atTextReg.allMatches(textEditingController.text);
|
||||||
|
List<String?> parseAtList = [];
|
||||||
|
for (final item in matches) {
|
||||||
|
final str = item.group(0);
|
||||||
|
parseAtList.add(str);
|
||||||
|
}
|
||||||
|
for (String? key in parseAtList) {
|
||||||
|
if (key != null && mentionedMembersMap[key] != null) {
|
||||||
|
map[key] = mentionedMembersMap[key]!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mentionedMembersMap = map;
|
||||||
|
}
|
||||||
|
|
||||||
_handleAtText(String text, TUIChatSeparateViewModel model) async {
|
_handleAtText(String text, TUIChatSeparateViewModel model) async {
|
||||||
final text = textEditingController.text;
|
final text = textEditingController.text;
|
||||||
String? groupID = widget.conversationType == ConvType.group
|
String? groupID = widget.conversationType == ConvType.group
|
||||||
|
|
@ -449,22 +469,11 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
||||||
textEditingController.selection =
|
textEditingController.selection =
|
||||||
TextSelection.collapsed(offset: atIndex);
|
TextSelection.collapsed(offset: atIndex);
|
||||||
lastText = newText;
|
lastText = newText;
|
||||||
Map<String, V2TimGroupMemberFullInfo> map = {};
|
updateMentionedMap();
|
||||||
Iterable<Match> matches = atTextReg.allMatches(text);
|
|
||||||
List<String?> parseAtList = [];
|
|
||||||
for (final item in matches) {
|
|
||||||
final str = item.group(0);
|
|
||||||
parseAtList.add(str);
|
|
||||||
}
|
|
||||||
for (String? key in parseAtList) {
|
|
||||||
if (key != null && mentionedMembersMap[key] != null) {
|
|
||||||
map[key] = mentionedMembersMap[key]!;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mentionedMembersMap = map;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
updateMentionedMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
final int selfRole = widget.model.selfMemberInfo?.role ?? 0;
|
final int selfRole = widget.model.selfMemberInfo?.role ?? 0;
|
||||||
|
|
@ -709,8 +718,8 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
|
||||||
void didUpdateWidget(TIMUIKitInputTextField oldWidget) {
|
void didUpdateWidget(TIMUIKitInputTextField oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (widget.conversationID != oldWidget.conversationID) {
|
if (widget.conversationID != oldWidget.conversationID) {
|
||||||
handleSetDraftText(oldWidget.conversationID, oldWidget.conversationType);
|
|
||||||
mentionedMembersMap.clear();
|
mentionedMembersMap.clear();
|
||||||
|
handleSetDraftText(oldWidget.conversationID, oldWidget.conversationType);
|
||||||
if (oldWidget.initText != widget.initText) {
|
if (oldWidget.initText != widget.initText) {
|
||||||
textEditingController.text = widget.initText ?? "";
|
textEditingController.text = widget.initText ?? "";
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -309,12 +309,23 @@ class _TIMUIKitTextFieldLayoutNarrowState
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
String getAbstractMessage(V2TimMessage message) {
|
||||||
|
final String? customAbstractMessage = widget
|
||||||
|
.model.abstractMessageBuilder != null ? widget.model
|
||||||
|
.abstractMessageBuilder!(widget.model.repliedMessage!) : null;
|
||||||
|
return customAbstractMessage ?? MessageUtils
|
||||||
|
.getAbstractMessageAsync(
|
||||||
|
widget.model.repliedMessage!, widget.model.groupMemberList ?? []);
|
||||||
|
}
|
||||||
|
|
||||||
_buildRepliedMessage(V2TimMessage? repliedMessage) {
|
_buildRepliedMessage(V2TimMessage? repliedMessage) {
|
||||||
final haveRepliedMessage = repliedMessage != null;
|
final haveRepliedMessage = repliedMessage != null;
|
||||||
if (haveRepliedMessage) {
|
if (haveRepliedMessage) {
|
||||||
final text =
|
final text =
|
||||||
"${MessageUtils.getDisplayName(widget.model.repliedMessage!)}:${widget.model.abstractMessageBuilder != null ? widget.model.abstractMessageBuilder!(widget.model.repliedMessage!) : MessageUtils.getAbstractMessageAsync(widget.model.repliedMessage!, widget.model.groupMemberList ?? [])}";
|
"${MessageUtils.getDisplayName(
|
||||||
|
widget.model.repliedMessage!)}:${getAbstractMessage(
|
||||||
|
repliedMessage
|
||||||
|
)}";
|
||||||
return Container(
|
return Container(
|
||||||
color: widget.backgroundColor ?? hexToColor("f5f5f6"),
|
color: widget.backgroundColor ?? hexToColor("f5f5f6"),
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
import 'dart:ui' as ui;
|
||||||
import 'package:fc_native_video_thumbnail/fc_native_video_thumbnail.dart';
|
import 'package:fc_native_video_thumbnail/fc_native_video_thumbnail.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
|
@ -32,6 +33,7 @@ import 'package:universal_html/html.dart' as html;
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
|
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
|
||||||
// ignore: unnecessary_import
|
// ignore: unnecessary_import
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
@ -262,36 +264,62 @@ class _TIMUIKitTextFieldLayoutWideState
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getAbstractMessage(V2TimMessage message) {
|
||||||
|
final String? customAbstractMessage =
|
||||||
|
widget.model.abstractMessageBuilder != null
|
||||||
|
? widget.model.abstractMessageBuilder!(widget.model.repliedMessage!)
|
||||||
|
: null;
|
||||||
|
return customAbstractMessage ??
|
||||||
|
MessageUtils.getAbstractMessageAsync(
|
||||||
|
widget.model.repliedMessage!, widget.model.groupMemberList ?? []);
|
||||||
|
}
|
||||||
|
|
||||||
_buildRepliedMessage(V2TimMessage? repliedMessage) {
|
_buildRepliedMessage(V2TimMessage? repliedMessage) {
|
||||||
final haveRepliedMessage = repliedMessage != null;
|
final haveRepliedMessage = repliedMessage != null;
|
||||||
if (haveRepliedMessage) {
|
if (haveRepliedMessage) {
|
||||||
final text =
|
|
||||||
"${MessageUtils.getDisplayName(widget.model.repliedMessage!)}:${widget.model.abstractMessageBuilder != null ? widget.model.abstractMessageBuilder!(widget.model.repliedMessage!) : MessageUtils.getAbstractMessageAsync(widget.model.repliedMessage!, widget.model.groupMemberList ?? [])}";
|
|
||||||
return Container(
|
return Container(
|
||||||
color: widget.backgroundColor ?? hexToColor("f5f5f6"),
|
color: widget.backgroundColor ?? hexToColor("f5f5f6"),
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
Text(
|
||||||
|
TIM_t("回复 "),
|
||||||
|
style: TextStyle(
|
||||||
|
color: hexToColor("8f959e"), fontSize: 14),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
MessageUtils.getDisplayName(
|
||||||
|
widget.model.repliedMessage!),
|
||||||
|
softWrap: true,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: hexToColor("8f959e"),
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
text,
|
": ${getAbstractMessage(repliedMessage)}",
|
||||||
softWrap: true,
|
maxLines: 1,
|
||||||
maxLines: 3,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(color: hexToColor("8f959e"), fontSize: 14),
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: hexToColor("8f959e"),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 16,
|
width: 8,
|
||||||
),
|
),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
widget.model.repliedMessage = null;
|
widget.model.repliedMessage = null;
|
||||||
},
|
},
|
||||||
child: Icon(Icons.clear, color: hexToColor("8f959e"), size: 18),
|
child: Icon(Icons.cancel, color: hexToColor("8f959e"), size: 18),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -314,8 +342,9 @@ class _TIMUIKitTextFieldLayoutWideState
|
||||||
entry = null;
|
entry = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
initOffset: offset ??
|
initOffset: offset != null
|
||||||
Offset(MediaQuery.of(context).size.height * 0.5 + 20,
|
? Offset(offset.dx, max(offset.dy, 16))
|
||||||
|
: Offset(MediaQuery.of(context).size.height * 0.5 + 20,
|
||||||
MediaQuery.of(context).size.height * 0.5 - 100),
|
MediaQuery.of(context).size.height * 0.5 - 100),
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
|
@ -793,7 +822,7 @@ class _TIMUIKitTextFieldLayoutWideState
|
||||||
onClick: (offset) {
|
onClick: (offset) {
|
||||||
_sendEmoji(offset, widget.theme);
|
_sendEmoji(offset, widget.theme);
|
||||||
},
|
},
|
||||||
svgPath: "images/svg/send_face.svg"),
|
imgPath: "images/svg/send_face.png"),
|
||||||
if (config.showScreenshotButton && PlatformUtils().isDesktop)
|
if (config.showScreenshotButton && PlatformUtils().isDesktop)
|
||||||
DesktopControlBarItem(
|
DesktopControlBarItem(
|
||||||
item: "screenShot",
|
item: "screenShot",
|
||||||
|
|
@ -950,6 +979,7 @@ class _TIMUIKitTextFieldLayoutWideState
|
||||||
color: widget.backgroundColor ?? theme.desktopChatMessageInputBgColor,
|
color: widget.backgroundColor ?? theme.desktopChatMessageInputBgColor,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
_buildRepliedMessage(widget.repliedMessage),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 1,
|
height: 1,
|
||||||
child: Container(
|
child: Container(
|
||||||
|
|
@ -963,7 +993,6 @@ class _TIMUIKitTextFieldLayoutWideState
|
||||||
children: generateControlBar(widget.model, theme),
|
children: generateControlBar(widget.model, theme),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
_buildRepliedMessage(widget.repliedMessage),
|
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 6),
|
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 6),
|
||||||
constraints: const BoxConstraints(minHeight: 50),
|
constraints: const BoxConstraints(minHeight: 50),
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,14 @@ import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/chat_life_cyc
|
||||||
import 'package:tencent_cloud_chat_uikit/business_logic/listener_model/tui_group_listener_model.dart';
|
import 'package:tencent_cloud_chat_uikit/business_logic/listener_model/tui_group_listener_model.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart';
|
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.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';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_conversation_view_model.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
|
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/constants/history_message_constant.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/constants/history_message_constant.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/controller/tim_uikit_chat_controller.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/controller/tim_uikit_chat_controller.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/utils/frame.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/utils/frame.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/utils/optimize_utils.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/utils/optimize_utils.dart';
|
||||||
|
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/at_member_panel.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/at_member_panel.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/tim_uikit_multi_select_panel.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/tim_uikit_multi_select_panel.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/tim_uikit_send_file.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/tim_uikit_send_file.dart';
|
||||||
|
|
@ -50,7 +52,7 @@ class TIMUIKitChat extends StatefulWidget {
|
||||||
|
|
||||||
/// use for customize avatar
|
/// use for customize avatar
|
||||||
final Widget Function(BuildContext context, V2TimMessage message)?
|
final Widget Function(BuildContext context, V2TimMessage message)?
|
||||||
userAvatarBuilder;
|
userAvatarBuilder;
|
||||||
|
|
||||||
/// Use for show conversation name.
|
/// Use for show conversation name.
|
||||||
/// This field is not necessary to be provided, when `conversation` is provided, unless you want to cover this field manually.
|
/// This field is not necessary to be provided, when `conversation` is provided, unless you want to cover this field manually.
|
||||||
|
|
@ -61,7 +63,7 @@ class TIMUIKitChat extends StatefulWidget {
|
||||||
|
|
||||||
/// Avatar and name in message reaction secondary tap callback.
|
/// Avatar and name in message reaction secondary tap callback.
|
||||||
final void Function(String userID, TapDownDetails tapDetails)?
|
final void Function(String userID, TapDownDetails tapDetails)?
|
||||||
onSecondaryTapAvatar;
|
onSecondaryTapAvatar;
|
||||||
|
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
"Nickname will not shows in one-to-one chat, if you tend to control it in group chat, please use `isShowSelfNameInGroup` and `isShowOthersNameInGroup` from `config: TIMUIKitChatConfig` instead")
|
"Nickname will not shows in one-to-one chat, if you tend to control it in group chat, please use `isShowSelfNameInGroup` and `isShowOthersNameInGroup` from `config: TIMUIKitChatConfig` instead")
|
||||||
|
|
@ -108,18 +110,23 @@ class TIMUIKitChat extends StatefulWidget {
|
||||||
final TongueItemBuilder? tongueItemBuilder;
|
final TongueItemBuilder? tongueItemBuilder;
|
||||||
|
|
||||||
/// The `groupAtInfoList` from `V2TimConversation`.
|
/// The `groupAtInfoList` from `V2TimConversation`.
|
||||||
/// This field is not necessary to be provided, when `conversation` is provided, unless you want to cover this field manually.
|
/// This field is not necessary to be provided, when `conversation` is provided,
|
||||||
|
/// unless you want to cover this field manually.
|
||||||
final List<V2TimGroupAtInfo?>? groupAtInfoList;
|
final List<V2TimGroupAtInfo?>? groupAtInfoList;
|
||||||
|
|
||||||
/// The configuration for the whole `TIMUIKitChat` widget.
|
/// The configuration for the whole `TIMUIKitChat` widget.
|
||||||
final TIMUIKitChatConfig? config;
|
final TIMUIKitChatConfig? config;
|
||||||
|
|
||||||
/// The callback for jumping to the page for `TIMUIKitGroupApplicationList` or other pages to deal with enter group application for group administrator manually, in the case of [public group].
|
/// The callback for jumping to the page for `TIMUIKitGroupApplicationList`
|
||||||
|
/// or other pages to deal with enter group application for group administrator manually,
|
||||||
|
/// in the case of [public group].
|
||||||
/// The parameter here is `String groupID`
|
/// The parameter here is `String groupID`
|
||||||
final ValueChanged<String>? onDealWithGroupApplication;
|
final ValueChanged<String>? onDealWithGroupApplication;
|
||||||
|
|
||||||
/// The builder for abstract messages, normally used in replied message and forward message.
|
/// The generator for the abstract summary preview of a message,
|
||||||
final String Function(V2TimMessage message)? abstractMessageBuilder;
|
/// typically used in replied and forwarded messages.
|
||||||
|
/// Returns `null` to use the default message summary.
|
||||||
|
final String? Function(V2TimMessage message)? abstractMessageBuilder;
|
||||||
|
|
||||||
/// The configuration for tool tips panel, long press messages will show this panel.
|
/// The configuration for tool tips panel, long press messages will show this panel.
|
||||||
final ToolTipsConfig? toolTipsConfig;
|
final ToolTipsConfig? toolTipsConfig;
|
||||||
|
|
@ -140,45 +147,45 @@ class TIMUIKitChat extends StatefulWidget {
|
||||||
/// Custom text field
|
/// Custom text field
|
||||||
final Widget Function(BuildContext context)? textFieldBuilder;
|
final Widget Function(BuildContext context)? textFieldBuilder;
|
||||||
|
|
||||||
TIMUIKitChat(
|
TIMUIKitChat({Key? key,
|
||||||
{Key? key,
|
this.groupID,
|
||||||
this.groupID,
|
required this.conversation,
|
||||||
required this.conversation,
|
this.conversationID,
|
||||||
this.conversationID,
|
this.conversationType,
|
||||||
this.conversationType,
|
this.conversationShowName,
|
||||||
this.conversationShowName,
|
this.abstractMessageBuilder,
|
||||||
this.abstractMessageBuilder,
|
this.onTapAvatar,
|
||||||
this.onTapAvatar,
|
@Deprecated(
|
||||||
@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,
|
||||||
"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.showTotalUnReadCount = false,
|
||||||
this.showNickName = false,
|
this.messageItemBuilder,
|
||||||
this.showTotalUnReadCount = false,
|
@Deprecated(
|
||||||
this.messageItemBuilder,
|
"Please use [extraTipsActionItemBuilder] instead") this.exteraTipsActionItemBuilder,
|
||||||
@Deprecated("Please use [extraTipsActionItemBuilder] instead")
|
this.extraTipsActionItemBuilder,
|
||||||
this.exteraTipsActionItemBuilder,
|
this.draftText,
|
||||||
this.extraTipsActionItemBuilder,
|
this.textFieldHintText,
|
||||||
this.draftText,
|
this.initFindingMsg,
|
||||||
this.textFieldHintText,
|
this.userAvatarBuilder,
|
||||||
this.initFindingMsg,
|
this.appBarConfig,
|
||||||
this.userAvatarBuilder,
|
this.controller,
|
||||||
this.appBarConfig,
|
this.morePanelConfig,
|
||||||
this.controller,
|
this.customStickerPanel,
|
||||||
this.morePanelConfig,
|
this.config = const TIMUIKitChatConfig(),
|
||||||
this.customStickerPanel,
|
this.tongueItemBuilder,
|
||||||
this.config = const TIMUIKitChatConfig(),
|
this.groupAtInfoList,
|
||||||
this.tongueItemBuilder,
|
this.mainHistoryListConfig,
|
||||||
this.groupAtInfoList,
|
this.onDealWithGroupApplication,
|
||||||
this.mainHistoryListConfig,
|
this.toolTipsConfig,
|
||||||
this.onDealWithGroupApplication,
|
this.lifeCycle,
|
||||||
this.toolTipsConfig,
|
this.topFixWidget = const SizedBox(),
|
||||||
this.lifeCycle,
|
this.textFieldBuilder,
|
||||||
this.topFixWidget = const SizedBox(),
|
this.customEmojiStickerList = const [],
|
||||||
this.textFieldBuilder,
|
this.customAppBar,
|
||||||
this.customEmojiStickerList = const [],
|
this.onSecondaryTapAvatar})
|
||||||
this.customAppBar,
|
|
||||||
this.onSecondaryTapAvatar})
|
|
||||||
: super(key: key) {
|
: super(key: key) {
|
||||||
startTime = DateTime.now().millisecondsSinceEpoch;
|
startTime = DateTime
|
||||||
|
.now()
|
||||||
|
.millisecondsSinceEpoch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -188,11 +195,13 @@ class TIMUIKitChat extends StatefulWidget {
|
||||||
class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
|
class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
|
||||||
TUIChatSeparateViewModel model = TUIChatSeparateViewModel();
|
TUIChatSeparateViewModel model = TUIChatSeparateViewModel();
|
||||||
final TUIThemeViewModel themeViewModel = serviceLocator<TUIThemeViewModel>();
|
final TUIThemeViewModel themeViewModel = serviceLocator<TUIThemeViewModel>();
|
||||||
|
final TUIConversationViewModel conversationViewModel =
|
||||||
|
serviceLocator<TUIConversationViewModel>();
|
||||||
final TIMUIKitInputTextFieldController textFieldController =
|
final TIMUIKitInputTextFieldController textFieldController =
|
||||||
TIMUIKitInputTextFieldController();
|
TIMUIKitInputTextFieldController();
|
||||||
bool isInit = false;
|
bool isInit = false;
|
||||||
final TUIChatGlobalModel chatGlobalModel =
|
final TUIChatGlobalModel chatGlobalModel =
|
||||||
serviceLocator<TUIChatGlobalModel>();
|
serviceLocator<TUIChatGlobalModel>();
|
||||||
bool _dragging = false;
|
bool _dragging = false;
|
||||||
|
|
||||||
final GlobalKey alignKey = GlobalKey();
|
final GlobalKey alignKey = GlobalKey();
|
||||||
|
|
@ -200,13 +209,19 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
|
||||||
|
|
||||||
late AutoScrollController autoController = AutoScrollController(
|
late AutoScrollController autoController = AutoScrollController(
|
||||||
viewportBoundaryGetter: () =>
|
viewportBoundaryGetter: () =>
|
||||||
Rect.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom),
|
Rect.fromLTRB(0, 0, 0, MediaQuery
|
||||||
|
.of(context)
|
||||||
|
.padding
|
||||||
|
.bottom),
|
||||||
axis: Axis.vertical,
|
axis: Axis.vertical,
|
||||||
);
|
);
|
||||||
|
|
||||||
late AutoScrollController atMemberPanelScroll = AutoScrollController(
|
late AutoScrollController atMemberPanelScroll = AutoScrollController(
|
||||||
viewportBoundaryGetter: () =>
|
viewportBoundaryGetter: () =>
|
||||||
Rect.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom),
|
Rect.fromLTRB(0, 0, 0, MediaQuery
|
||||||
|
.of(context)
|
||||||
|
.padding
|
||||||
|
.bottom),
|
||||||
axis: Axis.vertical,
|
axis: Axis.vertical,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -220,11 +235,16 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
|
||||||
model.onTapAvatar = widget.onTapAvatar;
|
model.onTapAvatar = widget.onTapAvatar;
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
if (kProfileMode) {
|
if (kProfileMode) {
|
||||||
widget.endTime = DateTime.now().millisecondsSinceEpoch;
|
widget.endTime = DateTime
|
||||||
|
.now()
|
||||||
|
.millisecondsSinceEpoch;
|
||||||
int timeSpend = widget.endTime - widget.startTime;
|
int timeSpend = widget.endTime - widget.startTime;
|
||||||
print("Page render time:$timeSpend ms");
|
print("Page render time:$timeSpend ms");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Future.delayed(const Duration(milliseconds: 500), () {
|
||||||
|
updateDraft();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -245,8 +265,8 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
|
||||||
model = TUIChatSeparateViewModel();
|
model = TUIChatSeparateViewModel();
|
||||||
model.abstractMessageBuilder = widget.abstractMessageBuilder;
|
model.abstractMessageBuilder = widget.abstractMessageBuilder;
|
||||||
model.onTapAvatar = widget.onTapAvatar;
|
model.onTapAvatar = widget.onTapAvatar;
|
||||||
textFieldController.requestFocus();
|
|
||||||
Future.delayed(const Duration(milliseconds: 50), () {
|
Future.delayed(const Duration(milliseconds: 50), () {
|
||||||
|
updateDraft();
|
||||||
textFieldController.requestFocus();
|
textFieldController.requestFocus();
|
||||||
try {
|
try {
|
||||||
autoController.jumpTo(
|
autoController.jumpTo(
|
||||||
|
|
@ -261,6 +281,22 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateDraft() async {
|
||||||
|
final isTopic = widget.conversation.conversationID.contains("@TOPIC#");
|
||||||
|
if (isTopic) {
|
||||||
|
final topicInfoList = await TencentImSDKPlugin.v2TIMManager
|
||||||
|
.getGroupManager()
|
||||||
|
.getTopicInfoList(
|
||||||
|
groupID: widget.groupID!,
|
||||||
|
topicIDList: [widget.conversation.conversationID]);
|
||||||
|
final topicInfo = topicInfoList.data?.first.topicInfo;
|
||||||
|
final draftText = topicInfo?.draftText;
|
||||||
|
if (TencentUtils.checkString(draftText) != null) {
|
||||||
|
textFieldController.setTextField(draftText!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Widget _renderJoinGroupApplication(int amount, TUITheme theme) {
|
Widget _renderJoinGroupApplication(int amount, TUITheme theme) {
|
||||||
String option1 = amount.toString();
|
String option1 = amount.toString();
|
||||||
return Container(
|
return Container(
|
||||||
|
|
@ -318,7 +354,7 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
|
||||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||||
final TUITheme theme = value.theme;
|
final TUITheme theme = value.theme;
|
||||||
final closePanel =
|
final closePanel =
|
||||||
OptimizeUtils.throttle((_) => textFieldController.hideAllPanel(), 60);
|
OptimizeUtils.throttle((_) => textFieldController.hideAllPanel(), 60);
|
||||||
final isBuild = isInit;
|
final isBuild = isInit;
|
||||||
isInit = true;
|
isInit = true;
|
||||||
|
|
||||||
|
|
@ -337,7 +373,7 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
|
||||||
],
|
],
|
||||||
builder: (context, model, w) {
|
builder: (context, model, w) {
|
||||||
final TUIChatGlobalModel chatGlobalModel =
|
final TUIChatGlobalModel chatGlobalModel =
|
||||||
Provider.of<TUIChatGlobalModel>(context, listen: true);
|
Provider.of<TUIChatGlobalModel>(context, listen: true);
|
||||||
|
|
||||||
widget.controller?.model = model;
|
widget.controller?.model = model;
|
||||||
widget.controller?.textFieldController = textFieldController;
|
widget.controller?.textFieldController = textFieldController;
|
||||||
|
|
@ -347,13 +383,13 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
|
||||||
widget.onDealWithGroupApplication != null) {
|
widget.onDealWithGroupApplication != null) {
|
||||||
filteredApplicationList =
|
filteredApplicationList =
|
||||||
chatGlobalModel.groupApplicationList.where((item) {
|
chatGlobalModel.groupApplicationList.where((item) {
|
||||||
return (item.groupID == widget.conversationID) &&
|
return (item.groupID == widget.conversationID) &&
|
||||||
item.handleStatus == 0;
|
item.handleStatus == 0;
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
final TUIGroupListenerModel groupListenerModel =
|
final TUIGroupListenerModel groupListenerModel =
|
||||||
Provider.of<TUIGroupListenerModel>(context, listen: true);
|
Provider.of<TUIGroupListenerModel>(context, listen: true);
|
||||||
final NeedUpdate? needUpdate = groupListenerModel.needUpdate;
|
final NeedUpdate? needUpdate = groupListenerModel.needUpdate;
|
||||||
if (needUpdate != null &&
|
if (needUpdate != null &&
|
||||||
needUpdate.groupID == widget.conversationID) {
|
needUpdate.groupID == widget.conversationID) {
|
||||||
|
|
@ -379,13 +415,13 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: false,
|
||||||
appBar: (widget.customAppBar == null)
|
appBar: (widget.customAppBar == null)
|
||||||
? TIMUIKitAppBar(
|
? TIMUIKitAppBar(
|
||||||
showTotalUnReadCount: widget.showTotalUnReadCount,
|
showTotalUnReadCount: widget.showTotalUnReadCount,
|
||||||
config: widget.appBarConfig,
|
config: widget.appBarConfig,
|
||||||
conversationShowName: _getTitle(),
|
conversationShowName: _getTitle(),
|
||||||
conversationID: _getConvID(),
|
conversationID: _getConvID(),
|
||||||
showC2cMessageEditStatus:
|
showC2cMessageEditStatus:
|
||||||
widget.config?.showC2cMessageEditStatus ?? true,
|
widget.config?.showC2cMessageEditStatus ?? true,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
body: DropTarget(
|
body: DropTarget(
|
||||||
onDragDone: (detail) {
|
onDragDone: (detail) {
|
||||||
|
|
@ -421,90 +457,100 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
|
||||||
if (widget.topFixWidget != null) widget.topFixWidget!,
|
if (widget.topFixWidget != null) widget.topFixWidget!,
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
color: theme.chatBgColor,
|
color: theme.chatBgColor,
|
||||||
child: Align(
|
child: Align(
|
||||||
key: alignKey,
|
key: alignKey,
|
||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
child: Listener(
|
child: Listener(
|
||||||
onPointerMove: closePanel,
|
onPointerMove: closePanel,
|
||||||
child: TIMUIKitHistoryMessageListContainer(
|
child: TIMUIKitHistoryMessageListContainer(
|
||||||
conversation: widget.conversation,
|
conversation: widget.conversation,
|
||||||
textFieldController: textFieldController,
|
textFieldController: textFieldController,
|
||||||
customEmojiStickerList:
|
customEmojiStickerList:
|
||||||
widget.customEmojiStickerList,
|
widget.customEmojiStickerList,
|
||||||
isUseDefaultEmoji:
|
isUseDefaultEmoji:
|
||||||
widget.config!.isUseDefaultEmoji,
|
widget.config!.isUseDefaultEmoji,
|
||||||
key: listContainerKey,
|
key: listContainerKey,
|
||||||
isAllowScroll: true,
|
isAllowScroll: true,
|
||||||
userAvatarBuilder: widget.userAvatarBuilder,
|
userAvatarBuilder: widget
|
||||||
toolTipsConfig: widget.toolTipsConfig,
|
.userAvatarBuilder,
|
||||||
groupAtInfoList: widget.groupAtInfoList,
|
toolTipsConfig: widget.toolTipsConfig,
|
||||||
tongueItemBuilder: widget.tongueItemBuilder,
|
groupAtInfoList: widget.groupAtInfoList,
|
||||||
onLongPressForOthersHeadPortrait:
|
tongueItemBuilder: widget
|
||||||
(String? userId, String? nickName) {
|
.tongueItemBuilder,
|
||||||
textFieldController.longPressToAt(
|
onLongPressForOthersHeadPortrait:
|
||||||
nickName, userId);
|
(String? userId, String? nickName) {
|
||||||
},
|
textFieldController.longPressToAt(
|
||||||
mainHistoryListConfig:
|
nickName, userId);
|
||||||
|
},
|
||||||
|
mainHistoryListConfig:
|
||||||
widget.mainHistoryListConfig,
|
widget.mainHistoryListConfig,
|
||||||
initFindingMsg: widget.initFindingMsg,
|
initFindingMsg: widget.initFindingMsg,
|
||||||
extraTipsActionItemBuilder:
|
extraTipsActionItemBuilder:
|
||||||
widget.extraTipsActionItemBuilder ??
|
widget.extraTipsActionItemBuilder ??
|
||||||
widget.exteraTipsActionItemBuilder,
|
widget.exteraTipsActionItemBuilder,
|
||||||
conversationType: _getConvType(),
|
conversationType: _getConvType(),
|
||||||
scrollController: autoController,
|
scrollController: autoController,
|
||||||
onSecondaryTapAvatar:
|
onSecondaryTapAvatar:
|
||||||
widget.onSecondaryTapAvatar,
|
widget.onSecondaryTapAvatar,
|
||||||
onTapAvatar: widget.onTapAvatar,
|
onTapAvatar: widget.onTapAvatar,
|
||||||
// ignore: deprecated_member_use_from_same_package
|
// ignore: deprecated_member_use_from_same_package
|
||||||
showNickName: widget.showNickName,
|
showNickName: widget.showNickName,
|
||||||
messageItemBuilder:
|
messageItemBuilder:
|
||||||
widget.messageItemBuilder,
|
widget.messageItemBuilder,
|
||||||
conversationID: _getConvID(),
|
conversationID: _getConvID(),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
)),
|
)),
|
||||||
Selector<TUIChatSeparateViewModel, bool>(
|
Selector<TUIChatSeparateViewModel, bool>(
|
||||||
builder: (context, value, child) {
|
builder: (context, value, child) {
|
||||||
return value
|
return value
|
||||||
? MultiSelectPanel(
|
? MultiSelectPanel(
|
||||||
conversationType: _getConvType(),
|
conversationType: _getConvType(),
|
||||||
)
|
)
|
||||||
: (widget.textFieldBuilder != null
|
: (widget.textFieldBuilder != null
|
||||||
? widget.textFieldBuilder!(context)
|
? widget.textFieldBuilder!(context)
|
||||||
: TIMUIKitInputTextField(
|
: TIMUIKitInputTextField(
|
||||||
atMemberPanelScroll:
|
groupID: widget.groupID,
|
||||||
atMemberPanelScroll,
|
atMemberPanelScroll:
|
||||||
groupType:
|
atMemberPanelScroll,
|
||||||
widget.conversation.groupType,
|
groupType:
|
||||||
currentConversation:
|
widget.conversation.groupType,
|
||||||
widget.conversation,
|
currentConversation:
|
||||||
model: model,
|
widget.conversation,
|
||||||
controller: textFieldController,
|
model: model,
|
||||||
customEmojiStickerList:
|
controller: textFieldController,
|
||||||
widget.customEmojiStickerList,
|
customEmojiStickerList:
|
||||||
isUseDefaultEmoji:
|
widget.customEmojiStickerList,
|
||||||
widget.config!.isUseDefaultEmoji,
|
isUseDefaultEmoji:
|
||||||
customStickerPanel:
|
widget.config!.isUseDefaultEmoji,
|
||||||
widget.customStickerPanel,
|
customStickerPanel:
|
||||||
morePanelConfig:
|
widget.customStickerPanel,
|
||||||
widget.morePanelConfig,
|
morePanelConfig:
|
||||||
scrollController: autoController,
|
widget.morePanelConfig,
|
||||||
conversationID: _getConvID(),
|
scrollController: autoController,
|
||||||
conversationType: _getConvType(),
|
conversationID: _getConvID(),
|
||||||
initText: widget.draftText ??
|
conversationType: _getConvType(),
|
||||||
widget.conversation.draftText,
|
initText: TencentUtils.checkString(
|
||||||
hintText: widget.textFieldHintText,
|
widget.draftText) ?? (PlatformUtils().isWeb
|
||||||
showMorePanel: widget.config
|
? TencentUtils.checkString(
|
||||||
?.isAllowShowMorePanel ??
|
conversationViewModel.getWebDraft(
|
||||||
true,
|
conversationID: widget.conversation
|
||||||
showSendAudio: widget.config
|
.conversationID))
|
||||||
?.isAllowSoundMessage ??
|
:
|
||||||
true,
|
TencentUtils.checkString(widget
|
||||||
showSendEmoji: widget
|
.conversation.draftText)),
|
||||||
.config?.isAllowEmojiPanel ??
|
hintText: widget.textFieldHintText,
|
||||||
true,
|
showMorePanel: widget.config
|
||||||
));
|
?.isAllowShowMorePanel ??
|
||||||
|
true,
|
||||||
|
showSendAudio: widget.config
|
||||||
|
?.isAllowSoundMessage ??
|
||||||
|
true,
|
||||||
|
showSendEmoji: widget
|
||||||
|
.config?.isAllowEmojiPanel ??
|
||||||
|
true,
|
||||||
|
));
|
||||||
},
|
},
|
||||||
selector: (c, model) {
|
selector: (c, model) {
|
||||||
return model.isMultiSelect;
|
return model.isMultiSelect;
|
||||||
|
|
@ -533,13 +579,13 @@ class TIMUIKitChatProviderScope extends StatelessWidget {
|
||||||
final TUIChatGlobalModel globalModel = serviceLocator<TUIChatGlobalModel>();
|
final TUIChatGlobalModel globalModel = serviceLocator<TUIChatGlobalModel>();
|
||||||
TUIChatSeparateViewModel? model;
|
TUIChatSeparateViewModel? model;
|
||||||
final TUIGroupListenerModel groupListenerModel =
|
final TUIGroupListenerModel groupListenerModel =
|
||||||
serviceLocator<TUIGroupListenerModel>();
|
serviceLocator<TUIGroupListenerModel>();
|
||||||
final TUIThemeViewModel themeViewModel = serviceLocator<TUIThemeViewModel>();
|
final TUIThemeViewModel themeViewModel = serviceLocator<TUIThemeViewModel>();
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
|
|
||||||
/// You could get the model from here, and transfer it to other widget from TUIKit.
|
/// You could get the model from here, and transfer it to other widget from TUIKit.
|
||||||
final Widget Function(BuildContext, TUIChatSeparateViewModel, Widget?)
|
final Widget Function(BuildContext, TUIChatSeparateViewModel, Widget?)
|
||||||
builder;
|
builder;
|
||||||
final List<SingleChildWidget>? providers;
|
final List<SingleChildWidget>? providers;
|
||||||
|
|
||||||
/// `TIMUIKitChatController` needs to be provided if you use it outside.
|
/// `TIMUIKitChatController` needs to be provided if you use it outside.
|
||||||
|
|
@ -566,21 +612,20 @@ class TIMUIKitChatProviderScope extends StatelessWidget {
|
||||||
|
|
||||||
final AutoScrollController? scrollController;
|
final AutoScrollController? scrollController;
|
||||||
|
|
||||||
TIMUIKitChatProviderScope(
|
TIMUIKitChatProviderScope({Key? key,
|
||||||
{Key? key,
|
this.child,
|
||||||
this.child,
|
this.providers,
|
||||||
this.providers,
|
this.textFieldController,
|
||||||
this.textFieldController,
|
required this.builder,
|
||||||
required this.builder,
|
this.model,
|
||||||
this.model,
|
this.groupID,
|
||||||
this.groupID,
|
this.isBuild,
|
||||||
this.isBuild,
|
required this.conversationID,
|
||||||
required this.conversationID,
|
required this.conversationType,
|
||||||
required this.conversationType,
|
this.controller,
|
||||||
this.controller,
|
this.config,
|
||||||
this.config,
|
this.lifeCycle,
|
||||||
this.lifeCycle,
|
this.scrollController})
|
||||||
this.scrollController})
|
|
||||||
: super(key: key) {
|
: super(key: key) {
|
||||||
if (isBuild ?? false) {
|
if (isBuild ?? false) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -596,7 +641,7 @@ class TIMUIKitChatProviderScope extends StatelessWidget {
|
||||||
model?.initForEachConversation(
|
model?.initForEachConversation(
|
||||||
conversationType,
|
conversationType,
|
||||||
conversationID,
|
conversationID,
|
||||||
(String value) {
|
(String value) {
|
||||||
textFieldController?.textEditingController?.text = value;
|
textFieldController?.textEditingController?.text = value;
|
||||||
},
|
},
|
||||||
groupID: groupID,
|
groupID: groupID,
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,12 @@ class TIMUIKitChatConfig {
|
||||||
/// Define the lines in the text message input field on Desktop.
|
/// Define the lines in the text message input field on Desktop.
|
||||||
final int desktopMessageInputFieldLines;
|
final int desktopMessageInputFieldLines;
|
||||||
|
|
||||||
|
/// Specifies whether to use the draft feature on the Web, as the Chat SDK does not support this functionality.
|
||||||
|
/// If enabled, draft data will be stored in TUIKit's memory.
|
||||||
|
/// Note that the draft text will be lost upon refreshing the website.
|
||||||
|
/// [Default]: true.
|
||||||
|
final bool isUseDraftOnWeb;
|
||||||
|
|
||||||
const TIMUIKitChatConfig(
|
const TIMUIKitChatConfig(
|
||||||
{this.onTapLink,
|
{this.onTapLink,
|
||||||
this.timeDividerConfig,
|
this.timeDividerConfig,
|
||||||
|
|
@ -203,7 +209,7 @@ class TIMUIKitChatConfig {
|
||||||
this.isShowSelfNameInGroup = false,
|
this.isShowSelfNameInGroup = false,
|
||||||
this.offlinePushInfo,
|
this.offlinePushInfo,
|
||||||
@Deprecated("Please use [isShowGroupReadingStatus] instead")
|
@Deprecated("Please use [isShowGroupReadingStatus] instead")
|
||||||
this.isShowGroupMessageReadReceipt = true,
|
this.isShowGroupMessageReadReceipt = true,
|
||||||
this.upperRecallTime = 120,
|
this.upperRecallTime = 120,
|
||||||
this.isShowOthersNameInGroup = true,
|
this.isShowOthersNameInGroup = true,
|
||||||
this.urlPreviewType = UrlPreviewType.onlyHyperlink,
|
this.urlPreviewType = UrlPreviewType.onlyHyperlink,
|
||||||
|
|
@ -213,13 +219,14 @@ class TIMUIKitChatConfig {
|
||||||
this.notificationIOSSound = "",
|
this.notificationIOSSound = "",
|
||||||
this.isAllowSoundMessage = true,
|
this.isAllowSoundMessage = true,
|
||||||
@Deprecated("Please use [groupReadReceiptPermissionList] instead")
|
@Deprecated("Please use [groupReadReceiptPermissionList] instead")
|
||||||
this.groupReadReceiptPermisionList,
|
this.groupReadReceiptPermisionList,
|
||||||
this.groupReadReceiptPermissionList,
|
this.groupReadReceiptPermissionList,
|
||||||
this.isAllowEmojiPanel = true,
|
this.isAllowEmojiPanel = true,
|
||||||
this.isAllowShowMorePanel = true,
|
this.isAllowShowMorePanel = true,
|
||||||
this.isShowReadingStatus = true,
|
this.isShowReadingStatus = true,
|
||||||
this.desktopControlBarConfig,
|
this.desktopControlBarConfig,
|
||||||
this.isAllowLongPressMessage = true,
|
this.isAllowLongPressMessage = true,
|
||||||
|
this.isUseDraftOnWeb = true,
|
||||||
this.isAllowClickAvatar = true,
|
this.isAllowClickAvatar = true,
|
||||||
this.isEnableTextSelection,
|
this.isEnableTextSelection,
|
||||||
this.additionalDesktopMessageHoverBarItem,
|
this.additionalDesktopMessageHoverBarItem,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
|
||||||
|
|
||||||
class MessageRepliedData {
|
class MessageRepliedData {
|
||||||
late String messageAbstract;
|
late String messageAbstract;
|
||||||
late String messageSender;
|
late String messageSender;
|
||||||
|
|
@ -10,6 +12,42 @@ class MessageRepliedData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RepliedMessageAbstract {
|
||||||
|
final int? elemType;
|
||||||
|
final String? msgID;
|
||||||
|
final int? timestamp;
|
||||||
|
final String? seq;
|
||||||
|
final String? summary;
|
||||||
|
|
||||||
|
RepliedMessageAbstract(
|
||||||
|
{this.elemType, this.msgID, this.timestamp, this.seq, this.summary});
|
||||||
|
|
||||||
|
// fromJson constructor
|
||||||
|
RepliedMessageAbstract.fromJson(Map<String, dynamic> json)
|
||||||
|
: elemType = json['elemType'],
|
||||||
|
msgID = json['msgID'],
|
||||||
|
timestamp = json['timestamp'],
|
||||||
|
seq = json['seq'],
|
||||||
|
summary = json['summary'];
|
||||||
|
|
||||||
|
// toJson function
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'summary': summary,
|
||||||
|
'elemType': elemType,
|
||||||
|
'msgID': msgID,
|
||||||
|
'timestamp': timestamp,
|
||||||
|
'seq': seq,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNotEmpty method
|
||||||
|
bool get isNotEmpty =>
|
||||||
|
TencentUtils.checkString(msgID) != null &&
|
||||||
|
TencentUtils.checkString(timestamp.toString()) != null &&
|
||||||
|
TencentUtils.checkString(seq) != null;
|
||||||
|
}
|
||||||
|
|
||||||
class CloudCustomData {
|
class CloudCustomData {
|
||||||
Map<String, dynamic>? messageReply;
|
Map<String, dynamic>? messageReply;
|
||||||
Map<String, dynamic>? messageReaction = {};
|
Map<String, dynamic>? messageReaction = {};
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ class LinkPreviewEntry {
|
||||||
return isMarkdown
|
return isMarkdown
|
||||||
? LinkTextMarkdown(
|
? LinkTextMarkdown(
|
||||||
isEnableTextSelection: isEnableTextSelection,
|
isEnableTextSelection: isEnableTextSelection,
|
||||||
messageText: replaceSingleNewlineWithTwo(messageText),
|
messageText: addSpaceAfterLeftBracket(
|
||||||
|
addSpaceBeforeHttp(replaceSingleNewlineWithTwo(messageText))),
|
||||||
style: style,
|
style: style,
|
||||||
onLinkTap: onLinkTap)
|
onLinkTap: onLinkTap)
|
||||||
: LinkText(
|
: LinkText(
|
||||||
|
|
@ -30,10 +31,27 @@ class LinkPreviewEntry {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String addSpaceAfterLeftBracket(String inputText) {
|
||||||
|
return inputText.splitMapJoin(
|
||||||
|
RegExp(r'<\w+[^<>]*>'),
|
||||||
|
onMatch: (match) {
|
||||||
|
return match.group(0)!.replaceFirst('<', '< ');
|
||||||
|
},
|
||||||
|
onNonMatch: (text) => text,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static String replaceSingleNewlineWithTwo(String inputText) {
|
static String replaceSingleNewlineWithTwo(String inputText) {
|
||||||
return inputText.replaceAllMapped(
|
return inputText.split('\n').join('\n\n');
|
||||||
RegExp(r'(?<!\n)\n(?!\n)'),
|
}
|
||||||
(match) => '\n\n',
|
|
||||||
|
static String addSpaceBeforeHttp(String inputText) {
|
||||||
|
return inputText.splitMapJoin(
|
||||||
|
RegExp(r'http'),
|
||||||
|
onMatch: (match) {
|
||||||
|
return ' http';
|
||||||
|
},
|
||||||
|
onNonMatch: (text) => text,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
import 'package:tencent_im_base/base_widgets/tim_stateless_widget.dart';
|
import 'package:tencent_im_base/base_widgets/tim_stateless_widget.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/DefaultSpecialTextSpanBuilder.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/DefaultSpecialTextSpanBuilder.dart';
|
||||||
import 'package:tencent_cloud_chat_uikit/ui/widgets/link_preview/common/utils.dart';
|
import 'package:tencent_cloud_chat_uikit/ui/widgets/link_preview/common/utils.dart';
|
||||||
|
import 'package:markdown/markdown.dart' as md;
|
||||||
|
|
||||||
class LinkTextMarkdown extends TIMStatelessWidget {
|
class LinkTextMarkdown extends TIMStatelessWidget {
|
||||||
/// Callback for when link is tapped
|
/// Callback for when link is tapped
|
||||||
|
|
@ -40,6 +41,7 @@ class LinkTextMarkdown extends TIMStatelessWidget {
|
||||||
.copyWith(
|
.copyWith(
|
||||||
a: TextStyle(color: LinkUtils.hexToColor("015fff")),
|
a: TextStyle(color: LinkUtils.hexToColor("015fff")),
|
||||||
),
|
),
|
||||||
|
extensionSet: md.ExtensionSet.gitHubWeb,
|
||||||
onTapLink: (
|
onTapLink: (
|
||||||
String link,
|
String link,
|
||||||
String? href,
|
String? href,
|
||||||
|
|
@ -155,3 +157,20 @@ class LinkText extends TIMStatelessWidget {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TextBuilder extends MarkdownElementBuilder {
|
||||||
|
@override
|
||||||
|
Widget? visitText(md.Text text, TextStyle? preferredStyle) {
|
||||||
|
return Text(text.textContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RawHtmlSyntax extends md.InlineSyntax {
|
||||||
|
RawHtmlSyntax() : super(r'<.+?>');
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool onMatch(md.InlineParser parser, Match match) {
|
||||||
|
parser.addNode(md.Text(match[0]!));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import 'package:tencent_cloud_chat_uikit/ui/widgets/drag_widget.dart';
|
||||||
|
|
||||||
class TUIKitWidePopup {
|
class TUIKitWidePopup {
|
||||||
static OverlayEntry? entry;
|
static OverlayEntry? entry;
|
||||||
|
static bool isShow = false;
|
||||||
|
|
||||||
static showSecondaryConfirmDialog({
|
static showSecondaryConfirmDialog({
|
||||||
required TUIKitWideModalOperationKey operationKey,
|
required TUIKitWideModalOperationKey operationKey,
|
||||||
|
|
@ -17,7 +18,7 @@ class TUIKitWidePopup {
|
||||||
VoidCallback? onCancel,
|
VoidCallback? onCancel,
|
||||||
}) {
|
}) {
|
||||||
return TUIKitWidePopup.showPopupWindow(
|
return TUIKitWidePopup.showPopupWindow(
|
||||||
operationKey: operationKey,
|
operationKey: operationKey,
|
||||||
context: context,
|
context: context,
|
||||||
isDarkBackground: false,
|
isDarkBackground: false,
|
||||||
onCancel: onCancel,
|
onCancel: onCancel,
|
||||||
|
|
@ -56,37 +57,205 @@ class TUIKitWidePopup {
|
||||||
VoidCallback? onConfirm,
|
VoidCallback? onConfirm,
|
||||||
VoidCallback? onCancel,
|
VoidCallback? onCancel,
|
||||||
}) async {
|
}) async {
|
||||||
|
if (isShow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isShow = true;
|
||||||
|
|
||||||
final TUISelfInfoViewModel selfInfoViewModel =
|
final TUISelfInfoViewModel selfInfoViewModel =
|
||||||
serviceLocator<TUISelfInfoViewModel>();
|
serviceLocator<TUISelfInfoViewModel>();
|
||||||
|
|
||||||
if(selfInfoViewModel.globalConfig?.showDesktopModalFunc != null){
|
if (selfInfoViewModel.globalConfig?.showDesktopModalFunc != null) {
|
||||||
final res = await selfInfoViewModel.globalConfig!.showDesktopModalFunc!(
|
final res = await selfInfoViewModel.globalConfig!.showDesktopModalFunc!(
|
||||||
operationKey,
|
operationKey,
|
||||||
context,
|
context,
|
||||||
child,
|
child,
|
||||||
theme,
|
theme,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
offset,
|
offset,
|
||||||
initText,
|
initText,
|
||||||
borderRadius,
|
borderRadius,
|
||||||
isDarkBackground,
|
isDarkBackground,
|
||||||
title,
|
title,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
submitWidget,
|
submitWidget,
|
||||||
onConfirm,
|
onConfirm,
|
||||||
onCancel
|
onCancel);
|
||||||
);
|
|
||||||
|
|
||||||
if(res == true){
|
if (res == true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final isUseMaterialAlert = (offset == null);
|
||||||
|
|
||||||
|
final Widget contentWidget = Container(
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius:
|
||||||
|
borderRadius ?? const BorderRadius.all(Radius.circular(16)),
|
||||||
|
color: theme?.wideBackgroundColor ?? const Color(0xFFffffff),
|
||||||
|
border: isDarkBackground
|
||||||
|
? Border.all(
|
||||||
|
width: 2,
|
||||||
|
color: theme?.weakBackgroundColor ?? const Color(0xFFbebebe),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
boxShadow: (isDarkBackground || isUseMaterialAlert)
|
||||||
|
? null
|
||||||
|
: const [
|
||||||
|
BoxShadow(
|
||||||
|
color: Color(0xFFbebebe),
|
||||||
|
offset: Offset(3, 3),
|
||||||
|
blurRadius: 10,
|
||||||
|
spreadRadius: 1,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (title != null)
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: hexToColor("f5f6f7"),
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(16),
|
||||||
|
topRight: Radius.circular(16)),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
color: theme?.darkTextColor ?? const Color(0xFF444444)),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
if (onSubmit != null) {
|
||||||
|
onSubmit();
|
||||||
|
}
|
||||||
|
isShow = false;
|
||||||
|
if (offset == null) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
} else {
|
||||||
|
entry?.remove();
|
||||||
|
entry = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: onSubmit != null
|
||||||
|
? (submitWidget ?? const Icon(Icons.check))
|
||||||
|
: const Icon(Icons.close),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (title != null)
|
||||||
|
SizedBox(
|
||||||
|
height: 1,
|
||||||
|
child: Container(
|
||||||
|
color: theme?.weakDividerColor ?? const Color(0xFFE5E6E9),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (height != null && width != null)
|
||||||
|
Expanded(child: child(() {
|
||||||
|
isShow = false;
|
||||||
|
if (isUseMaterialAlert) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
} else {
|
||||||
|
entry?.remove();
|
||||||
|
entry = null;
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
if (height == null || width == null)
|
||||||
|
child(() {
|
||||||
|
isShow = false;
|
||||||
|
if (isUseMaterialAlert) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
} else {
|
||||||
|
entry?.remove();
|
||||||
|
entry = null;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
if (onCancel != null || onConfirm != null)
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(bottom: 16),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
if (onCancel != null)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(right: 16),
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: () {
|
||||||
|
isShow = false;
|
||||||
|
if (isUseMaterialAlert) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
} else {
|
||||||
|
entry?.remove();
|
||||||
|
entry = null;
|
||||||
|
}
|
||||||
|
onCancel();
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
TIM_t("取消"),
|
||||||
|
style: TextStyle(
|
||||||
|
color: theme?.weakTextColor ?? Colors.black),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
if (onConfirm != null)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(right: 16),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
isShow = false;
|
||||||
|
if (isUseMaterialAlert) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
} else {
|
||||||
|
entry?.remove();
|
||||||
|
entry = null;
|
||||||
|
}
|
||||||
|
onConfirm();
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
TIM_t("确定"),
|
||||||
|
style: TextStyle(color: theme?.primaryColor),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isUseMaterialAlert) {
|
||||||
|
return showDialog(
|
||||||
|
barrierDismissible: false,
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return WillPopScope(
|
||||||
|
child: AlertDialog(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
titlePadding: const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
|
||||||
|
contentPadding: const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
|
||||||
|
content: contentWidget,
|
||||||
|
),
|
||||||
|
onWillPop: () {
|
||||||
|
return Future.value(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = OverlayEntry(builder: (BuildContext context) {
|
entry = OverlayEntry(builder: (BuildContext context) {
|
||||||
return Material(
|
return Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
|
|
@ -100,133 +269,13 @@ class TUIKitWidePopup {
|
||||||
},
|
},
|
||||||
initOffset: offset ??
|
initOffset: offset ??
|
||||||
(width != null && height != null
|
(width != null && height != null
|
||||||
? Offset(MediaQuery.of(context).size.width * 0.5 - width / 2,
|
? Offset(
|
||||||
MediaQuery.of(context).size.height * 0.5 - height / 2)
|
MediaQuery.of(context).size.width * 0.5 - width / 2,
|
||||||
|
MediaQuery.of(context).size.height * 0.5 - height / 2)
|
||||||
: null),
|
: null),
|
||||||
child: Container(
|
child: contentWidget),
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius:
|
|
||||||
borderRadius ?? const BorderRadius.all(Radius.circular(16)),
|
|
||||||
color: theme?.wideBackgroundColor ?? const Color(0xFFffffff),
|
|
||||||
border: isDarkBackground
|
|
||||||
? Border.all(
|
|
||||||
width: 2,
|
|
||||||
color:
|
|
||||||
theme?.weakBackgroundColor ?? const Color(0xFFbebebe),
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
boxShadow: isDarkBackground
|
|
||||||
? null
|
|
||||||
: const [
|
|
||||||
BoxShadow(
|
|
||||||
color: Color(0xFFbebebe),
|
|
||||||
offset: Offset(3, 3),
|
|
||||||
blurRadius: 10,
|
|
||||||
spreadRadius: 1,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
if (title != null)
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: hexToColor("f5f6f7"),
|
|
||||||
borderRadius: const BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(16),
|
|
||||||
topRight: Radius.circular(16)),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
title,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 18,
|
|
||||||
color: theme?.darkTextColor ??
|
|
||||||
const Color(0xFF444444)),
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
if (onSubmit != null) {
|
|
||||||
onSubmit();
|
|
||||||
}
|
|
||||||
entry?.remove();
|
|
||||||
entry = null;
|
|
||||||
},
|
|
||||||
child: onSubmit != null
|
|
||||||
? (submitWidget ?? const Icon(Icons.check))
|
|
||||||
: const Icon(Icons.close),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (title != null)
|
|
||||||
SizedBox(
|
|
||||||
height: 1,
|
|
||||||
child: Container(
|
|
||||||
color: theme?.weakDividerColor ?? const Color(0xFFE5E6E9),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (height != null && width != null)
|
|
||||||
Expanded(child: child(() {
|
|
||||||
entry?.remove();
|
|
||||||
entry = null;
|
|
||||||
})),
|
|
||||||
if (height == null || width == null)
|
|
||||||
child(() {
|
|
||||||
entry?.remove();
|
|
||||||
entry = null;
|
|
||||||
}),
|
|
||||||
if (onCancel != null || onConfirm != null)
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(bottom: 16),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
if (onCancel != null)
|
|
||||||
Container(
|
|
||||||
margin: const EdgeInsets.only(right: 16),
|
|
||||||
child: OutlinedButton(
|
|
||||||
onPressed: () {
|
|
||||||
entry?.remove();
|
|
||||||
entry = null;
|
|
||||||
onCancel();
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
TIM_t("取消"),
|
|
||||||
style: TextStyle(
|
|
||||||
color:
|
|
||||||
theme?.weakTextColor ?? Colors.black),
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
if (onConfirm != null)
|
|
||||||
Container(
|
|
||||||
margin: const EdgeInsets.only(right: 16),
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: () {
|
|
||||||
entry?.remove();
|
|
||||||
entry = null;
|
|
||||||
onConfirm();
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
TIM_t("确定"),
|
|
||||||
style: TextStyle(color: theme?.primaryColor),
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
Overlay.of(context).insert(entry!);
|
Overlay.of(context).insert(entry!);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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: 2.1.0+2
|
version: 2.1.1
|
||||||
homepage: https://www.tencentcloud.com/products/im?from=pub
|
homepage: https://www.tencentcloud.com/products/im?from=pub
|
||||||
repository: https://github.com/TencentCloud/tc-chat-uikit-flutter
|
repository: https://github.com/TencentCloud/tc-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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue