tencent_cloud_chat_uikit source code update to version 4.0.5

This commit is contained in:
vinsonswang 2025-04-21 15:14:58 +08:00
parent ae3bf8be65
commit be9c53aa25
171 changed files with 2779 additions and 2367 deletions

View File

@ -1,3 +1,22 @@
# 4.0.5
* Upgrade tencent_cloud_chat_sdk to the minimum version 8.5.6864+6.
* Changed the SDK interface call from getConversationListByConversaionIds to getConversationListByConversationIds.
# 4.0.4
* Remove the import of tencent_im_base plugin.
* Upgrade tencent_cloud_chat_sdk to the minimum version 8.5.6864+4.
* Fix compilation issues in tim_uikit_group.dart, tui_group_listener_model.dart, tui_conversation_view_model.dart.
# 4.0.3
* Fix compilation issues on Flutter 3.27.1
# 4.0.2
* Optimize the display of group notification page.
* Optimize the display of read receipt page.
* TIMUIKitChatController sendMessage interface supports isExcludedFromContentModeration parameter.
* Fixed abnormal playback and recording of videos on Huawei P30.
* Optimize the display of tips messages when they are too long.
# 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.

View File

@ -3,6 +3,7 @@
import 'package:example/TIMUIKitGroupProfileExample.dart';
import 'package:example/TIMUIKitProfileExample.dart';
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
class TIMUIKitChatExample extends StatelessWidget {
@ -64,7 +65,6 @@ class TIMUIKitChatExample extends StatelessWidget {
config: const TIMUIKitChatConfig(
// 使
isAllowClickAvatar: true,
isUseDefaultEmoji: true,
isAllowLongPressMessage: true,
isShowReadingStatus: true,
isShowGroupReadingStatus: true,

View File

@ -1,6 +1,7 @@
// ignore_for_file: avoid_print, file_names, deprecated_member_use
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
class TIMUIKitSearchExample extends StatelessWidget {

View File

@ -1,14 +1,21 @@
// ignore_for_file: avoid_print
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimSDKListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/log_level_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'TIMUIKitAddFriendExample.dart';
import 'TIMUIKitAddGroupExample.dart';
import 'TIMUIKitBlackListExample.dart';
import 'TIMUIKitChatExample.dart';
import 'TIMUIKitContactExample.dart';
import 'TIMUIKitConversationExample.dart';
import 'TIMUIKitGroupExample.dart';
import 'TIMUIKitGroupProfileExample.dart';
import 'TIMUIKitNewContactExample.dart';
import 'TIMUIKitProfileExample.dart';
import 'TIMUIKitSearchExample.dart';
void main() {

View File

@ -8,7 +8,6 @@
#include <desktop_drop/desktop_drop_plugin.h>
#include <file_selector_linux/file_selector_plugin.h>
#include <image_clipboard/image_clipboard_plugin.h>
#include <pasteboard/pasteboard_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
@ -19,9 +18,6 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) image_clipboard_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "ImageClipboardPlugin");
image_clipboard_plugin_register_with_registrar(image_clipboard_registrar);
g_autoptr(FlPluginRegistrar) pasteboard_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "PasteboardPlugin");
pasteboard_plugin_register_with_registrar(pasteboard_registrar);

View File

@ -5,7 +5,6 @@
list(APPEND FLUTTER_PLUGIN_LIST
desktop_drop
file_selector_linux
image_clipboard
pasteboard
url_launcher_linux
)

View File

@ -10,7 +10,7 @@ import desktop_drop
import device_info_plus
import fc_native_video_thumbnail
import file_selector_macos
import image_clipboard
import flutter_image_compress_macos
import just_audio
import package_info_plus
import pasteboard
@ -20,6 +20,7 @@ import shared_preferences_foundation
import sqflite
import tencent_cloud_chat_sdk
import url_launcher_macos
import video_player_avfoundation
import wakelock_plus
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
@ -28,9 +29,9 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FcNativeVideoThumbnailPlugin.register(with: registry.registrar(forPlugin: "FcNativeVideoThumbnailPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
ImageClipboardPlugin.register(with: registry.registrar(forPlugin: "ImageClipboardPlugin"))
FlutterImageCompressMacosPlugin.register(with: registry.registrar(forPlugin: "FlutterImageCompressMacosPlugin"))
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PasteboardPlugin.register(with: registry.registrar(forPlugin: "PasteboardPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
PhotoManagerPlugin.register(with: registry.registrar(forPlugin: "PhotoManagerPlugin"))
@ -38,5 +39,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
TencentCloudChatSdkPlugin.register(with: registry.registrar(forPlugin: "TencentCloudChatSdkPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
}

View File

@ -35,10 +35,10 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
tencent_cloud_chat_uikit:
path: ../../tim_ui_kit
path: ../
tencent_cloud_chat_sdk: ^8.5.6864+6
tencent_im_sdk_plugin_web: ^0.3.9
archive: ^3.3.0
tencent_im_sdk_plugin_desktop: ^0.1.13
# dependency_overrides:
# tencent_cloud_chat_sdk:

View File

@ -9,7 +9,6 @@
#include <desktop_drop/desktop_drop_plugin.h>
#include <fc_native_video_thumbnail/fc_native_video_thumbnail_plugin_c_api.h>
#include <file_selector_windows/file_selector_windows.h>
#include <image_clipboard/image_clipboard_plugin_c_api.h>
#include <pasteboard/pasteboard_plugin.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
#include <tencent_cloud_chat_sdk/tencent_cloud_chat_sdk_plugin_c_api.h>
@ -22,8 +21,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("FcNativeVideoThumbnailPluginCApi"));
FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows"));
ImageClipboardPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ImageClipboardPluginCApi"));
PasteboardPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PasteboardPlugin"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(

View File

@ -6,7 +6,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
desktop_drop
fc_native_video_thumbnail
file_selector_windows
image_clipboard
pasteboard
permission_handler_windows
tencent_cloud_chat_sdk

View File

@ -0,0 +1,22 @@
import 'package:flutter/cupertino.dart';
enum TIMCallbackType { API_ERROR, FLUTTER_ERROR, INFO }
class TIMCallback {
TIMCallbackType? type;
String? errorMsg;
int? errorCode;
StackTrace? stackTrace;
Object? catchError;
int? infoCode;
String? infoRecommendText;
TIMCallback(
{this.catchError,
this.infoRecommendText,
this.errorMsg,
this.errorCode,
this.stackTrace,
this.infoCode,
this.type});
}

View File

@ -0,0 +1,53 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'dart:io';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
abstract class TIMState<T extends StatefulWidget> extends State<T> {
@override
initState() {
super.initState();
}
// override这个函数来承接处理onTIMCallback回调
// base层`TIMCallbackType.FLUTTER_ERROR`Flutter Framework异常
// callback请自行处理
void onTIMCallback(TIMCallback callbackValue) {
// TODO:
}
bool isAndroidDevice(){
return !kIsWeb && Platform.isAndroid;
}
bool isIosDevice(){
return !kIsWeb && Platform.isIOS;
}
bool isWebDevice(){
return kIsWeb;
}
setTIMState(VoidCallback fn){
}
@override
Widget build(BuildContext context) {
final onFlutterError = FlutterError.onError;
FlutterError.onError = (FlutterErrorDetails details) {
FlutterError.presentError(details);
// onFlutterError?.call(details);
onTIMCallback(TIMCallback(
type: TIMCallbackType.FLUTTER_ERROR,
stackTrace: details.stack,
errorMsg: "Error from Flutter"));
};
return timBuild(context);
}
// override这个方法来render界面
Widget timBuild(BuildContext context);
}

View File

@ -0,0 +1,45 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
abstract class TIMStatelessWidget extends StatelessWidget {
const TIMStatelessWidget({Key? key}) : super(key: key);
// override这个函数来承接处理onTIMCallback回调
// base层`TIMCallbackType.FLUTTER_ERROR`Flutter Framework异常
// callback请自行处理
void onTIMCallback(TIMCallback callbackValue) {
}
bool isAndroidDevice(){
return !kIsWeb && Platform.isAndroid;
}
bool isIosDevice(){
return !kIsWeb && Platform.isIOS;
}
bool isWebDevice(){
return kIsWeb;
}
@override
Widget build(BuildContext context) {
final onFlutterError = FlutterError.onError;
FlutterError.onError = (FlutterErrorDetails details) {
// onFlutterError?.call(details);
FlutterError.presentError(details);
onTIMCallback(TIMCallback(
type: TIMCallbackType.FLUTTER_ERROR,
stackTrace: details.stack,
errorMsg: "Error from Flutter"));
};
return timBuild(context);
}
// override这个方法来render界面
Widget timBuild(BuildContext context);
}

View File

@ -1,5 +1,4 @@
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class TUIKitBuildValue {
//

View File

@ -1,4 +1,4 @@
import 'package:tencent_im_base/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';

View File

@ -1,9 +1,11 @@
import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_state.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme_view_model.dart';
class TIMUIKitState<T extends StatefulWidget> extends TIMState<T> {
final CoreServicesImpl _coreServices = serviceLocator<CoreServicesImpl>();

View File

@ -1,9 +1,11 @@
import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_stateless_widget.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme_view_model.dart';
class TIMUIKitStatelessWidget extends TIMStatelessWidget {
final CoreServicesImpl _coreServices = serviceLocator<CoreServicesImpl>();

View File

@ -1,6 +1,11 @@
import 'package:flutter/cupertino.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_class.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
typedef MessageFunction = Future<V2TimMessage?> Function(V2TimMessage message);

View File

@ -1,3 +1,4 @@
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/base_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';

View File

@ -3,6 +3,17 @@
import 'dart:convert';
import 'package:flutter/cupertino.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/enum/group_change_info_type.dart';
import 'package:tencent_cloud_chat_sdk/manager/v2_tim_manager.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_change_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_topic_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
@ -135,7 +146,6 @@ class TUIGroupListenerModel extends ChangeNotifier {
addCategoryForTopic(String groupID, String categoryName) {
TencentImSDKPlugin.v2TIMManager.getGroupManager().setTopicInfo(
topicInfo: V2TimTopicInfo(customString: categoryName),
groupID: groupID, // id
);
}

View File

@ -1,3 +1,5 @@
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
class UserProfile {

View File

@ -1,8 +1,11 @@
import 'dart:convert';
import 'dart:io';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_elem_type.dart';
import 'package:tencent_cloud_chat_sdk/enum/offlinePushInfo.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/tim_uikit_cloud_custom_data.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';

View File

@ -7,6 +7,27 @@ import 'package:collection/collection.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:path_provider/path_provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/get_group_message_read_member_list_filter.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_filter_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/history_msg_get_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_priority_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_status.dart';
import 'package:tencent_cloud_chat_sdk/enum/offlinePushInfo.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_custom_elem.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_message_read_member_list.dart';
import 'package:tencent_cloud_chat_sdk/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_receipt.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_msg_create_info_result.dart';
import 'package:tencent_cloud_chat_sdk/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/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/chat_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_model_tools.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
@ -32,8 +53,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
final TUIChatGlobalModel globalModel = serviceLocator<TUIChatGlobalModel>();
final TUIChatModelTools tools = serviceLocator<TUIChatModelTools>();
final TUISelfInfoViewModel selfModel = serviceLocator<TUISelfInfoViewModel>();
final TUIConversationViewModel conversationViewModel =
serviceLocator<TUIConversationViewModel>();
final TUIConversationViewModel conversationViewModel = serviceLocator<TUIConversationViewModel>();
final _uuid = const Uuid();
ChatLifeCycle? lifeCycle;
@ -136,8 +156,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
List<V2TimMessage> currentHistoryMsgList = getOriginMessageList();
for (var v2TimMessage in currentHistoryMsgList) {
if (_selectedPositions.containsKey(v2TimMessage.msgID) &&
_selectedPositions[v2TimMessage.msgID]!) {
if (_selectedPositions.containsKey(v2TimMessage.msgID) && _selectedPositions[v2TimMessage.msgID]!) {
selectList.add(v2TimMessage);
}
}
@ -370,6 +389,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
? haveMoreLatestData = false
: tempHaveMoreData = false;
//
final currentRecordList = globalModel.messageListMap[conversationID];
@ -479,10 +499,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
_getMsgReadReceipt(List<V2TimMessage> message) async {
final msgID = message
.where((e) =>
(e.isSelf ?? true) &&
(e.needReadReceipt ?? false) &&
(e.status == MessageStatus.V2TIM_MSG_STATUS_SEND_SUCC))
.where((e) => (e.isSelf ?? true) && (e.needReadReceipt ?? false) && (e.status == MessageStatus.V2TIM_MSG_STATUS_SEND_SUCC))
.map((e) => e.msgID ?? '')
.toList();
if (msgID.isNotEmpty) {
@ -592,10 +609,10 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
}
}
void _notify() {
try {
void _notify(){
try{
notifyListeners();
} catch (e) {
}catch(e){
debugPrint(e.toString());
}
}
@ -684,6 +701,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
String? cloudCustomData,
String? localCustomData,
bool? isEditStatusMessage = false,
bool? isExcludedFromContentModeration,
}) async {
String receiver = convType == ConvType.c2c ? convID : '';
String groupID = convType == ConvType.group ? convID : '';
@ -703,6 +721,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
groupID: groupID,
offlinePushInfo: offlinePushInfo,
onlineUserOnly: onlineUserOnly ?? false,
isExcludedFromContentModeration: isExcludedFromContentModeration ?? false,
cloudCustomData: cloudCustomData ??
(showC2cMessageEditStatus == true
? json.encode({
@ -924,8 +943,8 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
_repliedMessage = null;
final sendMsgRes = await _messageService.sendMessage(
cloudCustomData: TencentUtils.checkString(
messageInfoWithSender?.cloudCustomData) ??
cloudCustomData:
TencentUtils.checkString(messageInfoWithSender?.cloudCustomData) ??
json.encode(cloudCustomData),
id: textMessageInfo.id as String,
offlinePushInfo: tools.buildMessagePushInfo(
@ -1153,11 +1172,9 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
for (var conversation in conversationList) {
final convID = conversation.groupID ?? conversation.userID ?? "";
final convType = conversation.type;
List<V2TimMessage> currentHistoryMsgList =
globalModel.messageListMap[conversationID] ?? [];
List<V2TimMessage> currentHistoryMsgList = globalModel.messageListMap[conversationID] ?? [];
for (var message in selectedMessages) {
final forwardMessageInfo =
await _messageService.createForwardMessage(msgID: message.msgID!);
final forwardMessageInfo = await _messageService.createForwardMessage(msgID: message.msgID!);
final messageInfo = forwardMessageInfo!.messageInfo;
if (messageInfo != null) {
tools.setUserInfoForMessage(messageInfo, forwardMessageInfo.id);
@ -1165,9 +1182,11 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
addSendingMessageID(messageInfo.id);
//
if (convID == conversationID) {
if (globalModel.getMessageListPosition(convID) !=
HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [messageInfo, ...currentHistoryMsgList];
if (globalModel.getMessageListPosition(convID) != HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [
messageInfo,
...currentHistoryMsgList
];
globalModel.setMessageList(conversationID, currentHistoryMsgList);
_notify();
}
@ -1202,8 +1221,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
for (var conversation in conversationList) {
final convID = conversation.groupID ?? conversation.userID ?? "";
final convType = conversation.type;
List<V2TimMessage> currentHistoryMsgList =
globalModel.messageListMap[conversationID] ?? [];
List<V2TimMessage> currentHistoryMsgList = globalModel.messageListMap[conversationID] ?? [];
final mergerMessageInfo = await _messageService.createMergerMessage(
msgIDList: msgIDList,
title: title,
@ -1216,9 +1234,11 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
addSendingMessageID(messageInfo.id);
//
if (convID == conversationID) {
if (globalModel.getMessageListPosition(convID) !=
HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [messageInfo, ...currentHistoryMsgList];
if (globalModel.getMessageListPosition(convID) != HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [
messageInfo,
...currentHistoryMsgList
];
globalModel.setMessageList(conversationID, currentHistoryMsgList);
_notify();
}
@ -1247,14 +1267,16 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
return null;
}
currentHistoryMsgList
.removeWhere((element) => element.msgID == message.msgID);
currentHistoryMsgList.removeWhere((element) => element.msgID == message.msgID);
message.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
addSendingMessageID(message.msgID);
globalModel.setMessageList(convID, currentHistoryMsgList);
if (globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [message, ...currentHistoryMsgList];
currentHistoryMsgList = [
message,
...currentHistoryMsgList
];
globalModel.setMessageList(conversationID, currentHistoryMsgList);
_notify();
}
@ -1312,7 +1334,6 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
Future<V2TimValueCallback<V2TimMessage>?>? sendMessageFromController({
required V2TimMessage? messageInfo,
/// Offline push info
OfflinePushInfo? offlinePushInfo,
MessagePriorityEnum priority = MessagePriorityEnum.V2TIM_PRIORITY_NORMAL,
@ -1351,6 +1372,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
offlinePushInfo: offlinePushInfo ??
tools.buildMessagePushInfo(
messageInfo, conversationID, conversationType ?? ConvType.c2c),
isExcludedFromContentModeration: messageInfo.isExcludedFromContentModeration,
);
}
return null;
@ -1427,8 +1449,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
for (var msgID in msgIDs) {
messageList.removeWhere((element) => element.msgID == msgID);
}
globalModel.setMessageList(conversationID, messageList,
isDeleteMsg: true);
globalModel.setMessageList(conversationID, messageList, isDeleteMsg: true);
}
}

View File

@ -1,6 +1,20 @@
// ignore_for_file: unnecessary_getters_setters, avoid_print
import 'package:flutter/cupertino.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_filter_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_role.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_role_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_type.dart';
import 'package:tencent_cloud_chat_sdk/enum/receive_message_opt_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_operation_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/group_profile_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/data_services/conversation/conversation_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
@ -9,7 +23,6 @@ import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart
import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/logger.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
class TUIGroupProfileModel extends ChangeNotifier {
final CoreServicesImpl _coreServices = serviceLocator<CoreServicesImpl>();

View File

@ -1,7 +1,13 @@
// ignore_for_file: avoid_print
import 'package:flutter/material.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/receive_message_opt_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_operation_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/profile_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/model/profile_model.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_friendship_view_model.dart';

View File

@ -1,5 +1,4 @@
// ignore_for_file: avoid_print, unnecessary_getters_setters, unused_element
import 'dart:async';
import 'dart:convert';
import 'dart:io';
@ -7,6 +6,21 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimAdvancedMsgListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/history_msg_get_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_elem_type.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_priority_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_status.dart';
import 'package:tencent_cloud_chat_sdk/enum/offlinePushInfo.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_custom_elem.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_application.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_image.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_download_progress.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_receipt.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_msg_create_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_class.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/chat_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_model_tools.dart';
@ -773,6 +787,7 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
needReadReceipt: needReadReceipt,
cloudCustomData: cloudCustomData,
localCustomData: localCustomData,
isExcludedFromContentModeration: messageInfo.isExcludedFromContentModeration ?? false,
convID: convID,
setInputField: setInputField,
id: messageInfo.id as String,
@ -892,6 +907,7 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
bool? needReadReceipt,
String? cloudCustomData,
String? localCustomData,
bool isExcludedFromContentModeration = false,
}) async {
String receiver = convType == ConvType.c2c ? convID : '';
String groupID = convType == ConvType.group ? convID : '';
@ -904,6 +920,7 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
localCustomData: localCustomData,
isExcludedFromUnreadCount: isExcludedFromUnreadCount ?? false,
offlinePushInfo: offlinePushInfo,
isExcludedFromContentModeration: isExcludedFromContentModeration,
onlineUserOnly: onlineUserOnly ?? false,
cloudCustomData: cloudCustomData ??
json.encode({

View File

@ -2,6 +2,11 @@
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimConversationListener.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_search_param.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/conversation_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart';
@ -12,8 +17,7 @@ import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
List<T> removeDuplicates<T>(
List<T> list, bool Function(T first, T second) isEqual) {
List<T> removeDuplicates<T>(List<T> list, bool Function(T first, T second) isEqual) {
List<T> output = [];
for (var i = 0; i < list.length; i++) {
bool found = false;
@ -34,14 +38,10 @@ class TUIConversationViewModel extends ChangeNotifier {
static const String conversationC2CPrefix = "c2c_";
static const String conversationGroupPrefix = "group_";
final TUISelfInfoViewModel selfInfoViewModel =
serviceLocator<TUISelfInfoViewModel>();
final ConversationService _conversationService =
serviceLocator<ConversationService>();
final FriendshipServices _friendshipServices =
serviceLocator<FriendshipServices>();
final TUIChatGlobalModel _chatGlobalModel =
serviceLocator<TUIChatGlobalModel>();
final TUISelfInfoViewModel selfInfoViewModel = serviceLocator<TUISelfInfoViewModel>();
final ConversationService _conversationService = serviceLocator<ConversationService>();
final FriendshipServices _friendshipServices = serviceLocator<FriendshipServices>();
final TUIChatGlobalModel _chatGlobalModel = serviceLocator<TUIChatGlobalModel>();
final MessageService _messageService = serviceLocator<MessageService>();
late V2TimConversationListener _conversationListener;
List<V2TimConversation?> _conversationList = [];
@ -51,8 +51,7 @@ class TUIConversationViewModel extends ChangeNotifier {
bool _haveMoreData = true;
int _totalUnReadCount = 0;
String? _scrollToConversation;
final TUIChatGlobalModel globalChatModel =
serviceLocator<TUIChatGlobalModel>();
final TUIChatGlobalModel globalChatModel = serviceLocator<TUIChatGlobalModel>();
String _nextSeq = "0";
ConversationLifeCycle? _lifeCycle;
@ -61,13 +60,10 @@ class TUIConversationViewModel extends ChangeNotifier {
if (PlatformUtils().isWeb) {
try {
_conversationList.sort((a, b) {
return b!.lastMessage!.timestamp!
.compareTo(a!.lastMessage!.timestamp!);
return b!.lastMessage!.timestamp!.compareTo(a!.lastMessage!.timestamp!);
});
final pinnedConversation = _conversationList
.where((element) => element?.isPinned == true)
.toList();
final pinnedConversation = _conversationList.where((element) => element?.isPinned == true).toList();
_conversationList.removeWhere((element) => element?.isPinned == true);
_conversationList = [...pinnedConversation, ..._conversationList];
// ignore: empty_catches
@ -79,8 +75,7 @@ class TUIConversationViewModel extends ChangeNotifier {
}
V2TimConversation? getConversation(String conversationID) {
return _conversationList.firstWhereOrNull(
(element) => element?.conversationID == conversationID);
return _conversationList.firstWhereOrNull((element) => element?.conversationID == conversationID);
}
String? get scrollToConversation => _scrollToConversation;
@ -127,8 +122,7 @@ class TUIConversationViewModel extends ChangeNotifier {
}
TUIConversationViewModel() {
_conversationListener =
V2TimConversationListener(onConversationChanged: (conversationList) {
_conversationListener = V2TimConversationListener(onConversationChanged: (conversationList) {
_onConversationListChanged(conversationList);
}, onNewConversation: (conversationList) {
_addNewConversation(conversationList);
@ -141,7 +135,7 @@ class TUIConversationViewModel extends ChangeNotifier {
if (!PlatformUtils().isWeb) {
loadInitConversation();
}
}, onConversationDeleted: (List<String> conversationIDList) {
}, onConversationDeleted:(List<String> conversationIDList) {
_onConversationDeleted(conversationIDList);
for (var conversationID in conversationIDList) {
String resultID = "";
@ -174,8 +168,7 @@ class TUIConversationViewModel extends ChangeNotifier {
Future<void> loadData({required int count}) async {
_haveMoreData = true;
final isRefresh = _nextSeq == "0";
final conversationResult = await _conversationService.getConversationList(
nextSeq: _nextSeq, count: count);
final conversationResult = await _conversationService.getConversationList(nextSeq: _nextSeq, count: count);
_nextSeq = conversationResult?.nextSeq ?? "";
final conversationList = conversationResult?.conversationList;
if (conversationList != null) {
@ -188,12 +181,8 @@ class TUIConversationViewModel extends ChangeNotifier {
} else {
combinedConversationList = [..._conversationList, ...conversationList];
}
final List<V2TimConversation?> finalConversationList = await _lifeCycle
?.conversationListWillMount(combinedConversationList) ??
combinedConversationList;
_conversationList = removeDuplicates<V2TimConversation?>(
finalConversationList,
(item1, item2) => item1?.conversationID == item2?.conversationID);
final List<V2TimConversation?> finalConversationList = await _lifeCycle?.conversationListWillMount(combinedConversationList) ?? combinedConversationList;
_conversationList = removeDuplicates<V2TimConversation?>(finalConversationList, (item1, item2) => item1?.conversationID == item2?.conversationID);
notifyListeners();
}
_totalUnReadCount = await _conversationService.getTotalUnreadCount();
@ -210,15 +199,11 @@ class TUIConversationViewModel extends ChangeNotifier {
required String conversationID,
required bool isPinned,
}) {
return _conversationService.pinConversation(
conversationID: conversationID, isPinned: isPinned);
return _conversationService.pinConversation(conversationID: conversationID, isPinned: isPinned);
}
Future<V2TimCallback?> clearHistoryMessage(
{required String convID, required int convType}) async {
if (_lifeCycle?.shouldClearHistoricalMessageForConversation != null &&
await _lifeCycle!.shouldClearHistoricalMessageForConversation(convID) ==
false) {
Future<V2TimCallback?> clearHistoryMessage({required String convID, required int convType}) async {
if (_lifeCycle?.shouldClearHistoricalMessageForConversation != null && await _lifeCycle!.shouldClearHistoricalMessageForConversation(convID) == false) {
return null;
}
@ -232,22 +217,17 @@ class TUIConversationViewModel extends ChangeNotifier {
}
searchFriends(String searchKey) async {
final res = await _friendshipServices.searchFriends(
searchParam: V2TimFriendSearchParam(keywordList: [searchKey]));
final res = await _friendshipServices.searchFriends(searchParam: V2TimFriendSearchParam(keywordList: [searchKey]));
return res;
}
Future<V2TimCallback?> deleteConversation(
{required String conversationID}) async {
if (_lifeCycle?.shouldDeleteConversation != null &&
await _lifeCycle!.shouldDeleteConversation(conversationID) == false) {
Future<V2TimCallback?> deleteConversation({required String conversationID}) async {
if (_lifeCycle?.shouldDeleteConversation != null && await _lifeCycle!.shouldDeleteConversation(conversationID) == false) {
return null;
}
final res = await _conversationService.deleteConversation(
conversationID: conversationID);
final res = await _conversationService.deleteConversation(conversationID: conversationID);
if (res.code == 0) {
_conversationList
.removeWhere((element) => element?.conversationID == conversationID);
_conversationList.removeWhere((element) => element?.conversationID == conversationID);
notifyListeners();
}
return res;
@ -255,11 +235,9 @@ class TUIConversationViewModel extends ChangeNotifier {
_onConversationListChanged(List<V2TimConversation> list) {
for (int element = 0; element < list.length; element++) {
int index = _conversationList.indexWhere(
(item) => item!.conversationID == list[element].conversationID);
int index = _conversationList.indexWhere((item) => item!.conversationID == list[element].conversationID);
if (index > -1) {
_conversationList.setAll(
index, [list[element]] as List<V2TimConversation?>);
_conversationList.setAll(index, [list[element]] as List<V2TimConversation?>);
} else {
_conversationList.add(list[element]);
}
@ -270,13 +248,10 @@ class TUIConversationViewModel extends ChangeNotifier {
_onConversationDeleted(List<String> list) {
for (int i = 0; i < list.length; i++) {
int index = _conversationList
.indexWhere((item) => item!.conversationID == list[i]);
int index = _conversationList.indexWhere((item) => item!.conversationID == list[i]);
if (index > -1) {
_conversationList.removeAt(index);
_conversationList = removeDuplicates<V2TimConversation?>(
_conversationList,
(item1, item2) => item1?.conversationID == item2?.conversationID);
_conversationList = removeDuplicates<V2TimConversation?>(_conversationList, (item1, item2) => item1?.conversationID == item2?.conversationID);
}
}
notifyListeners();
@ -284,19 +259,16 @@ class TUIConversationViewModel extends ChangeNotifier {
_addNewConversation(List<V2TimConversation> list) {
_conversationList.addAll(list);
_conversationList = removeDuplicates<V2TimConversation?>(_conversationList,
(item1, item2) => item1?.conversationID == item2?.conversationID);
_conversationList = removeDuplicates<V2TimConversation?>(_conversationList, (item1, item2) => item1?.conversationID == item2?.conversationID);
notifyListeners();
}
setConversationListener() {
_conversationService.addConversationListener(
listener: _conversationListener);
_conversationService.addConversationListener(listener: _conversationListener);
}
removeConversationListener() {
_conversationService.removeConversationListener(
listener: _conversationListener);
_conversationService.removeConversationListener(listener: _conversationListener);
}
Future<V2TimCallback> setConversationDraft({
@ -306,25 +278,19 @@ class TUIConversationViewModel extends ChangeNotifier {
String? groupID,
bool isAllowWeb = true,
}) async {
assert(!isTopic || (groupID != null && groupID.isNotEmpty),
"When 'isTopic' is true, 'groupID' must not be null or empty.");
assert(!isTopic || (groupID != null && groupID.isNotEmpty), "When 'isTopic' is true, 'groupID' must not be null or empty.");
if (PlatformUtils().isWeb && isAllowWeb) {
webDraftMap[conversationID] = draftText ?? "";
return V2TimCallback(code: 0, desc: "");
} else {
if (isTopic) {
final topicInfoList = await TencentImSDKPlugin.v2TIMManager
.getGroupManager()
.getTopicInfoList(groupID: groupID!, topicIDList: [conversationID]);
final topicInfoList = await TencentImSDKPlugin.v2TIMManager.getGroupManager().getTopicInfoList(groupID: groupID!, topicIDList: [conversationID]);
final topicInfo = topicInfoList.data?.first.topicInfo;
topicInfo?.draftText = draftText;
final res = await TencentImSDKPlugin.v2TIMManager
.getGroupManager()
.setTopicInfo(groupID: groupID, topicInfo: topicInfo!);
final res = await TencentImSDKPlugin.v2TIMManager.getGroupManager().setTopicInfo(topicInfo: topicInfo!);
return res;
} else {
return _conversationService.setConversationDraft(
conversationID: conversationID, draftText: draftText);
return _conversationService.setConversationDraft(conversationID: conversationID, draftText: draftText);
}
}
}

View File

@ -1,7 +1,15 @@
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimFriendshipListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_application_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_response_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_application.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_operation_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_status.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/block_list_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/friend_list_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/new_contact_life_cycle.dart';

View File

@ -2,13 +2,19 @@
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_result_item.dart';
import 'package:tencent_cloud_chat_uikit/data_services/friendShip/friendship_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/conversation/conversation_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
enum KeywordListMatchType {
V2TIM_KEYWORD_LIST_MATCH_TYPE_OR,

View File

@ -1,5 +1,5 @@
import 'package:flutter/cupertino.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/tim_uikit_config.dart';
class TUISelfInfoViewModel extends ChangeNotifier {

View File

@ -1,4 +1,7 @@
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimConversationListener.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation_result.dart';
abstract class ConversationService {
Future<V2TimConversationResult?> getConversationList({

View File

@ -1,7 +1,12 @@
import 'package:tencent_cloud_chat_sdk/enum/V2TimConversationListener.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation_result.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/data_services/conversation/conversation_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
class ConversationServicesImpl extends ConversationService {
final CoreServicesImpl _coreService = serviceLocator<CoreServicesImpl>();
@ -114,7 +119,7 @@ class ConversationServicesImpl extends ConversationService {
{required String convID}) async {
final result = await TencentImSDKPlugin.v2TIMManager
.getConversationManager()
.getConversationListByConversaionIds(conversationIDList: [convID]);
.getConversationListByConversationIds(conversationIDList: [convID]);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,

View File

@ -1,7 +1,13 @@
import 'package:flutter/cupertino.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimSDKListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/log_level_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.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/data_services/core/tim_uikit_config.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
enum AppStatus { foreground, background }

View File

@ -2,11 +2,19 @@
import 'package:collection/collection.dart';
import 'package:flutter/cupertino.dart';
import 'package:tencent_chat_i18n_tool/tools/i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimSDKListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/log_level_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_status.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_setting_model.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/common_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/logger.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_callback.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/listener_model/tui_group_listener_model.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_conversation_view_model.dart';
@ -18,6 +26,9 @@ import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/web_support/uikit_web_support.dart'
if (dart.library.html) 'package:tencent_cloud_chat_uikit/data_services/core/web_support/uikit_web_support_implement.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme_view_model.dart';
typedef EmptyAvatarBuilder = Widget Function(BuildContext context);

View File

@ -1,6 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/tim_uikit_wide_modal_operation_key.dart';
import 'package:tencent_im_base/theme/tui_theme.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class TIMUIKitConfig {
/// Control if show online status of friends or contacts.

View File

@ -1,4 +1,17 @@
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimFriendshipListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_application_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_response_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_application_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_check_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_operation_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_status.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
abstract class FriendshipServices {
Future<List<V2TimFriendInfoResult>?> getFriendsInfo({

View File

@ -1,8 +1,24 @@
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimFriendshipListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_application_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_response_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_application_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_check_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_operation_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_status.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/friendShip/friendship_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/error_message_converter.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
class FriendshipServicesImpl implements FriendshipServices {
final CoreServicesImpl _coreService = serviceLocator<CoreServicesImpl>();

View File

@ -1,4 +1,18 @@
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimGroupListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_application_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_filter_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_role_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_application_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_operation_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
abstract class GroupServices {
Future<List<V2TimGroupInfo>?> getJoinedGroupList();

View File

@ -1,9 +1,25 @@
import 'package:tencent_cloud_chat_sdk/enum/V2TimGroupListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_application_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_filter_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_role_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_application_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_operation_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/error_message_converter.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/optimize_utils.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
class GroupServicesImpl extends GroupServices {
static List<Function?> groupInfoCallBackList = [];

View File

@ -3,13 +3,32 @@
import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimAdvancedMsgListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimSimpleMsgListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/get_group_message_read_member_list_filter.dart';
import 'package:tencent_cloud_chat_sdk/enum/history_msg_get_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_priority_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/offlinePushInfo.dart';
import 'package:tencent_cloud_chat_sdk/enum/receive_message_opt_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_message_read_member_list.dart';
import 'package:tencent_cloud_chat_sdk/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_list_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_online_url.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_receipt.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_msg_create_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_conversation_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/error_message_converter.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
class MessageServiceImpl extends MessageService {
final CoreServicesImpl _coreService = serviceLocator<CoreServicesImpl>();
@ -349,6 +368,7 @@ class MessageServiceImpl extends MessageService {
OfflinePushInfo? offlinePushInfo,
String? cloudCustomData,
String? localCustomData,
bool isExcludedFromContentModeration = false,
}) async {
final result =
await TencentImSDKPlugin.v2TIMManager.getMessageManager().sendMessage(
@ -361,6 +381,7 @@ class MessageServiceImpl extends MessageService {
needReadReceipt: needReadReceipt,
localCustomData: localCustomData,
cloudCustomData: cloudCustomData,
isExcludedFromContentModeration: isExcludedFromContentModeration,
);
if (result.code != 0) {
String recommendText = ErrorMessageConverter.getErrorMessage(result.code);

View File

@ -1,4 +1,21 @@
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimAdvancedMsgListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimSimpleMsgListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/get_group_message_read_member_list_filter.dart';
import 'package:tencent_cloud_chat_sdk/enum/history_msg_get_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_priority_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/offlinePushInfo.dart';
import 'package:tencent_cloud_chat_sdk/enum/receive_message_opt_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_message_read_member_list.dart';
import 'package:tencent_cloud_chat_sdk/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_list_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_online_url.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_receipt.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_msg_create_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
class MessageListResponse {
final bool haveMoreData;
@ -71,7 +88,8 @@ abstract class MessageService {
bool needReadReceipt = false,
OfflinePushInfo? offlinePushInfo,
String? cloudCustomData, //
String? localCustomData});
String? localCustomData,
bool isExcludedFromContentModeration});
Future<V2TimValueCallback<V2TimMessage>> sendReplyMessage({
required String id, // ID

View File

@ -16,7 +16,7 @@ import 'package:tencent_cloud_chat_uikit/data_services/message/message_service_i
import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_search_view_model.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart';
import 'package:tencent_im_base/theme/tui_theme_view_model.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme_view_model.dart';
final serviceLocator = GetIt.instance;
bool boolIsInitailized = false;

View File

@ -1,12 +1,10 @@
library tencent_cloud_chat_uikit;
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/manager/v2_tim_manager.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'data_services/core/core_services_implements.dart';
export 'data_services/core/core_services_implements.dart';
export 'package:tencent_im_base/theme/tui_theme.dart';
export 'package:tencent_im_base/theme/color.dart';
// Sticker
export 'package:tim_ui_kit_sticker_plugin/tim_ui_kit_sticker_plugin.dart';
@ -34,7 +32,6 @@ export 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitAppBar/ti
export 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list.dart';
export 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field.dart';
export 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitGroup/tim_uikit_group_application_list.dart';
export 'package:tencent_im_base/tencent_im_base.dart';
export 'package:tencent_cloud_chat_uikit/ui/widgets/link_preview/models/link_preview_content.dart';
export 'package:tencent_cloud_chat_uikit/ui/widgets/column_menu.dart';
export 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitProfile/widget/tim_uikit_profile_userinfo_card/tim_uikit_profile_userinfo_card.dart';

37
lib/theme/color.dart Normal file
View File

@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
Color hexToColor(String hexString) {
return Color(int.parse(hexString, radix: 16)).withAlpha(255);
}
class CommonColor {
static const weakBackgroundColor = Color(0xFFEDEDED);
static const weakDividerColor = Color(0xFFE5E6E9);
static const primaryColor = Color(0xFF147AFF);
static const lightPrimaryColor = Color(0xFFC0E1FF);
static const secondaryColor = Color(0xFF147AFF);
static const weakTextColor = Color(0xFF999999);
static const infoColor = Color(0xFFFF9C19);
static const cautionColor = Color(0xFFFF584C);
static const ownerColor = Colors.orange;
static const adminColor = Colors.blue;
static const inputFillColor = Color.fromARGB(0, 242, 243, 245);
static const textgrey = Color(0xFFAEA4A3);
static const defaultTheme = TUITheme(
weakBackgroundColor: Color(0xFFEDEDED),
weakDividerColor: Color(0xFFE5E6E9),
primaryColor: Color(0xFF147AFF),
secondaryColor: Color(0xFF147AFF),
infoColor: Color(0xFFFF9C19),
lightPrimaryColor: Color(0xFFC0E1FF),
weakTextColor: Color(0xFF999999),
darkTextColor: Color(0xFF444444),
cautionColor: Color(0xFFFF584C),
ownerColor: Colors.orange,
adminColor: Colors.blue,
inputFillColor: Color.fromARGB(0, 242, 243, 245),
textgrey: Color(0xFFAEA4A3),
);
}

597
lib/theme/tui_theme.dart Normal file
View File

@ -0,0 +1,597 @@
import 'package:flutter/material.dart';
class TUITheme {
const TUITheme({
this.primaryColor = const Color(0xFF00449E),
this.secondaryColor = const Color(0xFF147AFF),
this.infoColor = const Color(0xFFFF9C19),
this.weakBackgroundColor = const Color(0xFFEDEDED),
this.wideBackgroundColor = Colors.white,
this.weakDividerColor = const Color(0xFFE5E6E9),
this.weakTextColor = const Color(0xFF999999),
this.darkTextColor = const Color(0xFF444444),
this.lightPrimaryColor = const Color(0xFF3371CD),
this.textColor,
this.cautionColor = const Color(0xFFFF584C),
this.ownerColor = Colors.orange,
this.adminColor = Colors.blue,
this.white = Colors.white,
this.black = Colors.black,
this.inputFillColor = const Color(0xFFEDEDED),
this.textgrey = const Color(0xFFAEA4A3),
///
this.selectPanelBgColor = const Color(0xFFF9F9FA),
/// icon颜色
this.selectPanelTextIconColor = const Color(0xFF37393F),
/// Appbar
this.appbarBgColor = const Color(0xFFF2F3F5),
/// Appbar
this.appbarTextColor = const Color(0xFF010000),
///
this.conversationItemBgColor = Colors.white, // 1
///
this.conversationItemBorderColor = const Color(0xFFE5E6E9), // 1
///
this.conversationItemActiveBgColor = const Color(0xFFEDEDED), // 1
///
this.conversationItemPinedBgColor = const Color(0xFFEDEDED), // 1
/// Title字体颜色
this.conversationItemTitleTextColor = Colors.black, // 1
/// LastMessage字体颜色
this.conversationItemLastMessageTextColor = const Color(0xFF999999), // 1
/// Time字体颜色
this.conversationItemTitmeTextColor = const Color(0xFF999999), // 1
/// 线
this.conversationItemOnlineStatusBgColor = Colors.green, // 1
/// 线
this.conversationItemOfflineStatusBgColor = Colors.grey, // 1
///
this.conversationItemUnreadCountBgColor = const Color(0xFFFF584C), // 1
///
this.conversationItemUnreadCountTextColor = Colors.white, // 1
/// 稿
this.conversationItemDraftTextColor = const Color(0xFFFF584C), // 1
/// Icon颜色
this.conversationItemNoNotificationIconColor = const Color(0xFF999999), // 1
///
this.conversationItemSliderTextColor = Colors.white, // 1
/// Clear背景颜色
this.conversationItemSliderClearBgColor = const Color(0xFF00449E), // 1
/// Pin背景颜色
this.conversationItemSliderPinBgColor = const Color(0xFFFF9C19), // 1
/// Delete背景颜色
this.conversationItemSliderDeleteBgColor = Colors.red, // 1
///
this.conversationItemChooseBgColor = const Color(0xFFE7F0FF), // 1
///
this.chatBgColor, // 1
///
this.desktopChatMessageInputBgColor, // 1
///
this.chatTimeDividerTextColor = const Color(0xFF999999), // 1
///
this.chatHeaderBgColor = const Color(0xFFF2F3F5),
/// Title字体颜色
this.chatHeaderTitleTextColor = const Color(0xFF010000),
/// Back字体颜色
this.chatHeaderBackTextColor = const Color(0xFF010000),
/// Action字体颜色
this.chatHeaderActionTextColor = const Color(0xFF010000),
///
this.chatMessageItemTextColor = Colors.black, // 1
///
this.chatMessageItemFromSelfBgColor = const Color(0xFFD1E3FF),
///
this.chatMessageItemFromOthersBgColor = const Color(0xFFEDEDED), // 1
///
this.chatMessageItemUnreadStatusTextColor = const Color(0xFF999999), // 1
///
this.chatMessageTongueBgColor = const Color(0xFFAEA4A3),
///
this.chatMessageTongueTextColor = const Color(0xFFAEA4A3),
});
//
// Primary Color For The App
final Color? primaryColor;
//
// Secondary Color For The App
final Color? secondaryColor;
//
// Info Color, Used For Secondary Action Or Info
final Color? infoColor;
//
// Weak Background Color, Lighter Than Main Background, Used For Marginal Space Or Shadowy Space
final Color? weakBackgroundColor;
//
// Weak Background Color, Lighter Than Main Background, Used For Marginal Space Or Shadowy Space
final Color? wideBackgroundColor;
// 线线
// Weak Divider Color, Used For Divider Or Border
final Color? weakDividerColor;
//
// Weak Text Color
final Color? weakTextColor;
//
// Dark Text Color
final Color? darkTextColor;
// AppBar或Panels
// Light Primary Color, Used For AppBar Or Several Panels
final Color? lightPrimaryColor;
//
// TextColor
final Color? textColor;
//
// Caution Color, Used For Warning Actions
final Color? cautionColor;
//
// Group Owner Identification Color
final Color? ownerColor;
//
// Group Admin Identification Color
final Color? adminColor;
//
// white
final Color? white;
//
// black
final Color? black;
//
// input fill color
final Color? inputFillColor;
//
// grey text color
final Color? textgrey;
///
///
/// Appbar
final Color? appbarBgColor;
/// Appbar
final Color? appbarTextColor;
///
final Color? selectPanelBgColor;
/// icon颜色
final Color? selectPanelTextIconColor;
///
final Color? conversationItemBgColor;
///
final Color? conversationItemBorderColor;
///
final Color? conversationItemActiveBgColor;
///
final Color? conversationItemPinedBgColor;
/// Title字体颜色
final Color? conversationItemTitleTextColor;
/// LastMessage字体颜色
final Color? conversationItemLastMessageTextColor;
/// Time字体颜色
final Color? conversationItemTitmeTextColor;
/// 线
final Color? conversationItemOnlineStatusBgColor;
/// 线
final Color? conversationItemOfflineStatusBgColor;
///
final Color? conversationItemUnreadCountBgColor;
///
final Color? conversationItemUnreadCountTextColor;
/// 稿
final Color? conversationItemDraftTextColor;
/// Icon颜色
final Color? conversationItemNoNotificationIconColor;
///
final Color? conversationItemSliderTextColor;
/// Clear背景颜色
final Color? conversationItemSliderClearBgColor;
/// Pin背景颜色
final Color? conversationItemSliderPinBgColor;
/// Delete背景颜色
final Color? conversationItemSliderDeleteBgColor;
///
final Color? conversationItemChooseBgColor;
///
final Color? chatBgColor;
///
final Color? desktopChatMessageInputBgColor;
///
final Color? chatTimeDividerTextColor;
///
final Color? chatHeaderBgColor;
/// Title字体颜色
final Color? chatHeaderTitleTextColor;
/// Back字体颜色
final Color? chatHeaderBackTextColor;
/// Action字体颜色
final Color? chatHeaderActionTextColor;
///
final Color? chatMessageItemTextColor;
///
final Color? chatMessageItemFromSelfBgColor;
///
final Color? chatMessageItemFromOthersBgColor;
///
final Color? chatMessageItemUnreadStatusTextColor;
///
final Color? chatMessageTongueBgColor;
///
final Color? chatMessageTongueTextColor;
static const TUITheme light = TUITheme();
static const TUITheme dark = TUITheme();
MaterialColor get primaryMaterialColor => createMaterialColor(primaryColor!);
MaterialColor get lightPrimaryMaterialColor =>
createMaterialColor(lightPrimaryColor!);
TUITheme.fromJson(Map<String, dynamic> json)
: primaryColor = json['primaryColor'] as Color?,
secondaryColor = json['secondaryColor'] as Color?,
infoColor = json['infoColor'] as Color?,
weakBackgroundColor = json['weakBackgroundColor'] as Color?,
wideBackgroundColor = json['wideBackgroundColor'] as Color?,
weakDividerColor = json['weakDividerColor'] as Color?,
weakTextColor = json['weakTextColor'] as Color?,
darkTextColor = json['darkTextColor'] as Color?,
lightPrimaryColor = json['lightPrimaryColor'] as Color?,
textColor = json['textColor'] as Color?,
cautionColor = json['cautionColor'] as Color?,
ownerColor = json['ownerColor'] as Color?,
white = json['white'] as Color?,
black = json['black'] as Color?,
inputFillColor = json["inputFillColor"] as Color?,
textgrey = json['textgrey'] as Color?,
adminColor = json['adminColor'] as Color?,
selectPanelBgColor = json['selectPanelBgColor'] as Color?,
selectPanelTextIconColor = json['selectPanelTextIconColor'] as Color?,
appbarBgColor = json['appbarBgColor'] as Color?,
appbarTextColor = json['appbarTextColor'] as Color?,
///
conversationItemBgColor = json['conversationItemBgColor'] as Color?,
///
conversationItemBorderColor =
json['conversationItemBorderColor'] as Color?,
///
conversationItemActiveBgColor =
json['conversationItemActiveBgColor'] as Color?,
///
conversationItemPinedBgColor =
json['conversationItemPinedBgColor'] as Color?,
/// Title字体颜色
conversationItemTitleTextColor =
json['conversationItemTitleTextColor'] as Color?,
/// LastMessage字体颜色
conversationItemLastMessageTextColor =
json['conversationItemLastMessageTextColor'] as Color?,
/// Time字体颜色
conversationItemTitmeTextColor =
json['conversationItemTitmeTextColor'] as Color?,
/// 线
conversationItemOnlineStatusBgColor =
json['conversationItemOnlineStatusBgColor'] as Color?,
/// 线
conversationItemOfflineStatusBgColor =
json['conversationItemOfflineStatusBgColor'] as Color?,
///
conversationItemUnreadCountBgColor =
json['conversationItemUnreadCountBgColor'] as Color?,
///
conversationItemUnreadCountTextColor =
json['conversationItemUnreadCountTextColor'] as Color?,
conversationItemChooseBgColor =
json['conversationItemChooseBgColor'] as Color?,
/// 稿
conversationItemDraftTextColor =
json['conversationItemDraftTextColor'] as Color?,
/// Icon颜色
conversationItemNoNotificationIconColor =
json['conversationItemNoNotificationIconColor'] as Color?,
///
conversationItemSliderTextColor =
json['conversationItemSliderTextColor'] as Color?,
/// Clear背景颜色
conversationItemSliderClearBgColor =
json['conversationItemSliderClearBgColor'] as Color?,
/// Pin背景颜色
conversationItemSliderPinBgColor =
json['conversationItemSliderPinBgColor'] as Color?,
/// Delete背景颜色
conversationItemSliderDeleteBgColor =
json['conversationItemSliderDeleteBgColor'] as Color?,
///
chatBgColor = json['chatBgColor'] as Color?,
///
desktopChatMessageInputBgColor =
json['desktopChatMessageInputBgColor'] as Color?,
///
chatTimeDividerTextColor = json['chatTimeDividerTextColor'] as Color?,
///
chatHeaderBgColor = json['chatHeaderBgColor'] as Color?,
/// Title字体颜色
chatHeaderTitleTextColor = json['chatHeaderTitleTextColor'] as Color?,
/// Back字体颜色
chatHeaderBackTextColor = json['chatHeaderBackTextColor'] as Color?,
/// Action字体颜色
chatHeaderActionTextColor = json['chatHeaderActionTextColor'] as Color?,
///
chatMessageItemTextColor = json['chatMessageItemTextColor'] as Color?,
///
chatMessageItemFromSelfBgColor =
json['chatMessageItemFromSelfBgColor'] as Color?,
///
chatMessageItemFromOthersBgColor =
json['chatMessageItemFromOthersBgColor'] as Color?,
///
chatMessageItemUnreadStatusTextColor =
json['chatMessageItemUnreadStatusTextColor'] as Color?,
///
chatMessageTongueBgColor = json['chatMessageTongueBgColor'] as Color?,
///
chatMessageTongueTextColor =
json['chatMessageTongueTextColor'] as Color?;
toJson() => <String, dynamic>{
'primaryColor': primaryColor,
'secondaryColor': secondaryColor,
'infoColor': infoColor,
'weakBackgroundColor': weakBackgroundColor,
'wideBackgroundColor': wideBackgroundColor,
'weakDividerColor': weakDividerColor,
'weakTextColor': weakTextColor,
'darkTextColor': darkTextColor,
'lightPrimaryColor': lightPrimaryColor,
'textColor': textColor,
'cautionColor': cautionColor,
'ownerColor': ownerColor,
'adminColor': adminColor,
'white': white,
'black': black,
'inputFillColor': inputFillColor,
'textgrey': textgrey,
"selectPanelBgColor": selectPanelBgColor,
"selectPanelTextIconColor": selectPanelTextIconColor,
"appbarBgColor": appbarBgColor,
"appbarTextColor": appbarTextColor,
///
"conversationItemBgColor": conversationItemBgColor,
///
"conversationItemBorderColor": conversationItemBorderColor,
///
"conversationItemActiveBgColor": conversationItemActiveBgColor,
///
"conversationItemPinedBgColor": conversationItemPinedBgColor,
/// Title字体颜色
"conversationItemTitleTextColor": conversationItemTitleTextColor,
/// LastMessage字体颜色
"conversationItemLastMessageTextColor":
conversationItemLastMessageTextColor,
/// Time字体颜色
"conversationItemTitmeTextColor": conversationItemTitmeTextColor,
/// 线
"conversationItemOnlineStatusBgColor":
conversationItemOnlineStatusBgColor,
/// 线
"conversationItemOfflineStatusBgColor":
conversationItemOfflineStatusBgColor,
///
"conversationItemUnreadCountBgColor":
conversationItemUnreadCountBgColor,
///
"conversationItemUnreadCountTextColor":
conversationItemUnreadCountTextColor,
/// 稿
"conversationItemDraftTextColor": conversationItemDraftTextColor,
/// Icon颜色
"conversationItemNoNotificationIconColor":
conversationItemNoNotificationIconColor,
///
"conversationItemSliderTextColor": conversationItemSliderTextColor,
/// Clear背景颜色
"conversationItemSliderClearBgColor":
conversationItemSliderClearBgColor,
/// Pin背景颜色
"conversationItemSliderPinBgColor": conversationItemSliderPinBgColor,
/// Delete背景颜色
"conversationItemSliderDeleteBgColor":
conversationItemSliderDeleteBgColor,
/// Delete背景颜色
"conversationItemChooseBgColor": conversationItemChooseBgColor,
///
"chatBgColor": chatBgColor,
///
"desktopChatMessageInputBgColor": desktopChatMessageInputBgColor,
///
"chatTimeDividerTextColor": chatTimeDividerTextColor,
///
"chatHeaderBgColor": chatHeaderBgColor,
/// Title字体颜色
"chatHeaderTitleTextColor": chatHeaderTitleTextColor,
/// Back字体颜色
"chatHeaderBackTextColor": chatHeaderBackTextColor,
/// Action字体颜色
"chatHeaderActionTextColor": chatHeaderActionTextColor,
///
"chatMessageItemTextColor": chatMessageItemTextColor,
///
"chatMessageItemFromSelfBgColor": chatMessageItemFromSelfBgColor,
///
"chatMessageItemFromOthersBgColor": chatMessageItemFromOthersBgColor,
///
"chatMessageItemUnreadStatusTextColor":
chatMessageItemUnreadStatusTextColor,
///
"chatMessageTongueBgColor": chatMessageTongueBgColor,
///
"chatMessageTongueTextColor": chatMessageTongueTextColor,
};
MaterialColor createMaterialColor(Color color) {
List strengths = <double>[.05];
Map<int, Color> swatch = <int, Color>{};
final int r = color.red, g = color.green, b = color.blue;
for (int i = 1; i < 10; i++) {
strengths.add(0.1 * i);
}
for (var strength in strengths) {
final double ds = 0.5 - strength;
swatch[(strength * 1000).round()] = Color.fromRGBO(
r + ((ds < 0 ? r : (255 - r)) * ds).round(),
g + ((ds < 0 ? g : (255 - g)) * ds).round(),
b + ((ds < 0 ? b : (255 - b)) * ds).round(),
1,
);
}
return MaterialColor(color.value, swatch);
}
}

View File

@ -0,0 +1,16 @@
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
class TUIThemeViewModel extends ChangeNotifier {
TUITheme _theme = CommonColor.defaultTheme;
TUITheme get theme {
return _theme;
}
set theme(TUITheme theme) {
_theme = theme;
notifyListeners();
}
}

View File

@ -2,6 +2,13 @@
import 'package:flutter/cupertino.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:tencent_cloud_chat_sdk/enum/history_msg_get_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_priority_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/offlinePushInfo.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.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';

View File

@ -1,4 +1,5 @@
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_conversation_view_model.dart';
class TIMUIKitConversationController {

View File

@ -1,8 +1,11 @@
import 'package:flutter/cupertino.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_operation_result.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_profile_view_model.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/text_input_bottom_sheet.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class TIMUIKitProfileController {
late TUIProfileViewModel model;

View File

@ -1,4 +1,4 @@
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
class ErrorMessageConverter {
static Map<int, String> errorCodeMap = {

View File

@ -1,6 +1,4 @@
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
final outputLogger = TencentCloudChatLog();

View File

@ -2,12 +2,25 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_change_info_type.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_tips_elem_type.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_elem_type.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_change_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_tips_elem.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_image.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/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/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/ui/constants/history_message_constant.dart';
import 'package:tencent_cloud_chat_uikit/ui/constants/time.dart';
import 'package:collection/collection.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/common_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/logger.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class MessageUtils {
// CallingData的方式和Trtc的方法一致
@ -274,7 +287,7 @@ class MessageUtils {
static Widget wrapMessageTips(Widget child, TUITheme? theme) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 10), child: child);
margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 30), child: child);
}
static String getAbstractMessageAsync(V2TimMessage message,

View File

@ -7,11 +7,11 @@ import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.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/platform.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class PermissionRequestInfo extends StatefulWidget {
final Function removeOverLay;

View File

@ -1,7 +1,7 @@
// ignore_for_file: prefer_typing_uninitialized_variables
import 'package:intl/intl.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
class TimeAgo {
List<String> dayMap() {

View File

@ -1,9 +1,11 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.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/widgets/wide_popup.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/add_friend_life_cycle.dart';
@ -11,9 +13,9 @@ import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_inf
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/friendShip/friendship_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitAddFriend/tim_uikit_send_application.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class TIMUIKitAddFriend extends StatefulWidget {
final bool? isShowDefaultGroup;

View File

@ -1,4 +1,7 @@
import 'package:flutter/material.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
@ -6,9 +9,9 @@ import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/add_friend_li
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/friendShip/friendship_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class SendApplication extends StatefulWidget {
final V2TimUserFullInfo friendInfo;

View File

@ -1,18 +1,22 @@
import 'package:flutter/material.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_type.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.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/widgets/wide_popup.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.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_base.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/add_group_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_friendship_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/conversation/conversation_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitAddGroup/tim_uikit_send_application.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
class TIMUIKitAddGroup extends StatefulWidget {
/// The life cycle hooks for adding group business logic

View File

@ -1,14 +1,18 @@
import 'package:flutter/material.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_type.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.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_state.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/add_group_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class SendJoinGroupApplication extends StatefulWidget {
final V2TimGroupInfo groupInfo;

View File

@ -1,16 +1,17 @@
import 'package:flutter/material.dart';
import 'package:flutter_slidable_plus_plus/flutter_slidable_plus_plus.dart';
import 'package:provider/provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.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';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_friendship_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme_view_model.dart';
typedef BlackListItemBuilder = Widget Function(
BuildContext context, V2TimFriendInfo friendInfo);
@ -88,8 +89,7 @@ class _TIMUIKitBlackListState extends TIMUIKitState<TIMUIKitBlackList> {
child: Text(
showName,
style: TextStyle(
color: theme.black,
fontSize: isDesktopScreen ? 14 : 18),
color: theme.black, fontSize: isDesktopScreen ? 14 : 18),
),
)),
if (isDesktopScreen)
@ -133,6 +133,7 @@ class _TIMUIKitBlackListState extends TIMUIKitState<TIMUIKitBlackList> {
return widget.itemBuilder ?? _itemBuilder;
}
@override
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
return MultiProvider(

View File

@ -1,6 +1,8 @@
import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_at_info.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';
@ -8,7 +10,6 @@ import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_glo
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/common_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKItMessageList/TIMUIKitTongue/tim_uikit_chat_history_message_list_tongue.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tuple/tuple.dart';
class TIMUIKitHistoryMessageListTongueContainer extends StatefulWidget {

View File

@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKItMessageList/TIMUIKitTongue/tim_uikit_chat_history_message_list_tongue.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class TIMUIKitTongueItem extends TIMUIKitStatelessWidget {
/// the callback after clicking

View File

@ -5,6 +5,11 @@ import 'package:flutter/material.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:provider/provider.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_elem_type.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_at_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.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';
@ -18,6 +23,7 @@ import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKItMessageLi
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKItMessageList/utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/keepalive_wrapper.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'TIMUIKitTongue/tim_uikit_chat_history_message_list_tongue.dart';
import 'TIMUIKitTongue/tim_uikit_chat_history_message_list_tongue_container.dart';

View File

@ -6,6 +6,13 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:provider/provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_elem_type.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_status.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/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_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_state.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart';
@ -36,6 +43,9 @@ import 'package:tencent_cloud_chat_uikit/ui/widgets/wide_popup.dart';
import 'package:tencent_super_tooltip/tencent_super_tooltip.dart';
import 'package:visibility_detector/visibility_detector.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme_view_model.dart';
import '../TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_select_emoji.dart';
typedef MessageRowBuilder = Widget? Function(
@ -58,8 +68,7 @@ typedef MessageRowBuilder = Widget? Function(
Function onScrollToIndexBegin,
);
typedef MessageNickNameBuilder = Widget Function(
BuildContext context, V2TimMessage message, TUIChatSeparateViewModel model);
typedef MessageNickNameBuilder = Widget Function(BuildContext context, V2TimMessage message, TUIChatSeparateViewModel model);
typedef MessageItemContent = Widget? Function(
V2TimMessage message,
@ -72,8 +81,7 @@ class MessageHoverControlItem {
Widget icon;
ValueChanged<TapDownDetails> onClick;
MessageHoverControlItem(
{required this.name, required this.icon, required this.onClick});
MessageHoverControlItem({required this.name, required this.icon, required this.onClick});
}
class MessageItemBuilder {
@ -141,11 +149,7 @@ class MessageToolTipItem {
final String iconImageAsset;
final VoidCallback onClick;
MessageToolTipItem(
{required this.label,
required this.id,
required this.iconImageAsset,
required this.onClick});
MessageToolTipItem({required this.label, required this.id, required this.iconImageAsset, required this.onClick});
}
class ToolTipsConfig {
@ -171,12 +175,10 @@ class ToolTipsConfig {
bool showTranslation;
/// A builder for additional custom items. We recommend using `additionalMessageToolTips` instead of this field since version 2.0, as you only need to provide the data rather than the whole widget. This makes usage easier and you don't need to worry about the UI display.
final Widget? Function(V2TimMessage message, Function() closeTooltip,
[Key? key, BuildContext? context])? additionalItemBuilder;
final Widget? Function(V2TimMessage message, Function() closeTooltip, [Key? key, BuildContext? context])? additionalItemBuilder;
/// A list of additional message tooltip menu items, provided with the data only. We recommend using this field instead of the previous `additionalItemBuilder`.
List<MessageToolTipItem> Function(
V2TimMessage message, Function() closeTooltip)? additionalMessageToolTips;
List<MessageToolTipItem> Function(V2TimMessage message, Function() closeTooltip)? additionalMessageToolTips;
ToolTipsConfig(
{this.showDeleteMessage = true,
@ -187,8 +189,7 @@ class ToolTipsConfig {
this.showCopyMessage = true,
this.showForwardMessage = true,
this.additionalMessageToolTips,
@Deprecated(
"Please use `additionalMessageToolTips` instead. You are now only expected to specify the data, rather than providing a whole widget. This makes usage easier, as you no longer need to worry about the UI display.")
@Deprecated("Please use `additionalMessageToolTips` instead. You are now only expected to specify the data, rather than providing a whole widget. This makes usage easier, as you no longer need to worry about the UI display.")
this.additionalItemBuilder});
}
@ -197,12 +198,10 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
final V2TimMessage message;
/// tap remote user avatar callback function
final void Function(String userID, TapDownDetails tapDetails)?
onTapForOthersPortrait;
final void Function(String userID, TapDownDetails tapDetails)? onTapForOthersPortrait;
/// secondary tap remote user avatar callback function
final void Function(String userID, TapDownDetails tapDetails)?
onSecondaryTapForOthersPortrait;
final void Function(String userID, TapDownDetails tapDetails)? onSecondaryTapForOthersPortrait;
/// the function use for reply message, when click replied message can scroll to it.
final Function? onScrollToIndex;
@ -211,8 +210,7 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
final Function? onScrollToIndexBegin;
/// the callback for long press event, except myself avatar
final Function(String? userId, String? nickName)?
onLongPressForOthersHeadPortrait;
final Function(String? userId, String? nickName)? onLongPressForOthersHeadPortrait;
/// message item builder, works for customize all message types and row layout.
final MessageItemBuilder? messageItemBuilder;
@ -232,8 +230,7 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
/// Auto mention user when send reply message
final bool allowAtUserWhenReply;
@Deprecated(
"Nickname will not show in one-to-one chat, if you tend to control it in group chat, please use `isShowSelfNameInGroup` and `isShowOthersNameInGroup` from `config: TIMUIKitChatConfig` instead")
@Deprecated("Nickname will not show in one-to-one chat, if you tend to control it in group chat, please use `isShowSelfNameInGroup` and `isShowOthersNameInGroup` from `config: TIMUIKitChatConfig` instead")
/// allow show user nick name
final bool showNickName;
@ -254,19 +251,16 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
final EdgeInsetsGeometry? textPadding;
/// avatar builder
final Widget Function(BuildContext context, V2TimMessage message)?
userAvatarBuilder;
final Widget Function(BuildContext context, V2TimMessage message)? userAvatarBuilder;
/// theme info for message and avatar
final MessageThemeData? themeData;
/// builder for nick name row
final Widget Function(BuildContext context, V2TimMessage message)?
topRowBuilder;
final Widget Function(BuildContext context, V2TimMessage message)? topRowBuilder;
/// builder for bottom raw which under message content
final Widget Function(BuildContext context, V2TimMessage message)?
bottomRowBuilder;
final Widget Function(BuildContext context, V2TimMessage message)? bottomRowBuilder;
// open MessageReaction
final bool? isUseMessageReaction;
@ -284,9 +278,7 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
const TIMUIKitHistoryMessageListItem(
{Key? key,
required this.message,
@Deprecated(
"Nickname will not show in one-to-one chat, if you tend to control it in group chat, please use `isShowSelfNameInGroup` and `isShowOthersNameInGroup` from `config: TIMUIKitChatConfig` instead")
this.showNickName = false,
@Deprecated("Nickname will not show in one-to-one chat, if you tend to control it in group chat, please use `isShowSelfNameInGroup` and `isShowOthersNameInGroup` from `config: TIMUIKitChatConfig` instead") this.showNickName = false,
this.onScrollToIndex,
this.onScrollToIndexBegin,
this.onTapForOthersPortrait,
@ -322,9 +314,7 @@ class TipsActionItem extends TIMUIKitStatelessWidget {
final String icon;
final String? package;
TipsActionItem(
{Key? key, required this.label, required this.icon, this.package})
: super(key: key);
TipsActionItem({Key? key, required this.label, required this.icon, this.package}) : super(key: key);
@override
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
@ -352,16 +342,13 @@ class TipsActionItem extends TIMUIKitStatelessWidget {
}
}
class _TIMUIKItHistoryMessageListItemState
extends TIMUIKitState<TIMUIKitHistoryMessageListItem>
with SingleTickerProviderStateMixin {
class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistoryMessageListItem> with SingleTickerProviderStateMixin {
SuperTooltip? tooltip;
late AnimationController _animationController;
// ignore: unused_field
final MessageService _messageService = serviceLocator<MessageService>();
final TUISelfInfoViewModel selfInfoModel =
serviceLocator<TUISelfInfoViewModel>();
final TUISelfInfoViewModel selfInfoModel = serviceLocator<TUISelfInfoViewModel>();
final TUIThemeViewModel themeModel = serviceLocator<TUIThemeViewModel>();
// bool isChecked = false;
@ -372,9 +359,7 @@ class _TIMUIKItHistoryMessageListItemState
@override
void initState() {
super.initState();
_animationController =
AnimationController(duration: const Duration(seconds: 1), vsync: this)
..repeat();
_animationController = AnimationController(duration: const Duration(seconds: 1), vsync: this)..repeat();
}
closeTooltip() {
@ -382,15 +367,10 @@ class _TIMUIKItHistoryMessageListItemState
}
bool isReplyMessage(V2TimMessage message) {
final hasCustomData =
message.cloudCustomData != null && message.cloudCustomData != "";
final hasCustomData = message.cloudCustomData != null && message.cloudCustomData != "";
if (hasCustomData) {
try {
final CloudCustomData messageCloudCustomData = CloudCustomData.fromJson(
json.decode(
TencentUtils.checkString(message.cloudCustomData) != null
? message.cloudCustomData!
: "{}"));
final CloudCustomData messageCloudCustomData = CloudCustomData.fromJson(json.decode(TencentUtils.checkString(message.cloudCustomData) != null ? message.cloudCustomData! : "{}"));
if (messageCloudCustomData.messageReply != null) {
MessageRepliedData.fromJson(messageCloudCustomData.messageReply!);
return true;
@ -403,8 +383,7 @@ class _TIMUIKItHistoryMessageListItemState
return false;
}
(bool isRevoke, bool isRevokeByAdmin) isRevokeMessage(
V2TimMessage message, TUIChatSeparateViewModel model) {
(bool isRevoke, bool isRevokeByAdmin) isRevokeMessage(V2TimMessage message, TUIChatSeparateViewModel model) {
if (message.status == 6) {
return (true, false);
} else if (model.chatConfig.isGroupAdminRecallEnabled) {
@ -420,11 +399,9 @@ class _TIMUIKItHistoryMessageListItemState
return (false, false);
}
Widget _messageItemBuilder(
V2TimMessage messageItem, TUIChatSeparateViewModel model) {
Widget _messageItemBuilder(V2TimMessage messageItem, TUIChatSeparateViewModel model) {
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 isFromSelf = messageItem.isSelf ?? true;
void clearJump() {
@ -435,8 +412,7 @@ class _TIMUIKItHistoryMessageListItemState
switch (msgType) {
case MessageElemType.V2TIM_ELEM_TYPE_CUSTOM:
final customWidget =
messageItemBuilder?.customMessageItemBuilder != null
final customWidget = messageItemBuilder?.customMessageItemBuilder != null
? messageItemBuilder!.customMessageItemBuilder!(
messageItem,
isShowJump,
@ -480,8 +456,7 @@ class _TIMUIKItHistoryMessageListItemState
);
case MessageElemType.V2TIM_ELEM_TYPE_TEXT:
if (isReplyMessage(messageItem)) {
final customWidget =
messageItemBuilder?.textReplyMessageItemBuilder != null
final customWidget = messageItemBuilder?.textReplyMessageItemBuilder != null
? messageItemBuilder!.textReplyMessageItemBuilder!(
messageItem,
isShowJump,
@ -561,8 +536,7 @@ class _TIMUIKItHistoryMessageListItemState
isShowMessageReaction: widget.isUseMessageReaction,
);
case MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS:
final customWidget =
messageItemBuilder?.groupTipsMessageItemBuilder != null
final customWidget = messageItemBuilder?.groupTipsMessageItemBuilder != null
? messageItemBuilder!.groupTipsMessageItemBuilder!(
messageItem,
isShowJump,
@ -604,8 +578,7 @@ class _TIMUIKItHistoryMessageListItemState
isShowMessageReaction: widget.isUseMessageReaction,
);
case MessageElemType.V2TIM_ELEM_TYPE_LOCATION:
final customWidget =
messageItemBuilder?.locationMessageItemBuilder != null
final customWidget = messageItemBuilder?.locationMessageItemBuilder != null
? messageItemBuilder!.locationMessageItemBuilder!(
messageItem,
isShowJump,
@ -614,8 +587,7 @@ class _TIMUIKItHistoryMessageListItemState
: null;
return customWidget ?? Text(TIM_t("[位置]"));
case MessageElemType.V2TIM_ELEM_TYPE_MERGER:
final customWidget =
messageItemBuilder?.mergerMessageItemBuilder != null
final customWidget = messageItemBuilder?.mergerMessageItemBuilder != null
? messageItemBuilder!.mergerMessageItemBuilder!(
messageItem,
isShowJump,
@ -640,11 +612,7 @@ class _TIMUIKItHistoryMessageListItemState
Widget _groupTipsMessageBuilder(TUIChatSeparateViewModel model) {
final messageItem = widget.message;
return Container(
padding: const EdgeInsets.only(bottom: 20),
child: TIMUIKitGroupTipsElem(
groupTipsElem: messageItem.groupTipsElem!,
groupMemberList: model.groupMemberList ?? []));
return Container(padding: const EdgeInsets.only(bottom: 20), child: TIMUIKitGroupTipsElem(groupTipsElem: messageItem.groupTipsElem!, groupMemberList: model.groupMemberList ?? []));
}
Widget _selfRevokeEditMessageBuilder(theme, TUIChatSeparateViewModel model) {
@ -660,8 +628,7 @@ class _TIMUIKItHistoryMessageListItemState
text: TIM_t("重新编辑"),
recognizer: TapGestureRecognizer()
..onTap = () {
widget.textFieldController
?.setTextField(widget.message.textElem?.text ?? "");
widget.textFieldController?.setTextField(widget.message.textElem?.text ?? "");
},
style: TextStyle(color: theme.primaryColor),
)
@ -678,15 +645,12 @@ class _TIMUIKItHistoryMessageListItemState
));
}
Widget _timeDividerBuilder(
theme, int timeStamp, TUIChatSeparateViewModel model) {
Widget _timeDividerBuilder(theme, int timeStamp, TUIChatSeparateViewModel model) {
return Container(
alignment: Alignment.center,
margin: const EdgeInsets.symmetric(vertical: 20),
child: Text(
model.chatConfig.timeDividerConfig?.timestampParser != null
? (model.chatConfig.timeDividerConfig?.timestampParser!(timeStamp))!
: TimeAgo().getTimeForMessage(timeStamp),
model.chatConfig.timeDividerConfig?.timestampParser != null ? (model.chatConfig.timeDividerConfig?.timestampParser!(timeStamp))! : TimeAgo().getTimeForMessage(timeStamp),
style: widget.themeData?.timelineTextStyle ??
TextStyle(
fontSize: 12,
@ -710,10 +674,7 @@ class _TIMUIKItHistoryMessageListItemState
width: 100,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
const Color(0x00C0E1FF),
theme.primaryColor ?? CommonColor.lightPrimaryColor
]),
gradient: LinearGradient(colors: [const Color(0x00C0E1FF), theme.primaryColor ?? CommonColor.lightPrimaryColor]),
)),
),
),
@ -745,8 +706,7 @@ class _TIMUIKItHistoryMessageListItemState
);
}
bool isRevocable(int timestamp) =>
(DateTime.now().millisecondsSinceEpoch / 1000).ceil() - timestamp < 120;
bool isRevocable(int timestamp) => (DateTime.now().millisecondsSinceEpoch / 1000).ceil() - timestamp < 120;
// TODO :
@ -767,38 +727,21 @@ class _TIMUIKItHistoryMessageListItemState
final screenHeight = MediaQuery.of(context).size.height;
final screenWidth = MediaQuery.of(context).size.width;
final isDesktopScreen =
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
final isLongMessage =
context.size!.height + 350 > screenHeight && !(isDesktopScreen);
final tapDetails =
(isDesktopScreen || isLongMessage) ? (details ?? _tapDetails) : details;
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
final isLongMessage = context.size!.height + 350 > screenHeight && !(isDesktopScreen);
final tapDetails = (isDesktopScreen || isLongMessage) ? (details ?? _tapDetails) : details;
final isSelf = message.isSelf ?? true;
final targetWidth =
min(MediaQuery.of(context).size.width * 0.84, 350).toDouble();
final double dx = !isSelf
? min(tapDetails?.globalPosition.dx ?? targetWidth,
screenWidth - targetWidth)
: max(tapDetails?.globalPosition.dx ?? targetWidth, targetWidth)
.toDouble();
final double dy = min(
tapDetails?.globalPosition.dy ?? MediaQuery.of(context).size.height,
MediaQuery.of(context).size.height - 320)
.toDouble();
final targetWidth = min(MediaQuery.of(context).size.width * 0.84, 350).toDouble();
final double dx = !isSelf ? min(tapDetails?.globalPosition.dx ?? targetWidth, screenWidth - targetWidth) : max(tapDetails?.globalPosition.dx ?? targetWidth, targetWidth).toDouble();
final double dy = min(tapDetails?.globalPosition.dy ?? MediaQuery.of(context).size.height, MediaQuery.of(context).size.height - 320).toDouble();
final finalTapDetail = tapDetails != null
? TapDownDetails(
globalPosition: Offset(dx, dy),
)
: null;
initTools(
context: c,
model: model,
isShowMoreSticker: isShowMoreSticker,
details: finalTapDetail,
theme: theme,
isFromWideToolTip: isFromWideTooltip);
initTools(context: c, model: model, isShowMoreSticker: isShowMoreSticker, details: finalTapDetail, theme: theme, isFromWideToolTip: isFromWideTooltip);
tooltip!.show(c, targetCenter: finalTapDetail?.globalPosition);
}
@ -811,26 +754,15 @@ class _TIMUIKItHistoryMessageListItemState
}
}
Future<V2TimValueCallback<V2TimMessageChangeInfo>> _modifySticker(
int sticker) async {
Future<V2TimValueCallback<V2TimMessageChangeInfo>> _modifySticker(int sticker) async {
return await Future.delayed(const Duration(milliseconds: 50), () async {
return await MessageReactionUtils.clickOnSticker(widget.message, sticker);
});
}
initTools(
{BuildContext? context,
bool isLongMessage = false,
required TUIChatSeparateViewModel model,
TUITheme? theme,
bool? isShowMoreSticker,
TapDownDetails? details,
bool? isFromWideToolTip}) {
final isUseMessageReaction = widget.message.elemType == 2
? false
: model.chatConfig.isUseMessageReaction;
final isDesktopScreen =
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
initTools({BuildContext? context, bool isLongMessage = false, required TUIChatSeparateViewModel model, TUITheme? theme, bool? isShowMoreSticker, TapDownDetails? details, bool? isFromWideToolTip}) {
final isUseMessageReaction = widget.message.elemType == 2 ? false : model.chatConfig.isUseMessageReaction;
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
final isSelf = widget.message.isSelf ?? true;
double arrowTipDistance = 30;
double arrowBaseWidth = 10;
@ -839,8 +771,7 @@ class _TIMUIKItHistoryMessageListItemState
TooltipDirection popupDirection = TooltipDirection.up;
double? left;
double? right;
SelectEmojiPanelPosition selectEmojiPanelPosition =
SelectEmojiPanelPosition.down;
SelectEmojiPanelPosition selectEmojiPanelPosition = SelectEmojiPanelPosition.down;
if (context != null) {
RenderBox? box = _key.currentContext?.findRenderObject() as RenderBox?;
if (details != null && box != null) {
@ -863,9 +794,7 @@ class _TIMUIKItHistoryMessageListItemState
Offset offset = box.localToGlobal(Offset.zero);
double boxWidth = box.size.width;
if (isSelf) {
right = screenWidth -
offset.dx -
((isUseMessageReaction) ? boxWidth : (boxWidth / 1.3));
right = screenWidth - offset.dx - ((isUseMessageReaction) ? boxWidth : (boxWidth / 1.3));
} else {
left = offset.dx;
}
@ -877,8 +806,7 @@ class _TIMUIKItHistoryMessageListItemState
popupDirection = TooltipDirection.down;
}
}
arrowTipDistance = (context.size!.height / 2).roundToDouble() +
(isLongMessage ? -120 : 10);
arrowTipDistance = (context.size!.height / 2).roundToDouble() + (isLongMessage ? -120 : 10);
}
}
@ -918,8 +846,7 @@ class _TIMUIKItHistoryMessageListItemState
showCloseButton: ShowCloseButton.none,
touchThroughAreaShape: ClipAreaShape.rectangle,
content: TIMUIKitMessageTooltip(
iSUseDefaultHoverBar: model.chatConfig.isUseMessageHoverBarOnDesktop &&
widget.customMessageHoverBarOnDesktop == null,
iSUseDefaultHoverBar: model.chatConfig.isUseMessageHoverBarOnDesktop && widget.customMessageHoverBarOnDesktop == null,
model: model,
groupMemberInfo: widget.groupMemberInfo,
isShowMoreSticker: isShowMoreSticker ?? false,
@ -927,8 +854,7 @@ class _TIMUIKItHistoryMessageListItemState
isUseMessageReaction: isUseMessageReaction,
message: widget.message,
allowAtUserWhenReply: widget.allowAtUserWhenReply,
onLongPressForOthersHeadPortrait:
widget.onLongPressForOthersHeadPortrait,
onLongPressForOthersHeadPortrait: widget.onLongPressForOthersHeadPortrait,
selectEmojiPanelPosition: selectEmojiPanelPosition,
onCloseTooltip: () => tooltip?.close(),
onSelectSticker: (int value) {
@ -939,8 +865,7 @@ class _TIMUIKItHistoryMessageListItemState
);
}
Widget _getMessageItemBuilder(V2TimMessage message, int? messageStatues,
TUIChatSeparateViewModel model) {
Widget _getMessageItemBuilder(V2TimMessage message, int? messageStatues, TUIChatSeparateViewModel model) {
final messageBuilder = _messageItemBuilder;
return messageBuilder(widget.message, model);
@ -982,8 +907,7 @@ class _TIMUIKItHistoryMessageListItemState
}
}
List<MessageHoverControlItem> getWideMessageHoverControlBar(
TUIChatSeparateViewModel model, TUITheme theme) {
List<MessageHoverControlItem> getWideMessageHoverControlBar(TUIChatSeparateViewModel model, TUITheme theme) {
return [
if (widget.isUseMessageReaction ?? false)
MessageHoverControlItem(
@ -994,8 +918,7 @@ class _TIMUIKItHistoryMessageListItemState
color: hexToColor("8f959e"),
),
onClick: (details) {
_onOpenToolTip(
context, widget.message, model, theme, details, true, true);
_onOpenToolTip(context, widget.message, model, theme, details, true, true);
},
),
if (widget.toolTipsConfig?.showReplyMessage ?? true)
@ -1009,21 +932,14 @@ class _TIMUIKItHistoryMessageListItemState
onClick: (_) {
model.repliedMessage = widget.message;
final isSelf = widget.message.isSelf ?? true;
final isGroup =
TencentUtils.checkString(widget.message.groupID) != null;
final isAtWhenReply = !isSelf &&
isGroup &&
widget.allowAtUserWhenReply &&
widget.onLongPressForOthersHeadPortrait != null;
final isGroup = TencentUtils.checkString(widget.message.groupID) != null;
final isAtWhenReply = !isSelf && isGroup && widget.allowAtUserWhenReply && widget.onLongPressForOthersHeadPortrait != null;
/// If replying to a self message, do not add a at tag, only requestFocus.
widget.onLongPressForOthersHeadPortrait!(
!isAtWhenReply ? null : widget.message.sender,
!isAtWhenReply ? null : widget.message.nickName);
widget.onLongPressForOthersHeadPortrait!(!isAtWhenReply ? null : widget.message.sender, !isAtWhenReply ? null : widget.message.nickName);
},
),
if ((widget.toolTipsConfig?.showForwardMessage ?? true) &&
!model.isVoteMessage(widget.message))
if ((widget.toolTipsConfig?.showForwardMessage ?? true) && !model.isVoteMessage(widget.message))
MessageHoverControlItem(
name: TIM_t("转发"),
icon: Icon(
@ -1063,8 +979,7 @@ class _TIMUIKItHistoryMessageListItemState
color: hexToColor("8f959e"),
),
onClick: (details) {
_onOpenToolTip(
context, widget.message, model, theme, details, true, false);
_onOpenToolTip(context, widget.message, model, theme, details, true, false);
},
),
...?model.chatConfig.additionalDesktopMessageHoverBarItem
@ -1074,37 +989,18 @@ class _TIMUIKItHistoryMessageListItemState
_onMsgSendFailIconTap(V2TimMessage message, TUIChatSeparateViewModel model) {
final convID = model.conversationID;
final convType = model.conversationType;
MessageUtils.handleMessageError(
model.reSendFailMessage(
message: message,
convType: convType ?? ConvType.c2c,
convID: convID),
context);
MessageUtils.handleMessageError(model.reSendFailMessage(message: message, convType: convType ?? ConvType.c2c, convID: convID), context);
}
Widget renderHoverTipAndReadStatus(
TUIChatSeparateViewModel model,
bool isSelf,
V2TimMessage message,
bool isPeerRead,
TUITheme theme,
bool isDownloadWaiting) {
final isDesktopScreen =
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
final customHoverBar = widget.customMessageHoverBarOnDesktop != null
? widget.customMessageHoverBarOnDesktop!(message)
: null;
final wideHoverTipList = (model.chatConfig.isUseMessageHoverBarOnDesktop &&
customHoverBar == null)
? getWideMessageHoverControlBar(model, theme)
: [];
final lastItemName =
wideHoverTipList.isNotEmpty ? wideHoverTipList.last.name : "";
Widget renderHoverTipAndReadStatus(TUIChatSeparateViewModel model, bool isSelf, V2TimMessage message, bool isPeerRead, TUITheme theme, bool isDownloadWaiting) {
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
final customHoverBar = widget.customMessageHoverBarOnDesktop != null ? widget.customMessageHoverBarOnDesktop!(message) : null;
final wideHoverTipList = (model.chatConfig.isUseMessageHoverBarOnDesktop && customHoverBar == null) ? getWideMessageHoverControlBar(model, theme) : [];
final lastItemName = wideHoverTipList.isNotEmpty ? wideHoverTipList.last.name : "";
// 1
Future<void> _conditionalDelay() async {
if (!(model.hasDelayedRenderSendingStatus(message.id ?? message.msgID!) ??
true)) {
if (!(model.hasDelayedRenderSendingStatus(message.id ?? message.msgID!) ?? true)) {
model.setDelayedRenderSendingStatus(message.id ?? message.msgID!);
await Future.delayed(const Duration(seconds: 1));
}
@ -1115,14 +1011,9 @@ class _TIMUIKItHistoryMessageListItemState
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
if (isDesktopScreen &&
isShowWideToolTip &&
customHoverBar == null &&
!((widget.message.elemType == 6 && isDownloadWaiting)))
if (isDesktopScreen && isShowWideToolTip && customHoverBar == null && !((widget.message.elemType == 6 && isDownloadWaiting)))
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
border: Border.all(color: hexToColor("d9dde0"), width: 1)),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(4), border: Border.all(color: hexToColor("d9dde0"), width: 1)),
margin: const EdgeInsets.symmetric(horizontal: 4),
child: Row(
children: wideHoverTipList
@ -1154,17 +1045,12 @@ class _TIMUIKItHistoryMessageListItemState
.toList(),
),
),
if (isDesktopScreen && isShowWideToolTip && customHoverBar != null)
customHoverBar,
if (!isDesktopScreen ||
(model.chatConfig.isUseMessageHoverBarOnDesktop &&
customHoverBar == null &&
!isShowWideToolTip))
if (isDesktopScreen && isShowWideToolTip && customHoverBar != null) customHoverBar,
if (!isDesktopScreen || (model.chatConfig.isUseMessageHoverBarOnDesktop && customHoverBar == null && !isShowWideToolTip))
const SizedBox(
height: 20,
),
if (isSelf &&
message.status == MessageStatus.V2TIM_MSG_STATUS_SEND_FAIL)
if (isSelf && message.status == MessageStatus.V2TIM_MSG_STATUS_SEND_FAIL)
Container(
padding: const EdgeInsets.only(bottom: 3),
margin: const EdgeInsets.only(right: 6),
@ -1195,8 +1081,7 @@ class _TIMUIKItHistoryMessageListItemState
},
),
if (model.chatConfig.isShowReadingStatus &&
isSelf &&
message.status == MessageStatus.V2TIM_MSG_STATUS_SEND_SUCC &&
isSelf && message.status == MessageStatus.V2TIM_MSG_STATUS_SEND_SUCC &&
(message.needReadReceipt ?? false) &&
!model.isVoteMessage(widget.message))
TIMUIKitMessageReadReceipt(
@ -1209,16 +1094,13 @@ class _TIMUIKItHistoryMessageListItemState
@override
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
final TUIChatSeparateViewModel model =
Provider.of<TUIChatSeparateViewModel>(context);
final isDownloadWaiting = context.select<TUIChatGlobalModel, bool>(
(value) => value.isWaiting(widget.message.msgID ?? ""));
final TUIChatSeparateViewModel model = Provider.of<TUIChatSeparateViewModel>(context);
final isDownloadWaiting = context.select<TUIChatGlobalModel, bool>((value) => value.isWaiting(widget.message.msgID ?? ""));
final TUITheme theme = value.theme;
final message = widget.message;
final msgType = message.elemType;
final 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 isRevokedMsg = revokeStatus.$1;
@ -1228,14 +1110,10 @@ class _TIMUIKItHistoryMessageListItemState
final isLatestDivider = msgType == 101;
final isPeerRead = message.isPeerRead ?? false;
final isGroupMessage = model.conversationType == ConvType.group;
final bool isRevokeEditable =
widget.message.elemType == MessageElemType.V2TIM_ELEM_TYPE_TEXT;
final isShowNickNameForSelf =
isGroupMessage && model.chatConfig.isShowSelfNameInGroup;
final isShowNickNameForOthers =
isGroupMessage && model.chatConfig.isShowOthersNameInGroup;
final isDesktopScreen =
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
final bool isRevokeEditable = widget.message.elemType == MessageElemType.V2TIM_ELEM_TYPE_TEXT;
final isShowNickNameForSelf = isGroupMessage && model.chatConfig.isShowSelfNameInGroup;
final isShowNickNameForOthers = isGroupMessage && model.chatConfig.isShowOthersNameInGroup;
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
if (isTimeDivider) {
return _timeDividerBuilder(theme, message.timestamp ?? 0, model);
}
@ -1250,8 +1128,7 @@ class _TIMUIKItHistoryMessageListItemState
if (isGroupTipsMsg) {
if (widget.messageItemBuilder?.groupTipsMessageItemBuilder != null) {
final groupTipsMessage =
widget.messageItemBuilder!.groupTipsMessageItemBuilder!(
final groupTipsMessage = widget.messageItemBuilder!.groupTipsMessageItemBuilder!(
message,
(model.jumpMsgID == message.msgID),
clearJump,
@ -1262,16 +1139,8 @@ class _TIMUIKItHistoryMessageListItemState
}
if (isRevokedMsg) {
final displayName = isAdminRevoke
? TIM_t("管理员")
: (isSelf
? TIM_t("")
: TencentUtils.checkString(message.nickName) ??
TencentUtils.checkString(message.sender) ??
message.userID);
return isSelf && isRevokeEditable && isRevocable(message.timestamp!)
? _selfRevokeEditMessageBuilder(theme, model)
: _revokedMessageBuilder(theme, displayName ?? "");
final displayName = isAdminRevoke ? TIM_t("管理员") : (isSelf ? TIM_t("") : TencentUtils.checkString(message.nickName) ?? TencentUtils.checkString(message.sender) ?? message.userID);
return isSelf && isRevokeEditable && isRevocable(message.timestamp!) ? _selfRevokeEditMessageBuilder(theme, model) : _revokedMessageBuilder(theme, displayName ?? "");
}
// 使
@ -1300,8 +1169,7 @@ class _TIMUIKItHistoryMessageListItemState
},
child: LayoutBuilder(
builder: (context, constraints) => Container(
padding:
EdgeInsets.only(left: isSelf ? 0 : 16, right: isSelf ? 16 : 0),
padding: EdgeInsets.only(left: isSelf ? 0 : 16, right: isSelf ? 16 : 0),
margin: widget.padding ?? const EdgeInsets.only(bottom: 20),
child: Row(
key: _key,
@ -1310,8 +1178,7 @@ class _TIMUIKItHistoryMessageListItemState
children: [
if (model.isMultiSelect)
Container(
margin: EdgeInsets.only(
right: 12, top: 10, left: isSelf ? 16 : 0),
margin: EdgeInsets.only(right: 12, top: 10, left: isSelf ? 16 : 0),
child: CheckBoxButton(
isChecked: model.getSelectedMessageList().contains(message),
onChanged: (value) {
@ -1322,16 +1189,14 @@ class _TIMUIKItHistoryMessageListItemState
Expanded(
child: MouseRegion(
onEnter: (_) {
if (isDesktopScreen &&
model.chatConfig.isUseMessageHoverBarOnDesktop) {
if (isDesktopScreen && model.chatConfig.isUseMessageHoverBarOnDesktop) {
setState(() {
isShowWideToolTip = true;
});
}
},
onExit: (_) {
if (isDesktopScreen &&
model.chatConfig.isUseMessageHoverBarOnDesktop) {
if (isDesktopScreen && model.chatConfig.isUseMessageHoverBarOnDesktop) {
Tooltip.dismissAllToolTips();
Future.delayed(const Duration(milliseconds: 100), () {
setState(() {
@ -1341,13 +1206,10 @@ class _TIMUIKItHistoryMessageListItemState
}
},
child: GestureDetector(
behavior: model.isMultiSelect
? HitTestBehavior.translucent
: null,
behavior: model.isMultiSelect ? HitTestBehavior.translucent : null,
onTap: () {
if (model.isMultiSelect) {
final checked =
model.getSelectedMessageList().contains(message);
final checked = model.getSelectedMessageList().contains(message);
model.setMessageItemChecked(message, !checked);
} else {
return;
@ -1355,81 +1217,59 @@ class _TIMUIKItHistoryMessageListItemState
},
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: isSelf
? MainAxisAlignment.end
: MainAxisAlignment.start,
mainAxisAlignment: isSelf ? MainAxisAlignment.end : MainAxisAlignment.start,
children: [
if (!isSelf && widget.showAvatar)
GestureDetector(
onLongPress: () {
if (widget.onLongPressForOthersHeadPortrait !=
null) {}
if (widget.onLongPressForOthersHeadPortrait != null) {}
if (model.chatConfig.isAllowLongPressAvatarToAt) {
widget.onLongPressForOthersHeadPortrait!(
message.sender, message.nickName);
widget.onLongPressForOthersHeadPortrait!(message.sender, message.nickName);
}
},
onTapDown: isDesktopScreen
? (details) {
if (widget.onTapForOthersPortrait != null &&
widget.allowAvatarTap) {
widget.onTapForOthersPortrait!(
message.sender ?? "", details);
if (widget.onTapForOthersPortrait != null && widget.allowAvatarTap) {
widget.onTapForOthersPortrait!(message.sender ?? "", details);
}
}
: null,
onTap: isDesktopScreen
? null
: () {
if (widget.onTapForOthersPortrait != null &&
widget.allowAvatarTap) {
widget.onTapForOthersPortrait!(
message.sender ?? "",
TapDownDetails());
if (widget.onTapForOthersPortrait != null && widget.allowAvatarTap) {
widget.onTapForOthersPortrait!(message.sender ?? "", TapDownDetails());
}
},
onSecondaryTap: isDesktopScreen
? null
: () {
if (widget.onSecondaryTapForOthersPortrait !=
null &&
widget.allowAvatarTap) {
widget.onSecondaryTapForOthersPortrait!(
message.sender ?? "",
TapDownDetails());
if (widget.onSecondaryTapForOthersPortrait != null && widget.allowAvatarTap) {
widget.onSecondaryTapForOthersPortrait!(message.sender ?? "", TapDownDetails());
}
},
onSecondaryTapDown: isDesktopScreen
? (details) {
if (widget.onSecondaryTapForOthersPortrait !=
null &&
widget.allowAvatarTap) {
widget.onSecondaryTapForOthersPortrait!(
message.sender ?? "", details);
if (widget.onSecondaryTapForOthersPortrait != null && widget.allowAvatarTap) {
widget.onSecondaryTapForOthersPortrait!(message.sender ?? "", details);
}
}
: null,
child: widget.userAvatarBuilder != null
? widget.userAvatarBuilder!(context, message)
: Container(
margin: (isSelf && isShowNickNameForSelf) ||
(!isSelf && isShowNickNameForOthers)
? const EdgeInsets.only(top: 2)
: null,
margin: (isSelf && isShowNickNameForSelf) || (!isSelf && isShowNickNameForOthers) ? const EdgeInsets.only(top: 2) : null,
child: SizedBox(
width: 40,
height: 40,
child: Avatar(
faceUrl: message.faceUrl ?? "",
showName: MessageUtils.getDisplayName(
message),
showName: MessageUtils.getDisplayName(message),
),
),
),
),
if (isSelf &&
widget.message.elemType == 6 &&
isDownloadWaiting)
if (isSelf && widget.message.elemType == 6 && isDownloadWaiting)
Container(
margin: const EdgeInsets.only(top: 46, right: 10),
child: LoadingAnimationWidget.threeArchedCircle(
@ -1438,96 +1278,52 @@ class _TIMUIKItHistoryMessageListItemState
),
),
Container(
margin: widget.showAvatar
? (isSelf
? const EdgeInsets.only(right: 13)
: const EdgeInsets.only(left: 13))
: null,
margin: widget.showAvatar ? (isSelf ? const EdgeInsets.only(right: 13) : const EdgeInsets.only(left: 13)) : null,
child: Column(
crossAxisAlignment: isSelf
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
crossAxisAlignment: isSelf ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: [
if ((isSelf && isShowNickNameForSelf) ||
(!isSelf && isShowNickNameForOthers))
if ((isSelf && isShowNickNameForSelf) || (!isSelf && isShowNickNameForOthers))
widget.topRowBuilder != null
? widget.topRowBuilder!(context, message)
: Container(
// margin: const EdgeInsets.only(bottom: 4),
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context)
.size
.width /
1.7),
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width / 1.7),
child: Text(
MessageUtils.getDisplayName(message),
overflow: TextOverflow.ellipsis,
style: widget.themeData
?.nickNameTextStyle ??
TextStyle(
fontSize: 12,
color: theme.weakTextColor),
style: widget.themeData?.nickNameTextStyle ?? TextStyle(fontSize: 12, color: theme.weakTextColor),
),
)),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
if (isSelf)
renderHoverTipAndReadStatus(
model,
isSelf,
message,
isPeerRead,
theme,
isDownloadWaiting),
if (isSelf) renderHoverTipAndReadStatus(model, isSelf, message, isPeerRead, theme, isDownloadWaiting),
Container(
constraints: BoxConstraints(
maxWidth: constraints.maxWidth * 0.77,
),
child: Builder(builder: (context) {
return GestureDetector(
child: IgnorePointer(
ignoring: model.isMultiSelect,
child: _getMessageItemBuilder(
message,
message.status,
model)),
child: IgnorePointer(ignoring: model.isMultiSelect, child: _getMessageItemBuilder(message, message.status, model)),
onSecondaryTapDown: (details) {
if (widget.onLongPress != null) {
widget.onLongPress!(
context, message);
widget.onLongPress!(context, message);
return;
}
if (!PlatformUtils().isMobile) {
if (widget.allowLongPress) {
_onOpenToolTip(
context,
message,
model,
theme,
details,
false,
false);
_onOpenToolTip(context, message, model, theme, details, false, false);
}
}
},
onLongPress: () {
if (widget.onLongPress != null) {
widget.onLongPress!(
context, message);
widget.onLongPress!(context, message);
return;
}
if (widget.allowLongPress &&
!isDesktopScreen) {
_onOpenToolTip(
context,
message,
model,
theme,
null,
false,
false);
if (widget.allowLongPress && !isDesktopScreen) {
_onOpenToolTip(context, message, model, theme, null, false, false);
}
},
onTapDown: (details) {
@ -1536,45 +1332,23 @@ class _TIMUIKItHistoryMessageListItemState
);
}),
),
if (!isSelf &&
message.elemType ==
MessageElemType
.V2TIM_ELEM_TYPE_SOUND &&
message.localCustomInt != null &&
message.localCustomInt !=
HistoryMessageDartConstant.read)
Padding(
padding: const EdgeInsets.only(
left: 5, bottom: 12),
child: Icon(Icons.circle,
color: theme.cautionColor,
size: 10)),
if (!isSelf)
renderHoverTipAndReadStatus(
model,
isSelf,
message,
isPeerRead,
theme,
isDownloadWaiting),
if (!isSelf && message.elemType == MessageElemType.V2TIM_ELEM_TYPE_SOUND && message.localCustomInt != null && message.localCustomInt != HistoryMessageDartConstant.read)
Padding(padding: const EdgeInsets.only(left: 5, bottom: 12), child: Icon(Icons.circle, color: theme.cautionColor, size: 10)),
if (!isSelf) renderHoverTipAndReadStatus(model, isSelf, message, isPeerRead, theme, isDownloadWaiting),
],
),
TIMUIKitTextTranslationElem(
message: message,
customEmojiStickerList:
widget.customEmojiStickerList,
customEmojiStickerList: widget.customEmojiStickerList,
isFromSelf: message.isSelf ?? true,
isShowJump: false,
clearJump: () {},
chatModel: model),
if (widget.bottomRowBuilder != null)
widget.bottomRowBuilder!(context, message)
if (widget.bottomRowBuilder != null) widget.bottomRowBuilder!(context, message)
],
),
),
if (!isSelf &&
widget.message.elemType == 6 &&
isDownloadWaiting)
if (!isSelf && widget.message.elemType == 6 && isDownloadWaiting)
Container(
margin: const EdgeInsets.only(top: 46, left: 10),
child: LoadingAnimationWidget.threeArchedCircle(
@ -1590,17 +1364,11 @@ class _TIMUIKItHistoryMessageListItemState
height: 40,
child: InkWell(
onTapDown: (details) {
if (widget.onTapForOthersPortrait !=
null &&
widget.allowAvatarTap) {
widget.onTapForOthersPortrait!(
message.sender ?? "", details);
if (widget.onTapForOthersPortrait != null && widget.allowAvatarTap) {
widget.onTapForOthersPortrait!(message.sender ?? "", details);
}
},
child: Avatar(
faceUrl: message.faceUrl ?? "",
showName: MessageUtils.getDisplayName(
message)),
child: Avatar(faceUrl: message.faceUrl ?? "", showName: MessageUtils.getDisplayName(message)),
),
),
],

View File

@ -7,13 +7,18 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:open_file/open_file.dart';
import 'package:provider/provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_role.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_elem_type.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_status.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/common_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/message.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_select_emoji.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart';
@ -25,6 +30,10 @@ import 'package:tencent_cloud_chat_uikit/ui/widgets/forward_message_screen.dart'
import 'package:url_launcher/url_launcher.dart';
import 'package:path/path.dart' as path;
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class TIMUIKitMessageTooltip extends StatefulWidget {
/// tool tips panel configuration, long press message will show tool tips panel
final ToolTipsConfig? toolTipsConfig;
@ -195,15 +204,13 @@ class TIMUIKitMessageTooltipState
bool showTranslation = true;
if (widget.message.localCustomData != null) {
final LocalCustomDataModel localCustomData = LocalCustomDataModel.fromMap(
json.decode(
TencentUtils.checkString(widget.message.localCustomData) ??
"{}"));
if (localCustomData.translatedText != null &&
localCustomData.translatedText != "") {
json.decode(TencentUtils.checkString(widget.message.localCustomData) ?? "{}"));
if (localCustomData.translatedText != null && localCustomData.translatedText != "") {
showTranslation = false;
}
}
final dynamicQuote =
model.chatConfig.isAtWhenReplyDynamic?.call(widget.message);

View File

@ -4,8 +4,11 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_at_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_text_field_controller.dart';
import 'package:tencent_im_base/tencent_im_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';
@ -130,8 +133,7 @@ class _TIMUIKitHistoryMessageListContainerState
direction: direction,
count: count ?? (kIsWeb ? 15 : HistoryMessageDartConstant.getCount),
lastMsgID: lastMsgID,
lastMsgSeq: lastSeq ?? -1,
);
lastMsgSeq: lastSeq ?? -1,);
} else {
return false;
}
@ -202,8 +204,7 @@ class _TIMUIKitHistoryMessageListContainerState
tongueItemBuilder: widget.tongueItemBuilder,
initFindingMsg: widget.initFindingMsg,
messageList: messageList,
onLoadMore: (String? a, LoadDirection direction,
[int? b, int? lastSeq]) async {
onLoadMore: (String? a, LoadDirection direction, [int? b, int? lastSeq]) async {
return await requestForData(a, direction, model, b, lastSeq);
},
);

View File

@ -1,13 +1,16 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_receipt.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/tim_uikit_wide_modal_operation_key.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/message_read_receipt.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/wide_popup.dart';
class TIMUIKitMessageReadReceipt extends TIMUIKitStatelessWidget {

View File

@ -1,4 +1,4 @@
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
class TIMUIKitChatUtils {
static String? getMessageIDWithinIndex(

View File

@ -2,17 +2,22 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimFriendshipListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimGroupListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_change_info_type.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/friendShip/friendship_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitAppBar/tim_uikit_appbar_title.dart';
import 'package:tuple/tuple.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class TIMUIKitAppBar extends StatefulWidget implements PreferredSizeWidget {
/// Appbar config

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
class TIMUIKitAppBarTitle extends StatelessWidget {
final Widget? title;

View File

@ -1,11 +1,12 @@
import 'package:flutter/material.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.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/view_models/tui_self_info_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/avatar.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class TIMUIKitMessageReactionDetail extends StatefulWidget {
/// the index of the current emoji sticker

View File

@ -1,13 +1,14 @@
import 'package:flutter/material.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/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/message_reaction_emoji.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_emoji_panel.dart'
as emoji;
import 'package:tencent_cloud_chat_uikit/ui/widgets/emoji.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/extended_wrap/extended_wrap.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
enum SelectEmojiPanelPosition { up, down }

View File

@ -3,6 +3,11 @@
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/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_value_callback.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.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';
@ -10,10 +15,10 @@ import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.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_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/extended_wrap/extended_wrap.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
class TIMUIKitMessageReactionShowItem extends TIMUIKitStatelessWidget {
/// the unicode of the emoji

View File

@ -1,5 +1,8 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.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';

View File

@ -1,5 +1,8 @@
import 'dart:convert';
import 'package:tencent_cloud_chat_sdk/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_value_callback.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart';

View File

@ -2,8 +2,8 @@ import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/common_utils.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart';

View File

@ -1,12 +1,12 @@
// ignore_for_file: unrelated_type_equality_checks
import 'package:flutter/material.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_custom_elem.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.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';
class TIMUIKitCustomElem extends TIMUIKitStatelessWidget {
final V2TimCustomElem? customElem;
final bool isFromSelf;

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart';

View File

@ -8,12 +8,21 @@ 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_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimAdvancedMsgListener.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_file_elem.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_download_progress.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_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_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:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.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';

View File

@ -1,8 +1,11 @@
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_tips_elem.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/message.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class TIMUIKitGroupTipsElem extends StatefulWidget {
final V2TimGroupTipsElem groupTipsElem;
@ -39,7 +42,8 @@ class _TIMUIKitGroupTipsElemState extends TIMUIKitState<TIMUIKitGroupTipsElem> {
return MessageUtils.wrapMessageTips(
Text(
groupTipsAbstractText,
softWrap: true,
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,

View File

@ -17,6 +17,10 @@ import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_image.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_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_state.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart';
@ -24,6 +28,7 @@ import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_glo
import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
import 'package:tencent_cloud_chat_uikit/ui/constants/history_message_constant.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/logger.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/message.dart';
@ -172,8 +177,7 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
if (model.getMessageProgress(widget.message.msgID) == 100) {
String savePath;
if (widget.message.imageElem!.path != null &&
widget.message.imageElem!.path != '' &&
File(widget.message.imageElem!.path!).existsSync()) {
widget.message.imageElem!.path != '' && File(widget.message.imageElem!.path!).existsSync()) {
savePath = widget.message.imageElem!.path!;
} else {
savePath = model.getFileMessageLocation(widget.message.msgID);
@ -594,6 +598,7 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
Widget? _renderImage(dynamic heroTag, TUITheme theme,
{V2TimImage? originalImg, V2TimImage? smallImg}) {
double positionRadio = 1.0;
if (smallImg?.width != null &&
smallImg?.height != null &&

View File

@ -3,18 +3,23 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_elem_type.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_status.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_model_tools.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/common_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/special_text/DefaultSpecialTextSpanBuilder.dart';
import 'package:extended_text/extended_text.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_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_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:tencent_cloud_chat_uikit/theme/tui_theme.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_show_panel.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitMessageItem/main.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitMessageItem/tim_uikit_chat_face_elem.dart';
@ -66,14 +71,10 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
MessageRepliedData? _getRepliedMessage() {
try {
final CloudCustomData messageCloudCustomData = CloudCustomData.fromJson(
json.decode(
TencentUtils.checkString(widget.message.cloudCustomData) != null
? widget.message.cloudCustomData!
: "{}"));
final CloudCustomData messageCloudCustomData = CloudCustomData.fromJson(json.decode(
TencentUtils.checkString(widget.message.cloudCustomData) != null ? widget.message.cloudCustomData! : "{}"));
if (messageCloudCustomData.messageReply != null) {
final MessageRepliedData repliedMessage =
MessageRepliedData.fromJson(messageCloudCustomData.messageReply!);
final MessageRepliedData repliedMessage = MessageRepliedData.fromJson(messageCloudCustomData.messageReply!);
return repliedMessage;
}
return null;
@ -99,8 +100,7 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
if (message == null) {
try {
final RepliedMessageAbstract repliedMessageAbstract =
RepliedMessageAbstract.fromJson(
jsonDecode(cloudCustomData.messageAbstract));
RepliedMessageAbstract.fromJson(jsonDecode(cloudCustomData.messageAbstract));
if (repliedMessageAbstract.isNotEmpty) {
message = V2TimMessage(
elemType: 0,
@ -127,25 +127,19 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
return Text(text,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12,
color: theme?.weakTextColor,
fontWeight: FontWeight.w400));
style: TextStyle(fontSize: 12, color: theme?.weakTextColor, fontWeight: FontWeight.w400));
}
_renderMessageSummary(TUITheme? theme) {
try {
final RepliedMessageAbstract repliedMessageAbstract =
RepliedMessageAbstract.fromJson(
jsonDecode(repliedMessage?.messageAbstract ?? ""));
RepliedMessageAbstract.fromJson(jsonDecode(repliedMessage?.messageAbstract ?? ""));
if (TencentUtils.checkString(repliedMessageAbstract.summary) != null) {
return _defaultRawMessageText(repliedMessageAbstract.summary!, theme);
}
return _defaultRawMessageText(
repliedMessage?.messageAbstract ?? TIM_t("[未知消息]"), theme);
return _defaultRawMessageText(repliedMessage?.messageAbstract ?? TIM_t("[未知消息]"), theme);
} catch (e) {
return _defaultRawMessageText(
repliedMessage?.messageAbstract ?? TIM_t("[未知消息]"), theme);
return _defaultRawMessageText(repliedMessage?.messageAbstract ?? TIM_t("[未知消息]"), theme);
}
}
@ -180,16 +174,13 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
final isAdminRevoke = revokeStatus.$2;
if (isRevokedMsg) {
return _defaultRawMessageText(
isAdminRevoke ? TIM_t("[消息被管理员撤回]") : TIM_t("[消息被撤回]"), theme);
return _defaultRawMessageText(isAdminRevoke ? TIM_t("[消息被管理员撤回]") : TIM_t("[消息被撤回]"), theme);
}
final messageType = message.elemType;
final isSelf = message.isSelf ?? true;
final customAbstractMessage =
widget.chatModel.abstractMessageBuilder != null
? widget.chatModel.abstractMessageBuilder!(message)
: null;
widget.chatModel.abstractMessageBuilder != null ? widget.chatModel.abstractMessageBuilder!(message) : null;
if (customAbstractMessage != null) {
return _defaultRawMessageText(
customAbstractMessage,
@ -222,15 +213,9 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
isShowJump: false);
case MessageElemType.V2TIM_ELEM_TYPE_IMAGE:
return TIMUIKitImageElem(
chatModel: widget.chatModel,
message: message,
isFrom: "reply",
isShowMessageReaction: false);
chatModel: widget.chatModel, message: message, isFrom: "reply", isShowMessageReaction: false);
case MessageElemType.V2TIM_ELEM_TYPE_VIDEO:
return TIMUIKitVideoElem(message,
chatModel: widget.chatModel,
isFrom: "reply",
isShowMessageReaction: false);
return TIMUIKitVideoElem(message, chatModel: widget.chatModel, isFrom: "reply", isShowMessageReaction: false);
case MessageElemType.V2TIM_ELEM_TYPE_LOCATION:
return _defaultRawMessageText(TIM_t("[位置]"), theme);
case MessageElemType.V2TIM_ELEM_TYPE_MERGER:
@ -262,8 +247,7 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
}
_showJumpColor() {
if ((widget.chatModel.jumpMsgID != widget.message.msgID) &&
(widget.message.msgID?.isNotEmpty ?? true)) {
if ((widget.chatModel.jumpMsgID != widget.message.msgID) && (widget.message.msgID?.isNotEmpty ?? true)) {
return;
}
isShining = true;
@ -287,26 +271,21 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
}
void _jumpToRawMsg() {
if (rawMessage?.status != MessageStatus.V2TIM_MSG_STATUS_LOCAL_REVOKED &&
rawMessage?.timestamp != null) {
if (rawMessage?.status != MessageStatus.V2TIM_MSG_STATUS_LOCAL_REVOKED && rawMessage?.timestamp != null) {
widget.scrollToIndex(rawMessage);
} else {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO, infoRecommendText: TIM_t("无法定位到原消息")));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("无法定位到原消息")));
}
}
Widget? _renderPreviewWidget() {
// If the link preview info from [localCustomData] is available, use it to render the preview card.
// Otherwise, it will returns null.
if (widget.message.localCustomData != null &&
widget.message.localCustomData!.isNotEmpty) {
if (widget.message.localCustomData != null && widget.message.localCustomData!.isNotEmpty) {
try {
final String localJSON = widget.message.localCustomData!;
final LocalCustomDataModel? localPreviewInfo =
LocalCustomDataModel.fromMap(json.decode(localJSON));
if (localPreviewInfo != null &&
!localPreviewInfo.isLinkPreviewEmpty()) {
final LocalCustomDataModel? localPreviewInfo = LocalCustomDataModel.fromMap(json.decode(localJSON));
if (localPreviewInfo != null && !localPreviewInfo.isLinkPreviewEmpty()) {
return Container(
margin: const EdgeInsets.only(top: 8),
child:
@ -327,16 +306,14 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
@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;
if (widget.isShowJump) {
if (!isShining) {
Future.delayed(Duration.zero, () {
_showJumpColor();
});
} else {
if ((widget.chatModel.jumpMsgID == widget.message.msgID) &&
(widget.message.msgID?.isNotEmpty ?? false)) {
if ((widget.chatModel.jumpMsgID == widget.message.msgID) && (widget.message.msgID?.isNotEmpty ?? false)) {
widget.clearJump();
}
}
@ -345,13 +322,11 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
final isFromSelf = widget.message.isSelf ?? true;
final defaultStyle = isFromSelf
? (theme.chatMessageItemFromSelfBgColor ??
theme.lightPrimaryMaterialColor.shade50)
? (theme.chatMessageItemFromSelfBgColor ?? theme.lightPrimaryMaterialColor.shade50)
: (theme.chatMessageItemFromOthersBgColor);
final backgroundColor = isShowJumpState
? const Color.fromRGBO(245, 166, 35, 1)
: (defaultStyle ?? widget.backgroundColor);
final backgroundColor =
isShowJumpState ? const Color.fromRGBO(245, 166, 35, 1) : (defaultStyle ?? widget.backgroundColor);
final borderRadius = isFromSelf
? const BorderRadius.only(
@ -365,29 +340,22 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10));
final textWithLink = LinkPreviewEntry.getHyperlinksText(
widget.message.textElem?.text ?? "",
widget.chatModel.chatConfig.isSupportMarkdownForTextMessage,
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,
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);
isEnableTextSelection: widget.chatModel.chatConfig.isEnableTextSelection ?? false);
return Container(
padding: widget.textPadding ?? EdgeInsets.all(isDesktopScreen ? 12 : 10),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: widget.borderRadius ?? borderRadius,
),
constraints:
BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.6),
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.6),
child: GestureDetector(
onTap: _jumpToRawMsg,
child: Column(
@ -399,20 +367,13 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
constraints: const BoxConstraints(minWidth: 120),
decoration: const BoxDecoration(
color: Color.fromRGBO(68, 68, 68, 0.05),
border: Border(
left: BorderSide(
color: Color.fromRGBO(68, 68, 68, 0.1), width: 2))),
border: Border(left: BorderSide(color: Color.fromRGBO(68, 68, 68, 0.1), width: 2))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
repliedMessage != null
? "${repliedMessage!.messageSender}:"
: "",
style: TextStyle(
fontSize: 12,
color: theme.weakTextColor,
fontWeight: FontWeight.w500),
repliedMessage != null ? "${repliedMessage!.messageSender}:" : "",
style: TextStyle(fontSize: 12, color: theme.weakTextColor, fontWeight: FontWeight.w500),
),
const SizedBox(
height: 4,
@ -436,35 +397,22 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
: ExtendedText(widget.message.textElem?.text ?? "",
softWrap: true,
style: widget.fontStyle ??
TextStyle(
fontSize: isDesktopScreen ? 14 : 16,
height: widget.chatModel.chatConfig.textHeight),
TextStyle(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 ??
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,
)),
// If the link preview info is available, render the preview card.
if (_renderPreviewWidget() != null &&
widget.chatModel.chatConfig.urlPreviewType ==
UrlPreviewType.previewCardAndHyperlink)
widget.chatModel.chatConfig.urlPreviewType == UrlPreviewType.previewCardAndHyperlink)
_renderPreviewWidget()!,
if (widget.isShowMessageReaction ?? true)
TIMUIKitMessageReactionShowPanel(message: widget.message)
if (widget.isShowMessageReaction ?? true) TIMUIKitMessageReactionShowPanel(message: widget.message)
],
),
),

View File

@ -3,6 +3,8 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_sound_elem.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';
@ -12,8 +14,6 @@ import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/constants/history_message_constant.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/sound_record.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'TIMUIKitMessageReaction/tim_uikit_message_reaction_show_panel.dart';
class TIMUIKitSoundElem extends StatefulWidget {

View File

@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:convert';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:extended_text/extended_text.dart';
import 'package:flutter/material.dart';
@ -65,8 +66,7 @@ class _TIMUIKitTextElemState extends TIMUIKitState<TIMUIKitTextElem> {
}
_showJumpColor() {
if ((widget.chatModel.jumpMsgID != widget.message.msgID) &&
(widget.message.msgID?.isNotEmpty ?? true)) {
if ((widget.chatModel.jumpMsgID != widget.message.msgID) && (widget.message.msgID?.isNotEmpty ?? true)) {
return;
}
isShining = true;
@ -93,16 +93,13 @@ class _TIMUIKitTextElemState extends TIMUIKitState<TIMUIKitTextElem> {
// get the link preview info
_getLinkPreview() {
if (widget.chatModel.chatConfig.urlPreviewType !=
UrlPreviewType.previewCardAndHyperlink) {
if (widget.chatModel.chatConfig.urlPreviewType != UrlPreviewType.previewCardAndHyperlink) {
return;
}
try {
if (widget.message.localCustomData != null &&
widget.message.localCustomData!.isNotEmpty) {
if (widget.message.localCustomData != null && widget.message.localCustomData!.isNotEmpty) {
final String localJSON = widget.message.localCustomData!;
final LocalCustomDataModel? localPreviewInfo =
LocalCustomDataModel.fromMap(json.decode(localJSON));
final LocalCustomDataModel? localPreviewInfo = LocalCustomDataModel.fromMap(json.decode(localJSON));
// If [localCustomData] is not empty, check if the link preview info exists
if (localPreviewInfo == null || localPreviewInfo.isLinkPreviewEmpty()) {
// If not exists, get it
@ -123,22 +120,18 @@ class _TIMUIKitTextElemState extends TIMUIKitState<TIMUIKitTextElem> {
LinkPreviewEntry.getFirstLinkPreviewContent(
message: widget.message,
onUpdateMessage: (message) {
widget.chatModel.updateMessageFromController(
msgID: widget.message.msgID!, message: message);
widget.chatModel.updateMessageFromController(msgID: widget.message.msgID!, message: message);
});
}
Widget? _renderPreviewWidget() {
// If the link preview info from [localCustomData] is available, use it to render the preview card.
// Otherwise, it will returns null.
if (widget.message.localCustomData != null &&
widget.message.localCustomData!.isNotEmpty) {
if (widget.message.localCustomData != null && widget.message.localCustomData!.isNotEmpty) {
try {
final String localJSON = widget.message.localCustomData!;
final LocalCustomDataModel? localPreviewInfo =
LocalCustomDataModel.fromMap(json.decode(localJSON));
if (localPreviewInfo != null &&
!localPreviewInfo.isLinkPreviewEmpty()) {
final LocalCustomDataModel? localPreviewInfo = LocalCustomDataModel.fromMap(json.decode(localJSON));
if (localPreviewInfo != null && !localPreviewInfo.isLinkPreviewEmpty()) {
return Container(
margin: const EdgeInsets.only(top: 8),
child:
@ -159,24 +152,17 @@ class _TIMUIKitTextElemState extends TIMUIKitState<TIMUIKitTextElem> {
@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;
final textWithLink = LinkPreviewEntry.getHyperlinksText(
widget.message.textElem?.text ?? "",
widget.chatModel.chatConfig.isSupportMarkdownForTextMessage,
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,
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);
isEnableTextSelection: widget.chatModel.chatConfig.isEnableTextSelection ?? false);
final borderRadius = widget.isFromSelf
? const BorderRadius.only(
topLeft: Radius.circular(10),
@ -195,21 +181,18 @@ class _TIMUIKitTextElemState extends TIMUIKitState<TIMUIKitTextElem> {
_showJumpColor();
});
} else {
if ((widget.chatModel.jumpMsgID == widget.message.msgID) &&
(widget.message.msgID?.isNotEmpty ?? false)) {
if ((widget.chatModel.jumpMsgID == widget.message.msgID) && (widget.message.msgID?.isNotEmpty ?? false)) {
widget.clearJump();
}
}
}
final defaultStyle = widget.isFromSelf
? (theme.chatMessageItemFromSelfBgColor ??
theme.lightPrimaryMaterialColor.shade50)
? (theme.chatMessageItemFromSelfBgColor ?? theme.lightPrimaryMaterialColor.shade50)
: (theme.chatMessageItemFromOthersBgColor);
final backgroundColor = isShowJumpState
? const Color.fromRGBO(245, 166, 35, 1)
: (defaultStyle ?? widget.backgroundColor);
final backgroundColor =
isShowJumpState ? const Color.fromRGBO(245, 166, 35, 1) : (defaultStyle ?? widget.backgroundColor);
return Container(
padding: widget.textPadding ?? EdgeInsets.all(isDesktopScreen ? 12 : 10),
@ -217,8 +200,7 @@ class _TIMUIKitTextElemState extends TIMUIKitState<TIMUIKitTextElem> {
color: backgroundColor,
borderRadius: widget.borderRadius ?? borderRadius,
),
constraints:
BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.6),
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.6),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -234,24 +216,13 @@ class _TIMUIKitTextElemState extends TIMUIKitState<TIMUIKitTextElem> {
: ExtendedText(widget.message.textElem?.text ?? "",
softWrap: true,
style: widget.fontStyle ??
TextStyle(
fontSize: isDesktopScreen ? 14 : 16,
height: widget.chatModel.chatConfig.textHeight),
TextStyle(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 ??
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,
@ -259,11 +230,9 @@ class _TIMUIKitTextElemState extends TIMUIKitState<TIMUIKitTextElem> {
)),
// If the link preview info is available, render the preview card.
if (_renderPreviewWidget() != null &&
widget.chatModel.chatConfig.urlPreviewType ==
UrlPreviewType.previewCardAndHyperlink)
widget.chatModel.chatConfig.urlPreviewType == UrlPreviewType.previewCardAndHyperlink)
_renderPreviewWidget()!,
if (widget.isShowMessageReaction ?? true)
TIMUIKitMessageReactionShowPanel(message: widget.message)
if (widget.isShowMessageReaction ?? true) TIMUIKitMessageReactionShowPanel(message: widget.message)
],
),
);

View File

@ -1,6 +1,8 @@
import 'dart:async';
import 'dart:convert';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:extended_text/extended_text.dart';
import 'package:flutter/material.dart';
@ -43,14 +45,12 @@ class TIMUIKitTextTranslationElem extends StatefulWidget {
State<StatefulWidget> createState() => _TIMUIKitTextTranslationElemState();
}
class _TIMUIKitTextTranslationElemState
extends TIMUIKitState<TIMUIKitTextTranslationElem> {
class _TIMUIKitTextTranslationElemState extends TIMUIKitState<TIMUIKitTextTranslationElem> {
bool isShowJumpState = false;
bool isShining = false;
_showJumpColor() {
if ((widget.chatModel.jumpMsgID != widget.message.msgID) &&
(widget.message.msgID?.isNotEmpty ?? true)) {
if ((widget.chatModel.jumpMsgID != widget.message.msgID) && (widget.message.msgID?.isNotEmpty ?? true)) {
return;
}
isShining = true;
@ -78,8 +78,7 @@ class _TIMUIKitTextTranslationElemState
@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;
final borderRadius = widget.isFromSelf
? const BorderRadius.only(
topLeft: Radius.circular(10),
@ -98,61 +97,49 @@ class _TIMUIKitTextTranslationElemState
_showJumpColor();
});
} else {
if ((widget.chatModel.jumpMsgID == widget.message.msgID) &&
(widget.message.msgID?.isNotEmpty ?? false)) {
if ((widget.chatModel.jumpMsgID == widget.message.msgID) && (widget.message.msgID?.isNotEmpty ?? false)) {
widget.clearJump();
}
}
}
final defaultStyle = widget.isFromSelf
? (theme.chatMessageItemFromSelfBgColor ??
theme.lightPrimaryMaterialColor.shade50)
? (theme.chatMessageItemFromSelfBgColor ?? theme.lightPrimaryMaterialColor.shade50)
: (theme.chatMessageItemFromOthersBgColor);
final backgroundColor = isShowJumpState
? const Color.fromRGBO(245, 166, 35, 1)
: (defaultStyle ?? widget.backgroundColor);
final backgroundColor =
isShowJumpState ? const Color.fromRGBO(245, 166, 35, 1) : (defaultStyle ?? widget.backgroundColor);
final LocalCustomDataModel localCustomData = LocalCustomDataModel.fromMap(
json.decode(
TencentUtils.checkString(widget.message.localCustomData) ?? "{}"));
final LocalCustomDataModel localCustomData =
LocalCustomDataModel.fromMap(json.decode(TencentUtils.checkString(widget.message.localCustomData) ?? "{}"));
final String? translateText = localCustomData.translatedText;
final textWithLink = LinkPreviewEntry.getHyperlinksText(translateText ?? "",
widget.chatModel.chatConfig.isSupportMarkdownForTextMessage,
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,
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);
isEnableTextSelection: widget.chatModel.chatConfig.isEnableTextSelection ?? false);
return TencentUtils.checkString(translateText) != null
? Container(
margin: const EdgeInsets.only(top: 6),
padding:
widget.textPadding ?? EdgeInsets.all(isDesktopScreen ? 12 : 10),
padding: widget.textPadding ?? EdgeInsets.all(isDesktopScreen ? 12 : 10),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: widget.borderRadius ?? borderRadius,
),
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.6),
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.6),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// If the [elemType] is text message, it will not be null here.
// You can render the widget from extension directly, with a [TextStyle] optionally.
widget.chatModel.chatConfig.urlPreviewType !=
UrlPreviewType.none
widget.chatModel.chatConfig.urlPreviewType != UrlPreviewType.none
? textWithLink!(
style: widget.fontStyle ??
TextStyle(
@ -163,23 +150,13 @@ class _TIMUIKitTextTranslationElemState
softWrap: true,
style: widget.fontStyle ??
TextStyle(
fontSize: isDesktopScreen ? 14 : 16,
height: widget.chatModel.chatConfig.textHeight),
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,
isUseQQPackage: widget.chatModel.chatConfig.stickerPanelConfig?.useQQStickerPackage ?? true,
isUseTencentCloudChatPackage:
widget.chatModel.chatConfig.stickerPanelConfig?.useTencentCloudChatStickerPackage ?? true,
isUseTencentCloudChatPackageOldKeys: widget
.chatModel
.chatConfig
.stickerPanelConfig
?.useTencentCloudChatStickerPackageOldKeys ??
.chatModel.chatConfig.stickerPanelConfig?.useTencentCloudChatStickerPackageOldKeys ??
false,
customEmojiStickerList: widget.customEmojiStickerList,
showAtBackground: true,
@ -200,8 +177,7 @@ class _TIMUIKitTextTranslationElemState
),
Text(
TIM_t("翻译完成"),
style: const TextStyle(
color: Color(0x72282c34), fontSize: 10),
style: const TextStyle(color: Color(0x72282c34), fontSize: 10),
)
],
)

View File

@ -4,12 +4,18 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:open_file/open_file.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_status.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_video_elem.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/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/message.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitMessageItem/TIMUIKitMessageReaction/tim_uikit_message_reaction_wrapper.dart';

View File

@ -0,0 +1,202 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:better_player_plus/better_player_plus.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_elem_type.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_online_url.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
class TIMUIKitVideoPlayer extends StatefulWidget {
final V2TimMessage message;
final bool controller;
final bool isSending;
const TIMUIKitVideoPlayer({
super.key,
required this.message,
required this.controller,
required this.isSending,
});
@override
State<StatefulWidget> createState() => TIMUIKitVideoPlayerState();
}
enum CurrentVideoType {
online,
local,
}
class CurrentVideoInfo {
final String path;
final CurrentVideoType type;
final double aspectRatio;
CurrentVideoInfo({
required this.path,
required this.type,
required this.aspectRatio,
});
}
class TIMUIKitVideoPlayerState extends State<TIMUIKitVideoPlayer> {
final String _tag = "TencentCloudChatMessageVideoPlayer";
BetterPlayerController? _betterPlayerController;
@override
void initState() {
super.initState();
_initializePlayer();
}
Future<void> _initializePlayer() async {
try {
final info = await getMessageInfo();
if (info != null && mounted) {
BetterPlayerDataSource dataSource;
if (info.type == CurrentVideoType.online) {
dataSource = BetterPlayerDataSource(
BetterPlayerDataSourceType.network,
info.path,
);
} else {
dataSource = BetterPlayerDataSource(
BetterPlayerDataSourceType.file,
info.path,
);
}
final betterPlayerConfiguration = BetterPlayerConfiguration(
aspectRatio: info.aspectRatio,
fit: BoxFit.contain,
autoPlay: true,
allowedScreenSleep: false,
fullScreenByDefault: false,
controlsConfiguration: const BetterPlayerControlsConfiguration(
enableFullscreen: false,
enablePlayPause: true,
enableProgressBar: true,
enableProgressText: true,
showControlsOnInitialize: false,
enableMute:false,
enableOverflowMenu:false,
enableSkips:false,
),
);
_betterPlayerController = BetterPlayerController(
betterPlayerConfiguration,
betterPlayerDataSource: dataSource,
);
if (mounted) {
setState(() {
});
}
}
} catch (e) {
debugPrint("Video initialization error: $e");
}
}
@override
void dispose() {
_betterPlayerController?.dispose();
super.dispose();
}
Future<CurrentVideoInfo?> getMessageInfo() async {
if (widget.message.elemType == MessageElemType.V2TIM_ELEM_TYPE_VIDEO) {
double aspectRatio = (9 / 16);
if (widget.isSending) {
var lp = widget.message.videoElem!.videoPath ?? "";
if (lp.isNotEmpty) {
console("view sending message video path");
if (File(lp).existsSync() && !kIsWeb) {
return CurrentVideoInfo(path: lp, type: CurrentVideoType.local, aspectRatio: aspectRatio);
}
}
}
if (widget.message.videoElem!.snapshotWidth != null && widget.message.videoElem!.snapshotHeight != null) {
if (widget.message.videoElem!.snapshotHeight != 0) {
aspectRatio = (widget.message.videoElem!.snapshotWidth!) / (widget.message.videoElem!.snapshotHeight!);
}
}
if (TencentUtils.checkString(widget.message.videoElem!.videoPath) != null) {
//
if (File(widget.message.videoElem!.videoPath!).existsSync()) {
console("video: local video path exists");
return CurrentVideoInfo(path: widget.message.videoElem!.videoPath!, type: CurrentVideoType.local, aspectRatio: aspectRatio);
}
} else if (TencentUtils.checkString(widget.message.videoElem!.localVideoUrl) != null) {
//
if (File(widget.message.videoElem!.localVideoUrl!).existsSync()) {
console("video: local url exists");
return CurrentVideoInfo(path: widget.message.videoElem!.localVideoUrl!, type: CurrentVideoType.local, aspectRatio: aspectRatio);
}
} else {
// 线(todo 使 getMessageOnlineUrl )
if (widget.message.videoElem != null) {
if (widget.message.videoElem!.snapshotUrl != null) {
console("video: online url ${widget.message.videoElem!.videoUrl}");
return CurrentVideoInfo(
path: widget.message.videoElem!.videoUrl!,
type: CurrentVideoType.online,
aspectRatio: aspectRatio,
);
}
}
if (!kIsWeb) {
V2TimValueCallback<V2TimMessageOnlineUrl> urlres = await TencentImSDKPlugin.v2TIMManager.getMessageManager().getMessageOnlineUrl(msgID: widget.message.msgID ?? "");
if (urlres.data != null) {
if (urlres.data?.videoElem != null) {
if (TencentUtils.checkString(urlres.data?.videoElem?.videoUrl) != null) {
console("view video online url ${urlres.data?.videoElem?.videoUrl}");
return CurrentVideoInfo(path: urlres.data!.videoElem!.videoUrl!, type: CurrentVideoType.online, aspectRatio: aspectRatio);
}
}
}
}
}
} else {
console("The component received a non-video message parameter. please check");
}
console("has no view video source. please check");
return null;
}
console(String log) {
print("$_tag, $log");
}
@override
Widget build(BuildContext context) {
if (widget.message.hasRiskContent == true) {
return const Center(
child: Text(
"Risk Video",
style: TextStyle(color: Colors.white),
),
);
}
if (_betterPlayerController == null) {
return Container();
}
return AspectRatio(
aspectRatio: _betterPlayerController!.videoPlayerController?.value.aspectRatio ?? 9 / 16,
child: BetterPlayer(
controller: _betterPlayerController!,
),
);
}
}

View File

@ -1,15 +1,20 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_merger_elem.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.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/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/TIMUIKitChat/TIMUIKItMessageList/tim_uikit_chat_history_message_list_item.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/merger_message_screen.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.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';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
import 'TIMUIKitMessageReaction/tim_uikit_message_reaction_show_panel.dart';
class TIMUIKitMergerElem extends StatefulWidget {

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.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';

View File

@ -1,105 +0,0 @@
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:wechat_camera_picker/wechat_camera_picker.dart';
class IntlCameraPickerTextDelegate extends CameraPickerTextDelegate {
/// Confirm string for the confirm button.
///
@override
String get confirm => TIM_t('确认');
/// Tips string above the shooting button before shooting.
///
@override
String get shootingTips => TIM_t('轻触拍照,长按摄像');
/// Tips string above the shooting button before shooting.
///
@override
String get shootingWithRecordingTips => TIM_t('轻触拍照,长按摄像');
/// Load failed string for item.
///
@override
String get loadFailed => TIM_t('加载失败');
/// Default loading string for the dialog.
///
@override
String get loading => TIM_t('加载中…');
/// Saving string for the dialog.
///
@override
String get saving => TIM_t('保存中…');
/// Semantics fields.
///
/// Fields below are only for semantics usage. For customizable these fields,
/// head over to [EnglishCameraPickerTextDelegate] for better understanding.
@override
String get sActionManuallyFocusHint => TIM_t('手动聚焦');
@override
String get sActionPreviewHint => TIM_t('预览');
@override
String get sActionRecordHint => TIM_t('录像');
@override
String get sActionShootHint => TIM_t('拍照');
@override
String get sActionShootingButtonTooltip => TIM_t('拍照按钮');
@override
String get sActionStopRecordingHint => TIM_t('停止录像');
@override
String sCameraLensDirectionLabel(CameraLensDirection value) {
switch (value) {
case CameraLensDirection.front:
return TIM_t('前置');
case CameraLensDirection.back:
return TIM_t('后置');
case CameraLensDirection.external:
return TIM_t('外置');
}
}
@override
String? sCameraPreviewLabel(CameraLensDirection? value) {
if (value == null) {
return null;
}
final option1 = sCameraLensDirectionLabel(value);
return TIM_t_para("{{option1}} 画面预览", "$option1 画面预览")(option1: option1);
}
@override
String sFlashModeLabel(FlashMode mode) {
final String _modeString;
switch (mode) {
case FlashMode.off:
_modeString = TIM_t('关闭');
break;
case FlashMode.auto:
_modeString = TIM_t('自动');
break;
case FlashMode.always:
_modeString = TIM_t('拍照时闪光');
break;
case FlashMode.torch:
_modeString = TIM_t('始终闪光');
break;
}
final option2 = _modeString;
return TIM_t_para("闪光模式: {{option2}}", "闪光模式: $option2")(option2: option2);
}
@override
String sSwitchCameraLensDirectionLabel(CameraLensDirection value) {
final option3 = sCameraLensDirectionLabel(value);
return TIM_t_para("切换至 {{option3}} 摄像头", "切换至 $option3 摄像头")(
option3: option3);
}
}

View File

@ -32,9 +32,7 @@ class DefaultSpecialTextSpanBuilder extends SpecialTextSpanBuilder {
@override
SpecialText? createSpecialText(String flag,
{TextStyle? textStyle,
SpecialTextGestureTapCallback? onTap,
int? index}) {
{TextStyle? textStyle, SpecialTextGestureTapCallback? onTap, int? index}) {
if (flag == '') {
return null;
}
@ -43,14 +41,12 @@ class DefaultSpecialTextSpanBuilder extends SpecialTextSpanBuilder {
if (isStart(flag, EmojiText.flag)) {
return EmojiText(textStyle,
isUseTencentCloudChatPackage: isUseTencentCloudChatPackage,
isUseTencentCloudChatPackageOldKeys:
isUseTencentCloudChatPackageOldKeys,
isUseTencentCloudChatPackageOldKeys: isUseTencentCloudChatPackageOldKeys,
isUseQQPackage: isUseQQPackage,
start: index! - (EmojiText.flag.length - 1),
customEmojiStickerList: customEmojiStickerList);
} else if (isStart(flag, HttpText.flag) && checkHttpLink) {
return HttpText(textStyle, onTap,
start: index! - (HttpText.flag.length - 1));
return HttpText(textStyle, onTap, start: index! - (HttpText.flag.length - 1));
}
return null;
}

View File

@ -111,7 +111,7 @@ class EmojiUtil {
String emojiName = emoji.split('.png')[0];
String compatibleEmojiName = emojiName;
if (isUseTencentCloudChatPackageOldKeys) {
// key
// use old emoji keys in 3.x version
compatibleEmojiName = getCompatibleEmojiName(emojiName);
}

View File

@ -1,17 +1,21 @@
import 'package:flutter/material.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitGroupProfile/widgets/tim_ui_group_member_search.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/group_member_list.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class AtText extends StatefulWidget {
final String? groupID;

View File

@ -1,5 +1,11 @@
import 'package:flutter/material.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_filter_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_state.dart';
import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
@ -10,6 +16,8 @@ import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitGroupProfile/widgets/t
import 'package:tencent_cloud_chat_uikit/ui/widgets/group_member_list.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class SelectCallInviter extends StatefulWidget {
final String? groupID;
const SelectCallInviter({

View File

@ -1,11 +1,13 @@
import 'package:flutter/material.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_statelesswidget.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/logger.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
class EmojiPanel extends TIMUIKitStatelessWidget {
final void Function(int unicode) onTapEmoji;
final void Function() onSubmitted;

View File

@ -1,6 +1,7 @@
// ignore_for_file: unused_field, avoid_print, unused_import
import 'dart:io';
import 'package:better_player_plus/better_player_plus.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:fc_native_video_thumbnail/fc_native_video_thumbnail.dart';
import 'package:flutter/foundation.dart';
@ -10,9 +11,11 @@ import 'package:image_picker/image_picker.dart';
import 'package:file_picker/file_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/TIMUIKitTextField/tim_uikit_call_invite_list.dart';
import 'package:wechat_camera_picker/wechat_camera_picker.dart';
import 'package:video_player/video_player.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';
@ -22,7 +25,6 @@ import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/message.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/intl_camer_picker.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
@ -31,6 +33,10 @@ import 'dart:typed_data';
import 'package:universal_html/html.dart' as html;
import 'package:tencent_cloud_chat_uikit/ui/utils/logger.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class MorePanelConfig {
static final int FILE_MAX_SIZE = 100 * 1024 * 1024;
static final int VIDEO_MAX_SIZE = 100 * 1024 * 1024;
@ -65,8 +71,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 {
@ -78,11 +83,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
@ -91,8 +92,7 @@ class MorePanel extends StatefulWidget {
class _MorePanelState extends TIMUIKitState<MorePanel> {
final ImagePicker _picker = ImagePicker();
final TUISelfInfoViewModel _selfInfoViewModel =
serviceLocator<TUISelfInfoViewModel>();
final TUISelfInfoViewModel _selfInfoViewModel = serviceLocator<TUISelfInfoViewModel>();
Uint8List? fileContent;
String? fileName;
File? tempFile;
@ -102,6 +102,8 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
final ScrollController _scrollController = ScrollController();
final DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
late BetterPlayerController _betterPlayerController;
@override
void initState() {
super.initState();
@ -111,33 +113,13 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
isInstallCallkit = value;
});
});
_betterPlayerController = BetterPlayerController(const BetterPlayerConfiguration());
}
}
List<MorePanelItem> itemList(TUIChatSeparateViewModel model, TUITheme theme) {
final config = widget.morePanelConfig ?? MorePanelConfig();
return [
if (PlatformUtils().isMobile)
MorePanelItem(
id: "screen",
title: TIM_t("拍摄"),
onTap: (c) {
_onFeatureTap("screen", c, model, theme);
},
icon: Container(
height: 64,
width: 64,
margin: const EdgeInsets.only(bottom: 4),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(5))),
child: SvgPicture.asset(
"images/screen.svg",
package: 'tencent_cloud_chat_uikit',
height: 64,
width: 64,
),
)),
if (!PlatformUtils().isWeb)
MorePanelItem(
id: "photo",
@ -154,9 +136,7 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
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/photo.svg",
package: 'tencent_cloud_chat_uikit',
@ -164,6 +144,44 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
width: 64,
),
)),
if (PlatformUtils().isMobile)
MorePanelItem(
id: "take_photo",
title: TIM_t("拍照"),
onTap: (c) {
_onFeatureTap("take_photo", c, model, theme);
},
icon: Container(
height: 64,
width: 64,
margin: const EdgeInsets.only(bottom: 4),
decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(5))),
child: SvgPicture.asset(
"images/screen.svg",
package: 'tencent_cloud_chat_uikit',
height: 64,
width: 64,
),
)),
if (PlatformUtils().isMobile)
MorePanelItem(
id: "take_video",
title: TIM_t("录像"),
onTap: (c) {
_onFeatureTap("take_video", c, model, theme);
},
icon: Container(
height: 64,
width: 64,
margin: const EdgeInsets.only(bottom: 4),
decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(5))),
child: Image.asset(
"images/take_video.png",
package: 'tencent_cloud_chat_uikit',
height: 64,
width: 64,
),
)),
if (PlatformUtils().isWeb)
MorePanelItem(
id: "image",
@ -180,9 +198,7 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
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/photo.svg",
package: 'tencent_cloud_chat_uikit',
@ -206,11 +222,8 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
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",
@ -227,9 +240,7 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
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/file.svg",
package: 'tencent_cloud_chat_uikit',
@ -253,9 +264,7 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
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',
@ -279,9 +288,7 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
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',
@ -320,28 +327,21 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
}).toList();
}
_sendVideoMessage(AssetEntity asset, 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;
}
final plugin = FcNativeVideoThumbnail();
final originFile = await asset.originFile;
final duration = asset.videoDuration.inSeconds;
final filePath = originFile!.path;
final convID = widget.conversationID;
final convType = widget.conversationType;
String tempPath = (await getTemporaryDirectory()).path +
p.basename(originFile.path) +
".jpeg";
String tempPath = (await getTemporaryDirectory()).path + p.basename(originFilePath) + ".jpeg";
await plugin.getVideoThumbnail(
srcFile: originFile.path,
srcFile: originFilePath,
destFile: tempPath,
format: 'jpeg',
width: 1280,
@ -350,11 +350,7 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
);
MessageUtils.handleMessageError(
model.sendVideoMessage(
videoPath: filePath,
duration: duration,
snapshotPath: tempPath,
convID: convID,
convType: convType),
videoPath: originFilePath, duration: duration, snapshotPath: tempPath, convID: convID, convType: convType),
context);
}
@ -414,46 +410,34 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
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(asset, 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();
@ -464,10 +448,7 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
}
}
_sendImageFromCamera(
TUIChatSeparateViewModel model,
TUITheme theme,
) async {
_sendImageFromCamera(TUIChatSeparateViewModel model, TUITheme theme, {required isVideo}) async {
try {
if (!await Permissions.checkPermission(
context,
@ -484,34 +465,41 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
final convID = widget.conversationID;
final convType = widget.conversationType;
final pickedFile = await CameraPicker.pickFromCamera(context,
pickerConfig: CameraPickerConfig(
enableRecording: true,
textDelegate: IntlCameraPickerTextDelegate()));
final originFile = await pickedFile?.originFile;
if (originFile != null) {
final type = pickedFile!.type;
final ImagePicker picker = ImagePicker();
XFile? originFile;
if (isVideo) {
originFile = await picker.pickVideo(source: ImageSource.camera);
} else {
originFile = await picker.pickImage(source: ImageSource.camera);
}
final size = await originFile!.length();
if (type == AssetType.image) {
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),
model.sendImageMessage(imagePath: originFile.path, convID: convID, convType: convType),
context);
}
if (type == AssetType.video) {
_sendVideoMessage(pickedFile, size, model);
}
} else {
// Toast.showToast(ToastType.fail, TIM_t("图片不能为空"), context);
//
_betterPlayerController.addEventsListener((event) {
if (event.betterPlayerEventType == BetterPlayerEventType.initialized) {
//
int durationInSeconds = _betterPlayerController.videoPlayerController?.value.duration?.inSeconds ?? 0;
_sendVideoMessage(originFile!.path, durationInSeconds, size, model);
}
});
//
_betterPlayerController.setupDataSource(
BetterPlayerDataSource(
BetterPlayerDataSourceType.file,
originFile.path, // URL
),
);
}
} catch (error) {
outputLogger.i("err: $error");
@ -527,17 +515,12 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
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()}");
@ -553,25 +536,18 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
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()}");
@ -589,43 +565,29 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
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();
}
@ -644,8 +606,11 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
case "photo":
_sendImageMessage(model, theme);
break;
case "screen":
_sendImageFromCamera(model, theme);
case "take_photo":
_sendImageFromCamera(model, theme, isVideo: false);
break;
case "take_video":
_sendImageFromCamera(model, theme, isVideo: true);
break;
case "file":
_sendFile(model, theme);
@ -673,14 +638,12 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
bool hasMicrophonePermission = false;
if (type == TYPE_VIDEO) {
hasCameraPermission = await Permissions.checkPermission(context, Permission.camera.value);
hasMicrophonePermission = await Permissions.checkPermission(
context, Permission.microphone.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;
}
@ -702,9 +665,7 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
_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 {
@ -716,11 +677,16 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
}
}
@override
void dispose() {
_betterPlayerController?.dispose();
super.dispose();
}
@override
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
final TUITheme theme = value.theme;
final TUIChatSeparateViewModel model =
Provider.of<TUIChatSeparateViewModel>(context);
final TUIChatSeparateViewModel model = Provider.of<TUIChatSeparateViewModel>(context);
final screenWidth = MediaQuery.of(context).size.width;
return Container(
height: 248,
@ -757,15 +723,12 @@ class _MorePanelState extends TIMUIKitState<MorePanel> {
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),
)
],
),

View File

@ -5,8 +5,8 @@ import 'dart:io';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:provider/provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.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';
@ -16,6 +16,8 @@ import 'package:tencent_cloud_chat_uikit/ui/utils/permission.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/sound_record.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/logger.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class SendSoundMessage extends StatefulWidget {
/// conversation ID

View File

@ -7,6 +7,11 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_role.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.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';
@ -142,8 +147,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
double inputWidth = 900;
Map<String, V2TimGroupMemberFullInfo> mentionedMembersMap = {};
late TextEditingController textEditingController;
final TUIConversationViewModel conversationModel =
serviceLocator<TUIConversationViewModel>();
final TUIConversationViewModel conversationModel = serviceLocator<TUIConversationViewModel>();
final TUISelfInfoViewModel selfModel = serviceLocator<TUISelfInfoViewModel>();
MuteStatus muteStatus = MuteStatus.none;
bool _isComposingText = false;
@ -155,28 +159,42 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
// Keep using original scheme.
return;
}
final stickerConfig =
widget.model.chatConfig.stickerPanelConfig ?? StickerPanelConfig();
final stickerConfig = widget.model.chatConfig.stickerPanelConfig ?? StickerPanelConfig();
if (stickerConfig.useTencentCloudChatStickerPackage) {
final tccEmojiSet = TUIKitStickerConstData.emojiList
.firstWhere((element) => element.name == "tcc1");
final tccEmojiSet = TUIKitStickerConstData.emojiList.firstWhere((element) => element.name == "tcc1");
stickerPackageList.add(CustomStickerPackage(
name: tccEmojiSet.name,
baseUrl: "assets/custom_face_resource/${tccEmojiSet.name}",
isEmoji: tccEmojiSet.isEmoji,
isDefaultEmoji: true,
stickerList: tccEmojiSet.list
.asMap()
.keys
.map((idx) =>
CustomSticker(index: idx, name: tccEmojiSet.list[idx]))
.toList(),
stickerList: tccEmojiSet.list.asMap().keys.map((idx) => CustomSticker(index: idx, name: tccEmojiSet.list[idx])).toList(),
menuItem: CustomSticker(
index: 0,
name: tccEmojiSet.icon,
)));
}
if (stickerConfig.useQQStickerPackage) {
final qqEmojiSet = TUIKitStickerConstData.emojiList.firstWhere((element) => element.name == "4349");
stickerPackageList.add(CustomStickerPackage(
name: qqEmojiSet.name,
baseUrl: "assets/custom_face_resource/${qqEmojiSet.name}",
isEmoji: qqEmojiSet.isEmoji,
isDefaultEmoji: true,
stickerList: qqEmojiSet.list.asMap().keys.map((idx) => CustomSticker(index: idx, name: qqEmojiSet.list[idx])).toList(),
menuItem: CustomSticker(
index: 0,
name: qqEmojiSet.icon,
)));
}
if (stickerConfig.unicodeEmojiList.isNotEmpty) {
final defEmojiList = TUIKitStickerConstData.defaultUnicodeEmojiList.map((emojiItem) {
return CustomSticker(index: 0, name: emojiItem.toString(), unicode: emojiItem);
}).toList();
stickerPackageList.add(CustomStickerPackage(name: "defaultEmoji", stickerList: defEmojiList, menuItem: defEmojiList[0]));
}
stickerPackageList.addAll(stickerConfig.customStickerPackages);
return stickerPackageList;
}
@ -204,8 +222,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
if (cursorPosition > 0) {
final EmojiUtil emojiUtil = EmojiUtil();
int removeLength = 1;
int openBracketIndex =
originalText.lastIndexOf('[', cursorPosition - 1);
int openBracketIndex = originalText.lastIndexOf('[', cursorPosition - 1);
if (openBracketIndex != -1 && originalText[cursorPosition - 1] == ']') {
// Small png emoji
@ -214,23 +231,18 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
if (emojiUtil.emojiMap.containsKey(key)) {
removeLength = cursorPosition - openBracketIndex;
}
} else if (cursorPosition > 1 &&
isEmoji(
originalText.substring(cursorPosition - 2, cursorPosition))) {
} else if (cursorPosition > 1 && isEmoji(originalText.substring(cursorPosition - 2, cursorPosition))) {
removeLength = 2;
}
text = originalText.substring(0, cursorPosition - removeLength) +
originalText.substring(cursorPosition);
text = originalText.substring(0, cursorPosition - removeLength) + originalText.substring(cursorPosition);
currentCursor = (currentCursor ?? removeLength) - removeLength;
}
textEditingController.text = text;
if (TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop) {
textEditingController.selection = TextSelection.fromPosition(
TextPosition(
offset: currentCursor ?? textEditingController.text.length));
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: currentCursor ?? textEditingController.text.length));
focusNode.requestFocus();
}
}
@ -250,9 +262,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
void _addStickerToText(String sticker) {
final currentText = textEditingController.text;
if (currentCursor != null &&
currentCursor! > -1 &&
currentCursor! < currentText.length + 1) {
if (currentCursor != null && currentCursor! > -1 && currentCursor! < currentText.length + 1) {
final firstString = currentText.substring(0, currentCursor);
final secondString = currentText.substring(currentCursor!);
currentCursor = currentCursor! + sticker.length;
@ -263,8 +273,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
if (TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop) {
textEditingController.selection = TextSelection.fromPosition(TextPosition(
offset: currentCursor ?? textEditingController.text.length));
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: currentCursor ?? textEditingController.text.length));
focusNode.requestFocus();
}
}
@ -273,23 +282,13 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
return text.replaceAll(RegExp(r'\ufeff'), "");
}
Future handleSetDraftText(
{String? id, ConvType? convType, String? groupID}) async {
Future handleSetDraftText({String? id, ConvType? convType, String? groupID}) async {
String text = textEditingController.text;
String convID = id ?? widget.conversationID;
final isTopic = convID.contains("@TOPIC#");
String conversationID = isTopic
? convID
: ((convType ?? widget.conversationType) == ConvType.c2c
? "${TUIConversationViewModel.conversationC2CPrefix}$convID"
: "${TUIConversationViewModel.conversationGroupPrefix}$convID");
String conversationID = isTopic ? convID : ((convType ?? widget.conversationType) == ConvType.c2c ? "${TUIConversationViewModel.conversationC2CPrefix}$convID" : "${TUIConversationViewModel.conversationGroupPrefix}$convID");
String draftText = _filterU200b(text);
return await conversationModel.setConversationDraft(
groupID: groupID ?? widget.groupID,
isTopic: isTopic,
isAllowWeb: widget.model.chatConfig.isUseDraftOnWeb,
conversationID: conversationID,
draftText: draftText);
return await conversationModel.setConversationDraft(groupID: groupID ?? widget.groupID, isTopic: isTopic, isAllowWeb: widget.model.chatConfig.isUseDraftOnWeb, conversationID: conversationID, draftText: draftText);
}
// onSubmitted一样
@ -330,28 +329,26 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
// This part of the code is written to adapt to the Native side requirements.
// It extracts the substring needed to interact with Native side by splitting
// and parsing the given data value.
int groupID = 1;
if (data.contains("yz")) {
groupID = 1;
}
if (data.contains("ys")) {
groupID = 2;
}
if (data.contains("gcs")) {
groupID = 3;
}
RegExp regex = RegExp(r'assets\/custom_face_resource\/(4350|4351|4352)');
if (regex.hasMatch(data)) {
index += 1;
data = (data.split("/")[3]).split("@")[0];
}
if (widget.model.repliedMessage != null) {
MessageUtils.handleMessageError(
widget.model.sendFaceMessage(
index: index,
data: data,
convID: widget.conversationID,
convType: convType),
context);
MessageUtils.handleMessageError(widget.model.sendFaceMessage(index: groupID, data: data, convID: widget.conversationID, convType: convType), context);
} else {
MessageUtils.handleMessageError(
widget.model.sendFaceMessage(
index: index,
data: data,
convID: widget.conversationID,
convType: convType),
context);
MessageUtils.handleMessageError(widget.model.sendFaceMessage(index: groupID, data: data, convID: widget.conversationID, convType: convType), context);
}
}
@ -371,24 +368,11 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
final convType = widget.conversationType;
if (text.isNotEmpty && text != zeroWidthSpace) {
if (widget.model.repliedMessage != null) {
MessageUtils.handleMessageError(
widget.model.sendReplyMessage(
text: text,
convID: widget.conversationID,
convType: convType,
atUserIDList: getUserIdFromMemberInfoMap()),
context);
MessageUtils.handleMessageError(widget.model.sendReplyMessage(text: text, convID: widget.conversationID, convType: convType, atUserIDList: getUserIdFromMemberInfoMap()), context);
} else if (mentionedMembersMap.isNotEmpty) {
widget.model.sendTextAtMessage(
text: text,
convType: widget.conversationType,
convID: widget.conversationID,
atUserList: getUserIdFromMemberInfoMap());
widget.model.sendTextAtMessage(text: text, convType: widget.conversationType, convID: widget.conversationID, atUserList: getUserIdFromMemberInfoMap());
} else {
MessageUtils.handleMessageError(
widget.model.sendTextMessage(
text: text, convID: widget.conversationID, convType: convType),
context);
MessageUtils.handleMessageError(widget.model.sendTextMessage(text: text, convID: widget.conversationID, convType: convType), context);
}
textEditingController.clear();
currentCursor = null;
@ -401,8 +385,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
void goDownBottom() {
if (globalModel.getMessageListPosition(widget.conversationID) ==
HistoryMessagePosition.notShowLatest) {
if (globalModel.getMessageListPosition(widget.conversationID) == HistoryMessagePosition.notShowLatest) {
return;
}
Future.delayed(const Duration(milliseconds: 50), () {
@ -431,18 +414,14 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
String _getShowName(V2TimGroupMemberFullInfo? item) {
return TencentUtils.checkStringWithoutSpace(item?.nameCard) ??
TencentUtils.checkStringWithoutSpace(item?.nickName) ??
TencentUtils.checkStringWithoutSpace(item?.userID) ??
"";
return TencentUtils.checkStringWithoutSpace(item?.nameCard) ?? TencentUtils.checkStringWithoutSpace(item?.nickName) ?? TencentUtils.checkStringWithoutSpace(item?.userID) ?? "";
}
mentionMemberInMessage(String? userID, String? nickName) {
if (TencentUtils.checkString(userID) == null) {
focusNode.requestFocus();
} else {
final memberInfo = widget.model.groupMemberList
?.firstWhereOrNull((element) => element?.userID == userID) ??
final memberInfo = widget.model.groupMemberList?.firstWhereOrNull((element) => element?.userID == userID) ??
V2TimGroupMemberFullInfo(
userID: userID ?? "",
nickName: nickName,
@ -453,8 +432,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
//please do not delete space
focusNode.requestFocus();
textEditingController.text = text;
textEditingController.selection =
TextSelection.fromPosition(TextPosition(offset: text.length));
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: text.length));
lastText = text;
_isComposingText = false;
narrowTextFieldKey.currentState?.showKeyboard = true;
@ -482,16 +460,10 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
maxLines: null,
);
textPainter.layout(maxWidth: inputWidth);
final TextPosition lastLineOffset = textPainter
.getPositionForOffset(Offset(textPainter.width, textPainter.height));
final Offset caretPosition =
textPainter.getOffsetForCaret(lastLineOffset, Rect.zero);
final TextPosition lastLineOffset = textPainter.getPositionForOffset(Offset(textPainter.width, textPainter.height));
final Offset caretPosition = textPainter.getOffsetForCaret(lastLineOffset, Rect.zero);
final dx = min(inputWidth - 180, caretPosition.dx + 16);
final dy = max(
24,
21 * widget.model.chatConfig.desktopMessageInputFieldLines -
caretPosition.dy)
.toDouble();
final dy = max(24, 21 * widget.model.chatConfig.desktopMessageInputFieldLines - caretPosition.dy).toDouble();
return Offset(dx, dy);
}
@ -528,19 +500,13 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
mentionedMembersMap = map;
}
(int, String, bool)? findChangedCharacter(
String originalString, String newString) {
(int, String, bool)? findChangedCharacter(String originalString, String newString) {
if (newString.length < originalString.length) {
final originalStringLength = originalString.length;
final newStringLength = newString.length;
for (int i = 0; i < newString.length; ++i) {
if (originalString[originalStringLength - i - 1] !=
newString[newStringLength - i - 1]) {
return (
newStringLength - i,
originalString[originalStringLength - i - 1],
false
);
if (originalString[originalStringLength - i - 1] != newString[newStringLength - i - 1]) {
return (newStringLength - i, originalString[originalStringLength - i - 1], false);
}
}
return (newString.length, originalString[newString.length], false);
@ -559,11 +525,8 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
_handleAtText(String text, TUIChatSeparateViewModel model) async {
final text = textEditingController.text;
final String originalText = lastText;
String? groupID = widget.conversationType == ConvType.group
? widget.conversationID
: null;
final isDesktopScreen =
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
String? groupID = widget.conversationType == ConvType.group ? widget.conversationID : null;
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
if (groupID == null) {
lastText = text;
@ -583,11 +546,9 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
String atTag = originalText.substring(atIndex, spaceIndex);
String deletedChar = originalText[diffIndex];
if (shouldRemoveAtTag(atTag, deletedChar)) {
final newText = originalText.substring(0, atIndex) +
originalText.substring(spaceIndex + 1);
final newText = originalText.substring(0, atIndex) + originalText.substring(spaceIndex + 1);
textEditingController.text = newText;
textEditingController.selection =
TextSelection.collapsed(offset: atIndex);
textEditingController.selection = TextSelection.collapsed(offset: atIndex);
lastText = newText;
updateMentionedMap();
return;
@ -597,14 +558,13 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
final int selfRole = widget.model.selfMemberInfo?.role ?? 0;
final bool canAtAll = widget.model.chatConfig.isMemberCanAtAll
? true
: (selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN ||
selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
final bool canAtAll = widget.model.chatConfig.isMemberCanAtAll ? true : (selfRole == GroupMemberRoleType
.V2TIM_GROUP_MEMBER_ROLE_ADMIN || selfRole
==
GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
if (isDesktopScreen) {
(int, String, bool)? changedCharacterRecord =
findChangedCharacter(originalText, text);
(int, String, bool)? changedCharacterRecord = findChangedCharacter(originalText, text);
int? changedTextPosition = changedCharacterRecord?.$1;
String? changedCharacter = changedCharacterRecord?.$2;
bool isAdded = changedCharacterRecord?.$3 ?? false;
@ -613,13 +573,10 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
int? atPlace;
if (changedTextPosition != null) {
subText = isAdded == true
? text.substring(0, changedTextPosition + 1)
: text.substring(0, changedTextPosition);
subText = isAdded == true ? text.substring(0, changedTextPosition + 1) : text.substring(0, changedTextPosition);
atPlace = subText.lastIndexOf('@');
if (atPlace != -1) {
keyword = text.substring(
atPlace + 1, changedTextPosition + (isAdded ? 1 : 0));
keyword = text.substring(atPlace + 1, changedTextPosition + (isAdded ? 1 : 0));
}
} else {
atPlace = -1;
@ -632,28 +589,21 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
model.atPositionY = atPosition.dy;
isAddingAtSearchWords = true;
}
List<V2TimGroupMemberFullInfo> showAtMemberList = (model
.groupMemberList ??
[])
List<V2TimGroupMemberFullInfo> showAtMemberList = (model.groupMemberList ?? [])
.where((element) {
final showName = (TencentUtils.checkStringWithoutSpace(
element?.friendRemark) ??
final showName = (TencentUtils.checkStringWithoutSpace(element?.friendRemark) ??
TencentUtils.checkStringWithoutSpace(element?.nameCard) ??
TencentUtils.checkStringWithoutSpace(element?.nickName) ??
TencentUtils.checkStringWithoutSpace(element?.userID) ??
"")
.toLowerCase();
keyword ??= "";
return element != null &&
showName.contains(keyword!.toLowerCase()) &&
TencentUtils.checkString(showName) != null &&
element.userID != widget.model.selfMemberInfo?.userID;
return element != null && showName.contains(keyword!.toLowerCase()) && TencentUtils.checkString(showName) != null && element.userID != widget.model.selfMemberInfo?.userID;
})
.whereType<V2TimGroupMemberFullInfo>()
.toList();
showAtMemberList.sort(
(V2TimGroupMemberFullInfo userA, V2TimGroupMemberFullInfo userB) {
showAtMemberList.sort((V2TimGroupMemberFullInfo userA, V2TimGroupMemberFullInfo userB) {
final isUserAIsGroupAdmin = userA.role == 300;
final isUserAIsGroupOwner = userA.role == 400;
@ -676,11 +626,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
keyword ??= "";
if (canAtAll && showAtMemberList.isNotEmpty && keyword!.isEmpty) {
showAtMemberList = [
V2TimGroupMemberFullInfo(
userID: "__kImSDK_MesssageAtALL__", nickName: TIM_t("所有人")),
...showAtMemberList
];
showAtMemberList = [V2TimGroupMemberFullInfo(userID: "__kImSDK_MesssageAtALL__", nickName: TIM_t("所有人")), ...showAtMemberList];
}
model.activeAtIndex = 0;
@ -692,19 +638,11 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
model.showAtMemberList = [];
isAddingAtSearchWords = false;
}
} else if (textLength > 0 &&
text[textLength - 1] == "@" &&
lastText.length < textLength) {
List<V2TimGroupMemberFullInfo> selectedAtMemberList =
await Navigator.push(
} else if (textLength > 0 && text[textLength - 1] == "@" && lastText.length < textLength) {
List<V2TimGroupMemberFullInfo> selectedAtMemberList = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AtText(
groupMemberList: model.groupMemberList,
groupInfo: model.groupInfo,
groupID: groupID,
canAtAll: canAtAll,
groupType: widget.groupType),
builder: (context) => AtText(groupMemberList: model.groupMemberList, groupInfo: model.groupInfo, groupID: groupID, canAtAll: canAtAll, groupType: widget.groupType),
),
);
@ -714,8 +652,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
if (memberInfo != null) {
mentionedMembersMap["@$showName"] = memberInfo;
String addAtCharacter = i == 0 ? "" : "@";
textEditingController.text =
"${textEditingController.text}$addAtCharacter$showName ";
textEditingController.text = "${textEditingController.text}$addAtCharacter$showName ";
lastText = "${textEditingController.text}$addAtCharacter$showName ";
}
}
@ -726,22 +663,17 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
void replaceAtTag(String selectedMember) {
int cursorPosition = textEditingController.selection.baseOffset;
int atIndex =
textEditingController.text.lastIndexOf('@', cursorPosition - 1);
int atIndex = textEditingController.text.lastIndexOf('@', cursorPosition - 1);
if (atIndex >= 0) {
String beforeAt = textEditingController.text.substring(0, atIndex);
String afterAt = textEditingController.text.substring(cursorPosition);
textEditingController.text =
beforeAt + '@' + selectedMember + ' ' + afterAt;
textEditingController.selection =
TextSelection.collapsed(offset: atIndex + selectedMember.length + 2);
textEditingController.text = beforeAt + '@' + selectedMember + ' ' + afterAt;
textEditingController.selection = TextSelection.collapsed(offset: atIndex + selectedMember.length + 2);
lastText = beforeAt + '@' + selectedMember + ' ' + afterAt;
}
}
void handleAtMember(
{V2TimGroupMemberFullInfo? memberInfo,
bool? isAddToCursorPosition = false}) {
void handleAtMember({V2TimGroupMemberFullInfo? memberInfo, bool? isAddToCursorPosition = false}) {
if (memberInfo != null) {
final String showName = _getShowName(memberInfo);
mentionedMembersMap["@$showName"] = memberInfo;
@ -755,24 +687,17 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
KeyEventResult handleDesktopKeyEvent(FocusNode node, RawKeyEvent event) {
final activeIndex = widget.model.activeAtIndex;
final showMemberList = widget.model.showAtMemberList;
final isPressEnter = (event.physicalKey == PhysicalKeyboardKey.enter) ||
(event.physicalKey == PhysicalKeyboardKey.numpadEnter);
final isPressEnter = (event.physicalKey == PhysicalKeyboardKey.enter) || (event.physicalKey == PhysicalKeyboardKey.numpadEnter);
if (event.runtimeType == RawKeyDownEvent) {
if (event.physicalKey == PhysicalKeyboardKey.backspace) {
if (textEditingController.text.isEmpty && lastText.isEmpty) {
widget.model.repliedMessage = null;
return KeyEventResult.handled;
}
} else if ((event.isShiftPressed ||
event.isAltPressed ||
event.isControlPressed ||
event.isMetaPressed) &&
isPressEnter) {
} else if ((event.isShiftPressed || event.isAltPressed || event.isControlPressed || event.isMetaPressed) && isPressEnter) {
final offset = textEditingController.selection.baseOffset;
textEditingController.text =
'${lastText.substring(0, offset)}\n${lastText.substring(offset)}';
textEditingController.selection =
TextSelection.fromPosition(TextPosition(offset: offset + 1));
textEditingController.text = '${lastText.substring(0, offset)}\n${lastText.substring(offset)}';
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: offset + 1));
lastText = textEditingController.text;
return KeyEventResult.handled;
@ -782,34 +707,26 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
onSubmitted();
} else {
isAddingAtSearchWords = false;
final V2TimGroupMemberFullInfo? memberInfo =
showMemberList[activeIndex];
final V2TimGroupMemberFullInfo? memberInfo = showMemberList[activeIndex];
if (memberInfo != null) {
handleAtMember(
memberInfo: memberInfo, isAddToCursorPosition: true);
handleAtMember(memberInfo: memberInfo, isAddToCursorPosition: true);
}
}
return KeyEventResult.handled;
}
}
if (event.isKeyPressed(LogicalKeyboardKey.arrowUp) &&
isAddingAtSearchWords &&
showMemberList.isNotEmpty) {
if (event.isKeyPressed(LogicalKeyboardKey.arrowUp) && isAddingAtSearchWords && showMemberList.isNotEmpty) {
final newIndex = max(activeIndex - 1, 0);
widget.model.activeAtIndex = newIndex;
widget.atMemberPanelScroll?.scrollToIndex(newIndex,
preferPosition: AutoScrollPosition.middle);
widget.atMemberPanelScroll?.scrollToIndex(newIndex, preferPosition: AutoScrollPosition.middle);
return KeyEventResult.handled;
}
if (event.isKeyPressed(LogicalKeyboardKey.arrowDown) &&
isAddingAtSearchWords &&
showMemberList.isNotEmpty) {
if (event.isKeyPressed(LogicalKeyboardKey.arrowDown) && isAddingAtSearchWords && showMemberList.isNotEmpty) {
final newIndex = min(activeIndex + 1, showMemberList.length - 1);
widget.model.activeAtIndex = newIndex;
widget.atMemberPanelScroll?.scrollToIndex(newIndex,
preferPosition: AutoScrollPosition.middle);
widget.atMemberPanelScroll?.scrollToIndex(newIndex, preferPosition: AutoScrollPosition.middle);
return KeyEventResult.handled;
}
}
@ -827,8 +744,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
} else {
focusNode = FocusNode();
}
textEditingController =
widget.controller?.textEditingController ?? TextEditingController();
textEditingController = widget.controller?.textEditingController ?? TextEditingController();
if (widget.initText != null) {
textEditingController.text = widget.initText!;
}
@ -836,10 +752,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
widget.controller?.addListener(controllerHandler);
}
final AppLocale appLocale = I18nUtils.findDeviceLocale(null);
languageType =
(appLocale == AppLocale.zhHans || appLocale == AppLocale.zhHant)
? 'zh'
: 'en';
languageType = (appLocale == AppLocale.zhHans || appLocale == AppLocale.zhHant) ? 'zh' : 'en';
textEditingController.addListener(() {
_isComposingText = textEditingController.value.composing.start != -1;
});
@ -849,13 +762,11 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
controllerHandler() {
final actionType = widget.controller?.actionType;
if (actionType == ActionType.longPressToAt) {
mentionMemberInMessage(
widget.controller?.atUserID, widget.controller?.atUserName);
mentionMemberInMessage(widget.controller?.atUserID, widget.controller?.atUserName);
} else if (actionType == ActionType.setTextField) {
final newText = widget.controller?.inputText ?? "";
textEditingController.text = newText;
textEditingController.selection = TextSelection.fromPosition(
TextPosition(offset: textEditingController.text.length));
textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: textEditingController.text.length));
lastText = textEditingController.text;
focusNode.requestFocus();
return;
@ -873,18 +784,14 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
super.didUpdateWidget(oldWidget);
if (widget.conversationID != oldWidget.conversationID) {
mentionedMembersMap.clear();
handleSetDraftText(
id: oldWidget.conversationID,
convType: oldWidget.conversationType,
groupID: oldWidget.groupID);
handleSetDraftText(id: oldWidget.conversationID, convType: oldWidget.conversationType, groupID: oldWidget.groupID);
if (oldWidget.initText != widget.initText) {
textEditingController.text = widget.initText ?? "";
} else {
textEditingController.clear();
}
}
if (widget.initText != oldWidget.initText &&
TencentUtils.checkString(widget.initText) != null) {
if (widget.initText != oldWidget.initText && TencentUtils.checkString(widget.initText) != null) {
textEditingController.text = widget.initText!;
focusNode.requestFocus();
}
@ -902,12 +809,8 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
Future<bool> getMemberMuteStatus(String userID) async {
// Get the mute state of the members recursively
if (widget.model.groupMemberList?.any((item) => (item?.userID == userID)) ??
false) {
final int muteUntil = widget.model.groupMemberList
?.firstWhere((item) => (item?.userID == userID))
?.muteUntil ??
0;
if (widget.model.groupMemberList?.any((item) => (item?.userID == userID)) ?? false) {
final int muteUntil = widget.model.groupMemberList?.firstWhere((item) => (item?.userID == userID))?.muteUntil ?? 0;
return muteUntil * 1000 > DateTime.now().millisecondsSinceEpoch;
} else {
return false;
@ -920,30 +823,22 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
final int selfRole = widget.model.selfMemberInfo?.role ?? 0;
final bool willNotBeenMuted =
(selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN ||
selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
final bool willNotBeenMuted = (selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN || selfRole == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
if (widget.conversationType == ConvType.group && !willNotBeenMuted) {
if ((model.groupInfo?.isAllMuted ?? false) &&
muteStatus != MuteStatus.all) {
if ((model.groupInfo?.isAllMuted ?? false) && muteStatus != MuteStatus.all) {
Future.delayed(const Duration(seconds: 0), () {
setState(() {
muteStatus = MuteStatus.all;
});
});
} else if (selfModel.loginInfo?.userID != null &&
await getMemberMuteStatus(selfModel.loginInfo!.userID!) &&
muteStatus != MuteStatus.me) {
} else if (selfModel.loginInfo?.userID != null && await getMemberMuteStatus(selfModel.loginInfo!.userID!) && muteStatus != MuteStatus.me) {
Future.delayed(const Duration(seconds: 0), () {
setState(() {
muteStatus = MuteStatus.me;
});
});
} else if (!(model.groupInfo?.isAllMuted ?? false) &&
!(selfModel.loginInfo?.userID != null &&
await getMemberMuteStatus(selfModel.loginInfo!.userID!)) &&
muteStatus != MuteStatus.none) {
} else if (!(model.groupInfo?.isAllMuted ?? false) && !(selfModel.loginInfo?.userID != null && await getMemberMuteStatus(selfModel.loginInfo!.userID!)) && muteStatus != MuteStatus.none) {
Future.delayed(const Duration(seconds: 0), () {
setState(() {
muteStatus = MuteStatus.none;
@ -972,8 +867,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
@override
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
final theme = value.theme;
final TUIChatSeparateViewModel model =
Provider.of<TUIChatSeparateViewModel>(context);
final TUIChatSeparateViewModel model = Provider.of<TUIChatSeparateViewModel>(context);
_getMuteType(model);
@ -993,8 +887,7 @@ class _InputTextFieldState extends TIMUIKitState<TIMUIKitInputTextField> {
}
final forbiddenText = getForbiddenText();
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
inputWidth = constraints.maxWidth;
return TUIKitScreenUtils.getDeviceWidget(
context: context,

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:tencent_im_base/tencent_im_base.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
enum ActionType {
hideAllPanel,

View File

@ -5,6 +5,8 @@ import 'package:extended_text_field/extended_text_field.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.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';
@ -12,6 +14,8 @@ import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_glo
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_setting_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/message.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/optimize_utils.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/permission.dart';

View File

@ -16,6 +16,9 @@ import 'package:package_info_plus/package_info_plus.dart';
import 'package:pasteboard/pasteboard.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.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';
@ -37,6 +40,9 @@ import 'package:universal_html/html.dart' as html;
import 'package:url_launcher/url_launcher.dart';
import 'package:uuid/uuid.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
import 'package:tencent_cloud_chat_uikit/theme/color.dart';
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
class DesktopControlBarItem {
final String item;

Some files were not shown because too many files have changed in this diff Show More