tencent_cloud_chat_uikit source code update to version 4.0.1

This commit is contained in:
vinsonswang 2024-12-17 19:57:23 +08:00
parent 7a2d31ea71
commit eb2dd69ac9
14 changed files with 392 additions and 358 deletions

View File

@ -1,6 +1,10 @@
# 4.0.1
* Upgraded the plugin tim_ui_kit_sticker_plugin to 4.0.1.
* Use the 'useTencentCloudChatStickerPackageOldKeys' parameter in StickerPanelConfig to control whether the emoticon is compatible with version 3.x.
# 4.0.0
## Breaking changes
* Upgraded the plugin tim_ui_kit_sticker_plugin to 4.0.0, no longer supports QQ emoji and unicode emoji.
* Upgraded the plugin tim_ui_kit_sticker_plugin to 4.0.0.
* Delete the useQQStickerPackage and unicodeEmojiList parameters in StickerPanelConfig.
* Delete the isUseDefaultEmoji parameter in TIMUIKitChatConfig.
* Delete the isUseDefaultEmoji parameter in each widget.

View File

@ -368,9 +368,15 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
widget.message.textElem?.text ?? "",
widget.chatModel.chatConfig.isSupportMarkdownForTextMessage,
onLinkTap: widget.chatModel.chatConfig.onTapLink,
isUseQQPackage: widget
.chatModel.chatConfig.stickerPanelConfig?.useQQStickerPackage ??
true,
isUseTencentCloudChatPackage: widget.chatModel.chatConfig
.stickerPanelConfig?.useTencentCloudChatStickerPackage ??
true,
isUseTencentCloudChatPackageOldKeys: widget.chatModel.chatConfig
.stickerPanelConfig?.useTencentCloudChatStickerPackageOldKeys ??
false,
customEmojiStickerList: widget.customEmojiStickerList,
isEnableTextSelection:
widget.chatModel.chatConfig.isEnableTextSelection ?? false);
@ -434,12 +440,21 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
fontSize: isDesktopScreen ? 14 : 16,
height: widget.chatModel.chatConfig.textHeight),
specialTextSpanBuilder: DefaultSpecialTextSpanBuilder(
isUseQQPackage: widget.chatModel.chatConfig
.stickerPanelConfig?.useQQStickerPackage ??
true,
isUseTencentCloudChatPackage: widget
.chatModel
.chatConfig
.stickerPanelConfig
?.useTencentCloudChatStickerPackage ??
true,
isUseTencentCloudChatPackageOldKeys: widget
.chatModel
.chatConfig
.stickerPanelConfig
?.useTencentCloudChatStickerPackageOldKeys ??
false,
customEmojiStickerList: widget.customEmojiStickerList,
showAtBackground: true,
)),

View File

@ -165,9 +165,15 @@ class _TIMUIKitTextElemState extends TIMUIKitState<TIMUIKitTextElem> {
widget.message.textElem?.text ?? "",
widget.chatModel.chatConfig.isSupportMarkdownForTextMessage,
onLinkTap: widget.chatModel.chatConfig.onTapLink,
isUseQQPackage: widget
.chatModel.chatConfig.stickerPanelConfig?.useQQStickerPackage ??
true,
isUseTencentCloudChatPackage: widget.chatModel.chatConfig
.stickerPanelConfig?.useTencentCloudChatStickerPackage ??
true,
isUseTencentCloudChatPackageOldKeys: widget.chatModel.chatConfig
.stickerPanelConfig?.useTencentCloudChatStickerPackageOldKeys ??
false,
customEmojiStickerList: widget.customEmojiStickerList,
isEnableTextSelection:
widget.chatModel.chatConfig.isEnableTextSelection ?? false);
@ -232,12 +238,21 @@ class _TIMUIKitTextElemState extends TIMUIKitState<TIMUIKitTextElem> {
fontSize: isDesktopScreen ? 14 : 16,
height: widget.chatModel.chatConfig.textHeight),
specialTextSpanBuilder: DefaultSpecialTextSpanBuilder(
isUseQQPackage: widget.chatModel.chatConfig
.stickerPanelConfig?.useQQStickerPackage ??
true,
isUseTencentCloudChatPackage: widget
.chatModel
.chatConfig
.stickerPanelConfig
?.useTencentCloudChatStickerPackage ??
true,
isUseTencentCloudChatPackageOldKeys: widget
.chatModel
.chatConfig
.stickerPanelConfig
?.useTencentCloudChatStickerPackageOldKeys ??
false,
customEmojiStickerList: widget.customEmojiStickerList,
showAtBackground: true,
checkHttpLink: true,

View File

@ -122,9 +122,15 @@ class _TIMUIKitTextTranslationElemState
final textWithLink = LinkPreviewEntry.getHyperlinksText(translateText ?? "",
widget.chatModel.chatConfig.isSupportMarkdownForTextMessage,
onLinkTap: widget.chatModel.chatConfig.onTapLink,
isUseQQPackage: widget
.chatModel.chatConfig.stickerPanelConfig?.useQQStickerPackage ??
true,
isUseTencentCloudChatPackage: widget.chatModel.chatConfig
.stickerPanelConfig?.useTencentCloudChatStickerPackage ??
true,
isUseTencentCloudChatPackageOldKeys: widget.chatModel.chatConfig
.stickerPanelConfig?.useTencentCloudChatStickerPackageOldKeys ??
false,
customEmojiStickerList: widget.customEmojiStickerList,
isEnableTextSelection:
widget.chatModel.chatConfig.isEnableTextSelection ?? false);
@ -160,12 +166,21 @@ class _TIMUIKitTextTranslationElemState
fontSize: isDesktopScreen ? 14 : 16,
height: widget.chatModel.chatConfig.textHeight),
specialTextSpanBuilder: DefaultSpecialTextSpanBuilder(
isUseQQPackage: widget.chatModel.chatConfig
.stickerPanelConfig?.useQQStickerPackage ??
true,
isUseTencentCloudChatPackage: widget
.chatModel
.chatConfig
.stickerPanelConfig
?.useTencentCloudChatStickerPackage ??
true,
isUseTencentCloudChatPackageOldKeys: widget
.chatModel
.chatConfig
.stickerPanelConfig
?.useTencentCloudChatStickerPackageOldKeys ??
false,
customEmojiStickerList: widget.customEmojiStickerList,
showAtBackground: true,
)),

View File

