diff --git a/CHANGELOG.md b/CHANGELOG.md index add7d22..de4a940 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/lib/business_logic/view_models/tui_chat_global_model.dart b/lib/business_logic/view_models/tui_chat_global_model.dart index da3ddaf..327e6fa 100644 --- a/lib/business_logic/view_models/tui_chat_global_model.dart +++ b/lib/business_logic/view_models/tui_chat_global_model.dart @@ -706,7 +706,6 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass { Future 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) { diff --git a/lib/ui/utils/logger.dart b/lib/ui/utils/logger.dart index 6c3ce30..249c65c 100644 --- a/lib/ui/utils/logger.dart +++ b/lib/ui/utils/logger.dart @@ -42,7 +42,7 @@ class TUIKitOutput extends LogOutput { Future 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; } diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list.dart b/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list.dart index afe222a..29716a6 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list.dart @@ -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 Function(String?, LoadDirection direction, [int?]) - onLoadMore; + final Future Function(String?, LoadDirection direction, [int?]) onLoadMore; /// configuration for list view final TIMUIKitHistoryMessageListConfig? mainHistoryListConfig; @@ -104,8 +105,7 @@ class TIMUIKitHistoryMessageList extends StatefulWidget { State createState() => _TIMUIKitHistoryMessageListState(); } -class _TIMUIKitHistoryMessageListState - extends TIMUIKitState { +class _TIMUIKitHistoryMessageListState extends TIMUIKitState { 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 valueKey = - key as ValueKey; + final ValueKey valueKey = key as ValueKey; 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( 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 valueKey = - key as ValueKey; + final ValueKey valueKey = key as ValueKey; 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, 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>( 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) { diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field.dart index eeb037c..56fe765 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field.dart @@ -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 { double inputWidth = 900; Map mentionedMembersMap = {}; late TextEditingController textEditingController; - final TUIConversationViewModel conversationModel = - serviceLocator(); + final TUIConversationViewModel conversationModel = serviceLocator(); final TUISelfInfoViewModel selfModel = serviceLocator(); MuteStatus muteStatus = MuteStatus.none; bool _isComposingText = false; @@ -154,56 +154,38 @@ class _InputTextFieldState extends TIMUIKitState { // 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 { 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 { 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 { } 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 { 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 { } 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 { 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 { } 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 { } 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 { //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 { 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 { 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 { _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 { 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 { } 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 { 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 { model.atPositionY = atPosition.dy; isAddingAtSearchWords = true; } - List showAtMemberList = (model - .groupMemberList ?? - []) + List 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() .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 { 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 { 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 { 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 { 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 { 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 { } 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 { 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 { 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 { 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 { Future 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 { } 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 { @override Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { final theme = value.theme; - final TUIChatSeparateViewModel model = - Provider.of(context); + final TUIChatSeparateViewModel model = Provider.of(context); _getMuteType(model); @@ -1003,8 +849,7 @@ class _InputTextFieldState extends TIMUIKitState { } 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, diff --git a/lib/ui/views/TIMUIKitGroupProfile/group_member/tui_add_group_member.dart b/lib/ui/views/TIMUIKitGroupProfile/group_member/tui_add_group_member.dart index aeefa6a..016a262 100644 --- a/lib/ui/views/TIMUIKitGroupProfile/group_member/tui_add_group_member.dart +++ b/lib/ui/views/TIMUIKitGroupProfile/group_member/tui_add_group_member.dart @@ -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 createState() => _AddGroupMemberPageState(); @@ -25,7 +25,7 @@ class _AddGroupMemberPageState extends TIMUIKitState { 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 { ) ], shadowColor: theme.weakDividerColor, - backgroundColor: theme.appbarBgColor ?? - theme.primaryColor, + backgroundColor: theme.appbarBgColor ?? theme.primaryColor, iconTheme: IconThemeData( color: theme.appbarTextColor, )), diff --git a/lib/ui/views/TIMUIKitGroupProfile/group_member/tui_delete_group_member.dart b/lib/ui/views/TIMUIKitGroupProfile/group_member/tui_delete_group_member.dart index 36082e6..f7b3387 100644 --- a/lib/ui/views/TIMUIKitGroupProfile/group_member/tui_delete_group_member.dart +++ b/lib/ui/views/TIMUIKitGroupProfile/group_member/tui_delete_group_member.dart @@ -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 createState() => _DeleteGroupMemberPageState(); @@ -30,11 +29,8 @@ class _DeleteGroupMemberPageState extends TIMUIKitState { handleSearchGroupMembers(String searchText, context) async { searchText = searchText; - List currentGroupMember = - Provider.of(context, listen: false) - .groupMemberList; - final res = - await widget.model.searchGroupMember(V2TimGroupMemberSearchParam( + List currentGroupMember = Provider.of(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 { 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 { 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 { ) ], 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) { diff --git a/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_member_tile.dart b/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_member_tile.dart index 6f84e95..d0e34fc 100644 --- a/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_member_tile.dart +++ b/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_member_tile.dart @@ -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 _groupMemberListBuilder(List memberList, TUITheme theme, - TUIGroupProfileModel model, int showRange) { + List _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 _inviteMemberBuilder(bool isCanInviteMember, - bool isCanKickOffMember, theme, BuildContext context) { + List _inviteMemberBuilder(bool isCanInviteMember, bool isCanKickOffMember, theme, BuildContext context) { return []; } - void navigateToMemberList(BuildContext context, TUIGroupProfileModel model, - List memberList) { - final isDesktopScreen = - TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop; + void navigateToMemberList(BuildContext context, TUIGroupProfileModel model, List 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(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 { diff --git a/lib/ui/widgets/keepalive_wrapper.dart b/lib/ui/widgets/keepalive_wrapper.dart index bf39b96..da8f5bf 100644 --- a/lib/ui/widgets/keepalive_wrapper.dart +++ b/lib/ui/widgets/keepalive_wrapper.dart @@ -13,12 +13,13 @@ class KeepAliveWrapper extends StatefulWidget { _KeepAliveWrapperState createState() => _KeepAliveWrapperState(); } -class _KeepAliveWrapperState extends State - with AutomaticKeepAliveClientMixin { +class _KeepAliveWrapperState extends State with AutomaticKeepAliveClientMixin { @override Widget build(BuildContext context) { super.build(context); - return widget.child; + return RepaintBoundary( + child: widget.child, + ); } @override diff --git a/pubspec.yaml b/pubspec.yaml index 7ac157f..adbccea 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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