tencent_cloud_chat_uikit source code update to version 5.0.1+3

This commit is contained in:
vinsonswang 2025-12-03 15:06:50 +08:00
parent aecb38a604
commit 214558c7f4
9 changed files with 140 additions and 33 deletions

View File

@ -1,3 +1,23 @@
# 5.0.1+3
* Optimize UI refresh timing when joining a call midway.
# 5.0.1+2
* Optimize the dependency of the internationalization plugin intl.
# 5.0.1+1
* Fixed the issue of sending files on the web platform.
* Fixed the issue where the custom background color of text messages did not take effect.
# 5.0.1
* Optimize the display direction of C2C audio and video call prompt messages.
# 5.0.0+2
* Fixed the issue that the chat page avatar rounded corner configuration did not take effect.
* Fixed the issue where clicking multiple voice messages in succession would display the playback animation at the same time.
# 5.0.0+1
* Add the isExcludedFromUnreadCount field setting to the sendMessage method of MessageServiceImpl
# 5.0.0 # 5.0.0
* Migrate to Flutter 3.29.0. * Migrate to Flutter 3.29.0.

View File

@ -321,6 +321,7 @@ class MessageServiceImpl extends MessageService {
localCustomData: localCustomData, localCustomData: localCustomData,
cloudCustomData: cloudCustomData, cloudCustomData: cloudCustomData,
isExcludedFromContentModeration: isExcludedFromContentModeration, isExcludedFromContentModeration: isExcludedFromContentModeration,
isExcludedFromUnreadCount: isExcludedFromUnreadCount,
); );
if (result.code != 0) { if (result.code != 0) {
String recommendText = ErrorMessageConverter.getErrorMessage(result.code); String recommendText = ErrorMessageConverter.getErrorMessage(result.code);

View File

@ -15,6 +15,8 @@ import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message.dart'; if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_change_info.dart' import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_change_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message_change_info.dart'; if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message_change_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_user_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart' import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_value_callback.dart'; if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_value_callback.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_base.dart';
@ -81,6 +83,18 @@ typedef MessageItemContent = Widget? Function(
VoidCallback clearJump, VoidCallback clearJump,
); );
class RenderingDirectionResult {
final bool? isSelf;
final V2TimUserFullInfo? userInfo;
const RenderingDirectionResult({
this.isSelf,
this.userInfo,
});
}
typedef RenderingDirectionCallback = RenderingDirectionResult? Function(V2TimMessage message);
class MessageHoverControlItem { class MessageHoverControlItem {
String name; String name;
Widget icon; Widget icon;
@ -131,6 +145,8 @@ class MessageItemBuilder {
/// message nick name builder /// message nick name builder
final MessageNickNameBuilder? messageNickNameBuilder; final MessageNickNameBuilder? messageNickNameBuilder;
final RenderingDirectionCallback? renderingDirectionCallback;
MessageItemBuilder({ MessageItemBuilder({
this.locationMessageItemBuilder, this.locationMessageItemBuilder,
this.textMessageItemBuilder, this.textMessageItemBuilder,
@ -145,6 +161,7 @@ class MessageItemBuilder {
this.mergerMessageItemBuilder, this.mergerMessageItemBuilder,
this.messageRowBuilder, this.messageRowBuilder,
this.messageNickNameBuilder, this.messageNickNameBuilder,
this.renderingDirectionCallback,
}); });
} }
@ -283,7 +300,9 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
/// If provided, the default message action functionality will appear in the right-click context menu instead. /// If provided, the default message action functionality will appear in the right-click context menu instead.
final Widget? Function(V2TimMessage message)? customMessageHoverBarOnDesktop; final Widget? Function(V2TimMessage message)? customMessageHoverBarOnDesktop;
const TIMUIKitHistoryMessageListItem( final RenderingDirectionCallback? renderingDirectionCallback;
TIMUIKitHistoryMessageListItem(
{Key? key, {Key? key,
required this.message, required this.message,
@Deprecated( @Deprecated(
@ -312,7 +331,8 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
this.textFieldController, this.textFieldController,
this.onSecondaryTapForOthersPortrait, this.onSecondaryTapForOthersPortrait,
this.groupMemberInfo, this.groupMemberInfo,
this.customMessageHoverBarOnDesktop}) this.customMessageHoverBarOnDesktop,
this.renderingDirectionCallback,})
: super(key: key); : super(key: key);
@override @override
@ -366,6 +386,7 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
final GlobalKey _key = GlobalKey(); final GlobalKey _key = GlobalKey();
bool isShowWideToolTip = false; bool isShowWideToolTip = false;
TapDownDetails? _tapDetails; TapDownDetails? _tapDetails;
final CoreServicesImpl _coreServicesImpl = serviceLocator<CoreServicesImpl>();
@override @override
void initState() { void initState() {
@ -415,7 +436,19 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
final msgType = messageItem.elemType; final msgType = messageItem.elemType;
final isShowJump = (model.jumpMsgID == messageItem.msgID) && (messageItem.msgID?.isNotEmpty ?? false); final isShowJump = (model.jumpMsgID == messageItem.msgID) && (messageItem.msgID?.isNotEmpty ?? false);
final MessageItemBuilder? messageItemBuilder = widget.messageItemBuilder; final MessageItemBuilder? messageItemBuilder = widget.messageItemBuilder;
final isFromSelf = messageItem.isSelf ?? true;
RenderingDirectionResult? overrideIsSelfResult;
if (widget.renderingDirectionCallback != null) {
overrideIsSelfResult = widget.renderingDirectionCallback!(messageItem);
}
bool isFromSelf = true;
if (overrideIsSelfResult != null && overrideIsSelfResult.isSelf != null) {
isFromSelf = overrideIsSelfResult.isSelf!;
} else {
isFromSelf = messageItem.isSelf ?? true;
}
void clearJump() { void clearJump() {
Future.delayed(const Duration(milliseconds: 100), () { Future.delayed(const Duration(milliseconds: 100), () {
model.jumpMsgID = ""; model.jumpMsgID = "";
@ -456,7 +489,7 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
message: messageItem, message: messageItem,
soundElem: messageItem.soundElem!, soundElem: messageItem.soundElem!,
msgID: messageItem.msgID ?? "", msgID: messageItem.msgID ?? "",
isFromSelf: messageItem.isSelf ?? true, isFromSelf: isFromSelf,
clearJump: clearJump, clearJump: clearJump,
isShowJump: isShowJump, isShowJump: isShowJump,
localCustomInt: messageItem.localCustomInt, localCustomInt: messageItem.localCustomInt,
@ -501,7 +534,7 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
TIMUIKitTextElem( TIMUIKitTextElem(
chatModel: model, chatModel: model,
message: messageItem, message: messageItem,
isFromSelf: messageItem.isSelf ?? true, isFromSelf: isFromSelf,
clearJump: clearJump, clearJump: clearJump,
isShowJump: isShowJump, isShowJump: isShowJump,
borderRadius: widget.themeData?.messageBorderRadius, borderRadius: widget.themeData?.messageBorderRadius,
@ -542,7 +575,7 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
message: messageItem, message: messageItem,
messageID: messageItem.msgID, messageID: messageItem.msgID,
fileElem: messageItem.fileElem, fileElem: messageItem.fileElem,
isSelf: messageItem.isSelf ?? true, isSelf: isFromSelf,
clearJump: clearJump, clearJump: clearJump,
isShowJump: isShowJump, isShowJump: isShowJump,
isShowMessageReaction: widget.isUseMessageReaction, isShowMessageReaction: widget.isUseMessageReaction,
@ -1149,7 +1182,21 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
final TUITheme theme = value.theme; final TUITheme theme = value.theme;
final message = widget.message; final message = widget.message;
final msgType = message.elemType; final msgType = message.elemType;
final isSelf = message.isSelf ?? true;
RenderingDirectionResult? renderingDirectionResult;
if (widget.renderingDirectionCallback != null) {
renderingDirectionResult = widget.renderingDirectionCallback!(message);
}
bool isSelf = true;
String? faceUrl = message.faceUrl;
if (renderingDirectionResult != null && renderingDirectionResult.isSelf != null) {
isSelf = renderingDirectionResult.isSelf!;
faceUrl = renderingDirectionResult.userInfo?.faceUrl;
} else {
isSelf = message.isSelf ?? true;
}
final isGroupTipsMsg = msgType == MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS; final isGroupTipsMsg = msgType == MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS;
final revokeStatus = isRevokeMessage(message, model); final revokeStatus = isRevokeMessage(message, model);
@ -1323,7 +1370,8 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
width: 40, width: 40,
height: 40, height: 40,
child: Avatar( child: Avatar(
faceUrl: message.faceUrl ?? "", borderRadius: widget.themeData?.avatarBorderRadius,
faceUrl: faceUrl ?? "",
showName: MessageUtils.getDisplayName(message), showName: MessageUtils.getDisplayName(message),
), ),
), ),
@ -1414,7 +1462,7 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
TIMUIKitTextTranslationElem( TIMUIKitTextTranslationElem(
message: message, message: message,
customEmojiStickerList: widget.customEmojiStickerList, customEmojiStickerList: widget.customEmojiStickerList,
isFromSelf: message.isSelf ?? true, isFromSelf: isSelf,
isShowJump: false, isShowJump: false,
clearJump: () {}, clearJump: () {},
chatModel: model), chatModel: model),
@ -1443,7 +1491,9 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
} }
}, },
child: Avatar( child: Avatar(
faceUrl: message.faceUrl ?? "", showName: MessageUtils.getDisplayName(message)), borderRadius: widget.themeData?.avatarBorderRadius,
faceUrl: faceUrl ?? "",
showName: MessageUtils.getDisplayName(message)),
), ),
), ),
], ],

View File

@ -188,7 +188,8 @@ class _TIMUIKitHistoryMessageListContainerState extends TIMUIKitState<TIMUIKitHi
allowAtUserWhenReply: chatConfig.isAtWhenReply, allowAtUserWhenReply: chatConfig.isAtWhenReply,
allowAvatarTap: chatConfig.isAllowClickAvatar, allowAvatarTap: chatConfig.isAllowClickAvatar,
allowLongPress: chatConfig.isAllowLongPressMessage, allowLongPress: chatConfig.isAllowLongPressMessage,
isUseMessageReaction: chatConfig.isUseMessageReaction); isUseMessageReaction: chatConfig.isUseMessageReaction,
renderingDirectionCallback: widget.messageItemBuilder?.renderingDirectionCallback,);
}, },
tongueItemBuilder: widget.tongueItemBuilder, tongueItemBuilder: widget.tongueItemBuilder,
initFindingMsg: widget.initFindingMsg, initFindingMsg: widget.initFindingMsg,

