diff --git a/CHANGELOG.md b/CHANGELOG.md index a744134..8ebf4ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,32 @@ +# 2.5.0 + +## Breaking Changes + +* Migrated to Flutter 3.19. Support for Flutter 3.16 and earlier versions has been discontinued. + +## Notes + +* Starting from Flutter 3.19, it is recommended to apply Flutter's Gradle plugins using Gradle's declarative plugins {} block (also known as the Plugin DSL) ([see details](https://docs.flutter.dev/release/breaking-changes/flutter-gradle-plugin-apply)). +* In line with this, our sample app on the GitHub repo has also been migrated to this new approach. If you'd like to migrate to this new approach, please refer to our [sample app repo](https://github.com/TencentCloud/chat-demo-flutter). + +# 2.4.3 + +## Bug Fixes + +* Fixed an keyboard issue on Web. + +# 2.4.2 + +## Bug Fixes + +* Fixed an UI issue on Material3 mode. + # 2.4.1 +## Improvements + +* Enhanced stability for message reaction. + ## Bug Fixes * Fixed some bugs. @@ -8,7 +35,7 @@ ## Breaking Changes -* Migrated to Flutter 3.16.0. +* Migrated to Flutter 3.16. Support for Flutter 3.13 and earlier versions has been discontinued. * Upgraded the minimum supported Android Gradle Plugin to 7.3 to meet Flutter requirements. # 2.3.3 @@ -44,11 +71,11 @@ ## Breaking Changes -* Upgraded and migrated to support Flutter 3.13.0. Support for Flutter 3.10 and earlier versions has been dropped. +* Upgraded and migrated to support Flutter 3.13. Support for Flutter 3.10 and earlier versions has been discontinued. ## Recommendations -* Customers who do not wish to upgrade to Flutter 3.13.0 are advised to continue using version 2.2.1 of our Chat UIKit. However, we strongly recommend upgrading to Flutter 3.13.0 as it includes numerous performance improvements and introduces cutting-edge features. +* Customers who do not wish to upgrade to Flutter 3.13 are advised to continue using version 2.2.1 of our Chat UIKit. However, we strongly recommend upgrading to Flutter 3.13.0 as it includes numerous performance improvements and introduces cutting-edge features. # 2.2.1 diff --git a/example/pubspec.lock b/example/pubspec.lock index 51b3803..98e0645 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -237,10 +237,10 @@ packages: dependency: transitive description: name: dart_internal - sha256: "689dccc3d5f62affd339534cca548dce12b3a6b32f0f10861569d3025efc0567" + sha256: "04145b91ccec450325fee75692b1ab62eb615e8892c334f0f4d31c696a857873" url: "https://pub.dev" source: hosted - version: "0.2.9" + version: "0.2.10" desktop_drop: dependency: transitive description: @@ -301,18 +301,18 @@ packages: dependency: transitive description: name: extended_text - sha256: "7096a1e9a029534257d70f7dafb2798f932d589079e67ef3f58fdf0805f2f627" + sha256: "7f382de3af12992e34bd72ddd36becf90c4720900af126cb9859f0189af71ffe" url: "https://pub.dev" source: hosted - version: "12.0.0" + version: "13.0.0" extended_text_field: dependency: transitive description: name: extended_text_field - sha256: ed9655c70a47a54c7cc689cf7f89a2bde9ab7b530150b4d1808b7aa7eb8cdf90 + sha256: ee139de7c2b2a9d806ddd5fdfef5c728cf475298a7ce5834c5b822ef1e6225d7 url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.0.0" extended_text_library: dependency: transitive description: @@ -470,14 +470,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.0.16" - flutter_slidable_for_tencent_im: + flutter_slidable: dependency: transitive description: - name: flutter_slidable_for_tencent_im - sha256: "425faab6304305dd7d38aef448af02acd65f425bf2bd47ce3b70b0b4e714c17b" + name: flutter_slidable + sha256: "19ed4813003a6ff4e9c6bcce37e792a2a358919d7603b2b31ff200229191e44c" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "3.0.1" flutter_svg: dependency: transitive description: @@ -680,6 +680,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.8" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" link_preview_generator_for_us: dependency: transitive description: @@ -740,26 +764,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" mime: dependency: transitive description: @@ -836,10 +860,10 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" path_drawing: dependency: transitive description: @@ -1227,7 +1251,7 @@ packages: path: ".." relative: true source: path - version: "2.4.1" + version: "2.5.0" tencent_cloud_uikit_core: dependency: transitive description: @@ -1492,6 +1516,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.16" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" wakelock_for_us: dependency: transitive description: @@ -1581,5 +1613,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <3.3.0" - flutter: ">=3.16.0" + dart: ">=3.3.0 <3.4.0" + flutter: ">=3.19.0" 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 0d7f9ad..de859fc 100644 --- a/lib/business_logic/view_models/tui_chat_global_model.dart +++ b/lib/business_logic/view_models/tui_chat_global_model.dart @@ -199,7 +199,9 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass { clearCurrentConversation() { // Only keep the last 20 messages when existing a chat. _messageListMap[currentSelectedConv] = (_messageListMap[currentSelectedConv] ?? []).sublist(max(0, ((_messageListMap[currentSelectedConv] ?? []).length - 20))); - _currentConversationList.removeLast(); + if (_currentConversationList.isNotEmpty) { + _currentConversationList.removeLast(); + } // notifyListeners(); } @@ -639,6 +641,12 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass { Future onMessageDownloadProgressCallback(V2TimMessageDownloadProgress messageProgress) async { final currentProgress = getMessageProgress(messageProgress.msgID); + if (messageProgress.isError || messageProgress.errorCode != 0) { + V2TimMessage? message = await _findAndRetrieveMessage(messageProgress.msgID); + _handleDownloadError(messageProgress, message); + return; + } + if (messageProgress.isFinish && currentProgress < 100) { V2TimMessage? message = await _findAndRetrieveMessage(messageProgress.msgID); _handleFinishedDownload(messageProgress, message); @@ -670,6 +678,11 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass { } } + void _handleDownloadError(V2TimMessageDownloadProgress messageProgress, V2TimMessage? message) { + setMessageProgress(messageProgress.msgID, 0); + downloadFile(); + } + void _updateMessageAndDownloadFile(V2TimMessage message, V2TimMessageDownloadProgress messageProgress) { updateAsyncMessage(message, TencentUtils.checkString(message.userID) ?? TencentUtils.checkString(message.groupID) ?? ""); diff --git a/lib/ui/views/TIMUIKitBlackList/tim_uikit_black_list.dart b/lib/ui/views/TIMUIKitBlackList/tim_uikit_black_list.dart index 4b9e4f5..ef39a69 100644 --- a/lib/ui/views/TIMUIKitBlackList/tim_uikit_black_list.dart +++ b/lib/ui/views/TIMUIKitBlackList/tim_uikit_black_list.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_slidable_for_tencent_im/flutter_slidable.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:provider/provider.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart'; import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/block_list_life_cycle.dart'; diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list_item.dart b/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list_item.dart index 0cc1ae2..b1425b7 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list_item.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list_item.dart @@ -752,6 +752,8 @@ class _TIMUIKItHistoryMessageListItemState bool isRevocable(int timestamp) => (DateTime.now().millisecondsSinceEpoch / 1000).ceil() - timestamp < 120; + // TODO : 继续看这里 + _onOpenToolTip( c, V2TimMessage message, diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_show_item.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_show_item.dart index d7d3e5e..6bf72d2 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_show_item.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_show_item.dart @@ -4,7 +4,6 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.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_statelesswidget.dart'; import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart'; diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_file_elem.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_file_elem.dart index 728ba6c..41e7f1f 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_file_elem.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_file_elem.dart @@ -5,22 +5,22 @@ import 'dart:math'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; import 'package:loading_animation_widget/loading_animation_widget.dart'; import 'package:open_file/open_file.dart'; -import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart'; -import 'package:tencent_cloud_chat_uikit/ui/utils/permission.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/data_services/services_locatar.dart'; -import 'package:universal_html/html.dart' as html; +import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart'; +import 'package:tencent_cloud_chat_uikit/ui/utils/permission.dart'; import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart'; import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_wrapper.dart'; import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_file_icon.dart'; import 'package:tencent_cloud_chat_uikit/ui/widgets/textSize.dart'; +import 'package:universal_html/html.dart' as html; import 'package:url_launcher/url_launcher.dart'; -import 'package:http/http.dart' as http; class TIMUIKitFileElem extends StatefulWidget { final String? messageID; @@ -32,16 +32,7 @@ class TIMUIKitFileElem extends StatefulWidget { final bool? isShowMessageReaction; final TUIChatSeparateViewModel chatModel; - const TIMUIKitFileElem( - {Key? key, - required this.chatModel, - required this.messageID, - required this.fileElem, - required this.isSelf, - required this.isShowJump, - this.clearJump, - required this.message, - this.isShowMessageReaction}) + const TIMUIKitFileElem({Key? key, required this.chatModel, required this.messageID, required this.fileElem, required this.isSelf, required this.isShowJump, this.clearJump, required this.message, this.isShowMessageReaction}) : super(key: key); @override @@ -56,12 +47,11 @@ class _TIMUIKitFileElemState extends TIMUIKitState { late V2TimAdvancedMsgListener advancedMsgListener; final GlobalKey containerKey = GlobalKey(); double? containerHeight; + bool? _downloadFailed = false; @override void dispose() { - TencentImSDKPlugin.v2TIMManager - .getMessageManager() - .removeAdvancedMsgListener(listener: advancedMsgListener); + TencentImSDKPlugin.v2TIMManager.getMessageManager().removeAdvancedMsgListener(listener: advancedMsgListener); super.dispose(); } @@ -74,19 +64,27 @@ class _TIMUIKitFileElemState extends TIMUIKitState { }); } advancedMsgListener = V2TimAdvancedMsgListener( - onMessageDownloadProgressCallback: - (V2TimMessageDownloadProgress messageProgress) async { + onMessageDownloadProgressCallback: (V2TimMessageDownloadProgress messageProgress) async { if (messageProgress.msgID == widget.message.msgID) { + if (messageProgress.isError || messageProgress.errorCode != 0) { + setState(() { + _downloadFailed = true; + }); + return; + } + if (messageProgress.isFinish) { if (mounted) { setState(() { downloadProgress = 100; }); + + TencentImSDKPlugin.v2TIMManager.getMessageManager().removeAdvancedMsgListener( + listener: advancedMsgListener, + ); } } else { - final currentProgress = - (messageProgress.currentSize / messageProgress.totalSize * 100) - .floor(); + final currentProgress = (messageProgress.currentSize / messageProgress.totalSize * 100).floor(); if (mounted && currentProgress > downloadProgress) { setState(() { downloadProgress = currentProgress; @@ -96,16 +94,11 @@ class _TIMUIKitFileElemState extends TIMUIKitState { } }, ); - TencentImSDKPlugin.v2TIMManager - .getMessageManager() - .addAdvancedMsgListener(listener: advancedMsgListener); + TencentImSDKPlugin.v2TIMManager.getMessageManager().addAdvancedMsgListener(listener: advancedMsgListener); } Future getSavePath() async { - String savePathWithAppPath = - '/storage/emulated/0/Android/data/com.tencent.flutter.tuikit/cache/' + - (widget.message.msgID ?? "") + - widget.fileElem!.fileName!; + String savePathWithAppPath = '/storage/emulated/0/Android/data/com.tencent.flutter.tuikit/cache/' + (widget.message.msgID ?? "") + widget.fileElem!.fileName!; return savePathWithAppPath; } @@ -113,11 +106,7 @@ class _TIMUIKitFileElemState extends TIMUIKitState { if (PlatformUtils().isWeb) { return true; } - String savePath = TencentUtils.checkString( - model.getFileMessageLocation(widget.messageID)) ?? - TencentUtils.checkString(widget.message.fileElem!.localUrl) ?? - widget.message.fileElem?.path ?? - ''; + String savePath = TencentUtils.checkString(model.getFileMessageLocation(widget.messageID)) ?? TencentUtils.checkString(widget.message.fileElem!.localUrl) ?? widget.message.fileElem?.path ?? ''; File f = File(savePath); if (f.existsSync() && widget.messageID != null) { filePath = savePath; @@ -170,8 +159,7 @@ class _TIMUIKitFileElemState extends TIMUIKitState { downloadFile(TUITheme theme) async { if (PlatformUtils().isMobile) { if (PlatformUtils().isIOS) { - if (!await Permissions.checkPermission( - context, Permission.photosAddOnly.value, theme, false)) { + if (!await Permissions.checkPermission(context, Permission.photosAddOnly.value, theme, false)) { return; } } else { @@ -203,18 +191,13 @@ class _TIMUIKitFileElemState extends TIMUIKitState { } tryOpenFile(context, theme) async { - if (!PlatformUtils().isWeb && - (await hasZeroSize(filePath) || widget.message.status == 3)) { - onTIMCallback(TIMCallback( - type: TIMCallbackType.INFO, - infoRecommendText: "不支持 0KB 文件的传输", - infoCode: 6660417)); + if (!PlatformUtils().isWeb && (await hasZeroSize(filePath) || widget.message.status == 3)) { + onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: "不支持 0KB 文件的传输", infoCode: 6660417)); return; } if (PlatformUtils().isMobile) { if (PlatformUtils().isIOS) { - if (!await Permissions.checkPermission( - context, Permission.photosAddOnly.value, theme!, false)) { + if (!await Permissions.checkPermission(context, Permission.photosAddOnly.value, theme!, false)) { return; } } else { @@ -258,8 +241,7 @@ class _TIMUIKitFileElemState extends TIMUIKitState { headers: {'Content-Type': 'application/x-www-form-urlencoded'}, ); - final html.AnchorElement downloadAnchor = - html.document.createElement('a') as html.AnchorElement; + final html.AnchorElement downloadAnchor = html.document.createElement('a') as html.AnchorElement; final html.Blob blob = html.Blob([response.bodyBytes]); @@ -271,8 +253,7 @@ class _TIMUIKitFileElemState extends TIMUIKitState { html.AnchorElement( href: widget.fileElem?.path ?? "", ) - ..setAttribute( - "download", widget.message.fileElem?.fileName ?? fileName) + ..setAttribute("download", widget.message.fileElem?.fileName ?? fileName) ..setAttribute("target", '_blank') ..style.display = "none" ..click(); @@ -291,24 +272,14 @@ class _TIMUIKitFileElemState extends TIMUIKitState { final fileName = widget.fileElem!.fileName ?? ""; final fileSize = widget.fileElem!.fileSize; final borderRadius = widget.isSelf - ? const BorderRadius.only( - topLeft: Radius.circular(10), - topRight: Radius.circular(2), - bottomLeft: Radius.circular(10), - bottomRight: Radius.circular(10)) - : const BorderRadius.only( - topLeft: Radius.circular(2), - topRight: Radius.circular(10), - bottomLeft: Radius.circular(10), - bottomRight: Radius.circular(10)); + ? const BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(2), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)) + : const BorderRadius.only(topLeft: Radius.circular(2), topRight: Radius.circular(10), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)); String? fileFormat; - if (widget.fileElem?.fileName != null && - widget.fileElem!.fileName!.isNotEmpty) { + if (widget.fileElem?.fileName != null && widget.fileElem!.fileName!.isNotEmpty) { final String fileName = widget.fileElem!.fileName!; fileFormat = fileName.split(".")[max(fileName.split(".").length - 1, 0)]; } - final RenderBox? containerRenderBox = - containerKey.currentContext?.findRenderObject() as RenderBox?; + final RenderBox? containerRenderBox = containerKey.currentContext?.findRenderObject() as RenderBox?; if (containerRenderBox != null) { containerHeight = containerRenderBox.size.height; } @@ -333,113 +304,96 @@ class _TIMUIKitFileElemState extends TIMUIKitState { isShowMessageReaction: widget.isShowMessageReaction ?? true, message: widget.message, child: GestureDetector( - onTap: () async { - try { - if (PlatformUtils().isWeb) { - if (!isWebDownloading) { - downloadWebFile(widget.fileElem?.path ?? ""); - } - return; + onTap: () async { + try { + if (PlatformUtils().isWeb) { + if (!isWebDownloading) { + downloadWebFile(widget.fileElem?.path ?? ""); } - if (await hasFile()) { - if (received == 100) { - tryOpenFile(context, theme); - } else { - onTIMCallback( - TIMCallback( - type: TIMCallbackType.INFO, - infoRecommendText: TIM_t("正在下载中"), - infoCode: 6660411, - ), - ); - } - return; - } - if (checkIsWaiting()) { + return; + } + if (await hasFile()) { + if (received == 100) { + tryOpenFile(context, theme); + } else { onTIMCallback( TIMCallback( - type: TIMCallbackType.INFO, - infoRecommendText: TIM_t("已加入待下载队列,其他文件下载中"), - infoCode: 6660413), - ); - return; - } else { - await addUrlToWaitingPath(theme); - } - } catch (e) { - onTIMCallback(TIMCallback( - type: TIMCallbackType.INFO, - infoRecommendText: "文件处理异常", - infoCode: 6660416)); - } - }, - child: ConstrainedBox( - constraints: const BoxConstraints(maxHeight: 72), - child: Container( - width: 237, - decoration: BoxDecoration( - border: Border.all( - color: theme.weakDividerColor ?? - CommonColor.weakDividerColor, + type: TIMCallbackType.INFO, + infoRecommendText: TIM_t("正在下载中"), + infoCode: 6660411, ), - borderRadius: borderRadius), - child: Stack(children: [ - ClipRRect( - borderRadius: borderRadius, - child: LinearProgressIndicator( - minHeight: ((containerHeight) ?? 72) - 6, - value: (received == 100 ? 0 : received) / 100, - backgroundColor: received == 100 - ? theme.weakBackgroundColor - : Colors.white, - valueColor: AlwaysStoppedAnimation( - theme.lightPrimaryMaterialColor.shade50),), + ); + } + return; + } + if (checkIsWaiting()) { + onTIMCallback( + TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("已加入待下载队列,其他文件下载中"), infoCode: 6660413), + ); + return; + } else { + await addUrlToWaitingPath(theme); + } + } catch (e) { + onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: "文件处理异常", infoCode: 6660416)); + } + }, + child: ConstrainedBox( + constraints: const BoxConstraints(maxHeight: 72), + child: Container( + width: 237, + decoration: BoxDecoration( + border: Border.all( + color: theme.weakDividerColor ?? CommonColor.weakDividerColor, ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, horizontal: 12), - child: Row( - mainAxisAlignment: widget.isSelf - ? MainAxisAlignment.end - : MainAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - constraints: - const BoxConstraints(maxWidth: 160), - child: LayoutBuilder( - builder: (buildContext, boxConstraints) { - return CustomText( - fileName, - width: boxConstraints.maxWidth, - maxLines: 1, - style: TextStyle( - color: theme.darkTextColor, - fontSize: 16, - ), - ); - }, - ), - ), - if (fileSize != null) - Text( - showFileSize(fileSize), - style: TextStyle( - fontSize: 14, - color: theme.weakTextColor), - ) - ], - )), - TIMUIKitFileIcon( - fileFormat: fileFormat, + borderRadius: borderRadius), + child: Stack(children: [ + ClipRRect( + borderRadius: borderRadius, + child: LinearProgressIndicator( + minHeight: ((containerHeight) ?? 72) - 6, + value: (received == 100 ? 0 : received) / 100, + backgroundColor: received == 100 ? theme.weakBackgroundColor : Colors.white, + valueColor: AlwaysStoppedAnimation(theme.lightPrimaryMaterialColor.shade50), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), + child: Row(mainAxisAlignment: widget.isSelf ? MainAxisAlignment.end : MainAxisAlignment.start, children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + constraints: const BoxConstraints(maxWidth: 160), + child: LayoutBuilder( + builder: (buildContext, boxConstraints) { + return CustomText( + fileName, + width: boxConstraints.maxWidth, + maxLines: 1, + style: TextStyle( + color: theme.darkTextColor, + fontSize: 16, + ), + ); + }, ), - ])), - ]), - ), + ), + if (fileSize != null) + Text( + showFileSize(fileSize), + style: TextStyle(fontSize: 14, color: theme.weakTextColor), + ) + ], + )), + TIMUIKitFileIcon( + fileFormat: fileFormat, + ), + ])), + ]), ), + ), )), if (!widget.isSelf && isWebDownloading) Container( diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field_layout/narrow.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field_layout/narrow.dart index b16160f..0999262 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field_layout/narrow.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field_layout/narrow.dart @@ -322,14 +322,14 @@ class _TIMUIKitTextFieldLayoutNarrowState extends TIMUIKitState - Function(V2TimConversation conversationItem); +typedef ConversationItemSlideBuilder = List Function(V2TimConversation conversationItem); -typedef ConversationItemSecondaryMenuBuilder = Widget Function( - V2TimConversation conversationItem, VoidCallback onClose); +typedef ConversationItemSecondaryMenuBuilder = Widget Function(V2TimConversation conversationItem, VoidCallback onClose); class TIMUIKitConversation extends StatefulWidget { /// the callback after clicking conversation item @@ -143,12 +139,10 @@ class ConversationItemSlidePanel extends TIMUIKitStatelessWidget { } class _TIMUIKitConversationState extends TIMUIKitState { - final TUIConversationViewModel model = - serviceLocator(); + final TUIConversationViewModel model = serviceLocator(); late TIMUIKitConversationController _timuiKitConversationController; final TUIThemeViewModel themeViewModel = serviceLocator(); - final TUIFriendShipViewModel friendShipViewModel = - serviceLocator(); + final TUIFriendShipViewModel friendShipViewModel = serviceLocator(); late AutoScrollController _autoScrollController; @override @@ -172,30 +166,21 @@ class _TIMUIKitConversationState extends TIMUIKitState { } _clearHistory(V2TimConversation conversationItem) { - _timuiKitConversationController.clearHistoryMessage( - conversation: conversationItem); + _timuiKitConversationController.clearHistoryMessage(conversation: conversationItem); } _pinConversation(V2TimConversation conversation) { - _timuiKitConversationController.pinConversation( - conversationID: conversation.conversationID, - isPinned: !conversation.isPinned!); + _timuiKitConversationController.pinConversation(conversationID: conversation.conversationID, isPinned: !conversation.isPinned!); } _deleteConversation(V2TimConversation conversation) { - _timuiKitConversationController.deleteConversation( - conversationID: conversation.conversationID); + _timuiKitConversationController.deleteConversation(conversationID: conversation.conversationID); } List getFilteredConversation() { - List filteredConversationList = model.conversationList - .where( - (element) => (element?.groupID != null || element?.userID != null)) - .toList(); + List filteredConversationList = model.conversationList.where((element) => (element?.groupID != null || element?.userID != null)).toList(); if (widget.conversationCollector != null) { - filteredConversationList = filteredConversationList - .where(widget.conversationCollector!) - .toList(); + filteredConversationList = filteredConversationList.where(widget.conversationCollector!).toList(); } return filteredConversationList; } @@ -221,8 +206,7 @@ class _TIMUIKitConversationState extends TIMUIKitState { } } - Widget _defaultSecondaryMenu( - V2TimConversation conversationItem, VoidCallback onClose) { + Widget _defaultSecondaryMenu(V2TimConversation conversationItem, VoidCallback onClose) { return TUIKitColumnMenu(data: [ if (!PlatformUtils().isWeb) ColumnMenuItem( @@ -234,11 +218,7 @@ class _TIMUIKitConversationState extends TIMUIKitState { }), ColumnMenuItem( label: conversationItem.isPinned! ? TIM_t("取消置顶") : TIM_t("置顶"), - icon: Icon( - conversationItem.isPinned! - ? Icons.vertical_align_bottom - : Icons.vertical_align_top, - size: 16), + icon: Icon(conversationItem.isPinned! ? Icons.vertical_align_bottom : Icons.vertical_align_top, size: 16), onClick: () { onClose(); _pinConversation(conversationItem); @@ -263,8 +243,7 @@ class _TIMUIKitConversationState extends TIMUIKitState { onPressed: (context) { _clearHistory(conversationItem); }, - backgroundColor: theme.conversationItemSliderClearBgColor ?? - CommonColor.primaryColor, + backgroundColor: theme.conversationItemSliderClearBgColor ?? CommonColor.primaryColor, foregroundColor: theme.conversationItemSliderTextColor, label: TIM_t("清除聊天"), spacing: 0, @@ -274,8 +253,7 @@ class _TIMUIKitConversationState extends TIMUIKitState { onPressed: (context) { _pinConversation(conversationItem); }, - backgroundColor: - theme.conversationItemSliderPinBgColor ?? CommonColor.infoColor, + backgroundColor: theme.conversationItemSliderPinBgColor ?? CommonColor.infoColor, foregroundColor: theme.conversationItemSliderTextColor, label: conversationItem.isPinned! ? TIM_t("取消置顶") : TIM_t("置顶"), ), @@ -283,16 +261,14 @@ class _TIMUIKitConversationState extends TIMUIKitState { onPressed: (context) { _deleteConversation(conversationItem); }, - backgroundColor: - theme.conversationItemSliderDeleteBgColor ?? Colors.red, + backgroundColor: theme.conversationItemSliderDeleteBgColor ?? Colors.red, foregroundColor: theme.conversationItemSliderTextColor, label: TIM_t("删除"), ) ]; } - Widget _getSecondaryMenu( - V2TimConversation conversation, VoidCallback onClose) { + Widget _getSecondaryMenu(V2TimConversation conversation, VoidCallback onClose) { if (widget.itemSecondaryMenuBuilder != null) { return widget.itemSecondaryMenuBuilder!(conversation, onClose); } @@ -311,22 +287,16 @@ class _TIMUIKitConversationState extends TIMUIKitState { @override Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { final theme = value.theme; - final isDesktopScreen = - TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop; + final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop; return MultiProvider( - providers: [ - ChangeNotifierProvider.value(value: model), - ChangeNotifierProvider.value(value: friendShipViewModel) - ], + providers: [ChangeNotifierProvider.value(value: model), ChangeNotifierProvider.value(value: friendShipViewModel)], builder: (BuildContext context, Widget? w) { final _model = Provider.of(context); bool haveMoreData = _model.haveMoreData; - final _friendShipViewModel = - Provider.of(context); + final _friendShipViewModel = Provider.of(context); _model.lifeCycle = widget.lifeCycle; - List filteredConversationList = - getFilteredConversation(); + List filteredConversationList = getFilteredConversation(); if (TencentUtils.checkString(_model.scrollToConversation) != null) { _onScrollToConversation(_model.scrollToConversation!); @@ -348,21 +318,15 @@ class _TIMUIKitConversationState extends TIMUIKitState { final conversationItem = filteredConversationList[index]; - final V2TimUserStatus? onlineStatus = - _friendShipViewModel.userStatusList.firstWhere( - (item) => item.userID == conversationItem?.userID, - orElse: () => V2TimUserStatus(statusType: 0)); + final V2TimUserStatus? onlineStatus = _friendShipViewModel.userStatusList.firstWhere((item) => item.userID == conversationItem?.userID, orElse: () => V2TimUserStatus(statusType: 0)); if (widget.itemBuilder != null) { - return widget.itemBuilder!( - conversationItem!, onlineStatus); + return widget.itemBuilder!(conversationItem!, onlineStatus); } - final slideChildren = - _getSlideBuilder()(conversationItem!); + final slideChildren = _getSlideBuilder()(conversationItem!); - final isCurrent = conversationItem.conversationID == - model.selectedConversation?.conversationID; + final isCurrent = conversationItem.conversationID == model.selectedConversation?.conversationID; final isPined = conversationItem.isPinned ?? false; @@ -383,15 +347,10 @@ class _TIMUIKitConversationState extends TIMUIKitState { isDisturb: conversationItem.recvOpt != 0, lastMsg: conversationItem.lastMessage, isPined: isPined, - groupAtInfoList: - conversationItem.groupAtInfoList ?? [], + groupAtInfoList: conversationItem.groupAtInfoList ?? [], unreadCount: conversationItem.unreadCount ?? 0, draftText: conversationItem.draftText, - onlineStatus: (widget.isShowOnlineStatus && - conversationItem.userID != null && - conversationItem.userID!.isNotEmpty) - ? onlineStatus - : null, + onlineStatus: (widget.isShowOnlineStatus && conversationItem.userID != null && conversationItem.userID!.isNotEmpty) ? onlineStatus : null, draftTimestamp: conversationItem.draftTimestamp, convType: conversationItem.type), onTap: () => onTapConvItem(conversationItem), @@ -408,23 +367,12 @@ class _TIMUIKitConversationState extends TIMUIKitState { child: InkWell( onSecondaryTapDown: (details) { TUIKitWidePopup.showPopupWindow( - operationKey: TUIKitWideModalOperationKey - .conversationSecondaryMenu, + operationKey: TUIKitWideModalOperationKey.conversationSecondaryMenu, isDarkBackground: false, - borderRadius: const BorderRadius.all( - Radius.circular(4)), + borderRadius: const BorderRadius.all(Radius.circular(4)), context: context, - offset: Offset( - min( - details.globalPosition.dx, - MediaQuery.of(context).size.width - - 80), - min( - details.globalPosition.dy, - MediaQuery.of(context).size.height - - 130)), - child: (onClose) => _getSecondaryMenu( - conversationItem, onClose)); + offset: Offset(min(details.globalPosition.dx, MediaQuery.of(context).size.width - 80), min(details.globalPosition.dy, MediaQuery.of(context).size.height - 130)), + child: (onClose) => _getSecondaryMenu(conversationItem, onClose)); }, child: conversationLineItem(), ), @@ -433,19 +381,10 @@ class _TIMUIKitConversationState extends TIMUIKitState { key: ValueKey(conversationItem.conversationID), controller: _autoScrollController, index: index, - child: Slidable( - groupTag: 'conversation-list', - child: conversationLineItem(), - endActionPane: ActionPane( - extentRatio: - slideChildren.length > 2 ? 0.77 : 0.5, - motion: const DrawerMotion(), - children: slideChildren)), + child: Slidable(groupTag: 'conversation-list', child: conversationLineItem(), endActionPane: ActionPane(extentRatio: slideChildren.length > 2 ? 0.77 : 0.5, motion: const DrawerMotion(), children: slideChildren)), )); }) - : (widget.emptyBuilder != null - ? widget.emptyBuilder!() - : Container()); + : (widget.emptyBuilder != null ? widget.emptyBuilder!() : Container()); } return TUIKitScreenUtils.getDeviceWidget( @@ -459,9 +398,7 @@ class _TIMUIKitConversationState extends TIMUIKitState { child: conversationList(), ), ), - desktopWidget: Scrollbar( - controller: _autoScrollController, - child: conversationList())); + desktopWidget: Scrollbar(controller: _autoScrollController, child: conversationList())); }); } } diff --git a/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_manage.dart b/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_manage.dart index 46195b9..d9bd09d 100644 --- a/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_manage.dart +++ b/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_manage.dart @@ -2,20 +2,20 @@ import 'dart:math'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_slidable_for_tencent_im/flutter_slidable.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/TIMUIKitProfile/widget/tim_uikit_operation_item.dart'; -import 'package:tencent_cloud_chat_uikit/ui/widgets/column_menu.dart'; -import 'package:tencent_cloud_chat_uikit/ui/widgets/wide_popup.dart'; -import 'package:tencent_im_base/tencent_im_base.dart'; +import 'package:flutter_slidable/flutter_slidable.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_state.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/data_services/services_locatar.dart'; +import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart'; +import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitProfile/widget/tim_uikit_operation_item.dart'; import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart'; +import 'package:tencent_cloud_chat_uikit/ui/widgets/column_menu.dart'; import 'package:tencent_cloud_chat_uikit/ui/widgets/radio_button.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'; GlobalKey<_GroupProfileAddAdminState> groupProfileAddAdminKey = GlobalKey(); @@ -26,34 +26,23 @@ class GroupProfileGroupManage extends StatefulWidget { State createState() => GroupProfileGroupManageState(); } -class GroupProfileGroupManageState - extends TIMUIKitState { +class GroupProfileGroupManageState extends TIMUIKitState { bool isShowManageBox = false; @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); return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - decoration: BoxDecoration( - color: Colors.white, - border: isDesktopScreen - ? null - : Border( - bottom: BorderSide( - color: theme.weakDividerColor ?? - CommonColor.weakDividerColor))), + decoration: BoxDecoration(color: Colors.white, border: isDesktopScreen ? null : Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))), child: Column( children: [ InkWell( onTap: () { - final isDesktopScreen = - TUIKitScreenUtils.getFormFactor(context) == - DeviceType.Desktop; + final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop; if (!isDesktopScreen) { Navigator.push( context, @@ -72,15 +61,12 @@ class GroupProfileGroupManageState children: [ Text( TIM_t("群管理"), - style: TextStyle( - fontSize: isDesktopScreen ? 14 : 16, - color: theme.darkTextColor), + style: TextStyle(fontSize: isDesktopScreen ? 14 : 16, color: theme.darkTextColor), ), AnimatedRotation( turns: isShowManageBox ? 0.25 : 0, duration: const Duration(milliseconds: 200), - child: Icon(Icons.keyboard_arrow_right, - color: theme.weakTextColor), + child: Icon(Icons.keyboard_arrow_right, color: theme.weakTextColor), ) ], ), @@ -108,8 +94,7 @@ class GroupProfileGroupManagePage extends StatefulWidget { State createState() => _GroupProfileGroupManagePageState(); } -class _GroupProfileGroupManagePageState - extends TIMUIKitState { +class _GroupProfileGroupManagePageState extends TIMUIKitState { int? serverTime; @override @@ -128,38 +113,20 @@ class _GroupProfileGroupManagePageState @override Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { return MultiProvider( - providers: [ - ChangeNotifierProvider.value(value: widget.model), - ChangeNotifierProvider.value( - value: serviceLocator()) - ], + providers: [ChangeNotifierProvider.value(value: widget.model), ChangeNotifierProvider.value(value: serviceLocator())], builder: (context, w) { - final memberList = - Provider.of(context).groupMemberList; + final memberList = Provider.of(context).groupMemberList; final theme = Provider.of(context).theme; final isAllMuted = widget.model.groupInfo?.isAllMuted ?? false; - final bool isAllowMuteMember = - (widget.model.groupInfo?.groupType ?? "") != GroupType.Work; - final isDesktopScreen = - TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop; + final bool isAllowMuteMember = (widget.model.groupInfo?.groupType ?? "") != GroupType.Work; + final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop; Widget managePage() { return Column( children: [ Container( - padding: EdgeInsets.only( - top: 12, - left: isDesktopScreen ? 0 : 16, - bottom: isDesktopScreen ? 0 : 12, - right: isDesktopScreen ? 0 : 12), - decoration: BoxDecoration( - color: Colors.white, - border: isDesktopScreen - ? null - : Border( - bottom: BorderSide( - color: theme.weakDividerColor ?? - CommonColor.weakDividerColor))), + padding: EdgeInsets.only(top: 12, left: isDesktopScreen ? 0 : 16, bottom: isDesktopScreen ? 0 : 12, right: isDesktopScreen ? 0 : 12), + decoration: BoxDecoration(color: Colors.white, border: isDesktopScreen ? null : Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))), child: InkWell( onTap: isDesktopScreen ? null @@ -167,8 +134,7 @@ class _GroupProfileGroupManagePageState Navigator.push( context, MaterialPageRoute( - builder: (context) => - GroupProfileSetManagerPage( + builder: (context) => GroupProfileSetManagerPage( model: widget.model, ), )); @@ -177,22 +143,12 @@ class _GroupProfileGroupManagePageState ? Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(TIM_t("群管理员"), - style: TextStyle( - fontSize: 14, - color: theme.darkTextColor)), + Text(TIM_t("群管理员"), style: TextStyle(fontSize: 14, color: theme.darkTextColor)), ], ) : Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(TIM_t("设置管理员"), - style: TextStyle( - fontSize: isDesktopScreen ? 14 : 16, - color: theme.darkTextColor)), - Icon(Icons.keyboard_arrow_right, - color: theme.weakTextColor) - ], + children: [Text(TIM_t("设置管理员"), style: TextStyle(fontSize: isDesktopScreen ? 14 : 16, color: theme.darkTextColor)), Icon(Icons.keyboard_arrow_right, color: theme.weakTextColor)], ), ), ), @@ -202,21 +158,14 @@ class _GroupProfileGroupManagePageState ), if (!isDesktopScreen) Container( - padding: const EdgeInsets.only( - top: 12, left: 16, bottom: 12, right: 12), - decoration: BoxDecoration( - color: Colors.white, - border: Border( - bottom: BorderSide( - color: theme.weakDividerColor ?? - CommonColor.weakDividerColor))), + padding: const EdgeInsets.only(top: 12, left: 16, bottom: 12, right: 12), + decoration: BoxDecoration(color: Colors.white, border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( TIM_t("全员禁言"), - style: TextStyle( - fontSize: 16, color: theme.darkTextColor), + style: TextStyle(fontSize: 16, color: theme.darkTextColor), ), CupertinoSwitch( value: isAllMuted, @@ -231,9 +180,7 @@ class _GroupProfileGroupManagePageState Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(TIM_t("禁言"), - style: TextStyle( - fontSize: 14, color: theme.darkTextColor)), + Text(TIM_t("禁言"), style: TextStyle(fontSize: 14, color: theme.darkTextColor)), ], ), if (isDesktopScreen) @@ -253,14 +200,12 @@ class _GroupProfileGroupManagePageState ), if (!isDesktopScreen) Container( - padding: const EdgeInsets.symmetric( - vertical: 10, horizontal: 16), + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), color: theme.weakBackgroundColor, alignment: Alignment.topLeft, child: Text( TIM_t("全员禁言开启后,只允许群主和管理员发言。"), - style: - TextStyle(fontSize: 12, color: theme.weakTextColor), + style: TextStyle(fontSize: 12, color: theme.weakTextColor), ), ), if (!isAllMuted && isAllowMuteMember) @@ -276,14 +221,7 @@ class _GroupProfileGroupManagePageState : const EdgeInsets.only( bottom: 4, ), - decoration: isDesktopScreen - ? null - : BoxDecoration( - color: Colors.white, - border: Border( - bottom: BorderSide( - color: theme.weakDividerColor ?? - CommonColor.weakDividerColor))), + decoration: isDesktopScreen ? null : BoxDecoration(color: Colors.white, border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))), child: Row( children: [ Icon( @@ -304,21 +242,15 @@ class _GroupProfileGroupManagePageState key: groupProfileAddAdminKey, appbarTitle: TIM_t("设置禁言"), memberList: memberList.where((element) { - final isMute = (serverTime != null - ? (element?.muteUntil ?? 0) > serverTime! - : false); - final isMember = element!.role == - GroupMemberRoleType - .V2TIM_GROUP_MEMBER_ROLE_MEMBER; + final isMute = (serverTime != null ? (element?.muteUntil ?? 0) > serverTime! : false); + final isMember = element!.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER; return !isMute && isMember; }).toList(), - selectCompletedHandler: - (context, selectedMember) async { + selectCompletedHandler: (context, selectedMember) async { if (selectedMember.isNotEmpty) { for (var member in selectedMember) { final userID = member!.userID; - widget.model - .muteGroupMember(userID, true, serverTime); + widget.model.muteGroupMember(userID, true, serverTime); } } }, @@ -337,48 +269,29 @@ class _GroupProfileGroupManagePageState }, child: (onClose) => muteMember()); } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => muteMember())); + Navigator.push(context, MaterialPageRoute(builder: (context) => muteMember())); } }, ), if (!isAllMuted && isAllowMuteMember) ...memberList - .where((element) => (serverTime != null - ? (element?.muteUntil ?? 0) > serverTime! - : false)) + .where((element) => (serverTime != null ? (element?.muteUntil ?? 0) > serverTime! : false)) .map((e) => Container( - padding: isDesktopScreen - ? const EdgeInsets.only(left: 16) - : null, + padding: isDesktopScreen ? const EdgeInsets.only(left: 16) : null, child: GestureDetector( onSecondaryTapDown: (details) { TUIKitWidePopup.showPopupWindow( - operationKey: - TUIKitWideModalOperationKey.setUnmute, + operationKey: TUIKitWideModalOperationKey.setUnmute, isDarkBackground: false, - borderRadius: const BorderRadius.all( - Radius.circular(4)), + borderRadius: const BorderRadius.all(Radius.circular(4)), context: context, - offset: Offset( - min( - details.globalPosition.dx, - MediaQuery.of(context).size.width - - 80), - details.globalPosition.dy), + offset: Offset(min(details.globalPosition.dx, MediaQuery.of(context).size.width - 80), details.globalPosition.dy), child: (onClose) => TUIKitColumnMenu(data: [ ColumnMenuItem( label: TIM_t("删除"), - icon: const Icon( - Icons.remove_circle_outline, - size: 16), + icon: const Icon(Icons.remove_circle_outline, size: 16), onClick: () { - widget.model.muteGroupMember( - e.userID, - false, - serverTime); + widget.model.muteGroupMember(e.userID, false, serverTime); onClose(); }), ])); @@ -386,21 +299,17 @@ class _GroupProfileGroupManagePageState child: _buildListItem( context, e!, - ActionPane( - motion: const DrawerMotion(), - children: [ - SlidableAction( - onPressed: (_) { - widget.model.muteGroupMember( - e.userID, false, serverTime); - }, - flex: 1, - backgroundColor: theme.cautionColor ?? - CommonColor.cautionColor, - autoClose: true, - label: TIM_t("删除"), - ) - ])), + ActionPane(motion: const DrawerMotion(), children: [ + SlidableAction( + onPressed: (_) { + widget.model.muteGroupMember(e.userID, false, serverTime); + }, + flex: 1, + backgroundColor: theme.cautionColor ?? CommonColor.cautionColor, + autoClose: true, + label: TIM_t("删除"), + ) + ])), ), )) .toList() @@ -415,8 +324,7 @@ class _GroupProfileGroupManagePageState appBar: AppBar( title: Text( TIM_t("群管理"), - style: - TextStyle(color: theme.appbarTextColor, fontSize: 17), + style: TextStyle(color: theme.appbarTextColor, fontSize: 17), ), backgroundColor: theme.appbarBgColor ?? theme.primaryColor, shadowColor: theme.weakDividerColor, @@ -461,11 +369,9 @@ _getShowName(V2TimGroupMemberFullInfo? item) { : userID; } -Widget _buildListItem(BuildContext context, V2TimGroupMemberFullInfo memberInfo, - ActionPane? endActionPane) { +Widget _buildListItem(BuildContext context, V2TimGroupMemberFullInfo memberInfo, ActionPane? endActionPane) { final theme = Provider.of(context).theme; - final isDesktopScreen = - TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop; + final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop; Widget nameItem() { return Container( @@ -484,67 +390,42 @@ Widget _buildListItem(BuildContext context, V2TimGroupMemberFullInfo memberInfo, ), title: Row( children: [ - Text(_getShowName(memberInfo), - style: TextStyle(fontSize: isDesktopScreen ? 14 : 16)), + Text(_getShowName(memberInfo), style: TextStyle(fontSize: isDesktopScreen ? 14 : 16)), ], ), onTap: () {}, ), - if (!isDesktopScreen) - Divider( - thickness: 1, - indent: 74, - endIndent: 0, - color: theme.weakDividerColor, - height: 0) + if (!isDesktopScreen) Divider(thickness: 1, indent: 74, endIndent: 0, color: theme.weakDividerColor, height: 0) ]), ); } - return TUIKitScreenUtils.getDeviceWidget( - context: context, - desktopWidget: nameItem(), - defaultWidget: SingleChildScrollView( - child: Slidable(endActionPane: endActionPane, child: nameItem()))); + return TUIKitScreenUtils.getDeviceWidget(context: context, desktopWidget: nameItem(), defaultWidget: SingleChildScrollView(child: Slidable(endActionPane: endActionPane, child: nameItem()))); } /// 选择管理员 class GroupProfileSetManagerPage extends StatefulWidget { final TUIGroupProfileModel model; - const GroupProfileSetManagerPage({Key? key, required this.model}) - : super(key: key); + const GroupProfileSetManagerPage({Key? key, required this.model}) : super(key: key); @override State createState() => _GroupProfileSetManagerPageState(); } -class _GroupProfileSetManagerPageState - extends TIMUIKitState { - List _getAdminMemberList( - List memberList) { - return memberList - .where((member) => - member?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN) - .toList(); +class _GroupProfileSetManagerPageState extends TIMUIKitState { + List _getAdminMemberList(List memberList) { + return memberList.where((member) => member?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN).toList(); } - List _getOwnerList( - List memberList) { - return memberList - .where((member) => - member?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER) - .toList(); + List _getOwnerList(List memberList) { + return memberList.where((member) => member?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER).toList(); } - _removeAdmin( - BuildContext context, V2TimGroupMemberFullInfo memberFullInfo) async { + _removeAdmin(BuildContext context, V2TimGroupMemberFullInfo memberFullInfo) async { final res = await widget.model.setMemberToNormal(memberFullInfo.userID); if (res.code == 0) { - onTIMCallback(TIMCallback( - type: TIMCallbackType.INFO, - infoRecommendText: TIM_t("成功取消管理员身份"), - infoCode: 6661003)); + onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("成功取消管理员身份"), infoCode: 6661003)); } } @@ -560,8 +441,7 @@ class _GroupProfileSetManagerPageState final adminList = _getAdminMemberList(memberList); final ownerList = _getOwnerList(memberList); final String option2 = adminList.length.toString(); - final isDesktopScreen = - TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop; + final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop; Widget adminPage() { return SingleChildScrollView( @@ -571,8 +451,7 @@ class _GroupProfileSetManagerPageState Container( alignment: Alignment.topLeft, color: theme.weakDividerColor, - padding: - const EdgeInsets.symmetric(vertical: 6, horizontal: 16), + padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16), child: Text( TIM_t("群主"), style: TextStyle(fontSize: 14, color: theme.weakTextColor), @@ -590,9 +469,7 @@ class _GroupProfileSetManagerPageState ...ownerList .map( (e) => Container( - padding: isDesktopScreen - ? const EdgeInsets.only(left: 16) - : null, + padding: isDesktopScreen ? const EdgeInsets.only(left: 16) : null, child: _buildListItem(context, e!, null), ), ) @@ -601,11 +478,9 @@ class _GroupProfileSetManagerPageState Container( alignment: Alignment.topLeft, color: theme.weakDividerColor, - padding: - const EdgeInsets.symmetric(vertical: 6, horizontal: 16), + padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16), child: Text( - TIM_t_para("管理员 ({{option2}}/10)", "管理员 ($option2/10)")( - option2: option2), + TIM_t_para("管理员 ({{option2}}/10)", "管理员 ($option2/10)")(option2: option2), style: TextStyle(fontSize: 14, color: theme.weakTextColor), ), ), @@ -614,8 +489,7 @@ class _GroupProfileSetManagerPageState alignment: Alignment.topLeft, padding: const EdgeInsets.only(top: 10, bottom: 4, left: 16), child: Text( - TIM_t_para("管理员 ({{option2}}/10)", "管理员 ($option2/10)")( - option2: option2), + TIM_t_para("管理员 ({{option2}}/10)", "管理员 ($option2/10)")(option2: option2), style: TextStyle(fontSize: 14, color: theme.primaryColor), ), ), @@ -627,14 +501,7 @@ class _GroupProfileSetManagerPageState padding: const EdgeInsets.symmetric( vertical: 12, ), - decoration: isDesktopScreen - ? null - : BoxDecoration( - color: Colors.white, - border: Border( - bottom: BorderSide( - color: theme.weakDividerColor ?? - CommonColor.weakDividerColor))), + decoration: isDesktopScreen ? null : BoxDecoration(color: Colors.white, border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))), child: Row( children: [ Icon( @@ -662,15 +529,9 @@ class _GroupProfileSetManagerPageState }, child: (onClose) => GroupProfileAddAdmin( key: groupProfileAddAdminKey, - memberList: memberList - .where((element) => - element?.role == - GroupMemberRoleType - .V2TIM_GROUP_MEMBER_ROLE_MEMBER) - .toList(), + memberList: memberList.where((element) => element?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER).toList(), appbarTitle: TIM_t("设置管理员"), - selectCompletedHandler: - (context, selectedMember) async { + selectCompletedHandler: (context, selectedMember) async { if (selectedMember.isNotEmpty) { for (var member in selectedMember) { final userID = member!.userID; @@ -685,15 +546,9 @@ class _GroupProfileSetManagerPageState MaterialPageRoute( builder: (context) => GroupProfileAddAdmin( key: groupProfileAddAdminKey, - memberList: memberList - .where((element) => - element?.role == - GroupMemberRoleType - .V2TIM_GROUP_MEMBER_ROLE_MEMBER) - .toList(), + memberList: memberList.where((element) => element?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER).toList(), appbarTitle: TIM_t("设置管理员"), - selectCompletedHandler: - (context, selectedMember) async { + selectCompletedHandler: (context, selectedMember) async { if (selectedMember.isNotEmpty) { for (var member in selectedMember) { final userID = member!.userID; @@ -709,22 +564,15 @@ class _GroupProfileSetManagerPageState .map((e) => GestureDetector( onSecondaryTapDown: (details) { TUIKitWidePopup.showPopupWindow( - operationKey: - TUIKitWideModalOperationKey.deleteAdmin, + operationKey: TUIKitWideModalOperationKey.deleteAdmin, isDarkBackground: false, - borderRadius: - const BorderRadius.all(Radius.circular(4)), + borderRadius: const BorderRadius.all(Radius.circular(4)), context: context, - offset: Offset( - min(details.globalPosition.dx, - MediaQuery.of(context).size.width - 80), - details.globalPosition.dy), + offset: Offset(min(details.globalPosition.dx, MediaQuery.of(context).size.width - 80), details.globalPosition.dy), child: (onClose) => TUIKitColumnMenu(data: [ ColumnMenuItem( label: TIM_t("删除"), - icon: const Icon( - Icons.remove_circle_outline, - size: 16), + icon: const Icon(Icons.remove_circle_outline, size: 16), onClick: () { _removeAdmin(context, e); onClose(); @@ -732,26 +580,21 @@ class _GroupProfileSetManagerPageState ])); }, child: Container( - padding: isDesktopScreen - ? const EdgeInsets.only(left: 16) - : null, + padding: isDesktopScreen ? const EdgeInsets.only(left: 16) : null, child: _buildListItem( context, e!, - ActionPane( - motion: const DrawerMotion(), - children: [ - SlidableAction( - onPressed: (_) { - _removeAdmin(context, e); - }, - flex: 1, - backgroundColor: theme.cautionColor ?? - CommonColor.cautionColor, - autoClose: true, - label: TIM_t("删除"), - ) - ])), + ActionPane(motion: const DrawerMotion(), children: [ + SlidableAction( + onPressed: (_) { + _removeAdmin(context, e); + }, + flex: 1, + backgroundColor: theme.cautionColor ?? CommonColor.cautionColor, + autoClose: true, + label: TIM_t("删除"), + ) + ])), ), )) .toList(), @@ -785,16 +628,9 @@ class _GroupProfileSetManagerPageState class GroupProfileAddAdmin extends StatefulWidget { final List memberList; final String appbarTitle; - final void Function(BuildContext context, - List selectedMemberList)? - selectCompletedHandler; + final void Function(BuildContext context, List selectedMemberList)? selectCompletedHandler; - const GroupProfileAddAdmin( - {Key? key, - required this.memberList, - this.selectCompletedHandler, - required this.appbarTitle}) - : super(key: key); + const GroupProfileAddAdmin({Key? key, required this.memberList, this.selectCompletedHandler, required this.appbarTitle}) : super(key: key); @override State createState() => _GroupProfileAddAdminState(); @@ -828,14 +664,8 @@ class _GroupProfileAddAdminState extends TIMUIKitState { ), ...widget.memberList .map((e) => Container( - decoration: BoxDecoration( - color: Colors.white, - border: Border( - bottom: BorderSide( - color: theme.weakDividerColor ?? - CommonColor.weakDividerColor))), - padding: const EdgeInsets.symmetric( - vertical: 10, horizontal: 16), + decoration: BoxDecoration(color: Colors.white, border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? CommonColor.weakDividerColor))), + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), child: InkWell( onTap: () { final isChecked = selectedMemberList.contains(e); @@ -867,8 +697,7 @@ class _GroupProfileAddAdminState extends TIMUIKitState { const SizedBox( width: 10, ), - Text(_getShowName(e), - style: const TextStyle(fontSize: 16)) + Text(_getShowName(e), style: const TextStyle(fontSize: 16)) ], ), ), diff --git a/lib/ui/widgets/group_member_list.dart b/lib/ui/widgets/group_member_list.dart index 464763c..2feadcd 100644 --- a/lib/ui/widgets/group_member_list.dart +++ b/lib/ui/widgets/group_member_list.dart @@ -2,17 +2,17 @@ import 'package:azlistview_all_platforms/azlistview_all_platforms.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_slidable_for_tencent_im/flutter_slidable.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:lpinyin/lpinyin.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/ui/utils/optimize_utils.dart'; +import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart'; import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart'; import 'package:tencent_cloud_chat_uikit/ui/widgets/az_list_view.dart'; import 'package:tencent_cloud_chat_uikit/ui/widgets/radio_button.dart'; -import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; +import 'package:tencent_im_base/tencent_im_base.dart'; class GroupProfileMemberList extends StatefulWidget { final List memberList; @@ -23,8 +23,7 @@ class GroupProfileMemberList extends StatefulWidget { // when the @ need filter some group types final String? groupType; - final Function(List selectedMember)? - onSelectedMemberChange; + final Function(List selectedMember)? onSelectedMemberChange; // notice: onTapMemberItem and onSelectedMemberChange use together will triger together final Function(V2TimGroupMemberFullInfo memberInfo, TapDownDetails? tapDetails)? onTapMemberItem; // When sliding to the bottom bar callBack @@ -53,8 +52,7 @@ class GroupProfileMemberList extends StatefulWidget { State createState() => _GroupProfileMemberListState(); } -class _GroupProfileMemberListState - extends TIMUIKitState { +class _GroupProfileMemberListState extends TIMUIKitState { List selectedMember = []; _getShowName(V2TimGroupMemberFullInfo? item) { @@ -71,14 +69,12 @@ class _GroupProfileMemberListState : userID; } - List _getShowList( - List memberList) { + List _getShowList(List memberList) { final List showList = List.empty(growable: true); for (var i = 0; i < memberList.length; i++) { final item = memberList[i]; final showName = _getShowName(item); - if (item?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER || - item?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN) { + if (item?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER || item?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN) { showList.add(ISuspensionBeanImpl(memberInfo: item, tagIndex: "@")); } else { String pinyin = PinyinHelper.getPinyinE(showName); @@ -97,25 +93,17 @@ class _GroupProfileMemberListState if (widget.canAtAll) { final canAtGroupType = ["Work", "Public", "Meeting"]; if (canAtGroupType.contains(widget.groupType)) { - showList.insert( - 0, - ISuspensionBeanImpl( - memberInfo: V2TimGroupMemberFullInfo( - userID: "__kImSDK_MesssageAtALL__", nickName: TIM_t("所有人")), - tagIndex: "")); + showList.insert(0, ISuspensionBeanImpl(memberInfo: V2TimGroupMemberFullInfo(userID: "__kImSDK_MesssageAtALL__", nickName: TIM_t("所有人")), tagIndex: "")); } } return showList; } - Widget _buildListItem( - BuildContext context, V2TimGroupMemberFullInfo memberInfo) { + Widget _buildListItem(BuildContext context, V2TimGroupMemberFullInfo memberInfo) { final theme = Provider.of(context).theme; - final isDesktopScreen = - TUIKitScreenUtils.getFormFactor() == DeviceType.Desktop; - final isGroupMember = - memberInfo.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER; + final isDesktopScreen = TUIKitScreenUtils.getFormFactor() == DeviceType.Desktop; + final isGroupMember = memberInfo.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER; return Container( color: Colors.white, child: Slidable( @@ -128,8 +116,7 @@ class _GroupProfileMemberListState } }, flex: 1, - backgroundColor: - theme.cautionColor ?? CommonColor.cautionColor, + backgroundColor: theme.cautionColor ?? CommonColor.cautionColor, autoClose: true, label: TIM_t("删除"), ) @@ -146,9 +133,7 @@ class _GroupProfileMemberListState child: CheckBoxButton( onChanged: (isChecked) { if (isChecked) { - if (widget.maxSelectNum != null && - selectedMember.length >= - widget.maxSelectNum!) { + if (widget.maxSelectNum != null && selectedMember.length >= widget.maxSelectNum!) { return; } selectedMember.add(memberInfo); @@ -172,30 +157,22 @@ class _GroupProfileMemberListState type: 1, ), ), - Text(_getShowName(memberInfo), - style: TextStyle(fontSize: isDesktopScreen ? 14 : 16)), - memberInfo.role == - GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER + Text(_getShowName(memberInfo), style: TextStyle(fontSize: isDesktopScreen ? 14 : 16)), + memberInfo.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER ? Container( margin: const EdgeInsets.only(left: 5), child: Text(TIM_t("群主"), style: TextStyle( color: theme.ownerColor, - fontSize: isDesktopScreen ? 10 :12, + fontSize: isDesktopScreen ? 10 : 12, )), padding: const EdgeInsets.fromLTRB(5, 0, 5, 0), decoration: BoxDecoration( - border: Border.all( - color: theme.ownerColor ?? - CommonColor.ownerColor, - width: 1), - borderRadius: - const BorderRadius.all(Radius.circular(4.0)), + border: Border.all(color: theme.ownerColor ?? CommonColor.ownerColor, width: 1), + borderRadius: const BorderRadius.all(Radius.circular(4.0)), ), ) - : memberInfo.role == - GroupMemberRoleType - .V2TIM_GROUP_MEMBER_ROLE_ADMIN + : memberInfo.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN ? Container( margin: const EdgeInsets.only(left: 5), child: Text(TIM_t("管理员"), @@ -205,12 +182,8 @@ class _GroupProfileMemberListState )), padding: const EdgeInsets.fromLTRB(5, 0, 5, 0), decoration: BoxDecoration( - border: Border.all( - color: theme.adminColor ?? - CommonColor.adminColor, - width: 1), - borderRadius: const BorderRadius.all( - Radius.circular(4.0)), + border: Border.all(color: theme.adminColor ?? CommonColor.adminColor, width: 1), + borderRadius: const BorderRadius.all(Radius.circular(4.0)), ), ) : Container() @@ -225,8 +198,7 @@ class _GroupProfileMemberListState if (isChecked) { selectedMember.remove(memberInfo); } else { - if (widget.maxSelectNum != null && - selectedMember.length >= widget.maxSelectNum!) { + if (widget.maxSelectNum != null && selectedMember.length >= widget.maxSelectNum!) { return; } selectedMember.add(memberInfo); @@ -238,17 +210,11 @@ class _GroupProfileMemberListState } }, ), - Divider( - thickness: 1, - indent: 74, - endIndent: 0, - color: theme.weakBackgroundColor, - height: 0) + Divider(thickness: 1, indent: 74, endIndent: 0, color: theme.weakBackgroundColor, height: 0) ]))); } - static Widget getSusItem(BuildContext context, TUITheme theme, String tag, - {double susHeight = 40}) { + static Widget getSusItem(BuildContext context, TUITheme theme, String tag, {double susHeight = 40}) { if (tag == '@') { tag = TIM_t("群主、管理员"); } @@ -273,11 +239,9 @@ class _GroupProfileMemberListState Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { final TUITheme theme = value.theme; - final isDesktopScreen = - TUIKitScreenUtils.getFormFactor() == DeviceType.Desktop; + final isDesktopScreen = TUIKitScreenUtils.getFormFactor() == DeviceType.Desktop; - final throteFunction = - OptimizeUtils.throttle((ScrollNotification notification) { + final throteFunction = OptimizeUtils.throttle((ScrollNotification notification) { final pixels = notification.metrics.pixels; // 总像素高度 final maxScrollExtent = notification.metrics.maxScrollExtent; @@ -305,21 +269,19 @@ class _GroupProfileMemberListState child: Text(TIM_t("暂无群成员")), ) : Container( - padding: isDesktopScreen ? const EdgeInsets.symmetric( horizontal: 16) : null, - child: AZListViewContainer( - memberList: showList, - susItemBuilder: (context, index) { - final model = showList[index]; - return getSusItem( - context, theme, model.getSuspensionTag()); - }, - itemBuilder: (context, index) { - final memberInfo = showList[index].memberInfo - as V2TimGroupMemberFullInfo; + padding: isDesktopScreen ? const EdgeInsets.symmetric(horizontal: 16) : null, + child: AZListViewContainer( + memberList: showList, + susItemBuilder: (context, index) { + final model = showList[index]; + return getSusItem(context, theme, model.getSuspensionTag()); + }, + itemBuilder: (context, index) { + final memberInfo = showList[index].memberInfo as V2TimGroupMemberFullInfo; - return _buildListItem(context, memberInfo); - }), - ), + return _buildListItem(context, memberInfo); + }), + ), )) ], )), diff --git a/lib/ui/widgets/image_screen.dart b/lib/ui/widgets/image_screen.dart index c3de026..abfe6a9 100644 --- a/lib/ui/widgets/image_screen.dart +++ b/lib/ui/widgets/image_screen.dart @@ -235,35 +235,43 @@ class _ImageScreenState extends TIMUIKitState Positioned( left: 10, bottom: 50, - child: IconButton( - icon: Image.asset( - 'images/close.png', - package: 'tencent_cloud_chat_uikit', + child: SizedBox( + width: 48, + height: 48, + child: IconButton( + icon: Image.asset( + 'images/close.png', + package: 'tencent_cloud_chat_uikit', + ), + iconSize: 30, + onPressed: close, ), - iconSize: 30, - onPressed: close, )), if (widget.downloadFn != null) Positioned( right: 10, bottom: 50, - child: IconButton( - icon: Image.asset( - 'images/download.png', - package: 'tencent_cloud_chat_uikit', - ), - iconSize: 30, - onPressed: () async { - setState(() { - isLoading = true; - }); - await widget.downloadFn!(); - Future.delayed(const Duration(milliseconds: 200),(){ + child: SizedBox( + width: 48, + height: 48, + child: IconButton( + icon: Image.asset( + 'images/download.png', + package: 'tencent_cloud_chat_uikit', + ), + iconSize: 30, + onPressed: () async { setState(() { - isLoading = false; + isLoading = true; }); - }); - }, + await widget.downloadFn!(); + Future.delayed(const Duration(milliseconds: 200),(){ + setState(() { + isLoading = false; + }); + }); + }, + ), ), ), if (isLoading) diff --git a/lib/ui/widgets/video_custom_control.dart b/lib/ui/widgets/video_custom_control.dart index f696220..a55a493 100644 --- a/lib/ui/widgets/video_custom_control.dart +++ b/lib/ui/widgets/video_custom_control.dart @@ -3,22 +3,21 @@ import 'dart:async'; import 'package:chewie_for_us/chewie_for_us.dart'; -import 'package:chewie_for_us/src/helpers/utils.dart'; import 'package:chewie_for_us/src/animated_play_pause.dart'; +import 'package:chewie_for_us/src/helpers/utils.dart'; import 'package:chewie_for_us/src/material/material_progress_bar.dart'; import 'package:flutter/material.dart'; import 'package:loading_animation_widget/loading_animation_widget.dart'; +import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart'; import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart'; - -import 'package:video_player/video_player.dart'; -import 'center_play_button.dart'; -import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart'; import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart'; +import 'package:video_player/video_player.dart'; + +import 'center_play_button.dart'; class VideoCustomControls extends StatefulWidget { - const VideoCustomControls({required this.downloadFn, Key? key}) - : super(key: key); + const VideoCustomControls({required this.downloadFn, Key? key}) : super(key: key); final Future Function() downloadFn; @override @@ -27,8 +26,7 @@ class VideoCustomControls extends StatefulWidget { } } -class _VideoCustomControlsState extends TIMUIKitState - with SingleTickerProviderStateMixin { +class _VideoCustomControlsState extends TIMUIKitState with SingleTickerProviderStateMixin { late VideoPlayerValue _latestValue; bool _hideStuff = true; Timer? _hideTimer; @@ -43,6 +41,7 @@ class _VideoCustomControlsState extends TIMUIKitState late VideoPlayerController controller; ChewieController? _chewieController; + // We know that _chewieController is set in didChangeDependencies ChewieController get chewieController => _chewieController!; @@ -76,18 +75,11 @@ class _VideoCustomControlsState extends TIMUIKitState child: Stack( alignment: Alignment.center, children: [ - if (_latestValue.isBuffering) - const Center( - child: CircularProgressIndicator(color: Colors.white)) - else - _buildHitArea(), + if (_latestValue.isBuffering) const Center(child: CircularProgressIndicator(color: Colors.white)) else _buildHitArea(), Positioned( bottom: 0, width: MediaQuery.of(context).size.width, - child: Column(children: [ - _buildVideoControlBar(context), - _buildBottomBar() - ]), + child: Column(children: [_buildVideoControlBar(context), _buildBottomBar()]), ), if (isLoading) Container( @@ -143,37 +135,50 @@ class _VideoCustomControlsState extends TIMUIKitState margin: const EdgeInsets.fromLTRB(20, 0, 20, 20), child: Row( children: [ - IconButton( - icon: Image.asset( - 'images/close.png', - package: 'tencent_cloud_chat_uikit', + SizedBox( + width: 48, + height: 48, + child: IconButton( + icon: Image.asset( + 'images/close.png', + package: 'tencent_cloud_chat_uikit', + ), + iconSize: 30, + onPressed: () { + if (_latestValue.isPlaying) { + _playPause(); + } + Navigator.of(context).pop(); + }, ), - iconSize: 30, - onPressed: () { - if (_latestValue.isPlaying) { - _playPause(); - } - Navigator.of(context).pop(); - }, ), Expanded(child: Container()), - IconButton( - icon: Image.asset( - 'images/download.png', - package: 'tencent_cloud_chat_uikit', - ), - iconSize: 30, - onPressed: () async { - setState(() { - isLoading = true; - }); - await widget.downloadFn(); - Future.delayed(const Duration(milliseconds: 200),(){ + SizedBox( + width: 48, + height: 48, + child: IconButton( + icon: Image.asset( + 'images/download.png', + package: 'tencent_cloud_chat_uikit', + ), + iconSize: 30, + onPressed: () async { setState(() { - isLoading = false; + isLoading = true; }); - }); - }, + await widget.downloadFn(); + Future.delayed( + const Duration(milliseconds: 200), + () { + setState( + () { + isLoading = false; + }, + ); + }, + ); + }, + ), ) ], ), @@ -194,14 +199,8 @@ class _VideoCustomControlsState extends TIMUIKitState child: Row( children: [ _buildPlayPause(controller, iconColor), - if (chewieController.isLive) - const Expanded(child: Text('LIVE')) - else - _buildPositionStart(iconColor), - if (chewieController.isLive) - const SizedBox() - else - _buildProgressBar(), + if (chewieController.isLive) const Expanded(child: Text('LIVE')) else _buildPositionStart(iconColor), + if (chewieController.isLive) const SizedBox() else _buildProgressBar(), if (!chewieController.isLive) _buildPositionEnd(iconColor), ], ), @@ -237,8 +236,7 @@ class _VideoCustomControlsState extends TIMUIKitState )); } - GestureDetector _buildPlayPause( - VideoPlayerController controller, Color color) { + GestureDetector _buildPlayPause(VideoPlayerController controller, Color color) { return GestureDetector( onTap: _playPause, child: Container( @@ -314,8 +312,7 @@ class _VideoCustomControlsState extends TIMUIKitState _hideStuff = true; chewieController.toggleFullScreen(); - _showAfterExpandCollapseTimer = - Timer(const Duration(milliseconds: 300), () { + _showAfterExpandCollapseTimer = Timer(const Duration(milliseconds: 300), () { setState(() { _cancelAndRestartTimer(); }); @@ -384,11 +381,7 @@ class _VideoCustomControlsState extends TIMUIKitState _startHideTimer(); }, colors: chewieController.materialProgressColors ?? - ChewieProgressColors( - playedColor: Colors.white, - handleColor: Colors.white, - bufferedColor: Colors.white38, - backgroundColor: Colors.white24), + ChewieProgressColors(playedColor: Colors.white, handleColor: Colors.white, bufferedColor: Colors.white38, backgroundColor: Colors.white24), ), ), ); @@ -411,8 +404,7 @@ class _PlaybackSpeedDialog extends TIMUIKitStatelessWidget { Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { final TUITheme theme = value.theme; - final Color selectedColor = - theme.primaryColor ?? Theme.of(context).primaryColor; + final Color selectedColor = theme.primaryColor ?? Theme.of(context).primaryColor; return ListView.builder( shrinkWrap: true, diff --git a/pubspec.lock b/pubspec.lock index 9f072b5..fb57864 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -301,10 +301,10 @@ packages: dependency: transitive description: name: dart_internal - sha256: "689dccc3d5f62affd339534cca548dce12b3a6b32f0f10861569d3025efc0567" + sha256: "04145b91ccec450325fee75692b1ab62eb615e8892c334f0f4d31c696a857873" url: "https://pub.dev" source: hosted - version: "0.2.9" + version: "0.2.10" dart_style: dependency: transitive description: @@ -373,18 +373,18 @@ packages: dependency: "direct main" description: name: extended_text - sha256: "7096a1e9a029534257d70f7dafb2798f932d589079e67ef3f58fdf0805f2f627" + sha256: "7f382de3af12992e34bd72ddd36becf90c4720900af126cb9859f0189af71ffe" url: "https://pub.dev" source: hosted - version: "12.0.0" + version: "13.0.0" extended_text_field: dependency: "direct main" description: name: extended_text_field - sha256: ed9655c70a47a54c7cc689cf7f89a2bde9ab7b530150b4d1808b7aa7eb8cdf90 + sha256: ee139de7c2b2a9d806ddd5fdfef5c728cf475298a7ce5834c5b822ef1e6225d7 url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.0.0" extended_text_library: dependency: transitive description: @@ -534,14 +534,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.0.16" - flutter_slidable_for_tencent_im: + flutter_slidable: dependency: "direct main" description: - name: flutter_slidable_for_tencent_im - sha256: "425faab6304305dd7d38aef448af02acd65f425bf2bd47ce3b70b0b4e714c17b" + name: flutter_slidable + sha256: "19ed4813003a6ff4e9c6bcce37e792a2a358919d7603b2b31ff200229191e44c" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "3.0.1" flutter_svg: dependency: "direct main" description: @@ -831,18 +831,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" mime: dependency: transitive description: @@ -1657,5 +1657,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <3.3.0" - flutter: ">=3.16.0" + dart: ">=3.3.0 <3.4.0" + flutter: ">=3.19.0" diff --git a/pubspec.yaml b/pubspec.yaml index b81e686..e087925 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,11 +1,10 @@ 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.4.1 +version: 2.5.0 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 -# publish_to: none platforms: android: ios: @@ -15,7 +14,7 @@ platforms: environment: sdk: '>=3.0.0 <4.0.0' - flutter: ">=3.13.0" + flutter: ">=3.19.0" dependencies: flutter: @@ -31,7 +30,7 @@ dependencies: tencent_super_tooltip: ^0.0.1 video_player: ^2.7.0 chewie_for_us: ^1.5.0 - flutter_slidable_for_tencent_im: ^1.4.0 + flutter_slidable: ^3.0.1 flutter_plugin_record_plus: ^0.0.16 azlistview_all_platforms: ^2.1.2 lpinyin: ^2.0.3 @@ -45,8 +44,8 @@ dependencies: wechat_camera_picker: ^4.2.0-dev.2 flutter_easyrefresh: ^2.2.1 extended_image: ^8.2.0 - extended_text_field: ^13.0.0 - extended_text: ^12.0.0 + extended_text_field: ^14.0.0 + extended_text: ^13.0.0 package_info_plus: ^4.0.1 loading_animation_widget: ^1.1.0+3 permission_handler: ^10.2.0