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) {
@ -591,12 +608,12 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
_notify();
}
}
void _notify() {
try {
void _notify(){
try{
notifyListeners();
} catch (e) {
debugPrint(e.toString());
}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,9 +943,9 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
_repliedMessage = null;
final sendMsgRes = await _messageService.sendMessage(
cloudCustomData: TencentUtils.checkString(
messageInfoWithSender?.cloudCustomData) ??
json.encode(cloudCustomData),
cloudCustomData:
TencentUtils.checkString(messageInfoWithSender?.cloudCustomData) ??
json.encode(cloudCustomData),
id: textMessageInfo.id as String,
offlinePushInfo: tools.buildMessagePushInfo(
messageInfoWithSender, convID, convType),
@ -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();
}
@ -1264,7 +1286,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
msgID: message.msgID ?? "", onlineUserOnly: false);
removeSendingMessageID(message.msgID ?? "");
if (globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) {
HistoryMessagePosition.notShowLatest) {
globalModel.updateMessage(
res, convID, message.msgID!, convType, groupType, setInputField);
}
@ -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);
}
}
@ -1494,7 +1515,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
//
bool? hasDelayedRenderSendingStatus(String id) {
if (_sendingMessageIDMap.containsKey(id)) {
return _sendingMessageIDMap[id];
return _sendingMessageIDMap[id];
}
return 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

@ -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';
@ -127,11 +130,10 @@ class _TIMUIKitHistoryMessageListContainerState
if ((direction == LoadDirection.previous) ||
(direction == LoadDirection.latest && model.haveMoreLatestData)) {
return await model.loadChatRecord(
direction: direction,
count: count ?? (kIsWeb ? 15 : HistoryMessageDartConstant.getCount),
lastMsgID: lastMsgID,
lastMsgSeq: lastSeq ?? -1,
);
direction: direction,
count: count ?? (kIsWeb ? 15 : HistoryMessageDartConstant.getCount),
lastMsgID: lastMsgID,
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 ??
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,
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,36 +216,23 @@ 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 ??
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,
showAtBackground: true,
checkHttpLink: 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

@ -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 size = await originFile!.length();
if (type == AssetType.image) {
if (size >= MorePanelConfig.IMAGE_MAX_SIZE) {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("文件大小超出了限制")));
return;
}
MessageUtils.handleMessageError(
model.sendImageMessage(
imagePath: originFile.path,
convID: convID,
convType: convType),
context);
}
if (type == AssetType.video) {
_sendVideoMessage(pickedFile, size, model);
}
final ImagePicker picker = ImagePicker();
XFile? originFile;
if (isVideo) {
originFile = await picker.pickVideo(source: ImageSource.camera);
} else {
// Toast.showToast(ToastType.fail, TIM_t("图片不能为空"), context);
originFile = await picker.pickImage(source: ImageSource.camera);
}
final size = await originFile!.length();
if (!isVideo) {
if (size >= MorePanelConfig.IMAGE_MAX_SIZE) {
onTIMCallback(
TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("文件大小超出了限制")));
return;
}
MessageUtils.handleMessageError(
model.sendImageMessage(imagePath: originFile.path, convID: convID, convType: convType),
context);
} else {
//
_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