feat: Upgrade to UIKit 2.3.2

This commit is contained in:
anonymous 2023-09-27 23:21:40 +08:00
parent c28e1e9529
commit 038a3d483d
10 changed files with 187 additions and 447 deletions

View File

@ -1,3 +1,14 @@
# 2.3.2
## Improvements
* Enhanced message list performance.
## Bug Fixes
* Fixed an issue that prevented the group member addition/removal modal from closing.
* Addressed several other bugs.
# 2.3.1
## Bug Fixes

View File

@ -706,7 +706,6 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
Future<void> onMessageDownloadProgressCallback(
V2TimMessageDownloadProgress messageProgress) async {
outputLogger.i(messageProgress.toJson());
final currentProgress = getMessageProgress(messageProgress.msgID);
if (messageProgress.isFinish && currentProgress < 100) {
@ -1120,9 +1119,7 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
listWithTimestamp.add(V2TimMessage.fromJson(item.toJson()));
}
}
final returnValue = listWithTimestamp.reversed.toList();
outputLogger.i(returnValue.map((e) => e.toJson()).toList().toString());
return returnValue;
return listWithTimestamp.reversed.toList();
}
HistoryMessagePosition getMessageListPosition(String? conversationID) {

View File

@ -42,7 +42,7 @@ class TUIKitOutput extends LogOutput {
Future<String> getPlatformLogPath({String? path}) async {
if (TencentUtils.checkString(path) != null) {
outputLogger.i("The path to local log: $path");
print("The path to local log: $path");
return path!;
}
@ -54,7 +54,7 @@ class TUIKitOutput extends LogOutput {
"${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}";
final logPath = p.join(documentsDirectoryPath, "Documents", ".TencentCloudChat",
pkgName, "uikit_log", 'Flutter-TUIKit-$timeName.log');
outputLogger.i("The path to local log: $logPath");
print("The path to local log: $logPath");
return logPath;
}

View File

@ -7,15 +7,17 @@ import 'package:provider/provider.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_state.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.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/ui/utils/logger.dart';
// ignore: unused_import
import 'package:tencent_cloud_chat_uikit/ui/utils/optimize_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list_config.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKItMessageList/utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/keepalive_wrapper.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'TIMUIKitTongue/tim_uikit_chat_history_message_list_tongue.dart';
import 'TIMUIKitTongue/tim_uikit_chat_history_message_list_tongue_container.dart';
@ -73,8 +75,7 @@ class TIMUIKitHistoryMessageList extends StatefulWidget {
final V2TimMessage? initFindingMsg;
/// use for load more message
final Future<void> Function(String?, LoadDirection direction, [int?])
onLoadMore;
final Future<void> Function(String?, LoadDirection direction, [int?]) onLoadMore;
/// configuration for list view
final TIMUIKitHistoryMessageListConfig? mainHistoryListConfig;
@ -104,8 +105,7 @@ class TIMUIKitHistoryMessageList extends StatefulWidget {
State<StatefulWidget> createState() => _TIMUIKitHistoryMessageListState();
}
class _TIMUIKitHistoryMessageListState
extends TIMUIKitState<TIMUIKitHistoryMessageList> {
class _TIMUIKitHistoryMessageListState extends TIMUIKitState<TIMUIKitHistoryMessageList> {
V2TimMessage? findingMsg;
String findingSeq = "";
late TIMUIKitHistoryMessageListController _controller;
@ -116,8 +116,7 @@ class _TIMUIKitHistoryMessageListState
void initState() {
super.initState();
_controller = widget.controller ?? TIMUIKitHistoryMessageListController();
_autoScrollController =
_controller.scrollController ?? AutoScrollController();
_autoScrollController = _controller.scrollController ?? AutoScrollController();
_controller.addListener(_controllerListener);
initFinding();
}
@ -163,18 +162,14 @@ class _TIMUIKitHistoryMessageListState
findingMsg = null;
findingSeq = "";
loadingPlace = LoadingPlace.none;
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("无法定位到原消息"),
infoCode: 6660401));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("无法定位到原消息"), infoCode: 6660401));
}
_onScrollToIndex(V2TimMessage targetMsg) {
// This method called by @ messages or messages been searched, aims to jump to target message
loadingPlace = LoadingPlace.top;
const int singleLoadAmount = kIsWeb ? 15 : 40;
final lastTimestamp =
widget.messageList[widget.messageList.length - 1]?.timestamp;
final lastTimestamp = widget.messageList[widget.messageList.length - 1]?.timestamp;
final msgList = widget.messageList;
final targetTimeStamp = targetMsg.timestamp!;
@ -184,9 +179,7 @@ class _TIMUIKitHistoryMessageListState
int targetIndex = 1;
for (int i = msgList.length - 1; i >= 0; i--) {
final currentMsg = msgList[i];
if (currentMsg?.timestamp == targetTimeStamp &&
currentMsg?.elemType != 11 &&
currentMsg!.msgID == targetMsg.msgID) {
if (currentMsg?.timestamp == targetTimeStamp && currentMsg?.elemType != 11 && currentMsg!.msgID == targetMsg.msgID) {
// find the target index by timestamp and msgID
isFound = true;
targetIndex = -i;
@ -202,10 +195,8 @@ class _TIMUIKitHistoryMessageListState
);
// execute twice for accurate position, as the position located firstly can be wrong
_autoScrollController.scrollToIndex(targetIndex,
preferPosition: AutoScrollPosition.middle);
_autoScrollController.scrollToIndex(targetIndex,
preferPosition: AutoScrollPosition.middle);
_autoScrollController.scrollToIndex(targetIndex, preferPosition: AutoScrollPosition.middle);
_autoScrollController.scrollToIndex(targetIndex, preferPosition: AutoScrollPosition.middle);
widget.model.jumpMsgID = targetMsg.msgID!;
loadingPlace = LoadingPlace.none;
@ -258,8 +249,7 @@ class _TIMUIKitHistoryMessageListState
targetIndex,
preferPosition: AutoScrollPosition.middle,
);
_autoScrollController.scrollToIndex(targetIndex,
preferPosition: AutoScrollPosition.middle);
_autoScrollController.scrollToIndex(targetIndex, preferPosition: AutoScrollPosition.middle);
if (targetMsgID != null && targetMsgID != "") {
widget.model.jumpMsgID = targetMsgID;
}
@ -270,8 +260,7 @@ class _TIMUIKitHistoryMessageListState
} else {
if (widget.model.haveMoreData) {
findingSeq = targetSeq;
widget.onLoadMore(_getMessageId(widget.messageList.length - 1),
LoadDirection.previous, singleLoadAmount);
widget.onLoadMore(_getMessageId(widget.messageList.length - 1), LoadDirection.previous, singleLoadAmount);
} else {
showCantFindMsg();
}
@ -279,8 +268,7 @@ class _TIMUIKitHistoryMessageListState
}
_onScrollToIndexBegin(V2TimMessage targetMsg) {
final lastTimestamp =
widget.messageList[widget.messageList.length - 1]?.timestamp;
final lastTimestamp = widget.messageList[widget.messageList.length - 1]?.timestamp;
final msgList = widget.messageList;
final int targetTimeStamp = targetMsg.timestamp!;
@ -289,9 +277,7 @@ class _TIMUIKitHistoryMessageListState
int targetIndex = 1;
for (int i = msgList.length - 1; i >= 0; i--) {
final currentMsg = msgList[i];
if (currentMsg?.timestamp == targetTimeStamp &&
currentMsg?.elemType != 11 &&
currentMsg!.msgID == targetMsg.msgID) {
if (currentMsg?.timestamp == targetTimeStamp && currentMsg?.elemType != 11 && currentMsg!.msgID == targetMsg.msgID) {
isFound = true;
targetIndex = -i;
break;
@ -310,11 +296,8 @@ class _TIMUIKitHistoryMessageListState
if (receivedMessageListCount == 0) {
return [];
}
final haveTimeStampMessage =
widget.messageList[receivedMessageListCount]?.elemType == 11;
final endPoint = haveTimeStampMessage
? receivedMessageListCount + 1
: receivedMessageListCount;
final haveTimeStampMessage = widget.messageList[receivedMessageListCount]?.elemType == 11;
final endPoint = haveTimeStampMessage ? receivedMessageListCount + 1 : receivedMessageListCount;
return widget.messageList.sublist(0, endPoint).reversed.toList();
}
@ -333,19 +316,14 @@ class _TIMUIKitHistoryMessageListState
final receivedNewMessageList = globalModel.receivedMessageListCount;
final shouldShowUnreadMessage = receivedNewMessageList > 0;
final unreadMessageList = _getReceivedMessageList(receivedNewMessageList);
final readMessageList = messageList
.sublist(unreadMessageList.length, messageList.length)
.toList();
final readMessageList = messageList.sublist(unreadMessageList.length, messageList.length).toList();
final throttleFunction =
OptimizeUtils.multiThrottle((index, LoadDirection direction) async {
final msgID =
TIMUIKitChatUtils.getMessageIDWithinIndex(readMessageList, index);
final throttleFunction = OptimizeUtils.multiThrottle((index, LoadDirection direction) async {
final msgID = TIMUIKitChatUtils.getMessageIDWithinIndex(readMessageList, index);
await widget.onLoadMore(msgID, direction);
}, 20);
final throttleFunctionWithMsgID =
OptimizeUtils.multiThrottle((msgID, LoadDirection direction) async {
final throttleFunctionWithMsgID = OptimizeUtils.multiThrottle((msgID, LoadDirection direction) async {
await widget.onLoadMore(msgID, direction);
}, 200);
@ -368,63 +346,43 @@ class _TIMUIKitHistoryMessageListState
center: shouldShowUnreadMessage ? centerKey : null,
key: widget.mainHistoryListConfig?.key,
primary: widget.mainHistoryListConfig?.primary,
physics: (widget.isAllowScroll == false)
? const NeverScrollableScrollPhysics()
: widget.mainHistoryListConfig?.physics,
physics: (widget.isAllowScroll == false) ? const NeverScrollableScrollPhysics() : widget.mainHistoryListConfig?.physics,
// padding: widget.mainHistoryListConfig?.padding ?? EdgeInsets.zero,
// itemExtent: widget.mainHistoryListConfig?.itemExtent,
// prototypeItem: widget.mainHistoryListConfig?.prototypeItem,
cacheExtent: widget.mainHistoryListConfig?.cacheExtent ?? 1500,
semanticChildCount:
widget.mainHistoryListConfig?.semanticChildCount,
dragStartBehavior:
widget.mainHistoryListConfig?.dragStartBehavior ??
DragStartBehavior.start,
keyboardDismissBehavior:
widget.mainHistoryListConfig?.keyboardDismissBehavior ??
ScrollViewKeyboardDismissBehavior.manual,
semanticChildCount: widget.mainHistoryListConfig?.semanticChildCount,
dragStartBehavior: widget.mainHistoryListConfig?.dragStartBehavior ?? DragStartBehavior.start,
keyboardDismissBehavior: widget.mainHistoryListConfig?.keyboardDismissBehavior ?? ScrollViewKeyboardDismissBehavior.manual,
restorationId: widget.mainHistoryListConfig?.restorationId,
clipBehavior:
widget.mainHistoryListConfig?.clipBehavior ?? Clip.hardEdge,
clipBehavior: widget.mainHistoryListConfig?.clipBehavior ?? Clip.hardEdge,
reverse: true,
shrinkWrap: !shouldShowUnreadMessage,
controller: _autoScrollController,
slivers: [
SliverPadding(
padding:
widget.mainHistoryListConfig?.padding ?? EdgeInsets.zero,
padding: widget.mainHistoryListConfig?.padding ?? EdgeInsets.zero,
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
final messageItem = unreadMessageList[index];
if (index == unreadMessageList.length - 1 &&
widget.model.haveMoreLatestData == true) {
throttleFunctionWithMsgID(
messageItem?.msgID ?? "",
LoadDirection.latest);
if (index == unreadMessageList.length - 1 && widget.model.haveMoreLatestData == true) {
throttleFunctionWithMsgID(messageItem?.msgID ?? "", LoadDirection.latest);
}
outputLogger.i("Rendering a unread message: ${getMessageIdentifier(messageItem, 0)}, message Type: ${messageItem?.elemType}");
return AutoScrollTag(
controller: _autoScrollController,
index: -index,
key: ValueKey(
getMessageIdentifier(messageItem, index)),
key: ValueKey(getMessageIdentifier(messageItem, index)),
highlightColor: Colors.black.withOpacity(0.1),
child: KeepAliveWrapper(
keepAlive: messageItem?.elemType ==
MessageElemType.V2TIM_ELEM_TYPE_SOUND,
child: Container(
child:
_getMessageItemBuilder(messageItem))),
child: KeepAliveWrapper(keepAlive: messageItem?.elemType == MessageElemType.V2TIM_ELEM_TYPE_SOUND, child: Container(child: _getMessageItemBuilder(messageItem))),
);
},
childCount: unreadMessageList.length,
findChildIndexCallback: (Key key) {
final ValueKey<String> valueKey =
key as ValueKey<String>;
final ValueKey<String> valueKey = key as ValueKey<String>;
final String data = valueKey.value;
final int index = unreadMessageList.indexWhere(
(element) =>
getMessageIdentifier(element, 0) == data);
final int index = unreadMessageList.indexWhere((element) => getMessageIdentifier(element, 0) == data);
return index != -1 ? index : null;
})),
),
@ -433,8 +391,7 @@ class _TIMUIKitHistoryMessageListState
key: centerKey,
),
SliverPadding(
padding:
widget.mainHistoryListConfig?.padding ?? EdgeInsets.zero,
padding: widget.mainHistoryListConfig?.padding ?? EdgeInsets.zero,
sliver: Selector<TUIChatSeparateViewModel, bool>(
selector: (context, model) {
return model.haveMoreData;
@ -449,64 +406,41 @@ class _TIMUIKitHistoryMessageListState
final messageItem = readMessageList[index];
if (index == readMessageList.length - 1) {
if (haveMoreData) {
throttleFunction(
index, LoadDirection.previous);
throttleFunction(index, LoadDirection.previous);
return Column(
children: [
LoadingAnimationWidget
.staggeredDotsWave(
color: theme.weakTextColor ??
Colors.grey,
LoadingAnimationWidget.staggeredDotsWave(
color: theme.weakTextColor ?? Colors.grey,
size: 28,
),
AutoScrollTag(
controller: _autoScrollController,
index: -index,
key: ValueKey(getMessageIdentifier(
messageItem, index)),
highlightColor:
Colors.black.withOpacity(0.1),
child: KeepAliveWrapper(
keepAlive: messageItem
?.elemType ==
MessageElemType
.V2TIM_ELEM_TYPE_SOUND,
child: Container(
child: _getMessageItemBuilder(
messageItem))),
key: ValueKey(getMessageIdentifier(messageItem, index)),
highlightColor: Colors.black.withOpacity(0.1),
child: KeepAliveWrapper(keepAlive: messageItem?.elemType == MessageElemType.V2TIM_ELEM_TYPE_SOUND, child: Container(child: _getMessageItemBuilder(messageItem))),
),
],
);
}
}
if (index == 0 &&
widget.model.haveMoreLatestData == true &&
globalModel.receivedMessageListCount < 10) {
if (index == 0 && widget.model.haveMoreLatestData == true && globalModel.receivedMessageListCount < 10) {
throttleFunction(index, LoadDirection.latest);
}
outputLogger.i("Rendering a read message: ${getMessageIdentifier(messageItem, 0)}, message Type: ${messageItem?.elemType}");
return AutoScrollTag(
controller: _autoScrollController,
index: -index,
key: ValueKey(
getMessageIdentifier(messageItem, index)),
key: ValueKey(getMessageIdentifier(messageItem, index)),
highlightColor: Colors.black.withOpacity(0.1),
child: KeepAliveWrapper(
keepAlive: messageItem?.elemType ==
MessageElemType.V2TIM_ELEM_TYPE_SOUND,
child: Container(
child: _getMessageItemBuilder(
messageItem))),
child: KeepAliveWrapper(keepAlive: messageItem?.elemType == MessageElemType.V2TIM_ELEM_TYPE_SOUND, child: Container(child: _getMessageItemBuilder(messageItem))),
);
},
childCount: readMessageList.length,
findChildIndexCallback: (Key key) {
final ValueKey<String> valueKey =
key as ValueKey<String>;
final ValueKey<String> valueKey = key as ValueKey<String>;
final String data = valueKey.value;
final int index = readMessageList.indexWhere(
(element) =>
getMessageIdentifier(element, 0) ==
data);
final int index = readMessageList.indexWhere((element) => getMessageIdentifier(element, 0) == data);
return index > -1 ? index : null;
}));
},
@ -539,17 +473,14 @@ class TIMUIKitHistoryMessageListSelector extends TIMUIKitStatelessWidget {
final Widget Function(BuildContext, List<V2TimMessage?>, Widget?) builder;
final String conversationID;
TIMUIKitHistoryMessageListSelector(
{Key? key, required this.builder, required this.conversationID})
: super(key: key);
TIMUIKitHistoryMessageListSelector({Key? key, required this.builder, required this.conversationID}) : super(key: key);
@override
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
return Selector<TUIChatGlobalModel, List<V2TimMessage?>>(
builder: builder,
shouldRebuild: (previous, next) {
final isEquals =
const DeepCollectionEquality.unordered().equals(previous, next);
final isEquals = const DeepCollectionEquality.unordered().equals(previous, next);
return !isEquals;
},
selector: (context, model) {

View File

@ -1,26 +1,27 @@
import 'dart:async';
import 'dart:math';
import 'package:collection/collection.dart';
import 'package:diff_match_patch/diff_match_patch.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_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/emoji_text.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field_layout/narrow.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:collection/collection.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_state.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_conversation_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/business_logic/view_models/tui_setting_model.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/ui/utils/message.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/emoji_text.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_at_text.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field_layout/narrow.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field_layout/wide.dart';
enum MuteStatus { none, me, all }
@ -141,8 +142,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
double inputWidth = 900;
Map<String, V2TimGroupMemberFullInfo> mentionedMembersMap = {};
late TextEditingController textEditingController;
final TUIConversationViewModel conversationModel =
serviceLocator<TUIConversationViewModel>();
final TUIConversationViewModel conversationModel = serviceLocator<TUIConversationViewModel>();
final TUISelfInfoViewModel selfModel = serviceLocator<TUISelfInfoViewModel>();
MuteStatus muteStatus = MuteStatus.none;
bool _isComposingText = false;
@ -154,56 +154,38 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
// Keep using original scheme.
return;
}
final stickerConfig =
widget.model.chatConfig.stickerPanelConfig ?? StickerPanelConfig();
final stickerConfig = widget.model.chatConfig.stickerPanelConfig ?? StickerPanelConfig();
if (stickerConfig.useTencentCloudChatStickerPackage) {
final tccEmojiSet = TUIKitStickerConstData.emojiList
.firstWhere((element) => element.name == "tcc1");
final tccEmojiSet = TUIKitStickerConstData.emojiList.firstWhere((element) => element.name == "tcc1");
stickerPackageList.add(CustomStickerPackage(
name: tccEmojiSet.name,
baseUrl: "assets/custom_face_resource/${tccEmojiSet.name}",
isEmoji: tccEmojiSet.isEmoji,
isDefaultEmoji: true,
stickerList: tccEmojiSet.list
.asMap()
.keys
.map((idx) =>
CustomSticker(index: idx, name: tccEmojiSet.list[idx]))
.toList(),
stickerList: tccEmojiSet.list.asMap().keys.map((idx) => CustomSticker(index: idx, name: tccEmojiSet.list[idx])).toList(),
menuItem: CustomSticker(
index: 0,
name: tccEmojiSet.icon,
)));
}
if (stickerConfig.useQQStickerPackage) {
final qqEmojiSet = TUIKitStickerConstData.emojiList
.firstWhere((element) => element.name == "4349");
final qqEmojiSet = TUIKitStickerConstData.emojiList.firstWhere((element) => element.name == "4349");
stickerPackageList.add(CustomStickerPackage(
name: qqEmojiSet.name,
baseUrl: "assets/custom_face_resource/${qqEmojiSet.name}",
isEmoji: qqEmojiSet.isEmoji,
isDefaultEmoji: true,
stickerList: qqEmojiSet.list
.asMap()
.keys
.map((idx) =>
CustomSticker(index: idx, name: qqEmojiSet.list[idx]))
.toList(),
stickerList: qqEmojiSet.list.asMap().keys.map((idx) => CustomSticker(index: idx, name: qqEmojiSet.list[idx])).toList(),
menuItem: CustomSticker(
index: 0,
name: qqEmojiSet.icon,
)));
}
if (stickerConfig.unicodeEmojiList.isNotEmpty) {
final defEmojiList =
TUIKitStickerConstData.defaultUnicodeEmojiList.map((emojiItem) {
return CustomSticker(
index: 0, name: emojiItem.toString(), unicode: emojiItem);
final defEmojiList = TUIKitStickerConstData.defaultUnicodeEmojiList.map((emojiItem) {
return CustomSticker(index: 0, name: emojiItem.toString(), unicode: emojiItem);
}).toList();
stickerPackageList.add(CustomStickerPackage(
name: "defaultEmoji",
stickerList: defEmojiList,
menuItem: defEmojiList[0]));
stickerPackageList.add(CustomStickerPackage(name: "defaultEmoji", stickerList: defEmojiList, menuItem: defEmojiList[0]));
}
stickerPackageList.addAll(stickerConfig.customStickerPackages);
@ -253,9 +235,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
textEditingController.text = text;
if (TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop) {
textEditingController.selection = TextSelection.fromPosition(
TextPosition(
offset: currentCursor ?? textEditingController.text.length));
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: currentCursor ?? textEditingController.text.length));
focusNode.requestFocus();
}
}
@ -263,9 +243,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
void addStickerToText(String sticker) {
final currentText = textEditingController.text;
if (currentCursor != null &&
currentCursor! > -1 &&
currentCursor! < currentText.length + 1) {
if (currentCursor != null && currentCursor! > -1 && currentCursor! < currentText.length + 1) {
final firstString = currentText.substring(0, currentCursor);
final secondString = currentText.substring(currentCursor!);
currentCursor = currentCursor! + sticker.length;
@ -276,8 +254,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
if (TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop) {
textEditingController.selection = TextSelection.fromPosition(TextPosition(
offset: currentCursor ?? textEditingController.text.length));
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: currentCursor ?? textEditingController.text.length));
focusNode.requestFocus();
}
}
@ -286,23 +263,13 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
return text.replaceAll(RegExp(r'\ufeff'), "");
}
Future handleSetDraftText(
{String? id, ConvType? convType, String? groupID}) async {
Future handleSetDraftText({String? id, ConvType? convType, String? groupID}) async {
String text = textEditingController.text;
String convID = id ?? widget.conversationID;
final isTopic = convID.contains("@TOPIC#");
String conversationID = isTopic
? convID
: ((convType ?? widget.conversationType) == ConvType.c2c
? "c2c_$convID"
: "group_$convID");
String conversationID = isTopic ? convID : ((convType ?? widget.conversationType) == ConvType.c2c ? "c2c_$convID" : "group_$convID");
String draftText = _filterU200b(text);
return await conversationModel.setConversationDraft(
groupID: groupID ?? widget.groupID,
isTopic: isTopic,
isAllowWeb: widget.model.chatConfig.isUseDraftOnWeb,
conversationID: conversationID,
draftText: draftText);
return await conversationModel.setConversationDraft(groupID: groupID ?? widget.groupID, isTopic: isTopic, isAllowWeb: widget.model.chatConfig.isUseDraftOnWeb, conversationID: conversationID, draftText: draftText);
}
// onSubmitted一样
@ -350,21 +317,9 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
if (widget.model.repliedMessage != null) {
MessageUtils.handleMessageError(
widget.model.sendFaceMessage(
index: index,
data: data,
convID: widget.conversationID,
convType: convType),
context);
MessageUtils.handleMessageError(widget.model.sendFaceMessage(index: index, data: data, convID: widget.conversationID, convType: convType), context);
} else {
MessageUtils.handleMessageError(
widget.model.sendFaceMessage(
index: index,
data: data,
convID: widget.conversationID,
convType: convType),
context);
MessageUtils.handleMessageError(widget.model.sendFaceMessage(index: index, data: data, convID: widget.conversationID, convType: convType), context);
}
}
@ -384,24 +339,11 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
final convType = widget.conversationType;
if (text.isNotEmpty && text != zeroWidthSpace) {
if (widget.model.repliedMessage != null) {
MessageUtils.handleMessageError(
widget.model.sendReplyMessage(
text: text,
convID: widget.conversationID,
convType: convType,
atUserIDList: getUserIdFromMemberInfoMap()),
context);
MessageUtils.handleMessageError(widget.model.sendReplyMessage(text: text, convID: widget.conversationID, convType: convType, atUserIDList: getUserIdFromMemberInfoMap()), context);
} else if (mentionedMembersMap.isNotEmpty) {
widget.model.sendTextAtMessage(
text: text,
convType: widget.conversationType,
convID: widget.conversationID,
atUserList: getUserIdFromMemberInfoMap());
widget.model.sendTextAtMessage(text: text, convType: widget.conversationType, convID: widget.conversationID, atUserList: getUserIdFromMemberInfoMap());
} else {
MessageUtils.handleMessageError(
widget.model.sendTextMessage(
text: text, convID: widget.conversationID, convType: convType),
context);
MessageUtils.handleMessageError(widget.model.sendTextMessage(text: text, convID: widget.conversationID, convType: convType), context);
}
textEditingController.clear();
currentCursor = null;
@ -414,8 +356,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
void goDownBottom() {
if (globalModel.getMessageListPosition(widget.conversationID) ==
HistoryMessagePosition.notShowLatest) {
if (globalModel.getMessageListPosition(widget.conversationID) == HistoryMessagePosition.notShowLatest) {
return;
}
Future.delayed(const Duration(milliseconds: 50), () {
@ -444,18 +385,14 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
String _getShowName(V2TimGroupMemberFullInfo? item) {
return TencentUtils.checkStringWithoutSpace(item?.nameCard) ??
TencentUtils.checkStringWithoutSpace(item?.nickName) ??
TencentUtils.checkStringWithoutSpace(item?.userID) ??
"";
return TencentUtils.checkStringWithoutSpace(item?.nameCard) ?? TencentUtils.checkStringWithoutSpace(item?.nickName) ?? TencentUtils.checkStringWithoutSpace(item?.userID) ?? "";
}
mentionMemberInMessage(String? userID, String? nickName) {
if (TencentUtils.checkString(userID) == null) {
focusNode.requestFocus();
} else {
final memberInfo = widget.model.groupMemberList
?.firstWhereOrNull((element) => element?.userID == userID) ??
final memberInfo = widget.model.groupMemberList?.firstWhereOrNull((element) => element?.userID == userID) ??
V2TimGroupMemberFullInfo(
userID: userID ?? "",
nickName: nickName,
@ -466,8 +403,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
//please do not delete space
focusNode.requestFocus();
textEditingController.text = text;
textEditingController.selection =
TextSelection.fromPosition(TextPosition(offset: text.length));
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: text.length));
lastText = text;
_isComposingText = false;
narrowTextFieldKey.currentState?.showKeyboard = true;
@ -495,16 +431,10 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
maxLines: null,
);
textPainter.layout(maxWidth: inputWidth);
final TextPosition lastLineOffset = textPainter
.getPositionForOffset(Offset(textPainter.width, textPainter.height));
final Offset caretPosition =
textPainter.getOffsetForCaret(lastLineOffset, Rect.zero);
final TextPosition lastLineOffset = textPainter.getPositionForOffset(Offset(textPainter.width, textPainter.height));
final Offset caretPosition = textPainter.getOffsetForCaret(lastLineOffset, Rect.zero);
final dx = min(inputWidth - 180, caretPosition.dx + 16);
final dy = max(
24,
21 * widget.model.chatConfig.desktopMessageInputFieldLines -
caretPosition.dy)
.toDouble();
final dy = max(24, 21 * widget.model.chatConfig.desktopMessageInputFieldLines - caretPosition.dy).toDouble();
return Offset(dx, dy);
}
@ -541,19 +471,13 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
mentionedMembersMap = map;
}
(int, String, bool)? findChangedCharacter(
String originalString, String newString) {
(int, String, bool)? findChangedCharacter(String originalString, String newString) {
if (newString.length < originalString.length) {
final originalStringLength = originalString.length;
final newStringLength = newString.length;
for (int i = 0; i < newString.length; ++i) {
if (originalString[originalStringLength - i - 1] !=
newString[newStringLength - i - 1]) {
return (
newStringLength - i,
originalString[originalStringLength - i - 1],
false
);
if (originalString[originalStringLength - i - 1] != newString[newStringLength - i - 1]) {
return (newStringLength - i, originalString[originalStringLength - i - 1], false);
}
}
return (newString.length, originalString[newString.length], false);
@ -572,11 +496,8 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
_handleAtText(String text, TUIChatSeparateViewModel model) async {
final text = textEditingController.text;
final String originalText = lastText;
String? groupID = widget.conversationType == ConvType.group
? widget.conversationID
: null;
final isDesktopScreen =
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
String? groupID = widget.conversationType == ConvType.group ? widget.conversationID : null;
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
if (groupID == null) {
lastText = text;
@ -596,11 +517,9 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
String atTag = originalText.substring(atIndex, spaceIndex);
String deletedChar = originalText[diffIndex];
if (shouldRemoveAtTag(atTag, deletedChar)) {
final newText = originalText.substring(0, atIndex) +
originalText.substring(spaceIndex + 1);
final newText = originalText.substring(0, atIndex) + originalText.substring(spaceIndex + 1);
textEditingController.text = newText;
textEditingController.selection =
TextSelection.collapsed(offset: atIndex);
textEditingController.selection = TextSelection.collapsed(offset: atIndex);
lastText = newText;
updateMentionedMap();
return;
@ -610,13 +529,10 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
final int selfRole = widget.model.selfMemberInfo?.role ?? 0;
final bool canAtAll =
(selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN ||
selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
final bool canAtAll = (selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN || selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
if (isDesktopScreen) {
(int, String, bool)? changedCharacterRecord =
findChangedCharacter(originalText, text);
(int, String, bool)? changedCharacterRecord = findChangedCharacter(originalText, text);
int? changedTextPosition = changedCharacterRecord?.$1;
String? changedCharacter = changedCharacterRecord?.$2;
bool isAdded = changedCharacterRecord?.$3 ?? false;
@ -625,13 +541,10 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
int? atPlace;
if (changedTextPosition != null) {
subText = isAdded == true
? text.substring(0, changedTextPosition + 1)
: text.substring(0, changedTextPosition);
subText = isAdded == true ? text.substring(0, changedTextPosition + 1) : text.substring(0, changedTextPosition);
atPlace = subText.lastIndexOf('@');
if (atPlace != -1) {
keyword = text.substring(
atPlace + 1, changedTextPosition + (isAdded ? 1 : 0));
keyword = text.substring(atPlace + 1, changedTextPosition + (isAdded ? 1 : 0));
}
} else {
atPlace = -1;
@ -644,28 +557,21 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
model.atPositionY = atPosition.dy;
isAddingAtSearchWords = true;
}
List<V2TimGroupMemberFullInfo> showAtMemberList = (model
.groupMemberList ??
[])
List<V2TimGroupMemberFullInfo> showAtMemberList = (model.groupMemberList ?? [])
.where((element) {
final showName = (TencentUtils.checkStringWithoutSpace(
element?.friendRemark) ??
final showName = (TencentUtils.checkStringWithoutSpace(element?.friendRemark) ??
TencentUtils.checkStringWithoutSpace(element?.nameCard) ??
TencentUtils.checkStringWithoutSpace(element?.nickName) ??
TencentUtils.checkStringWithoutSpace(element?.userID) ??
"")
.toLowerCase();
keyword ??= "";
return element != null &&
showName.contains(keyword!.toLowerCase()) &&
TencentUtils.checkString(showName) != null &&
element.userID != widget.model.selfMemberInfo?.userID;
return element != null && showName.contains(keyword!.toLowerCase()) && TencentUtils.checkString(showName) != null && element.userID != widget.model.selfMemberInfo?.userID;
})
.whereType<V2TimGroupMemberFullInfo>()
.toList();
showAtMemberList.sort(
(V2TimGroupMemberFullInfo userA, V2TimGroupMemberFullInfo userB) {
showAtMemberList.sort((V2TimGroupMemberFullInfo userA, V2TimGroupMemberFullInfo userB) {
final isUserAIsGroupAdmin = userA.role == 300;
final isUserAIsGroupOwner = userA.role == 400;
@ -688,11 +594,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
keyword ??= "";
if (canAtAll && showAtMemberList.isNotEmpty && keyword!.isEmpty) {
showAtMemberList = [
V2TimGroupMemberFullInfo(
userID: "__kImSDK_MesssageAtALL__", nickName: TIM_t("所有人")),
...showAtMemberList
];
showAtMemberList = [V2TimGroupMemberFullInfo(userID: "__kImSDK_MesssageAtALL__", nickName: TIM_t("所有人")), ...showAtMemberList];
}
model.activeAtIndex = 0;
@ -704,18 +606,11 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
model.showAtMemberList = [];
isAddingAtSearchWords = false;
}
} else if (textLength > 0 &&
text[textLength - 1] == "@" &&
lastText.length < textLength) {
} else if (textLength > 0 && text[textLength - 1] == "@" && lastText.length < textLength) {
V2TimGroupMemberFullInfo? memberInfo = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AtText(
groupMemberList: model.groupMemberList,
groupInfo: model.groupInfo,
groupID: groupID,
canAtAll: canAtAll,
groupType: widget.groupType),
builder: (context) => AtText(groupMemberList: model.groupMemberList, groupInfo: model.groupInfo, groupID: groupID, canAtAll: canAtAll, groupType: widget.groupType),
),
);
final showName = _getShowName(memberInfo);
@ -730,22 +625,17 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
void replaceAtTag(String selectedMember) {
int cursorPosition = textEditingController.selection.baseOffset;
int atIndex =
textEditingController.text.lastIndexOf('@', cursorPosition - 1);
int atIndex = textEditingController.text.lastIndexOf('@', cursorPosition - 1);
if (atIndex >= 0) {
String beforeAt = textEditingController.text.substring(0, atIndex);
String afterAt = textEditingController.text.substring(cursorPosition);
textEditingController.text =
beforeAt + '@' + selectedMember + ' ' + afterAt;
textEditingController.selection =
TextSelection.collapsed(offset: atIndex + selectedMember.length + 2);
textEditingController.text = beforeAt + '@' + selectedMember + ' ' + afterAt;
textEditingController.selection = TextSelection.collapsed(offset: atIndex + selectedMember.length + 2);
lastText = beforeAt + '@' + selectedMember + ' ' + afterAt;
}
}
void handleAtMember(
{V2TimGroupMemberFullInfo? memberInfo,
bool? isAddToCursorPosition = false}) {
void handleAtMember({V2TimGroupMemberFullInfo? memberInfo, bool? isAddToCursorPosition = false}) {
if (memberInfo != null) {
final String showName = _getShowName(memberInfo);
mentionedMembersMap["@$showName"] = memberInfo;
@ -759,24 +649,17 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
KeyEventResult handleDesktopKeyEvent(FocusNode node, RawKeyEvent event) {
final activeIndex = widget.model.activeAtIndex;
final showMemberList = widget.model.showAtMemberList;
final isPressEnter = (event.physicalKey == PhysicalKeyboardKey.enter) ||
(event.physicalKey == PhysicalKeyboardKey.numpadEnter);
final isPressEnter = (event.physicalKey == PhysicalKeyboardKey.enter) || (event.physicalKey == PhysicalKeyboardKey.numpadEnter);
if (event.runtimeType == RawKeyDownEvent) {
if (event.physicalKey == PhysicalKeyboardKey.backspace) {
if (textEditingController.text.isEmpty && lastText.isEmpty) {
widget.model.repliedMessage = null;
return KeyEventResult.handled;
}
} else if ((event.isShiftPressed ||
event.isAltPressed ||
event.isControlPressed ||
event.isMetaPressed) &&
isPressEnter) {
} else if ((event.isShiftPressed || event.isAltPressed || event.isControlPressed || event.isMetaPressed) && isPressEnter) {
final offset = textEditingController.selection.baseOffset;
textEditingController.text =
'${lastText.substring(0, offset)}\n${lastText.substring(offset)}';
textEditingController.selection =
TextSelection.fromPosition(TextPosition(offset: offset + 1));
textEditingController.text = '${lastText.substring(0, offset)}\n${lastText.substring(offset)}';
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: offset + 1));
lastText = textEditingController.text;
return KeyEventResult.handled;
@ -786,34 +669,26 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
onSubmitted();
} else {
isAddingAtSearchWords = false;
final V2TimGroupMemberFullInfo? memberInfo =
showMemberList[activeIndex];
final V2TimGroupMemberFullInfo? memberInfo = showMemberList[activeIndex];
if (memberInfo != null) {
handleAtMember(
memberInfo: memberInfo, isAddToCursorPosition: true);
handleAtMember(memberInfo: memberInfo, isAddToCursorPosition: true);
}
}
return KeyEventResult.handled;
}
}
if (event.isKeyPressed(LogicalKeyboardKey.arrowUp) &&
isAddingAtSearchWords &&
showMemberList.isNotEmpty) {
if (event.isKeyPressed(LogicalKeyboardKey.arrowUp) && isAddingAtSearchWords && showMemberList.isNotEmpty) {
final newIndex = max(activeIndex - 1, 0);
widget.model.activeAtIndex = newIndex;
widget.atMemberPanelScroll?.scrollToIndex(newIndex,
preferPosition: AutoScrollPosition.middle);
widget.atMemberPanelScroll?.scrollToIndex(newIndex, preferPosition: AutoScrollPosition.middle);
return KeyEventResult.handled;
}
if (event.isKeyPressed(LogicalKeyboardKey.arrowDown) &&
isAddingAtSearchWords &&
showMemberList.isNotEmpty) {
if (event.isKeyPressed(LogicalKeyboardKey.arrowDown) && isAddingAtSearchWords && showMemberList.isNotEmpty) {
final newIndex = min(activeIndex + 1, showMemberList.length - 1);
widget.model.activeAtIndex = newIndex;
widget.atMemberPanelScroll?.scrollToIndex(newIndex,
preferPosition: AutoScrollPosition.middle);
widget.atMemberPanelScroll?.scrollToIndex(newIndex, preferPosition: AutoScrollPosition.middle);
return KeyEventResult.handled;
}
}
@ -831,8 +706,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
} else {
focusNode = FocusNode();
}
textEditingController =
widget.controller?.textEditingController ?? TextEditingController();
textEditingController = widget.controller?.textEditingController ?? TextEditingController();
if (widget.initText != null) {
textEditingController.text = widget.initText!;
}
@ -840,10 +714,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
widget.controller?.addListener(controllerHandler);
}
final AppLocale appLocale = I18nUtils.findDeviceLocale(null);
languageType =
(appLocale == AppLocale.zhHans || appLocale == AppLocale.zhHant)
? 'zh'
: 'en';
languageType = (appLocale == AppLocale.zhHans || appLocale == AppLocale.zhHant) ? 'zh' : 'en';
textEditingController.addListener(() {
_isComposingText = textEditingController.value.composing.start != -1;
});
@ -853,13 +724,11 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
controllerHandler() {
final actionType = widget.controller?.actionType;
if (actionType == ActionType.longPressToAt) {
mentionMemberInMessage(
widget.controller?.atUserID, widget.controller?.atUserName);
mentionMemberInMessage(widget.controller?.atUserID, widget.controller?.atUserName);
} else if (actionType == ActionType.setTextField) {
final newText = widget.controller?.inputText ?? "";
textEditingController.text = newText;
textEditingController.selection = TextSelection.fromPosition(
TextPosition(offset: textEditingController.text.length));
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: textEditingController.text.length));
lastText = textEditingController.text;
focusNode.requestFocus();
return;
@ -877,18 +746,14 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
super.didUpdateWidget(oldWidget);
if (widget.conversationID != oldWidget.conversationID) {
mentionedMembersMap.clear();
handleSetDraftText(
id: oldWidget.conversationID,
convType: oldWidget.conversationType,
groupID: oldWidget.groupID);
handleSetDraftText(id: oldWidget.conversationID, convType: oldWidget.conversationType, groupID: oldWidget.groupID);
if (oldWidget.initText != widget.initText) {
textEditingController.text = widget.initText ?? "";
} else {
textEditingController.clear();
}
}
if (widget.initText != oldWidget.initText &&
TencentUtils.checkString(widget.initText) != null) {
if (widget.initText != oldWidget.initText && TencentUtils.checkString(widget.initText) != null) {
textEditingController.text = widget.initText!;
focusNode.requestFocus();
}
@ -906,12 +771,8 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
Future<bool> getMemberMuteStatus(String userID) async {
// Get the mute state of the members recursively
if (widget.model.groupMemberList?.any((item) => (item?.userID == userID)) ??
false) {
final int muteUntil = widget.model.groupMemberList
?.firstWhere((item) => (item?.userID == userID))
?.muteUntil ??
0;
if (widget.model.groupMemberList?.any((item) => (item?.userID == userID)) ?? false) {
final int muteUntil = widget.model.groupMemberList?.firstWhere((item) => (item?.userID == userID))?.muteUntil ?? 0;
return muteUntil * 1000 > DateTime.now().millisecondsSinceEpoch;
} else {
return false;
@ -924,42 +785,28 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
final int selfRole = widget.model.selfMemberInfo?.role ?? 0;
final bool willNotBeenMuted =
(selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN ||
selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
final bool willNotBeenMuted = (selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN || selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
if (widget.conversationType == ConvType.group && !willNotBeenMuted) {
if ((model.groupInfo?.isAllMuted ?? false) &&
muteStatus != MuteStatus.all) {
if ((model.groupInfo?.isAllMuted ?? false) && muteStatus != MuteStatus.all) {
Future.delayed(const Duration(seconds: 0), () {
setState(() {
muteStatus = MuteStatus.all;
});
});
} else if (selfModel.loginInfo?.userID != null &&
await getMemberMuteStatus(selfModel.loginInfo!.userID!) &&
muteStatus != MuteStatus.me) {
} else if (selfModel.loginInfo?.userID != null && await getMemberMuteStatus(selfModel.loginInfo!.userID!) && muteStatus != MuteStatus.me) {
Future.delayed(const Duration(seconds: 0), () {
setState(() {
muteStatus = MuteStatus.me;
});
});
} else if (!(model.groupInfo?.isAllMuted ?? false) &&
!(selfModel.loginInfo?.userID != null &&
await getMemberMuteStatus(selfModel.loginInfo!.userID!)) &&
muteStatus != MuteStatus.none) {
} else if (!(model.groupInfo?.isAllMuted ?? false) && !(selfModel.loginInfo?.userID != null && await getMemberMuteStatus(selfModel.loginInfo!.userID!)) && muteStatus != MuteStatus.none) {
Future.delayed(const Duration(seconds: 0), () {
setState(() {
muteStatus = MuteStatus.none;
});
});
}
} else {
Future.delayed(const Duration(seconds: 0), () {
setState(() {
muteStatus = MuteStatus.none;
});
});
}
}
@ -982,8 +829,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
@override
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
final theme = value.theme;
final TUIChatSeparateViewModel model =
Provider.of<TUIChatSeparateViewModel>(context);
final TUIChatSeparateViewModel model = Provider.of<TUIChatSeparateViewModel>(context);
_getMuteType(model);
@ -1003,8 +849,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
final forbiddenText = getForbiddenText();
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
inputWidth = constraints.maxWidth;
return TUIKitScreenUtils.getDeviceWidget(
context: context,

View File

@ -1,18 +1,18 @@
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_im_base/tencent_im_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/business_logic/separate_models/tui_group_profile_model.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/contact_list.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
GlobalKey<_AddGroupMemberPageState> addGroupMemberKey = GlobalKey();
class AddGroupMemberPage extends StatefulWidget {
final TUIGroupProfileModel model;
final VoidCallback? onClose;
const AddGroupMemberPage({Key? key, required this.model}) : super(key: key);
const AddGroupMemberPage({Key? key, required this.model, this.onClose}) : super(key: key);
@override
State<StatefulWidget> createState() => _AddGroupMemberPageState();
@ -25,7 +25,7 @@ class _AddGroupMemberPageState extends TIMUIKitState<AddGroupMemberPage> {
if (selectedContacts.isNotEmpty) {
final userIDs = selectedContacts.map((e) => e.userID).toList();
await widget.model.inviteUserToGroup(userIDs);
Navigator.pop(context);
widget.onClose ?? Navigator.pop(context);
}
}
@ -68,8 +68,7 @@ class _AddGroupMemberPageState extends TIMUIKitState<AddGroupMemberPage> {
)
],
shadowColor: theme.weakDividerColor,
backgroundColor: theme.appbarBgColor ??
theme.primaryColor,
backgroundColor: theme.appbarBgColor ?? theme.primaryColor,
iconTheme: IconThemeData(
color: theme.appbarTextColor,
)),

View File

@ -1,20 +1,19 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_im_base/tencent_im_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/business_logic/separate_models/tui_group_profile_model.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/group_member_list.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
GlobalKey<_DeleteGroupMemberPageState> deleteGroupMemberKey = GlobalKey();
class DeleteGroupMemberPage extends StatefulWidget {
final TUIGroupProfileModel model;
final VoidCallback? onClose;
const DeleteGroupMemberPage({Key? key, required this.model})
: super(key: key);
const DeleteGroupMemberPage({Key? key, required this.model, this.onClose}) : super(key: key);
@override
State<StatefulWidget> createState() => _DeleteGroupMemberPageState();
@ -30,11 +29,8 @@ class _DeleteGroupMemberPageState extends TIMUIKitState<DeleteGroupMemberPage> {
handleSearchGroupMembers(String searchText, context) async {
searchText = searchText;
List<V2TimGroupMemberFullInfo?> currentGroupMember =
Provider.of<TUIGroupProfileModel>(context, listen: false)
.groupMemberList;
final res =
await widget.model.searchGroupMember(V2TimGroupMemberSearchParam(
List<V2TimGroupMemberFullInfo?> currentGroupMember = Provider.of<TUIGroupProfileModel>(context, listen: false).groupMemberList;
final res = await widget.model.searchGroupMember(V2TimGroupMemberSearchParam(
keywordList: [searchText],
groupIDList: [widget.model.groupInfo!.groupID],
));
@ -55,25 +51,19 @@ class _DeleteGroupMemberPageState extends TIMUIKitState<DeleteGroupMemberPage> {
currentGroupMember = [];
}
setState(() {
searchMemberList =
isSearchTextExist(searchText) ? currentGroupMember : null;
searchMemberList = isSearchTextExist(searchText) ? currentGroupMember : null;
});
}
handleRole(groupMemberList) {
return groupMemberList
?.where((value) =>
value?.role ==
GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER)
.toList() ??
[];
return groupMemberList?.where((value) => value?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER).toList() ?? [];
}
void submitDelete() async {
if (selectedGroupMember.isNotEmpty) {
final userIDs = selectedGroupMember.map((e) => e.userID).toList();
widget.model.kickOffMember(userIDs);
Navigator.pop(context);
widget.onClose ?? Navigator.pop(context);
}
}
@ -86,8 +76,7 @@ class _DeleteGroupMemberPageState extends TIMUIKitState<DeleteGroupMemberPage> {
desktopWidget: Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: GroupProfileMemberList(
memberList:
handleRole(searchMemberList ?? widget.model.groupMemberList),
memberList: handleRole(searchMemberList ?? widget.model.groupMemberList),
canSelectMember: true,
canSlideDelete: false,
onSelectedMemberChange: (selectedMember) {
@ -115,14 +104,12 @@ class _DeleteGroupMemberPageState extends TIMUIKitState<DeleteGroupMemberPage> {
)
],
shadowColor: theme.weakBackgroundColor,
backgroundColor: theme.appbarBgColor ??
theme.primaryColor,
backgroundColor: theme.appbarBgColor ?? theme.primaryColor,
iconTheme: IconThemeData(
color: theme.appbarTextColor,
)),
body: GroupProfileMemberList(
memberList:
handleRole(searchMemberList ?? widget.model.groupMemberList),
memberList: handleRole(searchMemberList ?? widget.model.groupMemberList),
canSelectMember: true,
canSlideDelete: false,
onSelectedMemberChange: (selectedMember) {

View File

@ -3,17 +3,15 @@
import 'package:dotted_border/dotted_border.dart';
import 'package:flutter/material.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_statelesswidget.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_group_profile_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/tim_uikit_wide_modal_operation_key.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitGroupProfile/group_member/tui_add_group_member.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitGroupProfile/group_member/tui_delete_group_member.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitGroupProfile/group_member/tui_group_member_list.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/wide_popup.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
@ -38,8 +36,7 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
return friendRemark != "" ? friendRemark : showName;
}
List<Widget> _groupMemberListBuilder(List memberList, TUITheme theme,
TUIGroupProfileModel model, int showRange) {
List<Widget> _groupMemberListBuilder(List memberList, TUITheme theme, TUIGroupProfileModel model, int showRange) {
final isDesktopScreen = TUIKitScreenUtils.getFormFactor() == DeviceType.Desktop;
return _getMemberList(memberList, showRange).map((element) {
final faceUrl = element?.faceUrl ?? "";
@ -74,10 +71,7 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
Text(
showName,
textAlign: TextAlign.center,
style: TextStyle(
overflow: TextOverflow.ellipsis,
color: theme.weakTextColor,
fontSize: 10),
style: TextStyle(overflow: TextOverflow.ellipsis, color: theme.weakTextColor, fontSize: 10),
)
],
),
@ -86,21 +80,17 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
}).toList();
}
List<Widget> _inviteMemberBuilder(bool isCanInviteMember,
bool isCanKickOffMember, theme, BuildContext context) {
List<Widget> _inviteMemberBuilder(bool isCanInviteMember, bool isCanKickOffMember, theme, BuildContext context) {
return [];
}
void navigateToMemberList(BuildContext context, TUIGroupProfileModel model,
List<V2TimGroupMemberFullInfo?> memberList) {
final isDesktopScreen =
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
void navigateToMemberList(BuildContext context, TUIGroupProfileModel model, List<V2TimGroupMemberFullInfo?> memberList) {
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
if (!isDesktopScreen) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GroupProfileMemberListPage(
model: model, memberList: memberList),
builder: (context) => GroupProfileMemberListPage(model: model, memberList: memberList),
));
} else {
final option1 = memberList.length.toString();
@ -109,18 +99,15 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
context: context,
width: MediaQuery.of(context).size.width * 0.5,
height: MediaQuery.of(context).size.height * 0.8,
title: TIM_t_para("群成员({{option1}}人)", "群成员($option1人)")(
option1: option1),
child: (onClose) =>
GroupProfileMemberListPage(model: model, memberList: memberList));
title: TIM_t_para("群成员({{option1}}人)", "群成员($option1人)")(option1: option1),
child: (onClose) => GroupProfileMemberListPage(model: model, memberList: memberList));
}
}
@override
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
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 memberAmount = model.groupInfo?.memberCount ?? 0;
final option1 = memberAmount.toString();
@ -144,13 +131,7 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
children: [
Container(
padding: const EdgeInsets.only(bottom: 12),
decoration: isDesktopScreen
? null
: BoxDecoration(
border: Border(
bottom: BorderSide(
color: theme.weakDividerColor ??
CommonColor.weakDividerColor))),
decoration: isDesktopScreen ? null : BoxDecoration(border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))),
child: InkWell(
onTap: () async {
navigateToMemberList(context, model, memberList);
@ -158,18 +139,12 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(TIM_t("群成员"),
style: TextStyle(
color: theme.darkTextColor,
fontSize: isDesktopScreen ? 14 : 16)),
Text(TIM_t("群成员"), style: TextStyle(color: theme.darkTextColor, fontSize: isDesktopScreen ? 14 : 16)),
Row(
children: [
Text(
TIM_t_para("{{option1}}人", "$option1人")(
option1: option1),
style: TextStyle(
color: theme.darkTextColor,
fontSize: isDesktopScreen ? 14 : 16),
TIM_t_para("{{option1}}人", "$option1人")(option1: option1),
style: TextStyle(color: theme.darkTextColor, fontSize: isDesktopScreen ? 14 : 16),
),
Icon(
Icons.keyboard_arrow_right,
@ -188,15 +163,11 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
},
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 1,
color: theme.weakDividerColor ??
CommonColor.weakDividerColor),
border: Border.all(width: 1, color: theme.weakDividerColor ?? CommonColor.weakDividerColor),
borderRadius: const BorderRadius.all(Radius.circular(4)),
),
// height: 30,
padding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
@ -247,6 +218,7 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
},
child: (onClose) => AddGroupMemberPage(
model: model,
onClose: onClose,
key: addGroupMemberKey,
));
} else {
@ -285,11 +257,11 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
title: TIM_t("删除群成员"),
height: 460,
onSubmit: () {
deleteGroupMemberKey.currentState
?.submitDelete();
deleteGroupMemberKey.currentState?.submitDelete();
},
child: (onClose) => DeleteGroupMemberPage(
model: model,
onClose: onClose,
key: deleteGroupMemberKey,
),
);
@ -297,8 +269,7 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
DeleteGroupMemberPage(model: model),
builder: (context) => DeleteGroupMemberPage(model: model),
));
}
},
@ -319,9 +290,7 @@ class GroupMemberTile extends TIMUIKitStatelessWidget {
margin: EdgeInsets.only(top: isDesktopScreen ? 12 : 16),
child: Text(
TIM_t("查看更多群成员"),
style: TextStyle(
color: theme.weakTextColor,
fontSize: isDesktopScreen ? 12 : 14),
style: TextStyle(color: theme.weakTextColor, fontSize: isDesktopScreen ? 12 : 14),
),
),
onTap: () async {

View File

@ -13,12 +13,13 @@ class KeepAliveWrapper extends StatefulWidget {
_KeepAliveWrapperState createState() => _KeepAliveWrapperState();
}
class _KeepAliveWrapperState extends State<KeepAliveWrapper>
with AutomaticKeepAliveClientMixin {
class _KeepAliveWrapperState extends State<KeepAliveWrapper> with AutomaticKeepAliveClientMixin {
@override
Widget build(BuildContext context) {
super.build(context);
return widget.child;
return RepaintBoundary(
child: widget.child,
);
}
@override

View File

@ -1,6 +1,6 @@
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.
version: 2.3.1
version: 2.3.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
repository: https://github.com/TencentCloud/chat-uikit-flutter
documentation: https://comm.qq.com/im/doc/flutter/en/TUIKit/readme.html