feat: Upgrade to 2.5.1+4

This commit is contained in:
anonymous 2024-04-25 16:12:14 +08:00
parent da84ca9bc6
commit 68dc760e32
28 changed files with 1660 additions and 946 deletions

View File

@ -3,6 +3,7 @@
## Improvements
* Improved memory usage, enhancing performance.
* Improved the logger storage.
# 2.5.0

View File

@ -20,6 +20,7 @@ import shared_preferences_foundation
import sqflite
import tencent_cloud_chat_sdk
import url_launcher_macos
import wakelock_plus
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
@ -37,4 +38,5 @@ 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"))
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
}

View File

@ -161,14 +161,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.1"
chewie_for_us:
chewie:
dependency: transitive
description:
name: chewie_for_us
sha256: "0307723e811508d361fffa6f8bbd9040b1bfea5536544e4d655e10c27de002ec"
name: chewie
sha256: "8bc4ac4cf3f316e50a25958c0f5eb9bb12cf7e8308bb1d74a43b230da2cfc144"
url: "https://pub.dev"
source: hosted
version: "1.5.0"
version: "1.7.5"
clock:
dependency: transitive
description:
@ -241,6 +241,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.2.10"
dbus:
dependency: transitive
description:
name: dbus
sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
url: "https://pub.dev"
source: hosted
version: "0.7.10"
desktop_drop:
dependency: transitive
description:
@ -1233,33 +1241,33 @@ packages:
dependency: transitive
description:
name: tencent_cloud_chat_sdk
sha256: a78f1f20dc9ebe40aee1bbb47da097780028434d77e97774fbe733debb21e18e
sha256: "358e79b51aba5457418d3bb87e0bbd0f088a1eaf4c4463d09bdda93d1d655aa3"
url: "https://pub.dev"
source: hosted
version: "7.7.5296"
version: "7.9.5672"
tencent_cloud_chat_uikit:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "2.5.1"
version: "2.5.1+2"
tencent_cloud_uikit_core:
dependency: transitive
description:
name: tencent_cloud_uikit_core
sha256: "7ddb2c034e5f832261ba268957e282b7c2e738acb1d21aa40c62dad4eaa433ea"
sha256: "61a5400b3fe75c00252272469f332e7ec07f6d1932ee636a3f2b919cf9805cb8"
url: "https://pub.dev"
source: hosted
version: "1.5.2"
version: "1.6.0"
tencent_im_base:
dependency: transitive
description:
name: tencent_im_base
sha256: "035d97d24bebb87654700d4afc8227de8721a259ef5d0195f3207cb0eb0cdc7a"
sha256: daee1faac70fdf5fa4a53576db4fb7268ba5d897cc036353d3114a31abb76fb1
url: "https://pub.dev"
source: hosted
version: "3.3.775296"
version: "3.3.775297"
tencent_im_sdk_plugin_desktop:
dependency: "direct main"
description:
@ -1516,22 +1524,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "13.0.0"
wakelock_for_us:
wakelock_plus:
dependency: transitive
description:
name: wakelock_for_us
sha256: a5bdd445e51a617f7c24be8165230391447301f622aacd050038cee7b41989b4
name: wakelock_plus
sha256: f268ca2116db22e57577fb99d52515a24bdc1d570f12ac18bb762361d43b043d
url: "https://pub.dev"
source: hosted
version: "0.6.3+1"
wakelock_platform_interface:
version: "1.1.4"
wakelock_plus_platform_interface:
dependency: transitive
description:
name: wakelock_platform_interface
sha256: "1f4aeb81fb592b863da83d2d0f7b8196067451e4df91046c26b54a403f9de621"
name: wakelock_plus_platform_interface
sha256: "40fabed5da06caff0796dc638e1f07ee395fb18801fbff3255a2372db2d80385"
url: "https://pub.dev"
source: hosted
version: "0.3.0"
version: "1.1.0"
watcher:
dependency: transitive
description:

View File

@ -36,6 +36,10 @@ abstract class DefaultLifeCycle {
return message;
}
static Future<V2TimMessage> defaultTwoMessagesSolution(V2TimMessage message, [V2TimMessage? repliedMessage]) async {
return message;
}
static Future<List<V2TimMessage>> defaultMessageListSolution(List<V2TimMessage> list) async {
return list;
}

View File