@ -9,7 +9,9 @@ import 'emoji_text.dart';
class DefaultSpecialTextSpanBuilder extends SpecialTextSpanBuilder {
DefaultSpecialTextSpanBuilder({
this.isUseQQPackage = false,
this.isUseTencentCloudChatPackage = false,
this.isUseTencentCloudChatPackageOldKeys = false,
this.customEmojiStickerList = const [],
this.showAtBackground = false,
this.checkHttpLink = true,
@ -18,8 +20,12 @@ class DefaultSpecialTextSpanBuilder extends SpecialTextSpanBuilder {
/// whether show background for @somebody
final bool showAtBackground;
final bool isUseQQPackage;
final bool isUseTencentCloudChatPackage;
final bool isUseTencentCloudChatPackageOldKeys;
final bool checkHttpLink;
final List<CustomEmojiFaceData> customEmojiStickerList;
@ -37,6 +43,9 @@ class DefaultSpecialTextSpanBuilder extends SpecialTextSpanBuilder {
if (isStart(flag, EmojiText.flag)) {
return EmojiText(textStyle,
isUseTencentCloudChatPackage: isUseTencentCloudChatPackage,
isUseTencentCloudChatPackageOldKeys:
isUseTencentCloudChatPackageOldKeys,
isUseQQPackage: isUseQQPackage,
start: index! - (EmojiText.flag.length - 1),
customEmojiStickerList: customEmojiStickerList);
} else if (isStart(flag, HttpText.flag) && checkHttpLink) {

View File

@ -7,19 +7,25 @@ import 'package:tim_ui_kit_sticker_plugin/utils/tim_custom_face_data.dart';
class EmojiText extends SpecialText {
EmojiText(TextStyle? textStyle,
{this.start,
this.isUseQQPackage = false,
this.isUseTencentCloudChatPackage = false,
this.isUseTencentCloudChatPackageOldKeys = false,
this.customEmojiStickerList = const []})
: super(EmojiText.flag, ']', textStyle);
static const String flag = '[';
final int? start;
final bool isUseQQPackage;
final bool isUseTencentCloudChatPackage;
final bool isUseTencentCloudChatPackageOldKeys;
final List<CustomEmojiFaceData> customEmojiStickerList;
@override
InlineSpan finishText() {
final String key = toString();
final EmojiUtil emojiUtil = EmojiUtil(
isUseQQPackage: isUseQQPackage,
isUseTencentCloudChatPackage: isUseTencentCloudChatPackage,
isUseTencentCloudChatPackageOldKeys: isUseTencentCloudChatPackageOldKeys,
customEmojiStickerList: customEmojiStickerList);
if (emojiUtil.emojiMap.containsKey(key)) {
@ -30,11 +36,17 @@ class EmojiText extends SpecialText {
size = ts.fontSize! * 1.44;
}
if (isUseTencentCloudChatPackage == true &&
if (isUseQQPackage == true && (emojiUtil.emojiKeyCategoryMap["4349"]?.contains(key) ?? false)) {
return ImageSpan(AssetImage(emojiUtil.emojiMap[key]!, package: "tim_ui_kit_sticker_plugin"),
actualText: key,
imageWidth: size,
imageHeight: size,
start: start!,
// fit: BoxFit.cover,
margin: const EdgeInsets.all(0));
} else if (isUseTencentCloudChatPackage == true &&
(emojiUtil.emojiKeyCategoryMap["tcc1"]?.contains(key) ?? false)) {
return ImageSpan(
AssetImage(emojiUtil.emojiMap[key]!,
package: "tim_ui_kit_sticker_plugin"),
return ImageSpan(AssetImage(emojiUtil.emojiMap[key]!, package: "tim_ui_kit_sticker_plugin"),
actualText: key,
imageWidth: size,
imageHeight: size,
@ -59,7 +71,9 @@ class EmojiText extends SpecialText {
class EmojiUtil {
// Private constructor initializing the emoji data
EmojiUtil._internal(
{required this.isUseTencentCloudChatPackage,
{required this.isUseQQPackage,
required this.isUseTencentCloudChatPackage,
required this.isUseTencentCloudChatPackageOldKeys,
required this.customEmojiStickerList}) {
_emojiMap.addAll(loadDefaultEmojis());
@ -68,7 +82,9 @@ class EmojiUtil {
_emojiKeyCategoryMap["custom"] = customEmojis.$2;
}
final bool isUseQQPackage;
final bool isUseTencentCloudChatPackage;
final bool isUseTencentCloudChatPackageOldKeys;
final List<CustomEmojiFaceData> customEmojiStickerList;
// Load the default emojis into a Map
@ -77,12 +93,30 @@ class EmojiUtil {
for (final emojiGroup in TUIKitStickerConstData.emojiList) {
final groupName = emojiGroup.name;
final keyList = [];
if (isUseQQPackage && groupName == "4349") {
for (final emoji in emojiGroup.list) {
String emojiName = emoji.split('.png')[0];
defaultEmojiMap['[$emojiName]'] = '$_emojiFilePath/$groupName/$emojiName.png';
keyList.add('[$emojiName]');
final zhKey = TUIKitStickerConstData.emoji4349ZhMapList[emojiName];
defaultEmojiMap['[$zhKey]'] = '$_emojiFilePath/$groupName/$emojiName.png';
keyList.add('[$zhKey]');
}
_emojiKeyCategoryMap[groupName] = keyList;
}
if (isUseTencentCloudChatPackage && groupName == "tcc1") {
for (final emoji in emojiGroup.list) {
String emojiName = emoji.split('.png')[0];
defaultEmojiMap['[$emojiName]'] =
'$_emojiFilePath/$groupName/$emojiName.png';
keyList.add('[$emojiName]');
String compatibleEmojiName = emojiName;
if (isUseTencentCloudChatPackageOldKeys) {
// key
compatibleEmojiName = getCompatibleEmojiName(emojiName);
}
defaultEmojiMap['[$compatibleEmojiName]'] = '$_emojiFilePath/$groupName/$emojiName.png';
keyList.add('[$compatibleEmojiName]');
}
_emojiKeyCategoryMap[groupName] = keyList;
}
@ -97,8 +131,7 @@ class EmojiUtil {
for (final customEmojiGroup in customEmojiStickerList) {
for (final customEmoji in customEmojiGroup.list) {
String customEmojiName = customEmoji.split('.png')[0];
customEmojiMap['[$customEmojiName]'] =
'$_emojiFilePath/${customEmojiGroup.name}/$customEmojiName.png';
customEmojiMap['[$customEmojiName]'] = '$_emojiFilePath/${customEmojiGroup.name}/$customEmojiName.png';
keyList.add('[$customEmojiName]');
}
}
@ -125,10 +158,29 @@ class EmojiUtil {
// Factory constructor to return the singleton instance of EmojiUtil with custom parameters
factory EmojiUtil(
{bool isUseTencentCloudChatPackage = false,
{bool isUseQQPackage = false,
bool isUseTencentCloudChatPackage = false,
bool isUseTencentCloudChatPackageOldKeys = false,
List<CustomEmojiFaceData> customEmojiStickerList = const []}) {
return _instance ??= EmojiUtil._internal(
isUseQQPackage: isUseQQPackage,
customEmojiStickerList: customEmojiStickerList,
isUseTencentCloudChatPackage: isUseTencentCloudChatPackage);
isUseTencentCloudChatPackage: isUseTencentCloudChatPackage,
isUseTencentCloudChatPackageOldKeys: isUseTencentCloudChatPackageOldKeys);
}
static String getCompatibleEmojiName(String emojiName) {
String compatibleEmojiName = emojiName;
try {
compatibleEmojiName = emojiName.split('_')[1];
// Ok
if (compatibleEmojiName == 'Ok') {
compatibleEmojiName = 'OK';
}
} catch (e) {
print(e);
}
return compatibleEmojiName;
}
}

View File

@ -17,6 +17,7 @@ import 'package:tencent_cloud_chat_uikit/ui/utils/optimize_utils.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/TIMUIKitTextField/special_text/DefaultSpecialTextSpanBuilder.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/emoji_text.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_send_sound_message.dart';
import 'package:tencent_keyboard_visibility/tencent_keyboard_visibility.dart';
@ -37,6 +38,8 @@ class TIMUIKitTextFieldLayoutNarrow extends StatefulWidget {
/// Whether to use the default emoji
final bool isUseDefaultEmoji;
final bool isUseTencentCloudChatPackageOldKeys;
final TUIChatSeparateViewModel model;
/// background color
@ -103,6 +106,7 @@ class TIMUIKitTextFieldLayoutNarrow extends StatefulWidget {
required this.backSpaceText,
required this.addStickerToText,
required this.isUseDefaultEmoji,
this.isUseTencentCloudChatPackageOldKeys = false,
required this.languageType,
required this.textEditingController,
this.morePanelConfig,
@ -132,12 +136,10 @@ class TIMUIKitTextFieldLayoutNarrow extends StatefulWidget {
: super(key: key);
@override
State<TIMUIKitTextFieldLayoutNarrow> createState() =>
_TIMUIKitTextFieldLayoutNarrowState();
State<TIMUIKitTextFieldLayoutNarrow> createState() => _TIMUIKitTextFieldLayoutNarrowState();
}
class _TIMUIKitTextFieldLayoutNarrowState
extends TIMUIKitState<TIMUIKitTextFieldLayoutNarrow> {
class _TIMUIKitTextFieldLayoutNarrowState extends TIMUIKitState<TIMUIKitTextFieldLayoutNarrow> {
final TUISettingModel settingModel = serviceLocator<TUISettingModel>();
bool showMore = false;
@ -211,13 +213,16 @@ class _TIMUIKitTextFieldLayoutNarrowState
},
addCustomEmojiText: ((String singleEmojiName) {
String? emojiName = singleEmojiName.split('.png')[0];
final newText = TIM_t('[$emojiName]');
String compatibleEmojiName = emojiName;
if (widget.isUseTencentCloudChatPackageOldKeys) {
compatibleEmojiName = EmojiUtil.getCompatibleEmojiName(emojiName);
}
String newText = '[$compatibleEmojiName]';
widget.addStickerToText(newText);
setSendButton();
}),
defaultCustomEmojiStickerList: widget.isUseDefaultEmoji
? TUIKitStickerConstData.emojiList
: [])
defaultCustomEmojiStickerList: widget.isUseDefaultEmoji ? TUIKitStickerConstData.emojiList : [])
: StickerPanel(
isWideScreen: false,
sendTextMsg: () {
@ -237,7 +242,12 @@ class _TIMUIKitTextFieldLayoutNarrowState
},
addCustomEmojiText: ((String singleEmojiName) {
String? emojiName = singleEmojiName.split('.png')[0];
final newText = TIM_t('[$emojiName]');
String compatibleEmojiName = emojiName;
if (widget.isUseTencentCloudChatPackageOldKeys) {
compatibleEmojiName = EmojiUtil.getCompatibleEmojiName(emojiName);
}
String newText = '[$compatibleEmojiName]';
widget.addStickerToText(newText);
setSendButton();
}),
@ -246,10 +256,7 @@ class _TIMUIKitTextFieldLayoutNarrowState
}
if (showMore) {
return MorePanel(
morePanelConfig: widget.morePanelConfig,
conversationID: widget.conversationID,
conversationType: widget.conversationType);
return MorePanel(morePanelConfig: widget.morePanelConfig, conversationID: widget.conversationID, conversationType: widget.conversationType);
}
return const SizedBox(height: 0);
@ -271,8 +278,7 @@ class _TIMUIKitTextFieldLayoutNarrowState
return height;
} else if (showMore || showEmojiPanel) {
return 248.0 + (bottomPadding ?? 0.0);
} else if (widget.textEditingController.text.length >= 46 &&
showKeyboard == false) {
} else if (widget.textEditingController.text.length >= 46 && showKeyboard == false) {
return 25 + (bottomPadding ?? 0.0);
} else {
return bottomPadding ?? 0;
@ -325,20 +331,14 @@ class _TIMUIKitTextFieldLayoutNarrowState
}
String getAbstractMessage(V2TimMessage message) {
final String? customAbstractMessage =
widget.model.abstractMessageBuilder != null
? widget.model.abstractMessageBuilder!(message)
: null;
return customAbstractMessage ??
MessageUtils.getAbstractMessageAsync(
message, widget.model.groupMemberList ?? []);
final String? customAbstractMessage = widget.model.abstractMessageBuilder != null ? widget.model.abstractMessageBuilder!(message) : null;
return customAbstractMessage ?? MessageUtils.getAbstractMessageAsync(message, widget.model.groupMemberList ?? []);
}
_buildRepliedMessage(V2TimMessage? repliedMessage) {
final haveRepliedMessage = repliedMessage != null;
if (haveRepliedMessage) {
final String text =
"${MessageUtils.getDisplayName(repliedMessage)}:${getAbstractMessage(repliedMessage)}";
final String text = "${MessageUtils.getDisplayName(repliedMessage)}:${getAbstractMessage(repliedMessage)}";
return Container(
color: widget.backgroundColor ?? hexToColor("f5f5f6"),
alignment: Alignment.centerLeft,
@ -419,8 +419,7 @@ class _TIMUIKitTextFieldLayoutNarrowState
child: Column(
children: [
Container(
padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
constraints: const BoxConstraints(minHeight: 50),
child: Row(
children: [
@ -444,28 +443,24 @@ class _TIMUIKitTextFieldLayoutNarrowState
}
},
child: SvgPicture.asset(
showSendSoundText
? 'images/keyboard.svg'
: 'images/voice.svg',
showSendSoundText ? 'images/keyboard.svg' : 'images/voice.svg',
package: 'tencent_cloud_chat_uikit',
color: const Color.fromRGBO(68, 68, 68, 1),
height: 28,
width: 28,
),
),
const SizedBox(
width: 10,
),
Expanded(
child: showSendSoundText
? SendSoundMessage(
onDownBottom: widget.goDownBottom,
conversationID: widget.conversationID,
conversationType: widget.conversationType)
: Stack(children: [
Center(
child: KeyboardVisibility(
child: ExtendedTextField(
const SizedBox(
width: 10,
),
Expanded(
child: showSendSoundText
? SendSoundMessage(onDownBottom: widget.goDownBottom, conversationID: widget.conversationID, conversationType: widget.conversationType)
: Stack(
children: [
Center(
child: KeyboardVisibility(
child: ExtendedTextField(
maxLines: 4,
minLines: 1,
focusNode: widget.focusNode,
@ -479,24 +474,19 @@ class _TIMUIKitTextFieldLayoutNarrowState
});
},
keyboardType: TextInputType.multiline,
textInputAction:
PlatformUtils().isAndroid
? TextInputAction.newline
: TextInputAction.send,
textInputAction: PlatformUtils().isAndroid ? TextInputAction.newline : TextInputAction.send,
onEditingComplete: () {
widget.onSubmitted();
if (showKeyboard) {
widget.focusNode.requestFocus();
}
setState(() {
if (widget.textEditingController
.text.isEmpty) {
if (widget.textEditingController.text.isEmpty) {
showMoreButton = true;
}
});
},
textAlignVertical:
TextAlignVertical.top,
textAlignVertical: TextAlignVertical.top,
decoration: InputDecoration(
border: InputBorder.none,
hintStyle: const TextStyle(
@ -507,52 +497,42 @@ class _TIMUIKitTextFieldLayoutNarrowState
filled: true,
isDense: true,
hintText: widget.hintText ?? ''),
controller:
widget.textEditingController,
specialTextSpanBuilder: PlatformUtils()
.isWeb
controller: widget.textEditingController,
specialTextSpanBuilder: PlatformUtils().isWeb
? null
: DefaultSpecialTextSpanBuilder(
isUseTencentCloudChatPackage:
widget
.model
.chatConfig
.stickerPanelConfig
?.useTencentCloudChatStickerPackage ??
true,
customEmojiStickerList: widget
.customEmojiStickerList,
isUseQQPackage: widget.model.chatConfig.stickerPanelConfig?.useQQStickerPackage ?? true,
isUseTencentCloudChatPackage: widget.model.chatConfig.stickerPanelConfig?.useTencentCloudChatStickerPackage ?? true,
isUseTencentCloudChatPackageOldKeys: widget.model.chatConfig.stickerPanelConfig?.useTencentCloudChatStickerPackageOldKeys ?? false,
customEmojiStickerList: widget.customEmojiStickerList,
showAtBackground: true,
checkHttpLink: false,
)),
onChanged: (bool visibility) {
if (showKeyboard != visibility) {
setState(() {
showKeyboard = visibility;
});
}
onChanged: (bool visibility) {
if (showKeyboard != visibility) {
setState(() {
showKeyboard = visibility;
});
}
}),
),
RawKeyboardListener(
autofocus: true,
focusNode: FocusNode(),
onKey: (key) {
if (key is RawKeyDownEvent && key.logicalKey == LogicalKeyboardKey.backspace) {
if (widget.onDeleteText != null) {
widget.onDeleteText!(widget.textEditingController.text);
}
}
}, child: Container(),
),
]
),
RawKeyboardListener(
autofocus: true,
focusNode: FocusNode(),
onKey: (key) {
if (key is RawKeyDownEvent &&
key.logicalKey ==
LogicalKeyboardKey.backspace) {
if (widget.onDeleteText != null) {
widget.onDeleteText!(
widget.textEditingController.text);
}
}
},
child: Container(),
),
]),
),
const SizedBox(
width: 10,
),
),
const SizedBox(
width: 10,
),
if (widget.showSendEmoji)
InkWell(
onTap: () {
@ -560,25 +540,18 @@ class _TIMUIKitTextFieldLayoutNarrowState
widget.goDownBottom();
},
child: PlatformUtils().isWeb
? Icon(
showEmojiPanel
? Icons.keyboard_alt_outlined
: Icons.mood_outlined,
color: hexToColor("5c6168"),
size: 32)
? Icon(showEmojiPanel ? Icons.keyboard_alt_outlined : Icons.mood_outlined, color: hexToColor("5c6168"), size: 32)
: SvgPicture.asset(
showEmojiPanel
? 'images/keyboard.svg'
: 'images/face.svg',
showEmojiPanel ? 'images/keyboard.svg' : 'images/face.svg',
package: 'tencent_cloud_chat_uikit',
color: const Color.fromRGBO(68, 68, 68, 1),
height: 28,
width: 28,
),
),
const SizedBox(
width: 10,
),
const SizedBox(
width: 10,
),
if (widget.showMorePanel && showMoreButton)
InkWell(
onTap: () {
@ -587,8 +560,7 @@ class _TIMUIKitTextFieldLayoutNarrowState
widget.goDownBottom();
},
child: PlatformUtils().isWeb
? Icon(Icons.add_circle_outline_outlined,
color: hexToColor("5c6168"), size: 32)
? Icon(Icons.add_circle_outline_outlined, color: hexToColor("5c6168"), size: 32)
: SvgPicture.asset(
'images/add.svg',
package: 'tencent_cloud_chat_uikit',
@ -597,8 +569,7 @@ class _TIMUIKitTextFieldLayoutNarrowState
width: 28,
),
),
if ((isAndroidDevice() || isWebDevice()) &&
!showMoreButton)
if ((isAndroidDevice() || isWebDevice()) && !showMoreButton)
SizedBox(
height: 32.0,
child: ElevatedButton(
@ -620,10 +591,7 @@ class _TIMUIKitTextFieldLayoutNarrowState
),
),
AnimatedContainer(
duration: Duration(
milliseconds: (showKeyboard && PlatformUtils().isAndroid)
? 200
: 340),
duration: Duration(milliseconds: (showKeyboard && PlatformUtils().isAndroid) ? 200 : 340),
curve: Curves.fastOutSlowIn,
height: max(_getBottomHeight(), 0.0),
child: ListView(

View File

@ -30,6 +30,7 @@ import 'package:tencent_cloud_chat_uikit/ui/utils/optimize_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_shot.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/DefaultSpecialTextSpanBuilder.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/emoji_text.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/drag_widget.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/wide_popup.dart';
import 'package:universal_html/html.dart' as html;
@ -56,9 +57,7 @@ class DesktopControlBarItem {
required this.onClick,
this.showName,
this.size})
: assert(icon != null ||
TencentUtils.checkString(imgPath) != null ||
TencentUtils.checkString(svgPath) != null);
: assert(icon != null || TencentUtils.checkString(imgPath) != null || TencentUtils.checkString(svgPath) != null);
}
class DesktopControlBarConfig {
@ -93,6 +92,8 @@ class TIMUIKitTextFieldLayoutWide extends StatefulWidget {
/// Whether to use the default emoji
final bool isUseDefaultEmoji;
final bool isCompatibleWithTencentCloudChatPackageOldKeys;
final TUIChatSeparateViewModel model;
/// background color
@ -160,6 +161,7 @@ class TIMUIKitTextFieldLayoutWide extends StatefulWidget {
required this.backSpaceText,
required this.addStickerToText,
required this.isUseDefaultEmoji,
this.isCompatibleWithTencentCloudChatPackageOldKeys = false,
required this.languageType,
required this.textEditingController,
this.morePanelConfig,
@ -190,12 +192,10 @@ class TIMUIKitTextFieldLayoutWide extends StatefulWidget {
: super(key: key);
@override
State<TIMUIKitTextFieldLayoutWide> createState() =>
_TIMUIKitTextFieldLayoutWideState();
State<TIMUIKitTextFieldLayoutWide> createState() => _TIMUIKitTextFieldLayoutWideState();
}
class _TIMUIKitTextFieldLayoutWideState
extends TIMUIKitState<TIMUIKitTextFieldLayoutWide> {
class _TIMUIKitTextFieldLayoutWideState extends TIMUIKitState<TIMUIKitTextFieldLayoutWide> {
final TUISettingModel settingModel = serviceLocator<TUISettingModel>();
OverlayEntry? entry;
final ImagePicker _picker = ImagePicker();
@ -269,13 +269,11 @@ class _TIMUIKitTextFieldLayoutWideState
}
String getAbstractMessage(V2TimMessage message) {
final String? customAbstractMessage =
widget.model.abstractMessageBuilder != null
? widget.model.abstractMessageBuilder!(widget.model.repliedMessage!)
: null;
final String? customAbstractMessage = widget.model.abstractMessageBuilder != null
? widget.model.abstractMessageBuilder!(widget.model.repliedMessage!)
: null;
return customAbstractMessage ??
MessageUtils.getAbstractMessageAsync(
widget.model.repliedMessage!, widget.model.groupMemberList ?? []);
MessageUtils.getAbstractMessageAsync(widget.model.repliedMessage!, widget.model.groupMemberList ?? []);
}
_buildRepliedMessage(V2TimMessage? repliedMessage) {
@ -298,10 +296,7 @@ class _TIMUIKitTextFieldLayoutWideState
softWrap: true,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: hexToColor("8f959e"),
fontSize: 14,
fontWeight: FontWeight.bold),
style: TextStyle(color: hexToColor("8f959e"), fontSize: 14, fontWeight: FontWeight.bold),
),
Expanded(
child: Text(
@ -346,8 +341,7 @@ class _TIMUIKitTextFieldLayoutWideState
},
initOffset: offset != null
? Offset(offset.dx, max(offset.dy, 16))
: Offset(MediaQuery.of(context).size.height * 0.5 + 20,
MediaQuery.of(context).size.height * 0.5 - 100),
: Offset(MediaQuery.of(context).size.height * 0.5 + 20, MediaQuery.of(context).size.height * 0.5 - 100),
child: Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(8)),
@ -385,14 +379,17 @@ class _TIMUIKitTextFieldLayoutWideState
},
addCustomEmojiText: ((String singleEmojiName) {
String? emojiName = singleEmojiName.split('.png')[0];
final newText = TIM_t('[$emojiName]');
String compatibleEmojiName = emojiName;
if (widget.isCompatibleWithTencentCloudChatPackageOldKeys) {
compatibleEmojiName = EmojiUtil.getCompatibleEmojiName(emojiName);
}
String newText = '[$compatibleEmojiName]';
widget.addStickerToText(newText);
entry?.remove();
entry = null;
}),
defaultCustomEmojiStickerList: widget.isUseDefaultEmoji
? TUIKitStickerConstData.emojiList
: [])
defaultCustomEmojiStickerList: widget.isUseDefaultEmoji ? TUIKitStickerConstData.emojiList : [])
: Material(
color: Colors.transparent,
child: StickerPanel(
@ -415,9 +412,13 @@ class _TIMUIKitTextFieldLayoutWideState
entry = null;
},
addCustomEmojiText: ((String singleEmojiName) {
String? emojiName =
singleEmojiName.split('.png')[0];
final newText = TIM_t('[$emojiName]');
String? emojiName = singleEmojiName.split('.png')[0];
String compatibleEmojiName = emojiName;
if (widget.isCompatibleWithTencentCloudChatPackageOldKeys) {
compatibleEmojiName = EmojiUtil.getCompatibleEmojiName(emojiName);
}
String newText = '[$compatibleEmojiName]';
widget.addStickerToText(newText);
entry?.remove();
entry = null;
@ -468,17 +469,11 @@ class _TIMUIKitTextFieldLayoutWideState
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);
} else {
File file = File(result.files.single.path!);
@ -486,12 +481,7 @@ class _TIMUIKitTextFieldLayoutWideState
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();
@ -502,8 +492,7 @@ class _TIMUIKitTextFieldLayoutWideState
}
}
List<Widget> generateBarIcons(
List<DesktopControlBarItem> items, TUITheme theme) {
List<Widget> generateBarIcons(List<DesktopControlBarItem> items, TUITheme theme) {
final defaultItems = defaultControlBarItems.map((e) => e.item);
return items.map((e) {
final GlobalKey key = GlobalKey();
@ -511,15 +500,12 @@ class _TIMUIKitTextFieldLayoutWideState
margin: const EdgeInsets.only(right: 10),
child: InkWell(
onTap: () {
final alignBox =
key.currentContext?.findRenderObject() as RenderBox?;
final alignBox = key.currentContext?.findRenderObject() as RenderBox?;
var offset = alignBox?.localToGlobal(Offset.zero);
final double? dx = (offset?.dx != null) ? offset!.dx : null;
final double? dy =
(offset?.dy != null && alignBox?.size.height != null)
? offset!.dy -
(widget.chatConfig.desktopStickerPanelHeight + 20)
: null;
final double? dy = (offset?.dy != null && alignBox?.size.height != null)
? offset!.dy - (widget.chatConfig.desktopStickerPanelHeight + 20)
: null;
e.onClick((dx != null && dy != null) ? Offset(dx, dy) : null);
},
child: Tooltip(
@ -533,9 +519,7 @@ class _TIMUIKitTextFieldLayoutWideState
if (TencentUtils.checkString(e.svgPath) != null) {
return SvgPicture.asset(
e.svgPath!,
package: defaultItems.contains(e.item)
? 'tencent_cloud_chat_uikit'
: null,
package: defaultItems.contains(e.item) ? 'tencent_cloud_chat_uikit' : null,
key: key,
width: e.size ?? 16,
height: e.size ?? 16,
@ -544,9 +528,7 @@ class _TIMUIKitTextFieldLayoutWideState
if (TencentUtils.checkString(e.imgPath) != null) {
return Image.asset(
e.imgPath!,
package: defaultItems.contains(e.item)
? 'tencent_cloud_chat_uikit'
: null,
package: defaultItems.contains(e.item) ? 'tencent_cloud_chat_uikit' : null,
key: key,
width: e.size ?? 16,
height: e.size ?? 16,
@ -575,17 +557,12 @@ class _TIMUIKitTextFieldLayoutWideState
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) {
// ignore: avoid_print
@ -602,25 +579,18 @@ class _TIMUIKitTextFieldLayoutWideState
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) {
// ignore: avoid_print
@ -634,10 +604,8 @@ class _TIMUIKitTextFieldLayoutWideState
final originFile = await asset.originFile;
final size = await originFile!.length();
if (size >= 104857600) {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("发送失败,视频不能大于100MB"),
infoCode: 6660405));
onTIMCallback(
TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("发送失败,视频不能大于100MB"), infoCode: 6660405));
return;
}
@ -646,9 +614,7 @@ class _TIMUIKitTextFieldLayoutWideState
final convID = widget.conversationID;
final convType = widget.conversationType;
String tempPath = (await getTemporaryDirectory()).path +
p.extension(originFile.path, 3) +
".jpeg";
String tempPath = (await getTemporaryDirectory()).path + p.extension(originFile.path, 3) + ".jpeg";
await plugin.getVideoThumbnail(
srcFile: originFile.path,
@ -660,22 +626,14 @@ class _TIMUIKitTextFieldLayoutWideState
);
MessageUtils.handleMessageError(
model.sendVideoMessage(
videoPath: filePath,
duration: duration,
snapshotPath: tempPath,
convID: convID,
convType: convType),
videoPath: filePath, duration: duration, snapshotPath: tempPath, convID: convID, convType: convType),
context);
} catch (e) {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("视频文件异常"),
infoCode: 6660415));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频文件异常"), infoCode: 6660415));
}
}
_sendMediaMessage(
TUIChatSeparateViewModel model, TUITheme theme, FileType fileType) async {
_sendMediaMessage(TUIChatSeparateViewModel model, TUITheme theme, FileType fileType) async {
try {
final convID = widget.conversationID;
final convType = widget.conversationType;
@ -691,11 +649,7 @@ class _TIMUIKitTextFieldLayoutWideState
if (filePath != null) {
if (type == AssetType.image) {
MessageUtils.handleMessageError(
model.sendImageMessage(
imagePath: filePath,
convID: convID,
convType: convType),
context);
model.sendImageMessage(imagePath: filePath, convID: convID, convType: convType), context);
}
if (type == AssetType.video) {
@ -707,26 +661,20 @@ class _TIMUIKitTextFieldLayoutWideState
} else {
final plugin = FcNativeVideoThumbnail();
_addGreyOverlay();
FilePickerResult? result =
await FilePicker.platform.pickFiles(type: fileType);
FilePickerResult? result = await FilePicker.platform.pickFiles(type: fileType);
_removeOverlay();
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])
.toLowerCase())
.split("/")[0];
final String type =
TencentUtils.getFileType((savePath.split(".")[savePath.split(".").length - 1]).toLowerCase())
.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") {
String tempPath = (await getTemporaryDirectory()).path +
p.basename(savePath) +
".jpeg";
String tempPath = (await getTemporaryDirectory()).path + p.basename(savePath) + ".jpeg";
await plugin.getVideoThumbnail(
srcFile: savePath,
destFile: tempPath,
@ -736,11 +684,7 @@ class _TIMUIKitTextFieldLayoutWideState
height: 128,
);
MessageUtils.handleMessageError(
model.sendVideoMessage(
videoPath: savePath,
convID: convID,
convType: convType,
snapshotPath: tempPath),
model.sendVideoMessage(videoPath: savePath, convID: convID, convType: convType, snapshotPath: tempPath),
context);
}
} else {
@ -750,17 +694,13 @@ class _TIMUIKitTextFieldLayoutWideState
} catch (err) {
// ignore: avoid_print
outputLogger.i("send media err: $err");
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("视频文件异常"),
infoCode: 6660415));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频文件异常"), infoCode: 6660415));
}
}
_sendImageWithConfirmation(
{String? fileName, Size? fileSize, required String filePath}) async {
final option1 = widget.currentConversation.showName ??
(widget.conversationType == ConvType.group ? TIM_t("群聊") : TIM_t("对方"));
_sendImageWithConfirmation({String? fileName, Size? fileSize, required String filePath}) async {
final option1 =
widget.currentConversation.showName ?? (widget.conversationType == ConvType.group ? TIM_t("群聊") : TIM_t("对方"));
final size = fileSize ?? await ScreenshotHelper.getImageSize(filePath);
TUIKitWidePopup.showPopupWindow(
@ -779,9 +719,7 @@ class _TIMUIKitTextFieldLayoutWideState
height: min(360, size.height / 2),
child: InkWell(
onTap: () {
launchUrl(PlatformUtils().isWeb
? Uri.parse(filePath)
: Uri.file(filePath));
launchUrl(PlatformUtils().isWeb ? Uri.parse(filePath) : Uri.file(filePath));
},
child: PlatformUtils().isWeb
? Image.network(
@ -834,8 +772,7 @@ class _TIMUIKitTextFieldLayoutWideState
}
generateDefaultControlBarItems() {
final DesktopControlBarConfig config =
widget.chatConfig.desktopControlBarConfig ?? DesktopControlBarConfig();
final DesktopControlBarConfig config = widget.chatConfig.desktopControlBarConfig ?? DesktopControlBarConfig();
final List<DesktopControlBarItem> itemsList = [
if (config.showStickerPanel)
DesktopControlBarItem(
@ -900,13 +837,9 @@ class _TIMUIKitTextFieldLayoutWideState
keyword: '',
initMessageList: widget.model
.getOriginMessageList()
.getRange(
0,
min(widget.model.getOriginMessageList().length,
100))
.getRange(0, min(widget.model.getOriginMessageList().length, 100))
.toList(),
onTapConversation: (V2TimConversation conversation,
V2TimMessage? message) {},
onTapConversation: (V2TimConversation conversation, V2TimMessage? message) {},
),
theme: widget.theme);
},
@ -915,8 +848,7 @@ class _TIMUIKitTextFieldLayoutWideState
defaultControlBarItems = itemsList;
}
List<Widget> generateControlBar(
TUIChatSeparateViewModel model, TUITheme theme) {
List<Widget> generateControlBar(TUIChatSeparateViewModel model, TUITheme theme) {
final List<DesktopControlBarItem> itemsList = [
...defaultControlBarItems,
...(widget.chatConfig.additionalDesktopControlBarItems ?? [])
@ -930,29 +862,22 @@ class _TIMUIKitTextFieldLayoutWideState
final type = mimeType[0];
final blobUrl = html.Url.createObjectUrl(file);
if (type == 'image') {
_sendImageWithConfirmation(
filePath: blobUrl,
fileName: file.name,
fileSize: const Size(500, 500));
_sendImageWithConfirmation(filePath: blobUrl, fileName: file.name, fileSize: const Size(500, 500));
}
}
Future<void> _handleKeyEvent(RawKeyEvent event) async {
if (PlatformUtils().isDesktop &&
((event.isKeyPressed(LogicalKeyboardKey.controlLeft) &&
event.logicalKey == LogicalKeyboardKey.keyV) ||
(event.isMetaPressed &&
event.logicalKey == LogicalKeyboardKey.keyV))) {
((event.isKeyPressed(LogicalKeyboardKey.controlLeft) && event.logicalKey == LogicalKeyboardKey.keyV) ||
(event.isMetaPressed && event.logicalKey == LogicalKeyboardKey.keyV))) {
final bytes = await Pasteboard.image;
if (bytes != null) {
String directory;
if (PlatformUtils().isWindows) {
final String documentsDirectoryPath =
"${Platform.environment['USERPROFILE']}";
final String documentsDirectoryPath = "${Platform.environment['USERPROFILE']}";
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String pkgName = packageInfo.packageName;
directory = p.join(documentsDirectoryPath, "Documents",
".TencentCloudChat", pkgName, "screenshots");
directory = p.join(documentsDirectoryPath, "Documents", ".TencentCloudChat", pkgName, "screenshots");
} else {
final dic = await getApplicationSupportDirectory();
directory = dic.path;
@ -960,8 +885,7 @@ class _TIMUIKitTextFieldLayoutWideState
const uuid = Uuid();
final fileName = 'paste_image_${uuid.v4()}.png';
final scDirectory = Directory(directory);
final filePath =
'${scDirectory.path}${PlatformUtils().isWindows ? "\\" : "/"}$fileName';
final filePath = '${scDirectory.path}${PlatformUtils().isWindows ? "\\" : "/"}$fileName';
final file = File(filePath);
if (!await scDirectory.exists()) {
await scDirectory.create(recursive: true);
@ -1002,67 +926,57 @@ class _TIMUIKitTextFieldLayoutWideState
child: Column(
children: [
_buildRepliedMessage(widget.repliedMessage),
SizedBox(
height: 1,
child: Container(
color: theme.weakDividerColor ?? Colors.black12)),
Container(
padding:
const EdgeInsets.symmetric(vertical: 4, horizontal: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: generateControlBar(widget.model, theme),
SizedBox(height: 1, child: Container(color: theme.weakDividerColor ?? Colors.black12)),
Container(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: generateControlBar(widget.model, theme),
),
),
),
Container(
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 6),
constraints: const BoxConstraints(minHeight: 50),
child: Row(
children: [
Expanded(
child: ExtendedTextField(
scrollController: _scrollController,
autofocus: true,
maxLines:
widget.chatConfig.desktopMessageInputFieldLines,
minLines:
widget.chatConfig.desktopMessageInputFieldLines,
focusNode: widget.focusNode,
onChanged: debounceFunc,
keyboardType: TextInputType.multiline,
onEditingComplete: () {
// // widget.onSubmitted();
},
textAlignVertical: TextAlignVertical.top,
style: const TextStyle(fontSize: 14),
decoration: InputDecoration(
hoverColor: Colors.transparent,
border: InputBorder.none,
hintStyle: const TextStyle(
color: Color(0xffAEA4A3),
Expanded(
child: ExtendedTextField(
scrollController: _scrollController,
autofocus: true,
maxLines: widget.chatConfig.desktopMessageInputFieldLines,
minLines: widget.chatConfig.desktopMessageInputFieldLines,
focusNode: widget.focusNode,
onChanged: debounceFunc,
keyboardType: TextInputType.multiline,
onEditingComplete: () {
// // widget.onSubmitted();
},
textAlignVertical: TextAlignVertical.top,
style: const TextStyle(fontSize: 14),
decoration: InputDecoration(
hoverColor: Colors.transparent,
border: InputBorder.none,
hintStyle: const TextStyle(
color: Color(0xffAEA4A3),
),
fillColor: widget.backgroundColor ??
theme.desktopChatMessageInputBgColor ??
hexToColor("fafafa"),
filled: true,
isDense: true,
hintText: widget.hintText ?? '',
),
fillColor: widget.backgroundColor ??
theme.desktopChatMessageInputBgColor ??
hexToColor("fafafa"),
filled: true,
isDense: true,
hintText: widget.hintText ?? '',
),
controller: widget.textEditingController,
specialTextSpanBuilder: PlatformUtils().isWeb
? null
: DefaultSpecialTextSpanBuilder(
isUseTencentCloudChatPackage: widget
.model
.chatConfig
.stickerPanelConfig
?.useTencentCloudChatStickerPackage ??
true,
customEmojiStickerList:
widget.customEmojiStickerList,
showAtBackground: true,
)),
),
controller: widget.textEditingController,
specialTextSpanBuilder: PlatformUtils().isWeb
? null
: DefaultSpecialTextSpanBuilder(
isUseTencentCloudChatPackage:
widget.model.chatConfig.stickerPanelConfig?.useTencentCloudChatStickerPackage ??
true,
customEmojiStickerList: widget.customEmojiStickerList,
showAtBackground: true,
)),
),
],
),
),

View File

@ -24,18 +24,34 @@ class TimeDividerConfig {
/// StickerPanelConfig is a configuration class for the sticker panel component.
/// It allows customization of specific features such as display options for the
/// message area, sticker packages, and custom sticker packages.
/// message area, sticker packages, unicode emoji lists, and custom sticker packages.
class StickerPanelConfig {
/// Determines whether to use the QQ Sticker Package.
/// Default value: true
final bool useQQStickerPackage;
/// Determines whether to use the Tencent Cloud Chat Sticker Package.
/// Default value: true
final bool useTencentCloudChatStickerPackage;
/// Determines whether to compatible with the Tencent Cloud Chat Sticker Package 3.x version.
/// Default value : false
final bool useTencentCloudChatStickerPackageOldKeys;
/// A list of unicode emoji, represented as integers.
/// Default value: a list of common Unicode Emojis.
/// To exclude Unicode Emoji from the display, pass an empty list.
final List<int> unicodeEmojiList;
/// A list of CustomStickerPackage instances, where each instance represents a sticker package.
/// Default value: an empty list.
final List<CustomStickerPackage> customStickerPackages;
StickerPanelConfig({
this.useQQStickerPackage = true,
this.useTencentCloudChatStickerPackage = true,
this.useTencentCloudChatStickerPackageOldKeys = false,
this.unicodeEmojiList = TUIKitStickerConstData.defaultUnicodeEmojiList,
this.customStickerPackages = const [],
});
}

View File

@ -95,17 +95,11 @@ class _TIMUIKitLastMsgState extends TIMUIKitState<TIMUIKitLastMsg> {
});
}
} else {
String originalText =
String msgShowText =
await _getLastMsgShowText(widget.lastMsg, widget.context) ?? "";
String replaceText = TUIKitStickerConstData.emojiZhNameMap.keys
.fold(originalText, (previousValue, key) {
return previousValue.replaceAll(
key, TIM_t(TUIKitStickerConstData.emojiZhNameMap[key]!));
});
if (mounted) {
setState(() {
groupTipsAbstractText = replaceText;
groupTipsAbstractText = msgShowText;
});
}
}
@ -228,31 +222,37 @@ class _TIMUIKitLastMsgState extends TIMUIKitState<TIMUIKitLastMsg> {
color: theme.weakTextColor, fontSize: widget.fontSize)),
if (widget.draftText != null && widget.draftText != "")
Expanded(
child: ExtendedText(
groupTipsAbstractText,
softWrap: true,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
height: 1,
color: theme.weakTextColor,
fontSize: widget.fontSize),
),
child: ExtendedText(groupTipsAbstractText,
softWrap: true,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
height: 1,
color: theme.weakTextColor,
fontSize: widget.fontSize),
specialTextSpanBuilder: DefaultSpecialTextSpanBuilder(
isUseQQPackage: true,
isUseTencentCloudChatPackage: true,
showAtBackground: true,
)),
),
if (widget.draftText == null ||
widget.draftText == "" &&
TencentUtils.checkString(groupTipsAbstractText) != null)
Expanded(
child: ExtendedText(
groupTipsAbstractText,
softWrap: true,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
height: 1,
color: theme.weakTextColor,
fontSize: widget.fontSize),
),
child: ExtendedText(groupTipsAbstractText,
softWrap: true,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
height: 1,
color: theme.weakTextColor,
fontSize: widget.fontSize),
specialTextSpanBuilder: DefaultSpecialTextSpanBuilder(
isUseQQPackage: true,
isUseTencentCloudChatPackage: true,
showAtBackground: true,
)),
)
]);
}

View File

@ -3,14 +3,17 @@ import 'package:tim_ui_kit_sticker_plugin/utils/tim_custom_face_data.dart';
RegExp emojiExp = RegExp(r'\[([\u4e00-\u9fa5A-Za-z0-9]+)\]');
String mdTextCompiler(
String originalText, {
String mdTextCompiler(String originalText, {
bool isUseQQPackage = false,
bool isUseTencentCloudChatPackage = false,
bool isUseTencentCloudChatPackageOldKeys = false,
List<CustomEmojiFaceData> customEmojiStickerList = const [],
}) {
String text = originalText;
final EmojiUtil emojiUtil = EmojiUtil(
isUseQQPackage: isUseQQPackage,
isUseTencentCloudChatPackage: isUseTencentCloudChatPackage,
isUseTencentCloudChatPackageOldKeys: isUseTencentCloudChatPackageOldKeys,
customEmojiStickerList: customEmojiStickerList);
text = text.replaceAllMapped(emojiExp, (match) {
@ -25,4 +28,4 @@ String mdTextCompiler(
});
return text;
}
}

View File

@ -12,12 +12,17 @@ class LinkPreviewEntry {
static LinkPreviewText? getHyperlinksText(String messageText, bool isMarkdown,
{Function(String)? onLinkTap,
bool isEnableTextSelection = false,
bool isUseQQPackage = false,
bool isUseTencentCloudChatPackage = false,
bool isUseTencentCloudChatPackageOldKeys = false,
List<CustomEmojiFaceData> customEmojiStickerList = const []}) {
return ({TextStyle? style}) {
return isMarkdown
? LinkTextMarkdown(
isUseQQPackage: isUseQQPackage,
isUseTencentCloudChatPackage: isUseTencentCloudChatPackage,
isUseTencentCloudChatPackageOldKeys:
isUseTencentCloudChatPackageOldKeys,
customEmojiStickerList: customEmojiStickerList,
isEnableTextSelection: isEnableTextSelection,
messageText: addSpaceAfterLeftBracket(
@ -29,7 +34,10 @@ class LinkPreviewEntry {
messageText: messageText,
style: style,
onLinkTap: onLinkTap,
isUseQQPackage: isUseQQPackage,
isUseTencentCloudChatPackage: isUseTencentCloudChatPackage,
isUseTencentCloudChatPackageOldKeys:
isUseTencentCloudChatPackageOldKeys,
customEmojiStickerList: customEmojiStickerList);
};
}

View File

@ -28,14 +28,20 @@ class LinkTextMarkdown extends TIMStatelessWidget {
final bool? isEnableTextSelection;
final bool isUseQQPackage;
final bool isUseTencentCloudChatPackage;
final bool isUseTencentCloudChatPackageOldKeys;
final List<CustomEmojiFaceData> customEmojiStickerList;
const LinkTextMarkdown(
{Key? key,
required this.messageText,
this.isUseQQPackage = false,
this.isUseTencentCloudChatPackage = false,
this.isUseTencentCloudChatPackageOldKeys = false,
this.customEmojiStickerList = const [],
this.isEnableTextSelection,
this.onLinkTap,
@ -81,8 +87,12 @@ class LinkText extends TIMStatelessWidget {
/// text style for default words
final TextStyle? style;
final bool isUseQQPackage;
final bool isUseTencentCloudChatPackage;
final bool isUseTencentCloudChatPackageOldKeys;
final List<CustomEmojiFaceData> customEmojiStickerList;
final bool? isEnableTextSelection;
@ -93,7 +103,9 @@ class LinkText extends TIMStatelessWidget {
this.onLinkTap,
this.isEnableTextSelection,
this.style,
this.isUseQQPackage = false,
this.isUseTencentCloudChatPackage = false,
this.isUseTencentCloudChatPackageOldKeys = false,
this.customEmojiStickerList = const []})
: super(key: key);
@ -165,7 +177,10 @@ class LinkText extends TIMStatelessWidget {
},
style: style ?? const TextStyle(fontSize: 16.0),
specialTextSpanBuilder: DefaultSpecialTextSpanBuilder(
isUseQQPackage: isUseQQPackage,
isUseTencentCloudChatPackage: isUseTencentCloudChatPackage,
isUseTencentCloudChatPackageOldKeys:
isUseTencentCloudChatPackageOldKeys,
customEmojiStickerList: customEmojiStickerList,
showAtBackground: true,
));

View File

@ -1,6 +1,6 @@
name: tencent_cloud_chat_uikit
description: A powerful chat UI component library and business logic for Tencent Cloud Chat, creating seamless in-app chat modules for delightful user experiences.
version: 4.0.0
version: 4.0.1
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
@ -61,7 +61,7 @@ dependencies:
uuid: ^3.0.6
open_file: ^3.3.2
tencent_keyboard_visibility: ^1.0.1
tim_ui_kit_sticker_plugin: ^3.2.0
tim_ui_kit_sticker_plugin: ^4.0.1
tencent_im_base: ^8.0.0
fc_native_video_thumbnail: ^0.16.0
path: ^1.8.1