View File

@ -77,11 +77,11 @@ class _TIMUIKitSoundElemState extends TIMUIKitState<TIMUIKitSoundElem> {
} else { } else {
SoundPlayer.play(url: stateElement.url!); SoundPlayer.play(url: stateElement.url!);
widget.chatModel.currentPlayedMsgId = widget.msgID; widget.chatModel.currentPlayedMsgId = widget.msgID;
setState(() {
isPlaying = widget.chatModel.currentPlayedMsgId != '' && widget.chatModel.currentPlayedMsgId == widget.msgID;
});
} }
setState(() {
isPlaying = widget.chatModel.currentPlayedMsgId != '' && widget.chatModel.currentPlayedMsgId == widget.msgID;
});
} }
downloadMessageDetailAndSave() async { downloadMessageDetailAndSave() async {
@ -201,6 +201,9 @@ class _TIMUIKitSoundElemState extends TIMUIKitState<TIMUIKitSoundElem> {
} }
} }
} }
isPlaying = widget.chatModel.currentPlayedMsgId != '' && widget.chatModel.currentPlayedMsgId == widget.msgID;
return GestureDetector( return GestureDetector(
onTap: () => _playSound(), onTap: () => _playSound(),
child: Container( child: Container(

View File

@ -193,7 +193,7 @@ class _TIMUIKitTextElemState extends TIMUIKitState<TIMUIKitTextElem> {
: (theme.chatMessageItemFromOthersBgColor); : (theme.chatMessageItemFromOthersBgColor);
final backgroundColor = final backgroundColor =
isShowJumpState ? const Color.fromRGBO(245, 166, 35, 1) : (defaultStyle ?? widget.backgroundColor); isShowJumpState ? const Color.fromRGBO(245, 166, 35, 1) : (widget.backgroundColor ?? defaultStyle);
return Container( return Container(
padding: widget.textPadding ?? EdgeInsets.all(isDesktopScreen ? 12 : 10), padding: widget.textPadding ?? EdgeInsets.all(isDesktopScreen ? 12 : 10),

View File

@ -472,27 +472,35 @@ class _TIMUIKitTextFieldLayoutWideState extends TIMUIKitState<TIMUIKitTextFieldL
try { try {
final convID = widget.conversationID; final convID = widget.conversationID;
final convType = widget.conversationType; final convType = widget.conversationType;
FilePickerResult? result = await FilePicker.platform.pickFiles(); if (PlatformUtils().isWeb) {
_removeOverlay(); final html.FileUploadInputElement uploadInput = html.FileUploadInputElement();
if (result != null && result.files.isNotEmpty) { uploadInput.accept = '*/*';
if (PlatformUtils().isWeb) { uploadInput.click();
html.Node? inputElem; _removeOverlay();
inputElem = html.document.getElementById("__file_picker_web-file-input")?.querySelector("input"); uploadInput.onChange.listen((event) {
fileName = result.files.single.name; final file = uploadInput.files?.first;
if (file != null) {
MessageUtils.handleMessageError( final fileName = file.name;
model.sendFileMessage(inputElement: inputElem, fileName: fileName, convID: convID, convType: convType), MessageUtils.handleMessageError(
context); model.sendFileMessage(inputElement: uploadInput, fileName: fileName, convID: convID, convType: convType),
} else { context);
} else {
throw TypeError();
}
});
} else {
FilePickerResult? result = await FilePicker.platform.pickFiles();
_removeOverlay();
if (result != null && result.files.isNotEmpty) {
File file = File(result.files.single.path!); File file = File(result.files.single.path!);
final int size = file.lengthSync(); final int size = file.lengthSync();
final String savePath = file.path; final String savePath = file.path;
MessageUtils.handleMessageError( 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();
} }
} else {
throw TypeError();
} }
} catch (e) { } catch (e) {
// ignore: avoid_print // ignore: avoid_print

View File

@ -7,6 +7,7 @@ import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart'; import 'package:provider/single_child_widget.dart';
import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart'; import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimGroupListener.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart' import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart'; if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_application.dart' import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_application.dart'
@ -234,6 +235,7 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
bool isInit = false; bool isInit = false;
final TUIChatGlobalModel chatGlobalModel = serviceLocator<TUIChatGlobalModel>(); final TUIChatGlobalModel chatGlobalModel = serviceLocator<TUIChatGlobalModel>();
bool _dragging = false; bool _dragging = false;
V2TimGroupListener? _groupListener;
final GlobalKey alignKey = GlobalKey(); final GlobalKey alignKey = GlobalKey();
final GlobalKey listContainerKey = GlobalKey(); final GlobalKey listContainerKey = GlobalKey();
@ -256,6 +258,7 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
if (kProfileMode) { if (kProfileMode) {
Frame.init(); Frame.init();
} }
_addGroupListener();
model.abstractMessageBuilder = widget.abstractMessageBuilder; model.abstractMessageBuilder = widget.abstractMessageBuilder;
model.onTapAvatar = widget.onTapAvatar; model.onTapAvatar = widget.onTapAvatar;
WidgetsBinding.instance.addPostFrameCallback((_) async { WidgetsBinding.instance.addPostFrameCallback((_) async {
@ -274,6 +277,7 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
if (kProfileMode) { if (kProfileMode) {
Frame.destroy(); Frame.destroy();
} }
_removeGroupListener();
model.dispose(); model.dispose();
} }
@ -308,6 +312,26 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
} }
} }
void _addGroupListener() {
_groupListener = V2TimGroupListener(
onGroupAttributeChanged: (
String groupID,
Map<String, String> groupAttributeMap,) {
if (groupID == widget.conversationID) {
_updateJoinInGroupCallWidget();
}
}
);
TencentImSDKPlugin.v2TIMManager.addGroupListener(listener: _groupListener!);
}
void _removeGroupListener() {
if (_groupListener != null) {
TencentImSDKPlugin.v2TIMManager.removeGroupListener(listener: _groupListener!);
_groupListener = null;
}
}
updateDraft() async { updateDraft() async {
final isTopic = widget.conversation.conversationID.contains("@TOPIC#"); final isTopic = widget.conversation.conversationID.contains("@TOPIC#");
if (isTopic) { if (isTopic) {

View File

@ -1,6 +1,6 @@
name: tencent_cloud_chat_uikit name: tencent_cloud_chat_uikit
description: A powerful chat UI component library and business logic for Tencent Cloud Chat, creating seamless in-app chat modules for delightful user experiences. description: A powerful chat UI component library and business logic for Tencent Cloud Chat, creating seamless in-app chat modules for delightful user experiences.
version: 5.0.0 version: 5.0.1+3
homepage: https://trtc.io/products/chat?utm_source=gfs&utm_medium=link&utm_campaign=%E6%B8%A0%E9%81%93&_channel_track_key=k6WgfCKn 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 repository: https://github.com/TencentCloud/chat-uikit-flutter
documentation: https://comm.qq.com/im/doc/flutter/en/TUIKit/readme.html documentation: https://comm.qq.com/im/doc/flutter/en/TUIKit/readme.html
@ -24,14 +24,14 @@ dependencies:
tencent_chat_i18n_tool: ^2.3.8 tencent_chat_i18n_tool: ^2.3.8
adaptive_action_sheet: ^2.0.1 adaptive_action_sheet: ^2.0.1
provider: ^6.0.1 provider: ^6.0.1
intl: ^0.19.0 intl: any
get_it: ^7.2.0 get_it: ^7.2.0
dotted_border: ^2.0.0+2 dotted_border: ^2.0.0+2
flutter_svg: ^2.0.6 flutter_svg: ^2.0.6
image_picker: ^0.8.9 image_picker: ^0.8.9
file_picker: ^9.0.2 file_picker: ^9.0.2
tencent_super_tooltip: ^0.0.1 tencent_super_tooltip: ^0.0.1
better_player_plus: '>=1.0.4 <=1.0.5' better_player_plus: ^1.0.8
video_player: ^2.9.2 video_player: ^2.9.2
chewie: '>=1.8.4 <=1.8.5' chewie: '>=1.8.4 <=1.8.5'
flutter_slidable_plus_plus: ^0.1.0 flutter_slidable_plus_plus: ^0.1.0