@ -11,7 +11,7 @@ class ChatLifeCycle {
/// Before a new message will be sent.
/// Returns null can block the message from sending.
MessageFunction messageWillSend;
Future<V2TimMessage?> Function(V2TimMessage message, [V2TimMessage? repliedMessage]) messageWillSend;
/// After a new message been sent.
MessageFunctionNullCallback messageDidSend;
@ -43,7 +43,7 @@ class ChatLifeCycle {
this.shouldDeleteMessage = DefaultLifeCycle.defaultAsyncBooleanSolution,
this.messageDidSend = DefaultLifeCycle.defaultNullCallbackSolution,
this.didGetHistoricalMessageList = DefaultLifeCycle.defaultMessageListSolution,
this.messageWillSend = DefaultLifeCycle.defaultMessageSolution,
this.messageWillSend = DefaultLifeCycle.defaultTwoMessagesSolution,
this.modifiedMessageWillMount = DefaultLifeCycle.defaultMessageSolution,
this.newMessageWillMount = DefaultLifeCycle.defaultMessageSolution,
this.messageShouldMount = DefaultLifeCycle.defaultBooleanSolution,

View File

@ -17,7 +17,6 @@ import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.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';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
enum ConvType { none, c2c, group }
@ -504,6 +503,11 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
}
_onReceiveNewMsg(V2TimMessage msgComing) async {
final convID = TencentUtils.checkString(msgComing.userID) ?? msgComing.groupID;
if(convID != currentSelectedConv){
return;
}
final V2TimMessage? newMsg = _lifeCycle?.newMessageWillMount != null ? await _lifeCycle?.newMessageWillMount(msgComing) : msgComing;
if (newMsg == null) {
return;
@ -511,13 +515,12 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
// check the message is editing status msg. and flutter is only support the latest version
bool isEditMessage = _editStatusCheck(msgComing);
// if the message is edit status message dont up to screen
// if the message is edit status message don't up to screen
if (isEditMessage) {
return;
}
_checkFromUserisActive(msgComing);
final convID = TencentUtils.checkString(newMsg.userID) ?? newMsg.groupID;
final convType = TencentUtils.checkString(newMsg.groupID) != null ? ConvType.group : ConvType.c2c;
if (convID != null && convID == currentSelectedConv) {
final position = getMessageListPosition(convID);
@ -557,7 +560,8 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
}
}
} else if (convID != null) {
final currentMsg = _messageListMap[convID] ?? [];
final tempCurrentMsgList = _messageListMap[convID] ?? [];
final currentMsg = tempCurrentMsgList..sublist(max(0, (tempCurrentMsgList.length - 20)));
_messageListMap[convID] = [newMsg, ...currentMsg];
notifyListeners();
}
@ -641,6 +645,7 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
Future<void> onMessageDownloadProgressCallback(V2TimMessageDownloadProgress messageProgress) async {
final currentProgress = getMessageProgress(messageProgress.msgID);
print("onMessageDownloadProgressCallback, ${messageProgress.type} - ${messageProgress.isFinish} - ${messageProgress.currentSize} - $currentProgress - ");
if (messageProgress.isError || messageProgress.errorCode != 0) {
V2TimMessage? message = await _findAndRetrieveMessage(messageProgress.msgID);
@ -666,7 +671,7 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
if (message != null) {
bool isImageType = message.elemType == MessageElemType.V2TIM_ELEM_TYPE_IMAGE;
bool isVideoType = message.elemType == MessageElemType.V2TIM_ELEM_TYPE_VIDEO;
final originalImageType = PlatformUtils().isIOS ? 1 : 0;
const originalImageType = 0;
if (!isImageType && !isVideoType) {
_updateMessageLocationAndDownloadFile(messageProgress);
} else if ((isImageType && messageProgress.type == originalImageType) || (isVideoType && !messageProgress.isSnapshot)) {

View File

@ -119,9 +119,9 @@ class TUIConversationViewModel extends ChangeNotifier {
notifyListeners();
}, onSyncServerFinish: () {
// Remove the process to load such a many of conversations after launching
// if (!PlatformUtils().isWeb) {
// loadInitConversation();
// }
if (!PlatformUtils().isWeb) {
loadInitConversation();
}
});
}

View File

@ -95,9 +95,6 @@ class CoreServicesImpl implements CoreServices {
if (platform != null) {
TUIKitScreenUtils.deviceType = platform;
}
if (TencentUtils.checkString(uikitLogPath) != null) {
logOutputGenerator(uikitLogPath!);
}
addIdentifier();
if (extraLanguage != null) {
Future.delayed(const Duration(milliseconds: 1), () {

View File

@ -16,7 +16,8 @@ class MessageServiceImpl extends MessageService {
@override
Future<MessageListResponse> getHistoryMessageListV2({
HistoryMsgGetTypeEnum getType = HistoryMsgGetTypeEnum.V2TIM_GET_LOCAL_OLDER_MSG,
HistoryMsgGetTypeEnum getType =
HistoryMsgGetTypeEnum.V2TIM_GET_LOCAL_OLDER_MSG,
String? userID,
String? groupID,
int lastMsgSeq = -1,
@ -25,8 +26,16 @@ class MessageServiceImpl extends MessageService {
List<int>? messageTypeList,
}) async {
bool haveMoreData = true;
final res =
await TencentImSDKPlugin.v2TIMManager.getMessageManager().getHistoryMessageList(count: count, getType: getType, userID: userID, groupID: groupID, lastMsgID: lastMsgID, lastMsgSeq: lastMsgSeq, messageTypeList: messageTypeList);
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.getHistoryMessageList(
count: count,
getType: getType,
userID: userID,
groupID: groupID,
lastMsgID: lastMsgID,
lastMsgSeq: lastMsgSeq,
messageTypeList: messageTypeList);
final List<V2TimMessage> responseMessageList = res.data ?? [];
final conversationID = userID ?? groupID;
final cachedMessageList = messageListMap[conversationID];
@ -36,29 +45,41 @@ class MessageServiceImpl extends MessageService {
combinedMessageList = [...cachedMessageList, ...responseMessageList];
//
} else {
final bool existSendingMessage = sendingMessage[conversationID] != null && sendingMessage[conversationID]!.isNotEmpty;
final bool existSendingMessage = sendingMessage[conversationID] != null &&
sendingMessage[conversationID]!.isNotEmpty;
//
if (existSendingMessage) {
combinedMessageList = [...sendingMessage[conversationID]!, ...responseMessageList];
combinedMessageList = [
...sendingMessage[conversationID]!,
...responseMessageList
];
} else {
sendingMessage.remove(conversationID);
combinedMessageList = responseMessageList;
}
}
if (res.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
}
if (responseMessageList.isEmpty || (!PlatformUtils().isWeb && responseMessageList.length < count) || (PlatformUtils().isWeb && responseMessageList.length < min(count, 20))) {
if (responseMessageList.isEmpty ||
(!PlatformUtils().isWeb && responseMessageList.length < count) ||
(PlatformUtils().isWeb &&
responseMessageList.length < min(count, 20))) {
haveMoreData = false;
} else {
haveMoreData = true;
}
return MessageListResponse(haveMoreData: haveMoreData, data: combinedMessageList);
return MessageListResponse(
haveMoreData: haveMoreData, data: combinedMessageList);
}
@override
Future<List<V2TimMessage>> getHistoryMessageList({
HistoryMsgGetTypeEnum getType = HistoryMsgGetTypeEnum.V2TIM_GET_LOCAL_OLDER_MSG,
HistoryMsgGetTypeEnum getType =
HistoryMsgGetTypeEnum.V2TIM_GET_LOCAL_OLDER_MSG,
String? userID,
String? groupID,
int lastMsgSeq = -1,
@ -66,30 +87,53 @@ class MessageServiceImpl extends MessageService {
String? lastMsgID,
List<int>? messageTypeList,
}) async {
final res =
await TencentImSDKPlugin.v2TIMManager.getMessageManager().getHistoryMessageList(count: count, getType: getType, userID: userID, groupID: groupID, lastMsgID: lastMsgID, lastMsgSeq: lastMsgSeq, messageTypeList: messageTypeList);
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.getHistoryMessageList(
count: count,
getType: getType,
userID: userID,
groupID: groupID,
lastMsgID: lastMsgID,
lastMsgSeq: lastMsgSeq,
messageTypeList: messageTypeList);
final reponseMessageList = res.data ?? [];
if (res.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
}
return reponseMessageList;
}
@override
Future<V2TimMessageListResult?> getHistoryMessageListWithComplete({
HistoryMsgGetTypeEnum getType = HistoryMsgGetTypeEnum.V2TIM_GET_LOCAL_OLDER_MSG,
HistoryMsgGetTypeEnum getType =
HistoryMsgGetTypeEnum.V2TIM_GET_LOCAL_OLDER_MSG,
String? userID,
String? groupID,
int lastMsgSeq = -1,
int lastMsgSeq = 0,
required int count,
String? lastMsgID,
List<int>? messageTypeList,
}) async {
final res =
await TencentImSDKPlugin.v2TIMManager.getMessageManager().getHistoryMessageListV2(count: count, getType: getType, userID: userID, groupID: groupID, lastMsgID: lastMsgID, lastMsgSeq: lastMsgSeq, messageTypeList: messageTypeList);
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.getHistoryMessageListV2(
count: count,
getType: getType,
userID: userID,
groupID: groupID,
lastMsgID: lastMsgID,
lastMsgSeq: lastMsgSeq,
messageTypeList: messageTypeList);
final responseMessageList = res.data;
if (res.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
}
return responseMessageList;
}
@ -98,31 +142,45 @@ class MessageServiceImpl extends MessageService {
Future addSimpleMsgListener({
required V2TimSimpleMsgListener listener,
}) async {
return TencentImSDKPlugin.v2TIMManager.addSimpleMsgListener(listener: listener);
return TencentImSDKPlugin.v2TIMManager
.addSimpleMsgListener(listener: listener);
}
@override
Future<void> removeSimpleMsgListener({V2TimSimpleMsgListener? listener}) {
return TencentImSDKPlugin.v2TIMManager.removeSimpleMsgListener(listener: listener);
return TencentImSDKPlugin.v2TIMManager
.removeSimpleMsgListener(listener: listener);
}
@override
Future<void> addAdvancedMsgListener({
required V2TimAdvancedMsgListener listener,
}) {
return TencentImSDKPlugin.v2TIMManager.getMessageManager().addAdvancedMsgListener(listener: listener);
return TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.addAdvancedMsgListener(listener: listener);
}
@override
Future<V2TimValueCallback<V2TimGroupMessageReadMemberList>> getGroupMessageReadMemberList({
Future<V2TimValueCallback<V2TimGroupMessageReadMemberList>>
getGroupMessageReadMemberList({
required String messageID,
required GetGroupMessageReadMemberListFilter filter,
int nextSeq = 0,
int count = 100,
}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().getGroupMessageReadMemberList(messageID: messageID, filter: filter, nextSeq: nextSeq, count: count);
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.getGroupMessageReadMemberList(
messageID: messageID,
filter: filter,
nextSeq: nextSeq,
count: count);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@ -131,9 +189,14 @@ class MessageServiceImpl extends MessageService {
Future<V2TimValueCallback<List<V2TimMessageReceipt>>> getMessageReadReceipts({
required List<String> messageIDList,
}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().getMessageReadReceipts(messageIDList: messageIDList);
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.getMessageReadReceipts(messageIDList: messageIDList);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@ -142,43 +205,61 @@ class MessageServiceImpl extends MessageService {
Future<V2TimCallback> sendMessageReadReceipts({
required List<String> messageIDList,
}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().sendMessageReadReceipts(messageIDList: messageIDList);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
}
return result;
return _retryMarkMessageAsRead(action: (){
return TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.sendMessageReadReceipts(messageIDList: messageIDList);
});
}
@override
Future<V2TimMsgCreateInfoResult?> createTextMessage({required String text}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().createTextMessage(text: text);
Future<V2TimMsgCreateInfoResult?> createTextMessage(
{required String text}) async {
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.createTextMessage(text: text);
if (res.code == 0) {
final messageResult = res.data;
return messageResult;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@override
Future<V2TimMsgCreateInfoResult?> createCustomMessage({required String data}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().createCustomMessage(data: data);
Future<V2TimMsgCreateInfoResult?> createCustomMessage(
{required String data}) async {
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.createCustomMessage(data: data);
if (res.code == 0) {
final messageResult = res.data;
return messageResult;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@override
Future<V2TimMsgCreateInfoResult?> createFaceMessage({required int index, required String data}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().createFaceMessage(index: index, data: data);
Future<V2TimMsgCreateInfoResult?> createFaceMessage(
{required int index, required String data}) async {
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.createFaceMessage(index: index, data: data);
if (res.code == 0) {
final messageResult = res.data;
return messageResult;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@ -186,31 +267,51 @@ class MessageServiceImpl extends MessageService {
Future<V2TimValueCallback<V2TimMessage>> reSendMessage(
{required String msgID, // ID
bool? onlineUserOnly}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().reSendMessage(msgID: msgID, onlineUserOnly: onlineUserOnly ?? false);
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.reSendMessage(msgID: msgID, onlineUserOnly: onlineUserOnly ?? false);
if (res.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
}
return res;
}
@override
Future<V2TimMsgCreateInfoResult?> createTextAtMessage({required String text, required List<String> atUserList}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().createTextAtMessage(text: text, atUserList: atUserList);
Future<V2TimMsgCreateInfoResult?> createTextAtMessage(
{required String text, required List<String> atUserList}) async {
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.createTextAtMessage(text: text, atUserList: atUserList);
if (res.code == 0) {
final messageResult = res.data;
return messageResult;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@override
Future<V2TimMsgCreateInfoResult?> createImageMessage({String? imageName, String? imagePath, dynamic inputElement}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().createImageMessage(imageName: imageName, imagePath: imagePath ?? "", inputElement: inputElement);
Future<V2TimMsgCreateInfoResult?> createImageMessage(
{String? imageName, String? imagePath, dynamic inputElement}) async {
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.createImageMessage(
imageName: imageName,
imagePath: imagePath ?? "",
inputElement: inputElement);
if (res.code == 0) {
return res.data;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@ -219,11 +320,16 @@ class MessageServiceImpl extends MessageService {
required String soundPath,
required int duration,
}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().createSoundMessage(soundPath: soundPath, duration: duration);
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.createSoundMessage(soundPath: soundPath, duration: duration);
if (res.code == 0) {
return res.data;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@ -240,7 +346,8 @@ class MessageServiceImpl extends MessageService {
String? cloudCustomData,
String? localCustomData,
}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().sendMessage(
final result =
await TencentImSDKPlugin.v2TIMManager.getMessageManager().sendMessage(
id: id,
receiver: receiver,
groupID: groupID,
@ -252,7 +359,10 @@ class MessageServiceImpl extends MessageService {
cloudCustomData: cloudCustomData,
);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@ -264,22 +374,36 @@ class MessageServiceImpl extends MessageService {
}) async {
V2TimCallback result;
if (kIsWeb) {
result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().deleteMessages(msgIDs: [], webMessageInstanceList: [webMessageInstance]);
result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.deleteMessages(
msgIDs: [], webMessageInstanceList: [webMessageInstance]);
} else {
result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().deleteMessageFromLocalStorage(msgID: msgID);
result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.deleteMessageFromLocalStorage(msgID: msgID);
}
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@override
Future<V2TimCallback> revokeMessage({required String msgID, Object? webMessageInstance}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().revokeMessage(msgID: msgID, webMessageInstatnce: webMessageInstance);
Future<V2TimCallback> revokeMessage(
{required String msgID, Object? webMessageInstance}) async {
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.revokeMessage(msgID: msgID, webMessageInstatnce: webMessageInstance);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@ -288,9 +412,14 @@ class MessageServiceImpl extends MessageService {
Future<V2TimCallback> clearC2CHistoryMessage({
required String userID,
}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().clearC2CHistoryMessage(userID: userID);
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.clearC2CHistoryMessage(userID: userID);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@ -299,38 +428,77 @@ class MessageServiceImpl extends MessageService {
Future<V2TimCallback> clearGroupHistoryMessage({
required String groupID,
}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().clearGroupHistoryMessage(groupID: groupID);
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.clearGroupHistoryMessage(groupID: groupID);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
Future<V2TimCallback> _retryMarkMessageAsRead({
required Future<V2TimCallback> Function() action,
int retries = 3,
}) async {
V2TimCallback result;
int attempts = 0;
do {
result = await action();
if (result.code == 0) {
return result;
}
attempts++;
await Future.delayed(const Duration(milliseconds: 500));
} while (attempts < retries);
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
return result;
}
@override
Future<V2TimCallback> markC2CMessageAsRead({
required String userID,
}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().markC2CMessageAsRead(userID: userID);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
}
return result;
}) {
return _retryMarkMessageAsRead(action: () {
return TencentImSDKPlugin.v2TIMManager
.getConversationManager()
.cleanConversationUnreadMessageCount(
conversationID: "c2c_$userID",
cleanTimestamp: 0,
cleanSequence: 0,
);
});
}
@override
Future<V2TimCallback> markGroupMessageAsRead({
required String groupID,
}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().markGroupMessageAsRead(groupID: groupID);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
}
return result;
}) {
return _retryMarkMessageAsRead(action: () {
return TencentImSDKPlugin.v2TIMManager
.getConversationManager()
.cleanConversationUnreadMessageCount(
conversationID: "group_$groupID",
cleanTimestamp: 0,
cleanSequence: 0,
);
});
}
@override
Future<void> removeAdvancedMsgListener({V2TimAdvancedMsgListener? listener}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().removeAdvancedMsgListener(listener: listener);
Future<void> removeAdvancedMsgListener(
{V2TimAdvancedMsgListener? listener}) async {
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.removeAdvancedMsgListener(listener: listener);
return result;
}
@ -338,11 +506,16 @@ class MessageServiceImpl extends MessageService {
Future<List<V2TimMessage>?> downloadMergerMessage({
required String msgID,
}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().downloadMergerMessage(msgID: msgID);
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.downloadMergerMessage(msgID: msgID);
if (res.code == 0) {
return res.data;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@ -350,11 +523,16 @@ class MessageServiceImpl extends MessageService {
Future<V2TimMsgCreateInfoResult?> createForwardMessage({
required String msgID,
}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().createForwardMessage(msgID: msgID);
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.createForwardMessage(msgID: msgID);
if (res.code == 0) {
return res.data;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@ -365,30 +543,62 @@ class MessageServiceImpl extends MessageService {
required List<String> abstractList,
required String compatibleText,
}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().createMergerMessage(msgIDList: msgIDList, title: title, abstractList: abstractList, compatibleText: compatibleText);
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.createMergerMessage(
msgIDList: msgIDList,
title: title,
abstractList: abstractList,
compatibleText: compatibleText);
if (res.code == 0) {
return res.data;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@override
Future<V2TimCallback> deleteMessages({required List<String> msgIDs, List<dynamic>? webMessageInstanceList}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().deleteMessages(msgIDs: msgIDs, webMessageInstanceList: webMessageInstanceList);
Future<V2TimCallback> deleteMessages(
{required List<String> msgIDs,
List<dynamic>? webMessageInstanceList}) async {
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.deleteMessages(
msgIDs: msgIDs, webMessageInstanceList: webMessageInstanceList);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@override
Future<V2TimMsgCreateInfoResult?> createVideoMessage({String? videoPath, String? type, int? duration, String? snapshotPath, dynamic inputElement}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().createVideoMessage(videoFilePath: videoPath ?? "", type: type ?? "", duration: duration ?? 1, snapshotPath: snapshotPath ?? "", inputElement: inputElement);
Future<V2TimMsgCreateInfoResult?> createVideoMessage(
{String? videoPath,
String? type,
int? duration,
String? snapshotPath,
dynamic inputElement}) async {
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.createVideoMessage(
videoFilePath: videoPath ?? "",
type: type ?? "",
duration: duration ?? 1,
snapshotPath: snapshotPath ?? "",
inputElement: inputElement);
if (res.code == 0) {
return res.data;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@ -401,38 +611,75 @@ class MessageServiceImpl extends MessageService {
bool needReadReceipt = false,
required V2TimMessage replyMessage, //
}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().sendReplyMessage(id: id, receiver: receiver, offlinePushInfo: offlinePushInfo, groupID: groupID, needReadReceipt: needReadReceipt, replyMessage: replyMessage);
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.sendReplyMessage(
id: id,
receiver: receiver,
offlinePushInfo: offlinePushInfo,
groupID: groupID,
needReadReceipt: needReadReceipt,
replyMessage: replyMessage);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@override
Future<V2TimMsgCreateInfoResult?> createFileMessage({String? filePath, required String fileName, dynamic inputElement}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().createFileMessage(filePath: filePath ?? "", fileName: fileName, inputElement: inputElement);
Future<V2TimMsgCreateInfoResult?> createFileMessage(
{String? filePath,
required String fileName,
dynamic inputElement}) async {
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.createFileMessage(
filePath: filePath ?? "",
fileName: fileName,
inputElement: inputElement);
if (res.code == 0) {
return res.data;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@override
Future<V2TimMsgCreateInfoResult?> createLocationMessage({required String desc, required double longitude, required double latitude}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().createLocationMessage(desc: desc, longitude: longitude, latitude: latitude);
Future<V2TimMsgCreateInfoResult?> createLocationMessage(
{required String desc,
required double longitude,
required double latitude}) async {
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.createLocationMessage(
desc: desc, longitude: longitude, latitude: latitude);
if (res.code == 0) {
return res.data;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@override
Future<V2TimValueCallback<V2TimMessageSearchResult>> searchLocalMessages({required V2TimMessageSearchParam searchParam}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().searchLocalMessages(searchParam: searchParam);
Future<V2TimValueCallback<V2TimMessageSearchResult>> searchLocalMessages(
{required V2TimMessageSearchParam searchParam}) async {
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.searchLocalMessages(searchParam: searchParam);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@ -441,19 +688,30 @@ class MessageServiceImpl extends MessageService {
Future<List<V2TimMessage>?> findMessages({
required List<String> messageIDList,
}) async {
final res = await TencentImSDKPlugin.v2TIMManager.getMessageManager().findMessages(messageIDList: messageIDList);
final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.findMessages(messageIDList: messageIDList);
if (res.code == 0) {
return res.data;
}
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: res.desc, errorCode: res.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: res.desc,
errorCode: res.code));
return null;
}
@override
Future<V2TimCallback> setLocalCustomInt({required String msgID, required int localCustomInt}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().setLocalCustomInt(msgID: msgID, localCustomInt: localCustomInt);
Future<V2TimCallback> setLocalCustomInt(
{required String msgID, required int localCustomInt}) async {
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.setLocalCustomInt(msgID: msgID, localCustomInt: localCustomInt);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@ -463,9 +721,14 @@ class MessageServiceImpl extends MessageService {
required List<String> userIDList,
required ReceiveMsgOptEnum opt,
}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().setC2CReceiveMessageOpt(userIDList: userIDList, opt: opt);
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.setC2CReceiveMessageOpt(userIDList: userIDList, opt: opt);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@ -475,55 +738,96 @@ class MessageServiceImpl extends MessageService {
required String groupID,
required ReceiveMsgOptEnum opt,
}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().setGroupReceiveMessageOpt(groupID: groupID, opt: opt);
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.setGroupReceiveMessageOpt(groupID: groupID, opt: opt);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@override
Future<V2TimValueCallback<V2TimMessageChangeInfo>> modifyMessage({required V2TimMessage message}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().modifyMessage(message: message);
Future<V2TimValueCallback<V2TimMessageChangeInfo>> modifyMessage(
{required V2TimMessage message}) async {
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.modifyMessage(message: message);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@override
Future<V2TimCallback> setLocalCustomData({required String msgID, required String localCustomData}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().setLocalCustomData(msgID: msgID, localCustomData: localCustomData);
Future<V2TimCallback> setLocalCustomData(
{required String msgID, required String localCustomData}) async {
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.setLocalCustomData(msgID: msgID, localCustomData: localCustomData);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@override
Future<V2TimValueCallback<V2TimMessageOnlineUrl>> getMessageOnlineUrl({required String msgID}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().getMessageOnlineUrl(msgID: msgID);
Future<V2TimValueCallback<V2TimMessageOnlineUrl>> getMessageOnlineUrl(
{required String msgID}) async {
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.getMessageOnlineUrl(msgID: msgID);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@override
Future<V2TimCallback> downloadMessage({required String msgID, required int messageType, required int imageType, required bool isSnapshot}) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().downloadMessage(msgID: msgID, messageType: messageType, imageType: imageType, isSnapshot: isSnapshot);
Future<V2TimCallback> downloadMessage(
{required String msgID,
required int messageType,
required int imageType,
required bool isSnapshot}) async {
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.downloadMessage(
msgID: msgID,
messageType: messageType,
imageType: imageType,
isSnapshot: isSnapshot);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result;
}
@override
Future<String> translateText(String text, String target) async {
final result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().translateText(texts: [text], targetLanguage: target);
final result = await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.translateText(texts: [text], targetLanguage: target);
if (result.code != 0) {
_coreService.callOnCallback(TIMCallback(type: TIMCallbackType.API_ERROR, errorMsg: result.desc, errorCode: result.code));
_coreService.callOnCallback(TIMCallback(
type: TIMCallbackType.API_ERROR,
errorMsg: result.desc,
errorCode: result.code));
}
return result.data?[text] ?? "";
}

View File

@ -1,107 +1,15 @@
import 'dart:convert';
import 'dart:io';
import 'package:logger/logger.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path/path.dart' as p;
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
final outputLogger = Logger(
output: _outputLogger ?? logOutputGenerator(null),
);
final outputLogger = TencentCloudChatLog();
TUIKitOutput? _outputLogger;
TUIKitOutput logOutputGenerator(String? path) {
_outputLogger = TUIKitOutput(path);
return _outputLogger!;
}
class TUIKitOutput extends LogOutput {
Future<void> createDirectoryIfNotExists(String path) async {
final directory = Directory(p.dirname(path));
if (await directory.exists() == false) {
await directory.create(recursive: true);
}
}
Future<void> deleteFilesOlderThanDays(String directoryPath, int days) async {
final directory = Directory(directoryPath);
final threshold = DateTime.now().subtract(Duration(days: days));
await for (var fileEntity in directory.list(followLinks: false)) {
if (fileEntity is File) {
final lastModified = await fileEntity.lastModified();
if (lastModified.isBefore(threshold)) {
await fileEntity.delete();
}
}
}
}
Future<String> getPlatformLogPath({String? path}) async {
if (TencentUtils.checkString(path) != null) {
print("The path to local log: $path");
return path!;
}
final String documentsDirectoryPath =
"${Platform.environment['USERPROFILE']}";
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String pkgName = packageInfo.packageName;
var timeName =
"${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}";
final logPath = p.join(documentsDirectoryPath, "Documents", ".TencentCloudChat",
pkgName, "uikit_log", 'Flutter-TUIKit-$timeName.log');
print("The path to local log: $logPath");
return logPath;
}
File? logFile;
TUIKitOutput(String? path) {
if (!PlatformUtils().isWeb) {
getPlatformLogPath(path: path).then((logFilePath) async {
await createDirectoryIfNotExists(logFilePath);
deleteFilesOlderThanDays(p.dirname(logFilePath), 7);
logFile = File(logFilePath);
if (logFile != null) {
if (!logFile!.existsSync()) {
logFile!.createSync(recursive: true);
}
}
});
}
}
@override
void output(OutputEvent event) {
var msg = "\n";
for (var line in event.lines) {
msg += "$line \n";
}
if (!PlatformUtils().isWeb) {
if (logFile != null) {
final sink = logFile!.openWrite(
mode: FileMode.append,
encoding: const SystemEncoding(),
);
sink.write(utf8.decode(utf8.encode(msg)));
sink.close();
} else {
Future.delayed(const Duration(seconds: 1)).then((value) {
if (logFile != null) {
final sink = logFile!.openWrite(
mode: FileMode.append,
encoding: const SystemEncoding(),
);
sink.write(msg);
sink.close();
}
});
}
class TencentCloudChatLog{
void i(String text){
if(!PlatformUtils().isWeb){
TencentImSDKPlugin.v2TIMManager
.uikitTrace(trace: text);
}
}
}

View File

@ -32,11 +32,13 @@ class SoundPlayer {
_soundInterruptListener!();
}
await _audioPlayer.setUrl(url);
await _audioPlayer.play();
}
static stop() {
_audioPlayer.stop();
}
static dispose() {

View File

@ -1,19 +1,18 @@
import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';
import 'package:scroll_to_index/scroll_to_index.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';
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/base_widgets/tim_ui_kit_base.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 {
final Widget Function(void Function(), MessageListTongueType, int)?
tongueItemBuilder;
final Widget Function(void Function(), MessageListTongueType, int)? tongueItemBuilder;
final List<V2TimGroupAtInfo?>? groupAtInfoList;
final Function(String targetSeq) scrollToIndexBySeq;
final AutoScrollController scrollController;
@ -31,12 +30,10 @@ class TIMUIKitHistoryMessageListTongueContainer extends StatefulWidget {
}) : super(key: key);
@override
State<StatefulWidget> createState() =>
_TIMUIKitHistoryMessageListTongueContainerState();
State<StatefulWidget> createState() => _TIMUIKitHistoryMessageListTongueContainerState();
}
class _TIMUIKitHistoryMessageListTongueContainerState
extends TIMUIKitState<TIMUIKitHistoryMessageListTongueContainer> {
class _TIMUIKitHistoryMessageListTongueContainerState extends TIMUIKitState<TIMUIKitHistoryMessageListTongueContainer> {
bool isFinishJumpToAt = false;
List<V2TimGroupAtInfo?>? groupAtInfoList = [];
final TUIChatGlobalModel globalModel = serviceLocator<TUIChatGlobalModel>();
@ -50,10 +47,8 @@ class _TIMUIKitHistoryMessageListTongueContainerState
}
void changePositionState(HistoryMessagePosition newPosition) {
if (globalModel.getMessageListPosition(widget.model.conversationID) !=
newPosition) {
globalModel.setMessageListPosition(
widget.model.conversationID, newPosition);
if (globalModel.getMessageListPosition(widget.model.conversationID) != newPosition) {
globalModel.setMessageListPosition(widget.model.conversationID, newPosition);
}
}
@ -64,19 +59,11 @@ class _TIMUIKitHistoryMessageListTongueContainerState
if (offset <= 0.0 && conversationUnreadCount != 0) {
widget.model.showLatestUnread();
}
if (widget.scrollController.offset <=
widget.scrollController.position.minScrollExtent &&
!widget.scrollController.position.outOfRange &&
!widget.model.haveMoreLatestData) {
if (widget.scrollController.offset <= widget.scrollController.position.minScrollExtent && !widget.scrollController.position.outOfRange && !widget.model.haveMoreLatestData) {
changePositionState(HistoryMessagePosition.bottom);
} else if (widget.scrollController.offset <= screenHeight * 1.6 &&
widget.scrollController.offset > 0 &&
!widget.scrollController.position.outOfRange &&
!widget.model.haveMoreLatestData) {
} else if (widget.scrollController.offset <= screenHeight * 1.6 && widget.scrollController.offset > 0 && !widget.scrollController.position.outOfRange && !widget.model.haveMoreLatestData) {
changePositionState(HistoryMessagePosition.inTwoScreen);
} else if (widget.scrollController.offset > screenHeight * 1.6 &&
!widget.scrollController.position.outOfRange &&
!widget.model.haveMoreLatestData) {
} else if (widget.scrollController.offset > screenHeight * 1.6 && !widget.scrollController.position.outOfRange && !widget.model.haveMoreLatestData) {
changePositionState(HistoryMessagePosition.awayTwoScreen);
}
}
@ -85,15 +72,11 @@ class _TIMUIKitHistoryMessageListTongueContainerState
widget.scrollController.addListener(scrollHandler);
}
MessageListTongueType _getTongueValueType(
List<V2TimGroupAtInfo?>? groupAtInfoList) {
if (globalModel.getMessageListPosition(widget.model.conversationID) ==
HistoryMessagePosition.notShowLatest) {
MessageListTongueType _getTongueValueType(List<V2TimGroupAtInfo?>? groupAtInfoList) {
if (globalModel.getMessageListPosition(widget.model.conversationID) == HistoryMessagePosition.notShowLatest) {
return MessageListTongueType.none;
}
if (groupAtInfoList != null &&
groupAtInfoList.isNotEmpty &&
!isFinishJumpToAt) {
if (groupAtInfoList != null && groupAtInfoList.isNotEmpty && !isFinishJumpToAt) {
if (groupAtInfoList[0]!.atType == 1) {
return MessageListTongueType.atMe;
} else {
@ -109,8 +92,7 @@ class _TIMUIKitHistoryMessageListTongueContainerState
return MessageListTongueType.showUnread;
}
if (globalModel.getMessageListPosition(widget.model.conversationID) ==
HistoryMessagePosition.awayTwoScreen) {
if (globalModel.getMessageListPosition(widget.model.conversationID) == HistoryMessagePosition.awayTwoScreen) {
return MessageListTongueType.toLatest;
}
@ -128,14 +110,8 @@ class _TIMUIKitHistoryMessageListTongueContainerState
return Selector<TUIChatGlobalModel, Tuple2<HistoryMessagePosition, int>>(
builder: (context, value, child) {
return Positioned(
bottom: _getTongueValueType(groupAtInfoList) !=
MessageListTongueType.showPrevious
? 16
: null,
top: _getTongueValueType(groupAtInfoList) ==
MessageListTongueType.showPrevious
? 16
: null,
bottom: _getTongueValueType(groupAtInfoList) != MessageListTongueType.showPrevious ? 16 : null,
top: _getTongueValueType(groupAtInfoList) == MessageListTongueType.showPrevious ? 16 : null,
right: 16,
child: TIMUIKitHistoryMessageListTongue(
previousCount: widget.conversation.unreadCount ?? 0,
@ -153,29 +129,24 @@ class _TIMUIKitHistoryMessageListTongueContainerState
} else {
widget.scrollToIndexBySeq(groupAtInfoList!.removeAt(0)!.seq);
}
} else if ((widget.conversation.unreadCount ?? 0) > 20 &&
!isClickShowPrevious) {
} else if ((widget.conversation.unreadCount ?? 0) > 20 && !isClickShowPrevious) {
try {
isClickShowPrevious = true;
final String? lastSeqString =
widget.conversation.lastMessage?.seq;
final int? lastSeq =
TencentUtils.checkString(lastSeqString) != null
? int.parse(lastSeqString!)
: null;
final String? lastSeqString = widget.conversation.lastMessage?.seq;
final int? lastSeq = TencentUtils.checkString(lastSeqString) != null ? int.parse(lastSeqString!) : null;
final int? previousCount = widget.conversation.unreadCount;
if (lastSeq != null && previousCount != null) {
final targetSeq = lastSeq - previousCount;
await widget.model
.loadListForSpecificMessage(seq: targetSeq);
// widget.scrollToIndexBySeq((targetSeq + 1).toString());
await widget.model.loadListForSpecificMessage(seq: targetSeq);
// Future.delayed(const Duration(milliseconds: 100), () {
// widget.scrollToIndexBySeq((targetSeq).toString());
// });
}
} catch (e) {
// TODO:
}
// widget.model.loadListForSpecificMessage(seq: count);
} else if (value.item1 == HistoryMessagePosition.awayTwoScreen ||
globalModel.unreadCountForConversation > 0) {
} else if (value.item1 == HistoryMessagePosition.awayTwoScreen || globalModel.unreadCountForConversation > 0) {
widget.model.showLatestUnread();
widget.scrollController.animateTo(
widget.scrollController.position.minScrollExtent,
@ -191,8 +162,7 @@ class _TIMUIKitHistoryMessageListTongueContainerState
);
},
selector: (c, model) {
final mesageListPosition =
model.getMessageListPosition(widget.model.conversationID);
final mesageListPosition = model.getMessageListPosition(widget.model.conversationID);
final unreadCountForConversation = model.unreadCountForConversation;
return Tuple2(mesageListPosition, unreadCountForConversation);
},

View File

@ -646,7 +646,7 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
alignment: Alignment.center,
margin: const EdgeInsets.symmetric(vertical: 20),
child: Text(
model.chatConfig.timeDividerConfig?.timestampParser != null ? (model.chatConfig.timeDividerConfig?.timestampParser!(timeStamp))! : TimeAgo().getTimeForMessage(1709740800),
model.chatConfig.timeDividerConfig?.timestampParser != null ? (model.chatConfig.timeDividerConfig?.timestampParser!(timeStamp))! : TimeAgo().getTimeForMessage(timeStamp),
style: widget.themeData?.timelineTextStyle ??
TextStyle(
fontSize: 12,

View File

@ -213,6 +213,9 @@ class TIMUIKitMessageTooltipState
widget.message.elemType == MessageElemType.V2TIM_ELEM_TYPE_IMAGE &&
fileBeenDownloaded);
final dynamicQuote =
model.chatConfig.isAtWhenReplyDynamic?.call(widget.message);
final List<MessageToolTipItem> defaultTipsList = [
if (fileBeenDownloaded)
MessageToolTipItem(
@ -240,7 +243,8 @@ class TIMUIKitMessageTooltipState
onClick: () => _onTap("forwardMessage", model)),
if (shouldShowReplyAction)
MessageToolTipItem(
label: TIM_t(model.chatConfig.isAtWhenReply ? "回复" : "引用"),
label: TIM_t(
(dynamicQuote ?? model.chatConfig.isAtWhenReply) ? "回复" : "引用"),
id: "replyMessage",
iconImageAsset: "images/reply_message.png",
onClick: () => _onTap("replyMessage", model)),
@ -510,12 +514,14 @@ class TIMUIKitMessageTooltipState
break;
case "replyMessage":
model.repliedMessage = widget.message;
final dynamicQuote =
model.chatConfig.isAtWhenReplyDynamic?.call(widget.message);
final isSelf = widget.message.isSelf ?? true;
final isGroup =
TencentUtils.checkString(widget.message.groupID) != null;
final isAtWhenReply = !isSelf &&
isGroup &&
widget.allowAtUserWhenReply &&
(dynamicQuote ?? widget.allowAtUserWhenReply) &&
widget.onLongPressForOthersHeadPortrait != null;
/// If replying to a self message, do not add a at tag, only requestFocus.

View File

@ -32,7 +32,16 @@ class TIMUIKitFileElem extends StatefulWidget {
final bool? isShowMessageReaction;
final TUIChatSeparateViewModel chatModel;
const TIMUIKitFileElem({Key? key, required this.chatModel, required this.messageID, required this.fileElem, required this.isSelf, required this.isShowJump, this.clearJump, required this.message, this.isShowMessageReaction})
const TIMUIKitFileElem(
{Key? key,
required this.chatModel,
required this.messageID,
required this.fileElem,
required this.isSelf,
required this.isShowJump,
this.clearJump,
required this.message,
this.isShowMessageReaction})
: super(key: key);
@override
@ -44,14 +53,19 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
bool isWebDownloading = false;
final TUIChatGlobalModel model = serviceLocator<TUIChatGlobalModel>();
int downloadProgress = 0;
late V2TimAdvancedMsgListener advancedMsgListener;
V2TimAdvancedMsgListener? advancedMsgListener;
final GlobalKey containerKey = GlobalKey();
double? containerHeight;
bool? _downloadFailed = false;
@override
void dispose() {
TencentImSDKPlugin.v2TIMManager.getMessageManager().removeAdvancedMsgListener(listener: advancedMsgListener);
if (advancedMsgListener != null) {
TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.removeAdvancedMsgListener(listener: advancedMsgListener);
advancedMsgListener = null;
}
super.dispose();
}
@ -63,8 +77,15 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
hasFile();
});
}
}
Future<bool> addAdvancedMsgListenerForDownload() async {
if(advancedMsgListener != null){
return false;
}
advancedMsgListener = V2TimAdvancedMsgListener(
onMessageDownloadProgressCallback: (V2TimMessageDownloadProgress messageProgress) async {
onMessageDownloadProgressCallback:
(V2TimMessageDownloadProgress messageProgress) async {
if (messageProgress.msgID == widget.message.msgID) {
if (messageProgress.isError || messageProgress.errorCode != 0) {
setState(() {
@ -79,12 +100,17 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
downloadProgress = 100;
});
TencentImSDKPlugin.v2TIMManager.getMessageManager().removeAdvancedMsgListener(
listener: advancedMsgListener,
);
if (advancedMsgListener != null) {
TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.removeAdvancedMsgListener(listener: advancedMsgListener);
advancedMsgListener = null;
}
}
} else {
final currentProgress = (messageProgress.currentSize / messageProgress.totalSize * 100).floor();
final currentProgress =
(messageProgress.currentSize / messageProgress.totalSize * 100)
.floor();
if (mounted && currentProgress > downloadProgress) {
setState(() {
downloadProgress = currentProgress;
@ -94,11 +120,17 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
}
},
);
TencentImSDKPlugin.v2TIMManager.getMessageManager().addAdvancedMsgListener(listener: advancedMsgListener);
await TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.addAdvancedMsgListener(listener: advancedMsgListener!);
return true;
}
Future<String> getSavePath() async {
String savePathWithAppPath = '/storage/emulated/0/Android/data/com.tencent.flutter.tuikit/cache/' + (widget.message.msgID ?? "") + widget.fileElem!.fileName!;
String savePathWithAppPath =
'/storage/emulated/0/Android/data/com.tencent.flutter.tuikit/cache/' +
(widget.message.msgID ?? "") +
widget.fileElem!.fileName!;
return savePathWithAppPath;
}
@ -106,7 +138,11 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
if (PlatformUtils().isWeb) {
return true;
}
String savePath = TencentUtils.checkString(model.getFileMessageLocation(widget.messageID)) ?? TencentUtils.checkString(widget.message.fileElem!.localUrl) ?? widget.message.fileElem?.path ?? '';
String savePath = TencentUtils.checkString(
model.getFileMessageLocation(widget.messageID)) ??
TencentUtils.checkString(widget.message.fileElem!.localUrl) ??
widget.message.fileElem?.path ??
'';
File f = File(savePath);
if (f.existsSync() && widget.messageID != null) {
filePath = savePath;
@ -118,6 +154,12 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
if (model.getMessageProgress(widget.messageID) != 100) {
model.setMessageProgress(widget.messageID!, 100);
}
if (advancedMsgListener != null) {
TencentImSDKPlugin.v2TIMManager
.getMessageManager()
.removeAdvancedMsgListener(listener: advancedMsgListener);
advancedMsgListener = null;
}
return true;
}
return false;
@ -159,7 +201,8 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
downloadFile(TUITheme theme) async {
if (PlatformUtils().isMobile) {
if (PlatformUtils().isIOS) {
if (!await Permissions.checkPermission(context, Permission.photosAddOnly.value, theme, false)) {
if (!await Permissions.checkPermission(
context, Permission.photosAddOnly.value, theme, false)) {
return;
}
} else {
@ -191,13 +234,18 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
}
tryOpenFile(context, theme) async {
if (!PlatformUtils().isWeb && (await hasZeroSize(filePath) || widget.message.status == 3)) {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: "不支持 0KB 文件的传输", infoCode: 6660417));
if (!PlatformUtils().isWeb &&
(await hasZeroSize(filePath) || widget.message.status == 3)) {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: "不支持 0KB 文件的传输",
infoCode: 6660417));
return;
}
if (PlatformUtils().isMobile) {
if (PlatformUtils().isIOS) {
if (!await Permissions.checkPermission(context, Permission.photosAddOnly.value, theme!, false)) {
if (!await Permissions.checkPermission(
context, Permission.photosAddOnly.value, theme!, false)) {
return;
}
} else {
@ -241,7 +289,8 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
);
final html.AnchorElement downloadAnchor = html.document.createElement('a') as html.AnchorElement;
final html.AnchorElement downloadAnchor =
html.document.createElement('a') as html.AnchorElement;
final html.Blob blob = html.Blob([response.bodyBytes]);
@ -253,7 +302,8 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
html.AnchorElement(
href: widget.fileElem?.path ?? "",
)
..setAttribute("download", widget.message.fileElem?.fileName ?? fileName)
..setAttribute(
"download", widget.message.fileElem?.fileName ?? fileName)
..setAttribute("target", '_blank')
..style.display = "none"
..click();
@ -272,14 +322,24 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
final fileName = widget.fileElem!.fileName ?? "";
final fileSize = widget.fileElem!.fileSize;
final borderRadius = widget.isSelf
? const BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(2), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10))
: const BorderRadius.only(topLeft: Radius.circular(2), topRight: Radius.circular(10), bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10));
? const BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(2),
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10))
: const BorderRadius.only(
topLeft: Radius.circular(2),
topRight: Radius.circular(10),
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10));
String? fileFormat;
if (widget.fileElem?.fileName != null && widget.fileElem!.fileName!.isNotEmpty) {
if (widget.fileElem?.fileName != null &&
widget.fileElem!.fileName!.isNotEmpty) {
final String fileName = widget.fileElem!.fileName!;
fileFormat = fileName.split(".")[max(fileName.split(".").length - 1, 0)];
}
final RenderBox? containerRenderBox = containerKey.currentContext?.findRenderObject() as RenderBox?;
final RenderBox? containerRenderBox =
containerKey.currentContext?.findRenderObject() as RenderBox?;
if (containerRenderBox != null) {
containerHeight = containerRenderBox.size.height;
}
@ -312,6 +372,8 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
}
return;
}
await addAdvancedMsgListenerForDownload();
if (await hasFile()) {
if (received == 100) {
tryOpenFile(context, theme);
@ -328,14 +390,20 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
}
if (checkIsWaiting()) {
onTIMCallback(
TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("已加入待下载队列,其他文件下载中"), infoCode: 6660413),
TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("已加入待下载队列,其他文件下载中"),
infoCode: 6660413),
);
return;
} else {
await addUrlToWaitingPath(theme);
}
} catch (e) {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: "文件处理异常", infoCode: 6660416));
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: "文件处理异常",
infoCode: 6660416));
}
},
child: ConstrainedBox(
@ -344,7 +412,8 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
width: 237,
decoration: BoxDecoration(
border: Border.all(
color: theme.weakDividerColor ?? CommonColor.weakDividerColor,
color: theme.weakDividerColor ??
CommonColor.weakDividerColor,
),
borderRadius: borderRadius),
child: Stack(children: [
@ -353,19 +422,28 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
child: LinearProgressIndicator(
minHeight: ((containerHeight) ?? 72) - 6,
value: (received == 100 ? 0 : received) / 100,
backgroundColor: received == 100 ? theme.weakBackgroundColor : Colors.white,
valueColor: AlwaysStoppedAnimation(theme.lightPrimaryMaterialColor.shade50),
backgroundColor: received == 100
? theme.weakBackgroundColor
: Colors.white,
valueColor: AlwaysStoppedAnimation(
theme.lightPrimaryMaterialColor.shade50),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
child: Row(mainAxisAlignment: widget.isSelf ? MainAxisAlignment.end : MainAxisAlignment.start, children: [
padding: const EdgeInsets.symmetric(
vertical: 8, horizontal: 12),
child: Row(
mainAxisAlignment: widget.isSelf
? MainAxisAlignment.end
: MainAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
constraints: const BoxConstraints(maxWidth: 160),
constraints:
const BoxConstraints(maxWidth: 160),
child: LayoutBuilder(
builder: (buildContext, boxConstraints) {
return CustomText(
@ -383,7 +461,9 @@ class _TIMUIKitFileElemState extends TIMUIKitState<TIMUIKitFileElem> {
if (fileSize != null)
Text(
showFileSize(fileSize),
style: TextStyle(fontSize: 14, color: theme.weakTextColor),
style: TextStyle(
fontSize: 14,
color: theme.weakTextColor),
)
],
)),

View File

@ -45,7 +45,15 @@ class TIMUIKitImageElem extends StatefulWidget {
final bool? isShowMessageReaction;
final TUIChatSeparateViewModel chatModel;
const TIMUIKitImageElem({required this.message, this.isShowJump = false, required this.chatModel, this.clearJump, this.isFrom, Key? key, this.isShowMessageReaction}) : super(key: key);
const TIMUIKitImageElem(
{required this.message,
this.isShowJump = false,
required this.chatModel,
this.clearJump,
this.isFrom,
Key? key,
this.isShowMessageReaction})
: super(key: key);
@override
State<StatefulWidget> createState() => _TIMUIKitImageElem();
@ -65,7 +73,9 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
String getOriginImgURL() {
//
V2TimImage? img = MessageUtils.getImageFromImgList(widget.message.imageElem!.imageList, HistoryMessageDartConstant.oriImgPrior);
V2TimImage? img = MessageUtils.getImageFromImgList(
widget.message.imageElem!.imageList,
HistoryMessageDartConstant.oriImgPrior);
return img == null ? widget.message.imageElem!.path! : img.url!;
}
@ -114,7 +124,8 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
final http.Response r = await http.get(Uri.parse(imageUrl));
final data = r.bodyBytes;
final base64data = base64Encode(data);
final a = html.AnchorElement(href: 'data:image/jpeg;base64,$base64data');
final a =
html.AnchorElement(href: 'data:image/jpeg;base64,$base64data');
a.download = md5.convert(utf8.encode(imageUrl)).toString();
a.click();
a.remove();
@ -125,7 +136,8 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
}
if (PlatformUtils().isIOS) {
if (!await Permissions.checkPermission(context, Permission.photosAddOnly.value, theme!, false)) {
if (!await Permissions.checkPermission(
context, Permission.photosAddOnly.value, theme!, false)) {
return;
}
} else {
@ -160,7 +172,8 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
if (model.getMessageProgress(widget.message.msgID) == 100) {
String savePath;
if (widget.message.imageElem!.path != null && widget.message.imageElem!.path != '') {
if (widget.message.imageElem!.path != null &&
widget.message.imageElem!.path != '') {
savePath = widget.message.imageElem!.path!;
} else {
savePath = model.getFileMessageLocation(widget.message.msgID);
@ -171,21 +184,36 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
if (PlatformUtils().isIOS) {
if (result['isSuccess']) {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("图片保存成功"), infoCode: 6660406));
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("图片保存成功"),
infoCode: 6660406));
} else {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("图片保存失败"), infoCode: 6660407));
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("图片保存失败"),
infoCode: 6660407));
}
} else {
if (result != null) {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("图片保存成功"), infoCode: 6660406));
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("图片保存成功"),
infoCode: 6660406));
} else {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("图片保存失败"), infoCode: 6660407));
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("图片保存失败"),
infoCode: 6660407));
}
}
return;
}
} else {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("the message is downloading"), infoCode: -1));
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("the message is downloading"),
infoCode: -1));
}
return;
}
@ -194,15 +222,27 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
if (PlatformUtils().isIOS) {
if (result['isSuccess']) {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("图片保存成功"), infoCode: 6660406));
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("图片保存成功"),
infoCode: 6660406));
} else {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("图片保存失败"), infoCode: 6660407));
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("图片保存失败"),
infoCode: 6660407));
}
} else {
if (result != null) {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("图片保存成功"), infoCode: 6660406));
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("图片保存成功"),
infoCode: 6660406));
} else {
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("图片保存失败"), infoCode: 6660407));
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("图片保存失败"),
infoCode: 6660407));
}
}
return;
@ -223,7 +263,8 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
if (!isWeb && filePath != null && File(filePath).existsSync()) {
imageUrl = filePath;
isAssetBool = true;
} else if (localUrl != null && (!isWeb && File(localUrl).existsSync())) {
} else if (localUrl != null &&
(!isWeb && File(localUrl).existsSync())) {
imageUrl = localUrl;
isAssetBool = true;
} else {
@ -241,13 +282,19 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
);
}
} catch (e) {
onTIMCallback(TIMCallback(infoCode: 6660414, infoRecommendText: TIM_t("正在下载中"), type: TIMCallbackType.INFO));
onTIMCallback(TIMCallback(
infoCode: 6660414,
infoRecommendText: TIM_t("正在下载中"),
type: TIMCallbackType.INFO));
return;
}
}
V2TimImage? getImageFromList(V2TimImageTypesEnum imgType) {
V2TimImage? img = MessageUtils.getImageFromImgList(widget.message.imageElem!.imageList, HistoryMessageDartConstant.imgPriorMap[imgType] ?? HistoryMessageDartConstant.oriImgPrior);
V2TimImage? img = MessageUtils.getImageFromImgList(
widget.message.imageElem!.imageList,
HistoryMessageDartConstant.imgPriorMap[imgType] ??
HistoryMessageDartConstant.oriImgPrior);
return img;
}
@ -271,18 +318,26 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
));
bool checkIfDownloadSuccess() {
final localUrl = TencentUtils.checkString(model.getFileMessageLocation(widget.message.msgID)) ?? widget.message.imageElem!.imageList![0]!.localUrl;
return TencentUtils.checkString(localUrl) != null && File(localUrl!).existsSync();
final localUrl = TencentUtils.checkString(
model.getFileMessageLocation(widget.message.msgID)) ??
widget.message.imageElem!.imageList![0]!.localUrl;
return TencentUtils.checkString(localUrl) != null &&
File(localUrl!).existsSync();
}
_onClickOpenImageInNewWindow() {
final localUrl = TencentUtils.checkString(model.getFileMessageLocation(widget.message.msgID)) ?? widget.message.imageElem!.imageList![0]!.localUrl;
final localUrl = TencentUtils.checkString(
model.getFileMessageLocation(widget.message.msgID)) ??
widget.message.imageElem!.imageList![0]!.localUrl;
Future.delayed(const Duration(milliseconds: 0), () async {
final isDownloaded = checkIfDownloadSuccess();
if (isDownloaded) {
launchDesktopFile(localUrl ?? "");
} else {
onTIMCallback(TIMCallback(infoCode: 6660414, infoRecommendText: TIM_t("正在下载原始资源,请稍候..."), type: TIMCallbackType.INFO));
onTIMCallback(TIMCallback(
infoCode: 6660414,
infoRecommendText: TIM_t("正在下载原始资源,请稍候..."),
type: TIMCallbackType.INFO));
}
});
}
@ -291,14 +346,27 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
double? positionRadio,
String? originImgUrl,
}) {
final localUrl = TencentUtils.checkString(model.getFileMessageLocation(widget.message.msgID)) ?? widget.message.imageElem!.imageList![0]!.localUrl;
final localUrl = TencentUtils.checkString(
model.getFileMessageLocation(widget.message.msgID)) ??
widget.message.imageElem!.imageList![0]!.localUrl;
if (checkIfDownloadSuccess()) {
TUIKitWidePopup.showMedia(aspectRatio: positionRadio, context: context, mediaLocalPath: localUrl ?? "", onClickOrigin: () => _onClickOpenImageInNewWindow());
TUIKitWidePopup.showMedia(
aspectRatio: positionRadio,
context: context,
mediaLocalPath: localUrl ?? "",
onClickOrigin: () => _onClickOpenImageInNewWindow());
} else {
if (TencentUtils.checkString(originImgUrl) != null) {
TUIKitWidePopup.showMedia(aspectRatio: positionRadio, context: context, mediaURL: originImgUrl, onClickOrigin: () => _onClickOpenImageInNewWindow());
TUIKitWidePopup.showMedia(
aspectRatio: positionRadio,
context: context,
mediaURL: originImgUrl,
onClickOrigin: () => _onClickOpenImageInNewWindow());
} else {
onTIMCallback(TIMCallback(infoCode: 6660414, infoRecommendText: TIM_t("正在下载中"), type: TIMCallbackType.INFO));
onTIMCallback(TIMCallback(
infoCode: 6660414,
infoRecommendText: TIM_t("正在下载中"),
type: TIMCallbackType.INFO));
}
}
}
@ -365,7 +433,10 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
}
} else {
if (PlatformUtils().isDesktop) {
TUIKitWidePopup.showMedia(mediaLocalPath: imgPath, context: context, onClickOrigin: () => launchDesktopFile(imgPath ?? ""));
TUIKitWidePopup.showMedia(
mediaLocalPath: imgPath,
context: context,
onClickOrigin: () => launchDesktopFile(imgPath ?? ""));
} else {
Navigator.of(context).push(
PageRouteBuilder(
@ -383,56 +454,134 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
}
}
Widget _renderAllImage({dynamic heroTag, required TUITheme theme, bool isNetworkImage = false, String? webPath, V2TimImage? originalImg, V2TimImage? smallImg, String? smallLocalPath, String? originLocalPath}) {
Widget _renderAllImage(
{dynamic heroTag,
double? positionRadio,
required TUITheme theme,
bool isNetworkImage = false,
String? webPath,
V2TimImage? originalImg,
V2TimImage? smallImg,
String? smallLocalPath,
String? originLocalPath}) {
Widget getImageWidget() {
if (isNetworkImage) {
return Hero(
tag: heroTag,
child: PlatformUtils().isWeb
? Image.network(webPath ?? smallImg?.url ?? originalImg!.url!, fit: BoxFit.contain)
? Image.network(webPath ?? smallImg?.url ?? originalImg!.url!,
fit: BoxFit.contain)
: CachedNetworkImage(
alignment: Alignment.topCenter,
imageUrl: webPath ?? smallImg?.url ?? originalImg!.url!,
errorWidget: (context, error, stackTrace) => errorPage(theme),
errorWidget: (context, error, stackTrace) =>
errorPage(theme),
fit: BoxFit.contain,
cacheKey: smallImg?.uuid ?? originalImg!.uuid,
placeholder: (context, url) => Image(image: MemoryImage(kTransparentImage)),
placeholder: (context, url) =>
Image(image: MemoryImage(kTransparentImage)),
fadeInDuration: const Duration(milliseconds: 0),
));
} else {
final imgPath = (TencentUtils.checkString(smallLocalPath) != null ? smallLocalPath : originLocalPath)!;
return Hero(tag: heroTag, child: Image.file(File(imgPath), fit: BoxFit.contain));
final imgPath = (TencentUtils.checkString(smallLocalPath) != null
? smallLocalPath
: originLocalPath)!;
return Hero(
tag: heroTag,
child: Image.file(File(imgPath), fit: BoxFit.contain));
}
}
double? currentPositionRadio;
// File imgF = File((TencentUtils.checkString(originLocalPath) != null
// ? originLocalPath
// : smallLocalPath) ??
// "");
// bool isExist = imgF.existsSync();
//
// if (!isExist) {
// return errorDisplay(context, theme);
// }
// Image image = Image.file(imgF);
//
// image.image
// .resolve(const ImageConfiguration())
// .addListener(ImageStreamListener((image, synchronousCall) {
// if (image.image.width != 0 && image.image.height != 0) {
// currentPositionRadio = image.image.width / image.image.height;
// }
// }));
return GestureDetector(
onTap: () => onClickImage(
theme: theme, heroTag: heroTag, isNetworkImage: isNetworkImage, imgUrl: webPath ?? smallImg?.url ?? originalImg?.url ?? "", imgPath: (TencentUtils.checkString(originLocalPath) != null ? originLocalPath : smallLocalPath) ?? ""),
child: getImageWidget(),
theme: theme,
heroTag: heroTag,
isNetworkImage: isNetworkImage,
imgUrl: webPath ?? smallImg?.url ?? originalImg?.url ?? "",
imgPath: (TencentUtils.checkString(originLocalPath) != null
? originLocalPath
: smallLocalPath) ??
""),
child: Stack(
children: [
if (currentPositionRadio != null || positionRadio != null)
AspectRatio(
aspectRatio: (currentPositionRadio ?? positionRadio)!,
child: Container(
decoration: const BoxDecoration(color: Colors.transparent),
),
),
getImageWidget(),
],
),
);
}
void initImages() async {
final zeroImageLocal = TencentUtils.checkString(widget.message.imageElem?.imageList?.firstWhereOrNull((element) => element?.type == 0)?.localUrl);
final oneImageLocal = TencentUtils.checkString(widget.message.imageElem?.imageList?.firstWhereOrNull((element) => element?.type == 1)?.localUrl);
final twoImageLocal = TencentUtils.checkString(widget.message.imageElem?.imageList?.firstWhereOrNull((element) => element?.type == 2)?.localUrl);
final zeroImageLocal = TencentUtils.checkString(widget
.message.imageElem?.imageList
?.firstWhereOrNull((element) => element?.type == 0)
?.localUrl);
final oneImageLocal = TencentUtils.checkString(widget
.message.imageElem?.imageList
?.firstWhereOrNull((element) => element?.type == 1)
?.localUrl);
final twoImageLocal = TencentUtils.checkString(widget
.message.imageElem?.imageList
?.firstWhereOrNull((element) => element?.type == 2)
?.localUrl);
if (!PlatformUtils().isWeb && TencentUtils.checkString(widget.message.msgID) != null) {
if ((widget.message.imageElem?.imageList) == null || widget.message.imageElem!.imageList!.isEmpty) {
final response = await _messageService.getMessageOnlineUrl(msgID: widget.message.msgID!);
if (!PlatformUtils().isWeb &&
TencentUtils.checkString(widget.message.msgID) != null) {
if ((widget.message.imageElem?.imageList) == null ||
widget.message.imageElem!.imageList!.isEmpty) {
final response = await _messageService.getMessageOnlineUrl(
msgID: widget.message.msgID!);
final elem = response.data;
if (elem != null && elem.imageElem != null) {
widget.message.imageElem = elem.imageElem;
}
}
if (oneImageLocal == null || !File(oneImageLocal).existsSync()) {
_messageService.downloadMessage(msgID: widget.message.msgID!, messageType: 3, imageType: 1, isSnapshot: false);
_messageService.downloadMessage(
msgID: widget.message.msgID!,
messageType: 3,
imageType: 1,
isSnapshot: false);
}
if (twoImageLocal == null || !File(twoImageLocal).existsSync()) {
_messageService.downloadMessage(msgID: widget.message.msgID!, messageType: 3, imageType: 2, isSnapshot: false);
_messageService.downloadMessage(
msgID: widget.message.msgID!,
messageType: 3,
imageType: 2,
isSnapshot: false);
}
if (zeroImageLocal == null || !File(zeroImageLocal).existsSync()) {
_messageService.downloadMessage(msgID: widget.message.msgID!, messageType: 3, imageType: 0, isSnapshot: false);
_messageService.downloadMessage(
msgID: widget.message.msgID!,
messageType: 3,
imageType: 0,
isSnapshot: false);
}
}
}
@ -446,36 +595,83 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
bool isNeedShowLocalPath() {
final current = (DateTime.now().millisecondsSinceEpoch / 1000).ceil();
final timeStamp = widget.message.timestamp ?? current;
return (widget.message.isSelf ?? true) && (isSent || current - timeStamp < 300);
return (widget.message.isSelf ?? true) &&
(isSent || current - timeStamp < 300);
}
Widget? _renderImage(dynamic heroTag, TUITheme theme,
{V2TimImage? originalImg, V2TimImage? smallImg}) {
double positionRadio = 1.0;
if (smallImg?.width != null &&
smallImg?.height != null &&
smallImg?.width != 0 &&
smallImg?.height != 0) {
positionRadio = (smallImg!.width! / smallImg.height!);
}
Widget? _renderImage(dynamic heroTag, TUITheme theme, {V2TimImage? originalImg, V2TimImage? smallImg}) {
if (PlatformUtils().isWeb && widget.message.imageElem!.path != null) {
// Displaying on Web only
return _renderAllImage(heroTag: heroTag, theme: theme, isNetworkImage: true, smallImg: smallImg, originalImg: originalImg, webPath: widget.message.imageElem!.path);
return _renderAllImage(
heroTag: heroTag,
theme: theme,
isNetworkImage: true,
smallImg: smallImg,
originalImg: originalImg,
positionRadio: positionRadio,
webPath: widget.message.imageElem!.path);
}
try {
if ((isNeedShowLocalPath() && widget.message.imageElem!.path != null && widget.message.imageElem!.path!.isNotEmpty && File(widget.message.imageElem!.path!).existsSync())) {
return _renderAllImage(smallLocalPath: widget.message.imageElem!.path!, heroTag: heroTag, theme: theme, originLocalPath: widget.message.imageElem!.path!);
if ((isNeedShowLocalPath() &&
widget.message.imageElem!.path != null &&
widget.message.imageElem!.path!.isNotEmpty &&
File(widget.message.imageElem!.path!).existsSync())) {
return _renderAllImage(
smallLocalPath: widget.message.imageElem!.path!,
heroTag: heroTag,
theme: theme,
positionRadio: positionRadio,
originLocalPath: widget.message.imageElem!.path!);
}
} catch (e) {
// ignore: avoid_print
outputLogger.i(e);
outputLogger.i(e.toString());
}
try {
if ((TencentUtils.checkString(smallImg?.localUrl) != null && File((smallImg?.localUrl!)!).existsSync()) || (TencentUtils.checkString(originalImg?.localUrl) != null && File((originalImg?.localUrl!)!).existsSync())) {
return _renderAllImage(smallLocalPath: smallImg?.localUrl ?? "", heroTag: heroTag, theme: theme, originLocalPath: originalImg?.localUrl);
if ((TencentUtils.checkString(smallImg?.localUrl) != null &&
File((smallImg?.localUrl!)!).existsSync()) ||
(TencentUtils.checkString(originalImg?.localUrl) != null &&
File((originalImg?.localUrl!)!).existsSync())) {
return _renderAllImage(
smallLocalPath: smallImg?.localUrl ?? "",
heroTag: heroTag,
theme: theme,
positionRadio: positionRadio,
originLocalPath: originalImg?.localUrl);
}
} catch (e) {
// ignore: avoid_print
outputLogger.i(e);
return _renderAllImage(heroTag: heroTag, theme: theme, isNetworkImage: true, smallImg: smallImg, originalImg: originalImg);
outputLogger.i(e.toString());
return _renderAllImage(
heroTag: heroTag,
theme: theme,
isNetworkImage: true,
smallImg: smallImg,
positionRadio: positionRadio,
originalImg: originalImg);
}
if ((smallImg?.url ?? originalImg?.url) != null && (smallImg?.url ?? originalImg?.url)!.isNotEmpty) {
return _renderAllImage(heroTag: heroTag, theme: theme, isNetworkImage: true, smallImg: smallImg, originalImg: originalImg);
if ((smallImg?.url ?? originalImg?.url) != null &&
(smallImg?.url ?? originalImg?.url)!.isNotEmpty) {
return _renderAllImage(
heroTag: heroTag,
theme: theme,
isNetworkImage: true,
positionRadio: positionRadio,
smallImg: smallImg,
originalImg: originalImg);
}
return errorDisplay(context, theme);
@ -487,8 +683,10 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
if (widget.message.status == MessageStatus.V2TIM_MSG_STATUS_SENDING) {
isSent = true;
}
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
final heroTag = "${widget.message.msgID ?? widget.message.id ?? widget.message.timestamp ?? DateTime.now().millisecondsSinceEpoch}${widget.isFrom}";
final isDesktopScreen =
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
final heroTag =
"${widget.message.msgID ?? widget.message.id ?? widget.message.timestamp ?? DateTime.now().millisecondsSinceEpoch}${widget.isFrom}";
V2TimImage? originalImg = getImageFromList(V2TimImageTypesEnum.original);
V2TimImage? smallImg = getImageFromList(V2TimImageTypesEnum.small);
@ -499,14 +697,16 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
isFromSelf: widget.message.isSelf ?? true,
isShowMessageReaction: widget.isShowMessageReaction ?? true,
message: widget.message,
child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return ConstrainedBox(
constraints: BoxConstraints(
maxWidth: constraints.maxWidth * (isDesktopScreen ? 0.4 : 0.5),
minWidth: 64,
maxHeight: 256,
),
child: _renderImage(heroTag, theme, originalImg: originalImg, smallImg: smallImg),
child: _renderImage(heroTag, theme,
originalImg: originalImg, smallImg: smallImg),
);
}));
}
@ -515,7 +715,9 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
class ImageClipper extends CustomClipper<RRect> {
@override
RRect getClip(Size size) {
return RRect.fromRectAndRadius(Rect.fromLTWH(0, 0, size.width, min(size.height, 256)), const Radius.circular(5));
return RRect.fromRectAndRadius(
Rect.fromLTWH(0, 0, size.width, min(size.height, 256)),
const Radius.circular(5));
}
@override

View File

@ -5,6 +5,7 @@ import 'dart:convert';
import 'package:flutter/material.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';
@ -93,6 +94,9 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
}
final messageID = cloudCustomData.messageID;
if(PlatformUtils().isWeb){
return;
}
V2TimMessage? message = await widget.chatModel.findMessage(messageID);
if (message == null) {
try {
@ -168,7 +172,7 @@ class _TIMUIKitReplyElemState extends TIMUIKitState<TIMUIKitReplyElem> {
}
if (message == null) {
if (repliedMessage?.messageAbstract != null) {
_renderMessageSummary(theme);
return _renderMessageSummary(theme);
}
return const SizedBox(width: 0, height: 12);
}

View File

@ -261,7 +261,7 @@ class _SendSoundMessageState extends TIMUIKitState<SendSoundMessage> {
isRecording = true;
});
} else {
outputLogger.i(status);
outputLogger.i(status.toString());
}
});
final amplitudesResponseSubscription =

View File

@ -222,7 +222,7 @@ class _TIMUIKitTextFieldLayoutWideState extends TIMUIKitState<TIMUIKitTextFieldL
}
} catch (e) {
// ignore: avoid_print
outputLogger.i(e);
outputLogger.i(e.toString());
}
generateDefaultControlBarItems();
}

View File

@ -230,6 +230,8 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
axis: Axis.vertical,
);
Widget? joinInGroupCallWidget;
@override
void initState() {
super.initState();
@ -346,12 +348,21 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
return widget.conversation.type == 1 ? ConvType.c2c : ConvType.group;
}
_updateJoinInGroupCallWidget() async {
if (_getConvType() != ConvType.group) {
return;
}
joinInGroupCallWidget = await TUICore.instance.raiseExtension(TUIExtensionID.joinInGroup, {GROUP_ID: widget.conversationID!});
setState(() {});
}
@override
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
final TUITheme theme = value.theme;
final closePanel = OptimizeUtils.throttle((_) => textFieldController.hideAllPanel(), 60);
final isBuild = isInit;
isInit = true;
_updateJoinInGroupCallWidget();
return TIMUIKitChatProviderScope(
model: model,
@ -450,6 +461,7 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
if (widget.customAppBar != null) widget.customAppBar!,
if (filteredApplicationList.isNotEmpty) _renderJoinGroupApplication(filteredApplicationList.length, theme),
if (widget.topFixWidget != null) widget.topFixWidget!,
if (joinInGroupCallWidget != null) Center(child: joinInGroupCallWidget!),
Expanded(
child: Container(
color: theme.chatBgColor,

View File

@ -96,6 +96,10 @@ class TIMUIKitChatConfig {
/// [Default]: true.
final bool isAtWhenReply;
/// Control if allowed to at when reply automatically.
/// [Default]: true.
final bool Function(V2TimMessage message)? isAtWhenReplyDynamic;
/// The main switch of the group read receipt.
final bool isShowGroupMessageReadReceipt;
@ -258,6 +262,7 @@ class TIMUIKitChatConfig {
this.isUseMessageReaction = true,
this.isShowAvatar = true,
this.isShowSelfNameInGroup = false,
this.isAtWhenReplyDynamic,
this.offlinePushInfo,
@Deprecated("Please use [isShowGroupReadingStatus] instead")
this.isShowGroupMessageReadReceipt = true,

View File

@ -1,21 +1,15 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.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_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';
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_im_base/tencent_im_base.dart';
typedef GroupApplicationItemBuilder = Widget Function(
BuildContext context, V2TimGroupApplication applicationInfo, int index);
typedef GroupApplicationItemBuilder = Widget Function(BuildContext context, V2TimGroupApplication applicationInfo, int index);
enum ApplicationStatus {
none,
@ -30,16 +24,13 @@ class TIMUIKitGroupApplicationList extends StatefulWidget {
/// group ID
final String groupID;
const TIMUIKitGroupApplicationList(
{Key? key, this.itemBuilder, required this.groupID})
: super(key: key);
const TIMUIKitGroupApplicationList({Key? key, this.itemBuilder, required this.groupID}) : super(key: key);
@override
State<StatefulWidget> createState() => TIMUIKitGroupApplicationListState();
}
class TIMUIKitGroupApplicationListState
extends TIMUIKitState<TIMUIKitGroupApplicationList> {
class TIMUIKitGroupApplicationListState extends TIMUIKitState<TIMUIKitGroupApplicationList> {
final TUIChatGlobalModel model = serviceLocator<TUIChatGlobalModel>();
final GroupServices _groupServices = serviceLocator<GroupServices>();
List<V2TimGroupApplication> groupApplicationList = [];
@ -48,26 +39,20 @@ class TIMUIKitGroupApplicationListState
@override
void initState() {
super.initState();
groupApplicationList = model.groupApplicationList
.where((item) => (item.groupID == widget.groupID))
.toList();
applicationStatusList =
groupApplicationList.map((item) => ApplicationStatus.none).toList();
groupApplicationList = model.groupApplicationList.where((item) => (item.groupID == widget.groupID)).toList();
applicationStatusList = groupApplicationList.map((item) => ApplicationStatus.none).toList();
}
GroupApplicationItemBuilder _getItemBuilder() {
return widget.itemBuilder ?? _defaultItemBuilder;
}
Widget _defaultItemBuilder(
BuildContext context, V2TimGroupApplication applicationInfo, int index) {
Widget _defaultItemBuilder(BuildContext context, V2TimGroupApplication applicationInfo, int index) {
final theme = Provider.of<TUIThemeViewModel>(context).theme;
final ApplicationStatus currentStatus = applicationStatusList[index];
String _getUserName() {
if (applicationInfo.fromUserNickName != null &&
applicationInfo.fromUserNickName!.isNotEmpty &&
applicationInfo.fromUserNickName != applicationInfo.fromUser) {
if (applicationInfo.fromUserNickName != null && applicationInfo.fromUserNickName!.isNotEmpty && applicationInfo.fromUserNickName != applicationInfo.fromUser) {
return "${applicationInfo.fromUserNickName} (${applicationInfo.fromUser})";
} else {
return "${applicationInfo.fromUser}";
@ -76,17 +61,14 @@ class TIMUIKitGroupApplicationListState
String _getRequestMessage() {
String option2 = applicationInfo.requestMsg ?? "";
return TIM_t_para("验证消息: {{option2}}", "验证消息: $option2")(
option2: option2);
return TIM_t_para("验证消息: {{option2}}", "验证消息: $option2")(option2: option2);
}
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
border: Border(
bottom: BorderSide(
color: theme.weakDividerColor ?? const Color(0xFFDBDBDB))),
border: Border(bottom: BorderSide(color: theme.weakDividerColor ?? const Color(0xFFDBDBDB))),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
@ -96,11 +78,7 @@ class TIMUIKitGroupApplicationListState
child: SizedBox(
height: 40,
width: 40,
child: Avatar(
faceUrl: applicationInfo.fromUserFaceUrl ?? "",
showName: applicationInfo.fromUserNickName ??
applicationInfo.fromUser ??
""),
child: Avatar(faceUrl: applicationInfo.fromUserFaceUrl ?? "", showName: applicationInfo.fromUserNickName ?? applicationInfo.fromUser ?? ""),
),
),
Expanded(
@ -109,10 +87,7 @@ class TIMUIKitGroupApplicationListState
children: [
Text(
_getUserName(),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: theme.darkTextColor),
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: theme.darkTextColor),
),
Text(
_getRequestMessage(),
@ -120,21 +95,13 @@ class TIMUIKitGroupApplicationListState
),
],
)),
if (currentStatus == ApplicationStatus.none &&
applicationInfo.handleStatus == 0)
if (currentStatus == ApplicationStatus.none && applicationInfo.handleStatus == 0)
Container(
margin: const EdgeInsets.only(left: 8, right: 8),
child: InkWell(
child: Container(
padding:
const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: theme.primaryColor,
border: Border.all(
width: 1,
color: theme.weakTextColor ??
CommonColor.weakTextColor)),
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(4), color: theme.primaryColor, border: Border.all(width: 1, color: theme.weakTextColor ?? CommonColor.weakTextColor)),
child: Text(
TIM_t("同意"), // agree
style: const TextStyle(
@ -160,19 +127,11 @@ class TIMUIKitGroupApplicationListState
}
}),
),
if (currentStatus == ApplicationStatus.none &&
applicationInfo.handleStatus == 0)
if (currentStatus == ApplicationStatus.none && applicationInfo.handleStatus == 0)
InkWell(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: Colors.white,
border: Border.all(
width: 1,
color:
theme.weakTextColor ?? CommonColor.weakTextColor)),
padding:
const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(4), color: Colors.white, border: Border.all(width: 1, color: theme.weakTextColor ?? CommonColor.weakTextColor)),
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
child: Text(
TIM_t("拒绝"), // reject
style: TextStyle(
@ -182,12 +141,7 @@ class TIMUIKitGroupApplicationListState
),
onTap: () async {
final res = await _groupServices.refuseGroupApplication(
addTime: applicationInfo.addTime!,
groupID: applicationInfo.groupID,
fromUser: applicationInfo.fromUser!,
toUser: applicationInfo.toUser!,
type:
GroupApplicationTypeEnum.values[applicationInfo.type]);
addTime: applicationInfo.addTime!, groupID: applicationInfo.groupID, fromUser: applicationInfo.fromUser!, toUser: applicationInfo.toUser!, type: GroupApplicationTypeEnum.values[applicationInfo.type]);
if (res.code == 0) {
setState(() {
applicationStatusList[index] = ApplicationStatus.reject;
@ -198,8 +152,7 @@ class TIMUIKitGroupApplicationListState
}
},
),
if (currentStatus == ApplicationStatus.accept ||
applicationInfo.handleStatus == 1)
if (currentStatus == ApplicationStatus.accept || applicationInfo.handleResult == 1)
Container(
margin: const EdgeInsets.only(left: 8),
child: Text(
@ -207,8 +160,7 @@ class TIMUIKitGroupApplicationListState
style: TextStyle(fontSize: 15, color: theme.weakTextColor),
),
),
if (currentStatus == ApplicationStatus.reject ||
applicationInfo.handleStatus == 2)
if (currentStatus == ApplicationStatus.reject || applicationInfo.handleResult == 2)
Container(
margin: const EdgeInsets.only(left: 8),
child: Text(
@ -228,8 +180,7 @@ class TIMUIKitGroupApplicationListState
return MultiProvider(
providers: [ChangeNotifierProvider.value(value: model)],
builder: (context, w) {
final isDesktopScreen =
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
return Container(
decoration: isDesktopScreen ? null : BoxDecoration(color: theme.weakBackgroundColor),
child: ListView.builder(

View File

@ -2,10 +2,10 @@
import 'dart:async';
import 'package:chewie_for_us/chewie_for_us.dart';
import 'package:chewie_for_us/src/animated_play_pause.dart';
import 'package:chewie_for_us/src/helpers/utils.dart';
import 'package:chewie_for_us/src/material/material_progress_bar.dart';
import 'package:chewie/chewie.dart';
import 'package:chewie/src/animated_play_pause.dart';
import 'package:chewie/src/helpers/utils.dart';
import 'package:chewie/src/material/material_progress_bar.dart';
import 'package:flutter/material.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
@ -380,8 +380,7 @@ class _VideoCustomControlsState extends TIMUIKitState<VideoCustomControls> with
_startHideTimer();
},
colors: chewieController.materialProgressColors ??
ChewieProgressColors(playedColor: Colors.white, handleColor: Colors.white, bufferedColor: Colors.white38, backgroundColor: Colors.white24),
colors: chewieController.materialProgressColors ?? ChewieProgressColors(playedColor: Colors.white, handleColor: Colors.white, bufferedColor: Colors.white38, backgroundColor: Colors.white24),
),
),
);

View File

@ -1,30 +1,27 @@
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:chewie/chewie.dart';
import 'package:crypto/crypto.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_gallery_saver/image_gallery_saver.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_chat_global_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:universal_html/html.dart' as html;
import 'package:chewie_for_us/chewie_for_us.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/permission.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
import 'package:tencent_cloud_chat_uikit/ui/widgets/video_custom_control.dart';
import 'package:universal_html/html.dart' as html;
import 'package:video_player/video_player.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_base.dart';
class VideoScreen extends StatefulWidget {
const VideoScreen({required this.message,
required this.heroTag,
required this.videoElement,
Key? key})
: super(key: key);
const VideoScreen({required this.message, required this.heroTag, required this.videoElement, Key? key}) : super(key: key);
final V2TimMessage message;
final dynamic heroTag;
@ -37,8 +34,7 @@ class VideoScreen extends StatefulWidget {
class _VideoScreenState extends TIMUIKitState<VideoScreen> {
late VideoPlayerController videoPlayerController;
late ChewieController chewieController;
GlobalKey<ExtendedImageSlidePageState> slidePagekey =
GlobalKey<ExtendedImageSlidePageState>();
GlobalKey<ExtendedImageSlidePageState> slidePagekey = GlobalKey<ExtendedImageSlidePageState>();
final TUIChatGlobalModel model = serviceLocator<TUIChatGlobalModel>();
bool isInit = false;
@ -56,22 +52,19 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
}
//
Future<void> _saveNetworkVideo(context,
Future<void> _saveNetworkVideo(
context,
String videoUrl, {
bool isAsset = true,
}) async {
if (PlatformUtils().isWeb) {
RegExp exp = RegExp(r"((\.){1}[^?]{2,4})");
String? suffix = exp
.allMatches(videoUrl)
.last
.group(0);
String? suffix = exp.allMatches(videoUrl).last.group(0);
var xhr = html.HttpRequest();
xhr.open('get', videoUrl);
xhr.responseType = 'arraybuffer';
xhr.onLoad.listen((event) {
final a = html.AnchorElement(
href: html.Url.createObjectUrl(html.Blob([xhr.response])));
final a = html.AnchorElement(href: html.Url.createObjectUrl(html.Blob([xhr.response])));
a.download = '${md5.convert(utf8.encode(videoUrl)).toString()}$suffix';
a.click();
a.remove();
@ -92,7 +85,8 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
if ((androidInfo.version.sdkInt) >= 33) {
final videos = await Permissions.checkPermission(
context, Permission.videos.value,
context,
Permission.videos.value,
);
if (!videos) {
@ -100,7 +94,8 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
}
} else {
final storage = await Permissions.checkPermission(
context, Permission.storage.value,
context,
Permission.storage.value,
);
if (!storage) {
return;
@ -115,8 +110,7 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
}
if (model.getMessageProgress(widget.message.msgID) == 100) {
String savePath;
if (widget.message.videoElem!.localVideoUrl != null &&
widget.message.videoElem!.localVideoUrl != '') {
if (widget.message.videoElem!.localVideoUrl != null && widget.message.videoElem!.localVideoUrl != '') {
savePath = widget.message.videoElem!.localVideoUrl!;
} else {
savePath = model.getFileMessageLocation(widget.message.msgID);
@ -126,62 +120,35 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
var result = await ImageGallerySaver.saveFile(savePath);
if (PlatformUtils().isIOS) {
if (result['isSuccess']) {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("视频保存成功"),
infoCode: 6660402));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存成功"), infoCode: 6660402));
} else {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("视频保存失败"),
infoCode: 6660403));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存失败"), infoCode: 6660403));
}
} else {
if (result != null) {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("视频保存成功"),
infoCode: 6660402));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存成功"), infoCode: 6660402));
} else {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("视频保存失败"),
infoCode: 6660403));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存失败"), infoCode: 6660403));
}
}
}
} else {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("the message is downloading"),
infoCode: -1));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("the message is downloading"), infoCode: -1));
}
return;
}
var result = await ImageGallerySaver.saveFile(savePath);
if (PlatformUtils().isIOS) {
if (result['isSuccess']) {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("视频保存成功"),
infoCode: 6660402));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存成功"), infoCode: 6660402));
} else {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("视频保存失败"),
infoCode: 6660403));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存失败"), infoCode: 6660403));
}
} else {
if (result != null) {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("视频保存成功"),
infoCode: 6660402));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存成功"), infoCode: 6660402));
} else {
onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO,
infoRecommendText: TIM_t("视频保存失败"),
infoCode: 6660403));
onTIMCallback(TIMCallback(type: TIMCallbackType.INFO, infoRecommendText: TIM_t("视频保存失败"), infoCode: 6660403));
}
}
return;
@ -195,8 +162,7 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
isAsset: true,
);
}
if (widget.videoElement.videoPath != '' &&
widget.videoElement.videoPath != null) {
if (widget.videoElement.videoPath != '' && widget.videoElement.videoPath != null) {
File f = File(widget.videoElement.videoPath!);
if (f.existsSync()) {
return await _saveNetworkVideo(
@ -206,8 +172,7 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
);
}
}
if (widget.videoElement.localVideoUrl != '' &&
widget.videoElement.localVideoUrl != null) {
if (widget.videoElement.localVideoUrl != '' && widget.videoElement.localVideoUrl != null) {
File f = File(widget.videoElement.localVideoUrl!);
if (f.existsSync()) {
return await _saveNetworkVideo(
@ -246,8 +211,7 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
setVideoPlayerController() async {
if (!PlatformUtils().isWeb) {
if (TencentUtils.checkString(widget.message.msgID) != null &&
widget.videoElement.localVideoUrl == null) {
if (TencentUtils.checkString(widget.message.msgID) != null && widget.videoElement.localVideoUrl == null) {
String savePath = model.getFileMessageLocation(widget.message.msgID);
File f = File(savePath);
if (f.existsSync()) {
@ -257,8 +221,7 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
}
VideoPlayerController player = PlatformUtils().isWeb
? ((TencentUtils.checkString(widget.videoElement.videoPath) != null) ||
widget.message.status == MessageStatus.V2TIM_MSG_STATUS_SENDING
? ((TencentUtils.checkString(widget.videoElement.videoPath) != null) || widget.message.status == MessageStatus.V2TIM_MSG_STATUS_SENDING
? VideoPlayerController.networkUrl(
Uri.parse(widget.videoElement.videoPath!),
)
@ -269,8 +232,7 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
: VideoPlayerController.networkUrl(
Uri.parse(widget.videoElement.localVideoUrl!),
))
: (TencentUtils.checkString(widget.videoElement.videoPath) != null ||
widget.message.status == MessageStatus.V2TIM_MSG_STATUS_SENDING)
: (TencentUtils.checkString(widget.videoElement.videoPath) != null || widget.message.status == MessageStatus.V2TIM_MSG_STATUS_SENDING)
? VideoPlayerController.file(File(widget.videoElement.videoPath!))
: (TencentUtils.checkString(widget.videoElement.localVideoUrl) == null)
? VideoPlayerController.networkUrl(
@ -303,8 +265,7 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
@override
didUpdateWidget(oldWidget) {
if (oldWidget.videoElement.videoUrl != widget.videoElement.videoUrl ||
oldWidget.videoElement.videoPath != widget.videoElement.videoPath) {
if (oldWidget.videoElement.videoUrl != widget.videoElement.videoUrl || oldWidget.videoElement.videoPath != widget.videoElement.videoPath) {
setVideoPlayerController();
}
super.didUpdateWidget(oldWidget);
@ -330,10 +291,7 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
child: Container(
color: Colors.transparent,
constraints: BoxConstraints.expand(
height: MediaQuery
.of(context)
.size
.height,
height: MediaQuery.of(context).size.height,
),
child: ExtendedImageSlidePage(
key: slidePagekey,
@ -342,13 +300,12 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
return Colors.black;
}
double opacity = 0.0;
opacity = offset.distance /
(Offset(size.width, size.height).distance / 2.0);
return Colors.black
.withOpacity(min(1.0, max(1.0 - opacity, 0.0)));
opacity = offset.distance / (Offset(size.width, size.height).distance / 2.0);
return Colors.black.withOpacity(min(1.0, max(1.0 - opacity, 0.0)));
},
slideType: SlideType.onlyImage,
slideEndHandler: (Offset offset, {
slideEndHandler: (
Offset offset, {
ExtendedImageSlidePageState? state,
ScaleEndDetails? details,
}) {
@ -366,22 +323,13 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
? Chewie(
controller: chewieController,
)
: const Center(
child:
CircularProgressIndicator(color: Colors.white))),
: const Center(child: CircularProgressIndicator(color: Colors.white))),
heroBuilderForSlidingPage: (Widget result) {
return Hero(
tag: widget.heroTag,
child: result,
flightShuttleBuilder: (BuildContext flightContext,
Animation<double> animation,
HeroFlightDirection flightDirection,
BuildContext fromHeroContext,
BuildContext toHeroContext) {
final Hero hero =
(flightDirection == HeroFlightDirection.pop
? fromHeroContext.widget
: toHeroContext.widget) as Hero;
flightShuttleBuilder: (BuildContext flightContext, Animation<double> animation, HeroFlightDirection flightDirection, BuildContext fromHeroContext, BuildContext toHeroContext) {
final Hero hero = (flightDirection == HeroFlightDirection.pop ? fromHeroContext.widget : toHeroContext.widget) as Hero;
return hero.child;
},

View File

@ -2,15 +2,15 @@
import 'dart:io';
import 'package:chewie_for_us/chewie_for_us.dart';
import 'package:chewie/chewie.dart';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as p;
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_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/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';
import 'package:tencent_cloud_chat_uikit/ui/widgets/drag_widget.dart';
import 'package:path/path.dart' as p;
import 'package:video_player/video_player.dart';
class TUIKitWidePopup {
@ -70,26 +70,10 @@ class TUIKitWidePopup {
}
isShow = true;
final TUISelfInfoViewModel selfInfoViewModel =
serviceLocator<TUISelfInfoViewModel>();
final TUISelfInfoViewModel selfInfoViewModel = serviceLocator<TUISelfInfoViewModel>();
if (selfInfoViewModel.globalConfig?.showDesktopModalFunc != null) {
final res = await selfInfoViewModel.globalConfig!.showDesktopModalFunc!(
operationKey,
context,
child,
theme,
width,
height,
offset,
initText,
borderRadius,
isDarkBackground,
title,
onSubmit,
submitWidget,
onConfirm,
onCancel);
final res = await selfInfoViewModel.globalConfig!.showDesktopModalFunc!(operationKey, context, child, theme, width, height, offset, initText, borderRadius, isDarkBackground, title, onSubmit, submitWidget, onConfirm, onCancel);
if (res == true) {
return;
@ -102,8 +86,7 @@ class TUIKitWidePopup {
width: width,
height: height,
decoration: BoxDecoration(
borderRadius:
borderRadius ?? const BorderRadius.all(Radius.circular(16)),
borderRadius: borderRadius ?? const BorderRadius.all(Radius.circular(16)),
color: theme?.wideBackgroundColor ?? const Color(0xFFffffff),
border: isDarkBackground
? Border.all(
@ -129,9 +112,7 @@ class TUIKitWidePopup {
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: hexToColor("f5f6f7"),
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16)),
borderRadius: const BorderRadius.only(topLeft: Radius.circular(16), topRight: Radius.circular(16)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -139,9 +120,7 @@ class TUIKitWidePopup {
children: [
Text(
title,
style: TextStyle(
fontSize: 18,
color: theme?.darkTextColor ?? const Color(0xFF444444)),
style: TextStyle(fontSize: 18, color: theme?.darkTextColor ?? const Color(0xFF444444)),
),
InkWell(
onTap: () {
@ -156,9 +135,7 @@ class TUIKitWidePopup {
entry = null;
}
},
child: onSubmit != null
? (submitWidget ?? const Icon(Icons.check))
: const Icon(Icons.close),
child: onSubmit != null ? (submitWidget ?? const Icon(Icons.check)) : const Icon(Icons.close),
)
],
),
@ -212,8 +189,7 @@ class TUIKitWidePopup {
},
child: Text(
TIM_t("取消"),
style: TextStyle(
color: theme?.weakTextColor ?? Colors.black),
style: TextStyle(color: theme?.weakTextColor ?? Colors.black),
)),
),
if (onConfirm != null)
@ -293,8 +269,7 @@ class TUIKitWidePopup {
required VoidCallback onClickOrigin,
double? aspectRatio,
}) async {
assert((mediaLocalPath != null) || (mediaURL != null),
"At least one of mediaLocalPath or mediaURL must be provided.");
assert((mediaLocalPath != null) || (mediaURL != null), "At least one of mediaLocalPath or mediaURL must be provided.");
String _removeQueryString(String urlString) {
Uri uri = Uri.parse(urlString);
@ -310,10 +285,8 @@ class TUIKitWidePopup {
final String mediaPath = mediaLocalPath ?? mediaURL ?? "";
final isLocalResource = mediaLocalPath != null;
String fileExtension = p
.extension(isLocalResource ? mediaPath : _removeQueryString(mediaPath));
bool isVideo =
['.mp4', '.avi', '.mov', '.flv', '.wmv'].contains(fileExtension);
String fileExtension = p.extension(isLocalResource ? mediaPath : _removeQueryString(mediaPath));
bool isVideo = ['.mp4', '.avi', '.mov', '.flv', '.wmv'].contains(fileExtension);
VideoPlayerController? videoController;
ChewieController? chewieController;
@ -324,8 +297,7 @@ class TUIKitWidePopup {
if (isLocalResource) {
videoController = VideoPlayerController.file(File(mediaPath));
} else {
videoController =
VideoPlayerController.networkUrl(Uri.parse(mediaPath));
videoController = VideoPlayerController.networkUrl(Uri.parse(mediaPath));
}
await videoController.initialize();
@ -342,9 +314,7 @@ class TUIKitWidePopup {
mediaWidget = Chewie(controller: chewieController);
} else {
mediaWidget = isLocalResource
? Image.file(File(mediaPath), fit: BoxFit.contain)
: Image.network(mediaPath, fit: BoxFit.contain);
mediaWidget = isLocalResource ? Image.file(File(mediaPath), fit: BoxFit.contain) : Image.network(mediaPath, fit: BoxFit.contain);
}
showDialog(
@ -373,11 +343,7 @@ class TUIKitWidePopup {
maxWidth: MediaQuery.of(context).size.width * 0.85,
maxHeight: MediaQuery.of(context).size.height * 0.82,
),
child: aspectRatioFinal != null
? AspectRatio(
aspectRatio: aspectRatioFinal,
child: mediaWidget)
: mediaWidget,
child: aspectRatioFinal != null ? AspectRatio(aspectRatio: aspectRatioFinal, child: mediaWidget) : mediaWidget,
),
const SizedBox(height: 10),
InkWell(

View File

@ -217,14 +217,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.3"
chewie_for_us:
chewie:
dependency: "direct main"
description:
name: chewie_for_us
sha256: "0307723e811508d361fffa6f8bbd9040b1bfea5536544e4d655e10c27de002ec"
name: chewie
sha256: "8bc4ac4cf3f316e50a25958c0f5eb9bb12cf7e8308bb1d74a43b230da2cfc144"
url: "https://pub.dev"
source: hosted
version: "1.5.0"
version: "1.7.5"
clock:
dependency: transitive
description:
@ -313,6 +313,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.2"
dbus:
dependency: transitive
description:
name: dbus
sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
url: "https://pub.dev"
source: hosted
version: "0.7.10"
desktop_drop:
dependency: "direct main"
description:
@ -1308,26 +1316,26 @@ packages:
dependency: transitive
description:
name: tencent_cloud_chat_sdk
sha256: a78f1f20dc9ebe40aee1bbb47da097780028434d77e97774fbe733debb21e18e
sha256: "358e79b51aba5457418d3bb87e0bbd0f088a1eaf4c4463d09bdda93d1d655aa3"
url: "https://pub.dev"
source: hosted
version: "7.7.5296"
version: "7.9.5672"
tencent_cloud_uikit_core:
dependency: "direct main"
description:
name: tencent_cloud_uikit_core
sha256: "7ddb2c034e5f832261ba268957e282b7c2e738acb1d21aa40c62dad4eaa433ea"
sha256: "61a5400b3fe75c00252272469f332e7ec07f6d1932ee636a3f2b919cf9805cb8"
url: "https://pub.dev"
source: hosted
version: "1.5.2"
version: "1.6.0"
tencent_im_base:
dependency: "direct main"
description:
name: tencent_im_base
sha256: "035d97d24bebb87654700d4afc8227de8721a259ef5d0195f3207cb0eb0cdc7a"
sha256: daee1faac70fdf5fa4a53576db4fb7268ba5d897cc036353d3114a31abb76fb1
url: "https://pub.dev"
source: hosted
version: "3.3.775296"
version: "3.3.775297"
tencent_keyboard_visibility:
dependency: "direct main"
description:
@ -1560,22 +1568,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.16"
wakelock_for_us:
wakelock_plus:
dependency: transitive
description:
name: wakelock_for_us
sha256: a5bdd445e51a617f7c24be8165230391447301f622aacd050038cee7b41989b4
name: wakelock_plus
sha256: f268ca2116db22e57577fb99d52515a24bdc1d570f12ac18bb762361d43b043d
url: "https://pub.dev"
source: hosted
version: "0.6.3+1"
wakelock_platform_interface:
version: "1.1.4"
wakelock_plus_platform_interface:
dependency: transitive
description:
name: wakelock_platform_interface
sha256: "1f4aeb81fb592b863da83d2d0f7b8196067451e4df91046c26b54a403f9de621"
name: wakelock_plus_platform_interface
sha256: "40fabed5da06caff0796dc638e1f07ee395fb18801fbff3255a2372db2d80385"
url: "https://pub.dev"
source: hosted
version: "0.3.0"
version: "1.1.0"
watcher:
dependency: transitive
description:

View File

@ -1,6 +1,6 @@
name: tencent_cloud_chat_uikit
description: A powerful chat UI component library and business logic for Tencent Cloud Chat, creating seamless in-app chat modules for delightful user experiences.
version: 2.5.1
version: 2.5.1+4
homepage: https://trtc.io/products/chat?utm_source=gfs&utm_medium=link&utm_campaign=%E6%B8%A0%E9%81%93&_channel_track_key=k6WgfCKn
repository: https://github.com/TencentCloud/chat-uikit-flutter
documentation: https://comm.qq.com/im/doc/flutter/en/TUIKit/readme.html
@ -29,7 +29,7 @@ dependencies:
file_picker: ^5.3.0
tencent_super_tooltip: ^0.0.1
video_player: ^2.7.0
chewie_for_us: ^1.5.0
chewie: ^1.7.5
flutter_slidable: ^3.0.1
flutter_plugin_record_plus: ^0.0.16
azlistview_all_platforms: ^2.1.2
@ -62,10 +62,10 @@ dependencies:
open_file: ^3.3.2
tencent_keyboard_visibility: ^1.0.1
tim_ui_kit_sticker_plugin: ^3.1.0
tencent_im_base: ^3.3.775296
tencent_im_base: ^3.3.775297
fc_native_video_thumbnail: any
path: ^1.8.1
tencent_cloud_uikit_core: ^1.2.1
tencent_cloud_uikit_core: ^1.6.0
pasteboard: ^0.2.0
desktop_drop: ^0.4.4
device_info_plus: any
@ -82,6 +82,11 @@ dev_dependencies:
build_runner: any
lints: ^1.0.1
dependency_overrides:
# tencent_chat_i18n_tool:
# path: D:\Project\tencent-chat-i18n-tool
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec