From cc76651dba1334b14ae616f43c97bcb06c60a547 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 5 Jan 2026 21:14:54 +0800 Subject: [PATCH] refactor: use official upstream code for more panel and icon SVGs - Replace tim_uikit_more_panel.dart with official upstream version - Replace images/photo.svg, images/screen.svg, images/file.svg with official upstream versions - Remove all local customizations to avoid compatibility issues - Official SVGs have proper fill attributes (#5C6168) ensuring correct rendering --- LOCAL_CHANGES.md | 12 +- images/file.svg | 15 +- images/photo.svg | 17 +- images/screen.svg | 13 +- .../tim_uikit_more_panel.dart | 190 +++++------------- 5 files changed, 99 insertions(+), 148 deletions(-) diff --git a/LOCAL_CHANGES.md b/LOCAL_CHANGES.md index 8ddc20f..b5b75b8 100644 --- a/LOCAL_CHANGES.md +++ b/LOCAL_CHANGES.md @@ -26,13 +26,13 @@ * `Positioned` 底部距离从 `20` 调整为 `50`。 * `Positioned` 左右距离从 `20` 调整为 `10`。 -### `lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_more_panel.dart` -* **修改日期**: 2026-01-05 -* **修改目的**: 修复底部"照片"、"文件"图标显示为纯黑色的问题。 +### `lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_more_panel.dart` 及相关 SVG +* **修改日期**: 2026-01-05 +* **修改目的**: 完全使用官方 upstream 版本,避免本地定制导致的兼容性问题。 * **详细改动**: - * 将本地 `images/photo.svg` 替换为官方 SDK 的 `images/svg/send_image.svg`。 - * 将本地 `images/file.svg` 替换为官方 SDK 的 `images/svg/send_file.svg`。 - * **原因**: 在上游同步时,本地 SVG 文件被覆盖为缺少 `fill` 属性的版本,导致渲染为黑色。 + * 从 upstream/main 同步了 `tim_uikit_more_panel.dart` 的完整官方代码。 + * 从 upstream/main 同步了 `images/photo.svg`、`images/screen.svg`、`images/file.svg` 官方资源。 + * 移除了之前的所有本地修改(包括使用 `images/svg/send_image.svg` 等的尝试)。 ### `scripts/sync_from_upstream.sh` * **修改日期**: 2026-01-05 diff --git a/images/file.svg b/images/file.svg index ba5f2d1..cc0fb6d 100644 --- a/images/file.svg +++ b/images/file.svg @@ -1 +1,14 @@ - \ No newline at end of file + + + 编组 5 + + + + + + + + + + + diff --git a/images/photo.svg b/images/photo.svg index 838ca8b..2e8b1b2 100644 --- a/images/photo.svg +++ b/images/photo.svg @@ -1 +1,16 @@ - \ No newline at end of file + + + 编组 5 + + + + + + + + + + + + + diff --git a/images/screen.svg b/images/screen.svg index d58b683..60c1170 100644 --- a/images/screen.svg +++ b/images/screen.svg @@ -1 +1,12 @@ - \ No newline at end of file + + + 编组 3 + + + + + + + + + diff --git a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_more_panel.dart b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_more_panel.dart index 1f00c06..229e35b 100644 --- a/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_more_panel.dart +++ b/lib/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_more_panel.dart @@ -72,8 +72,7 @@ class MorePanelItem { final Widget icon; final Function(BuildContext context)? onTap; - MorePanelItem( - {this.onTap, required this.icon, required this.id, required this.title}); + MorePanelItem({this.onTap, required this.icon, required this.id, required this.title}); } class MorePanel extends StatefulWidget { @@ -85,11 +84,7 @@ class MorePanel extends StatefulWidget { final MorePanelConfig? morePanelConfig; - const MorePanel( - {required this.conversationID, - required this.conversationType, - Key? key, - this.morePanelConfig}) + const MorePanel({required this.conversationID, required this.conversationType, Key? key, this.morePanelConfig}) : super(key: key); @override @@ -98,8 +93,7 @@ class MorePanel extends StatefulWidget { class _MorePanelState extends TIMUIKitState { final ImagePicker _picker = ImagePicker(); - final TUISelfInfoViewModel _selfInfoViewModel = - serviceLocator(); + final TUISelfInfoViewModel _selfInfoViewModel = serviceLocator(); Uint8List? fileContent; String? fileName; File? tempFile; @@ -120,8 +114,7 @@ class _MorePanelState extends TIMUIKitState { isInstallCallkit = value; }); }); - _betterPlayerController = - BetterPlayerController(const BetterPlayerConfiguration()); + _betterPlayerController = BetterPlayerController(const BetterPlayerConfiguration()); } } @@ -144,11 +137,9 @@ class _MorePanelState extends TIMUIKitState { height: 64, width: 64, margin: const EdgeInsets.only(bottom: 4), - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(5))), + decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(5))), child: SvgPicture.asset( - "images/svg/send_image.svg", + "images/photo.svg", package: 'tencent_cloud_chat_uikit', height: 64, width: 64, @@ -165,9 +156,7 @@ class _MorePanelState extends TIMUIKitState { height: 64, width: 64, margin: const EdgeInsets.only(bottom: 4), - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(5))), + decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(5))), child: SvgPicture.asset( "images/screen.svg", package: 'tencent_cloud_chat_uikit', @@ -186,9 +175,7 @@ class _MorePanelState extends TIMUIKitState { height: 64, width: 64, margin: const EdgeInsets.only(bottom: 4), - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(5))), + decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(5))), child: Image.asset( "images/take_video.png", package: 'tencent_cloud_chat_uikit', @@ -212,11 +199,9 @@ class _MorePanelState extends TIMUIKitState { height: 64, width: 64, margin: const EdgeInsets.only(bottom: 4), - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(5))), + decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(5))), child: SvgPicture.asset( - "images/svg/send_image.svg", + "images/photo.svg", package: 'tencent_cloud_chat_uikit', height: 64, width: 64, @@ -238,11 +223,8 @@ class _MorePanelState extends TIMUIKitState { height: 64, width: 64, margin: const EdgeInsets.only(bottom: 4), - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(5))), - child: - Icon(Icons.video_file, color: hexToColor("5c6168"), size: 26), + decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(5))), + child: Icon(Icons.video_file, color: hexToColor("5c6168"), size: 26), )), MorePanelItem( id: "file", @@ -259,11 +241,9 @@ class _MorePanelState extends TIMUIKitState { height: 64, width: 64, margin: const EdgeInsets.only(bottom: 4), - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(5))), + decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(5))), child: SvgPicture.asset( - "images/svg/send_file.svg", + "images/file.svg", package: 'tencent_cloud_chat_uikit', height: 64, width: 64, @@ -285,9 +265,7 @@ class _MorePanelState extends TIMUIKitState { height: 64, width: 64, margin: const EdgeInsets.only(bottom: 4), - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(5))), + decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(5))), child: SvgPicture.asset( "images/video-call.svg", package: 'tencent_cloud_chat_uikit', @@ -311,9 +289,7 @@ class _MorePanelState extends TIMUIKitState { height: 64, width: 64, margin: const EdgeInsets.only(bottom: 4), - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(5))), + decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(5))), child: SvgPicture.asset( "images/voice-call.svg", package: 'tencent_cloud_chat_uikit', @@ -352,11 +328,9 @@ class _MorePanelState extends TIMUIKitState { }).toList(); } - _sendVideoMessage(String originFilePath, int duration, int size, - TUIChatSeparateViewModel model) async { + _sendVideoMessage(String originFilePath, int duration, int size, TUIChatSeparateViewModel model) async { if (size >= MorePanelConfig.VIDEO_MAX_SIZE) { - onTIMCallback(TIMCallback( - type: TIMCallbackType.INFO, infoRecommendText: TIM_t("文件大小超出了限制"))); + onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("文件大小超出了限制"))); return; } @@ -365,9 +339,7 @@ class _MorePanelState extends TIMUIKitState { final convID = widget.conversationID; final convType = widget.conversationType; - String tempPath = (await getTemporaryDirectory()).path + - p.basename(originFilePath) + - ".jpeg"; + String tempPath = (await getTemporaryDirectory()).path + p.basename(originFilePath) + ".jpeg"; await plugin.getVideoThumbnail( srcFile: originFilePath, @@ -379,11 +351,7 @@ class _MorePanelState extends TIMUIKitState { ); MessageUtils.handleMessageError( model.sendVideoMessage( - videoPath: originFilePath, - duration: duration, - snapshotPath: tempPath, - convID: convID, - convType: convType), + videoPath: originFilePath, duration: duration, snapshotPath: tempPath, convID: convID, convType: convType), context); } @@ -443,47 +411,34 @@ class _MorePanelState extends TIMUIKitState { if (filePath != null) { if (type == AssetType.image) { if (size >= MorePanelConfig.IMAGE_MAX_SIZE) { - onTIMCallback(TIMCallback( - type: TIMCallbackType.INFO, - infoRecommendText: TIM_t("文件大小超出了限制"))); + onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("文件大小超出了限制"))); return; } MessageUtils.handleMessageError( - model.sendImageMessage( - imagePath: filePath, - convID: convID, - convType: convType), - context); + model.sendImageMessage(imagePath: filePath, convID: convID, convType: convType), context); } if (type == AssetType.video) { - _sendVideoMessage(originFile!.path, - asset.videoDuration.inSeconds, size, model); + _sendVideoMessage(originFile!.path, asset.videoDuration.inSeconds, size, model); } } } } } else { - FilePickerResult? result = - await FilePicker.platform.pickFiles(type: FileType.media); + FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.media); if (result != null && result.files.isNotEmpty) { File file = File(result.files.single.path!); final String savePath = file.path; - final String type = TencentUtils.getFileType( - savePath.split(".")[savePath.split(".").length - 1]) - .split("/")[0]; + final String type = + TencentUtils.getFileType(savePath.split(".")[savePath.split(".").length - 1]).split("/")[0]; if (type == "image") { MessageUtils.handleMessageError( - model.sendImageMessage( - imagePath: savePath, convID: convID, convType: convType), - context); + model.sendImageMessage(imagePath: savePath, convID: convID, convType: convType), context); } else if (type == "video") { MessageUtils.handleMessageError( - model.sendVideoMessage( - videoPath: savePath, convID: convID, convType: convType), - context); + model.sendVideoMessage(videoPath: savePath, convID: convID, convType: convType), context); } } else { throw TypeError(); @@ -494,8 +449,7 @@ class _MorePanelState extends TIMUIKitState { } } - _sendImageFromCamera(TUIChatSeparateViewModel model, TUITheme theme, - {required isVideo}) async { + _sendImageFromCamera(TUIChatSeparateViewModel model, TUITheme theme, {required isVideo}) async { try { if (!await Permissions.checkPermission( context, @@ -522,25 +476,18 @@ class _MorePanelState extends TIMUIKitState { final size = await originFile!.length(); if (!isVideo) { if (size >= MorePanelConfig.IMAGE_MAX_SIZE) { - onTIMCallback(TIMCallback( - type: TIMCallbackType.INFO, - infoRecommendText: TIM_t("文件大小超出了限制"))); + onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("文件大小超出了限制"))); return; } MessageUtils.handleMessageError( - model.sendImageMessage( - imagePath: originFile.path, convID: convID, convType: convType), - context); + model.sendImageMessage(imagePath: originFile.path, convID: convID, convType: convType), context); } else { // 监听视频准备完成事件 _betterPlayerController.addEventsListener((event) { - if (event.betterPlayerEventType == - BetterPlayerEventType.initialized) { + if (event.betterPlayerEventType == BetterPlayerEventType.initialized) { // 获取视频时长(单位:秒) - int durationInSeconds = _betterPlayerController - .videoPlayerController?.value.duration?.inSeconds ?? - 0; + int durationInSeconds = _betterPlayerController.videoPlayerController?.value.duration?.inSeconds ?? 0; _sendVideoMessage(originFile!.path, durationInSeconds, size, model); } }); @@ -567,17 +514,12 @@ class _MorePanelState extends TIMUIKitState { fileContent = imageContent; html.Node? inputElem; - inputElem = html.document - .getElementById("__image_picker_web-file-input") - ?.querySelector("input"); + inputElem = html.document.getElementById("__image_picker_web-file-input")?.querySelector("input"); final convID = widget.conversationID; final convType = widget.conversationType; MessageUtils.handleMessageError( model.sendImageMessage( - inputElement: inputElem, - imagePath: tempFile?.path, - convID: convID, - convType: convType), + inputElement: inputElem, imagePath: tempFile?.path, convID: convID, convType: convType), context); } catch (e) { outputLogger.i("_sendFileErr: ${e.toString()}"); @@ -593,25 +535,18 @@ class _MorePanelState extends TIMUIKitState { fileContent = videoContent; if (fileName!.split(".")[fileName!.split(".").length - 1] != "mp4") { - onTIMCallback(TIMCallback( - type: TIMCallbackType.INFO, - infoRecommendText: TIM_t("视频消息仅限 mp4 格式"), - infoCode: 6660412)); + onTIMCallback( + TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频消息仅限 mp4 格式"), infoCode: 6660412)); return; } html.Node? inputElem; - inputElem = html.document - .getElementById("__image_picker_web-file-input") - ?.querySelector("input"); + inputElem = html.document.getElementById("__image_picker_web-file-input")?.querySelector("input"); final convID = widget.conversationID; final convType = widget.conversationType; MessageUtils.handleMessageError( model.sendVideoMessage( - inputElement: inputElem, - videoPath: tempFile?.path, - convID: convID, - convType: convType), + inputElement: inputElem, videoPath: tempFile?.path, convID: convID, convType: convType), context); } catch (e) { outputLogger.i("_sendFileErr: ${e.toString()}"); @@ -629,43 +564,29 @@ class _MorePanelState extends TIMUIKitState { if (result != null && result.files.isNotEmpty) { if (PlatformUtils().isWeb) { html.Node? inputElem; - inputElem = html.document - .getElementById("__file_picker_web-file-input") - ?.querySelector("input"); + inputElem = html.document.getElementById("__file_picker_web-file-input")?.querySelector("input"); fileName = result.files.single.name; MessageUtils.handleMessageError( - model.sendFileMessage( - inputElement: inputElem, - fileName: fileName, - convID: convID, - convType: convType), + model.sendFileMessage(inputElement: inputElem, fileName: fileName, convID: convID, convType: convType), context); return; } String? option2 = result.files.single.path ?? ""; - outputLogger - .i(TIM_t_para("选择成功{{option2}}", "选择成功$option2")(option2: option2)); + outputLogger.i(TIM_t_para("选择成功{{option2}}", "选择成功$option2")(option2: option2)); File file = File(result.files.single.path!); final int size = file.lengthSync(); if (size >= MorePanelConfig.FILE_MAX_SIZE) { - onTIMCallback(TIMCallback( - type: TIMCallbackType.INFO, - infoRecommendText: TIM_t("文件大小超出了限制"))); + onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("文件大小超出了限制"))); return; } final String savePath = file.path; MessageUtils.handleMessageError( - model.sendFileMessage( - filePath: savePath, - size: size, - convID: convID, - convType: convType), - context); + model.sendFileMessage(filePath: savePath, size: size, convID: convID, convType: convType), context); } else { throw TypeError(); } @@ -715,16 +636,13 @@ class _MorePanelState extends TIMUIKitState { bool hasCameraPermission = false; bool hasMicrophonePermission = false; if (type == TYPE_VIDEO) { - hasCameraPermission = - await Permissions.checkPermission(context, Permission.camera.value); - hasMicrophonePermission = await Permissions.checkPermission( - context, Permission.microphone.value); + hasCameraPermission = await Permissions.checkPermission(context, Permission.camera.value); + hasMicrophonePermission = await Permissions.checkPermission(context, Permission.microphone.value); if (!hasCameraPermission || !hasMicrophonePermission) { return; } } else { - hasMicrophonePermission = await Permissions.checkPermission( - context, Permission.microphone.value); + hasMicrophonePermission = await Permissions.checkPermission(context, Permission.microphone.value); if (!hasMicrophonePermission) { return; } @@ -746,9 +664,7 @@ class _MorePanelState extends TIMUIKitState { _tUICore.callService(TUICALLKIT_SERVICE_NAME, METHOD_NAME_CALL, { PARAM_NAME_TYPE: type, PARAM_NAME_USERIDS: inviteMember, - PARAM_NAME_GROUPID: widget.conversationType == ConvType.group - ? widget.conversationID - : "" + PARAM_NAME_GROUPID: widget.conversationType == ConvType.group ? widget.conversationID : "" }); } } else { @@ -769,8 +685,7 @@ class _MorePanelState extends TIMUIKitState { @override Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { final TUITheme theme = value.theme; - final TUIChatSeparateViewModel model = - Provider.of(context); + final TUIChatSeparateViewModel model = Provider.of(context); final screenWidth = MediaQuery.of(context).size.width; return Container( height: 248, @@ -807,15 +722,12 @@ class _MorePanelState extends TIMUIKitState { height: 64, width: 64, margin: const EdgeInsets.only(bottom: 4), - decoration: const BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(5))), + decoration: const BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(5))), child: item.icon, ), Text( item.title, - style: TextStyle( - fontSize: 12, color: theme.darkTextColor), + style: TextStyle(fontSize: 12, color: theme.darkTextColor), ) ], ),