feat: Upgrade to 2.7.2

This commit is contained in:
vinsonswang 2024-10-12 16:58:58 +08:00
parent 245b85f3ff
commit 3f4f7afb4e
14 changed files with 150 additions and 248 deletions

View File

@ -1,3 +1,14 @@
# 2.7.2
* Fix the issue where failed messages cannot be resent.
* Fix the issue where image messages that failed to send are not loaded using the local path.
* Fix the issue where the screen turns white after dissolving or leaving a group.
* Optimize the process of sending messages.
* Optimize the alignment of buttons in the long-press message menu.
* Limit the version range of the third-party library extended_image.
# 2.7.1
* Fixed the 'keepAspectRatio' parameter error.
# 2.7.0 # 2.7.0
## Breaking Changes ## Breaking Changes

View File

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

View File

@ -102,7 +102,6 @@ class TUIChatModelTools {
messageInfo.timestamp = messageInfo.timestamp =
(DateTime.now().millisecondsSinceEpoch / 1000).ceil(); (DateTime.now().millisecondsSinceEpoch / 1000).ceil();
messageInfo.isSelf = true; messageInfo.isSelf = true;
messageInfo.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
messageInfo.id = id; messageInfo.id = id;
return messageInfo; return messageInfo;

View File

@ -68,6 +68,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
String? _groupID; String? _groupID;
Map<String, String> get groupUserShowName => _groupUserShowName; Map<String, String> get groupUserShowName => _groupUserShowName;
final List<String> _sendingMessageIDList = [];
set groupUserShowName(Map<String, String> value) { set groupUserShowName(Map<String, String> value) {
_groupUserShowName = value; _groupUserShowName = value;
@ -688,6 +689,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
}) })
: ""), : ""),
); );
removeSendingMessageID(id);
if (isEditStatusMessage == false && if (isEditStatusMessage == false &&
globalModel.getMessageListPosition(conversationID) != globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) { HistoryMessagePosition.notShowLatest) {
@ -724,18 +726,12 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = final messageInfoWithSender =
tools.setUserInfoForMessage(messageInfo, textATMessageInfo.id!); tools.setUserInfoForMessage(messageInfo, textATMessageInfo.id!);
V2TimMessage? lifeCycleMsg; messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
if (lifeCycle?.messageWillSend != null) { addSendingMessageID(messageInfo.id);
lifeCycleMsg = await lifeCycle?.messageWillSend(messageInfoWithSender);
if (lifeCycleMsg == null) {
return null;
}
}
if (globalModel.getMessageListPosition(conversationID) != if (globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) { HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [ currentHistoryMsgList = [
lifeCycleMsg ?? messageInfoWithSender, messageInfoWithSender,
...currentHistoryMsgList ...currentHistoryMsgList
]; ];
globalModel.setMessageList(conversationID, currentHistoryMsgList); globalModel.setMessageList(conversationID, currentHistoryMsgList);
@ -756,25 +752,19 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
{required String data, {required String data,
required String convID, required String convID,
required ConvType convType}) async { required ConvType convType}) async {
final textATMessageInfo = final customMessageInfo =
await _messageService.createCustomMessage(data: data); await _messageService.createCustomMessage(data: data);
List<V2TimMessage> currentHistoryMsgList = getOriginMessageList(); List<V2TimMessage> currentHistoryMsgList = getOriginMessageList();
final messageInfo = textATMessageInfo!.messageInfo; final messageInfo = customMessageInfo!.messageInfo;
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = final messageInfoWithSender =
tools.setUserInfoForMessage(messageInfo, textATMessageInfo.id!); tools.setUserInfoForMessage(messageInfo, customMessageInfo.id!);
V2TimMessage? lifeCycleMsg; messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
if (lifeCycle?.messageWillSend != null) { addSendingMessageID(messageInfo.id);
lifeCycleMsg = await lifeCycle?.messageWillSend(messageInfoWithSender);
if (lifeCycleMsg == null) {
return null;
}
}
if (globalModel.getMessageListPosition(conversationID) != if (globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) { HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [ currentHistoryMsgList = [
lifeCycleMsg ?? messageInfoWithSender, messageInfoWithSender,
...currentHistoryMsgList ...currentHistoryMsgList
]; ];
globalModel.setMessageList(conversationID, currentHistoryMsgList); globalModel.setMessageList(conversationID, currentHistoryMsgList);
@ -783,10 +773,10 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
return _sendMessage( return _sendMessage(
convID: convID, convID: convID,
id: textATMessageInfo.id as String, id: customMessageInfo.id as String,
convType: convType, convType: convType,
offlinePushInfo: tools.buildMessagePushInfo( offlinePushInfo: tools.buildMessagePushInfo(
textATMessageInfo.messageInfo!, convID, convType)); customMessageInfo.messageInfo!, convID, convType));
} }
return null; return null;
} }
@ -796,25 +786,19 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
required String data, required String data,
required String convID, required String convID,
required ConvType convType}) async { required ConvType convType}) async {
final textMessageInfo = final faceMessageInfo =
await _messageService.createFaceMessage(index: index, data: data); await _messageService.createFaceMessage(index: index, data: data);
List<V2TimMessage> currentHistoryMsgList = getOriginMessageList(); List<V2TimMessage> currentHistoryMsgList = getOriginMessageList();
final messageInfo = textMessageInfo!.messageInfo; final messageInfo = faceMessageInfo!.messageInfo;
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = final messageInfoWithSender =
tools.setUserInfoForMessage(messageInfo, textMessageInfo.id!); tools.setUserInfoForMessage(messageInfo, faceMessageInfo.id!);
V2TimMessage? lifeCycleMsg; messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
if (lifeCycle?.messageWillSend != null) { addSendingMessageID(messageInfo.id);
lifeCycleMsg = await lifeCycle?.messageWillSend(messageInfoWithSender);
if (lifeCycleMsg == null) {
return null;
}
}
if (globalModel.getMessageListPosition(conversationID) != if (globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) { HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [ currentHistoryMsgList = [
lifeCycleMsg ?? messageInfoWithSender, messageInfoWithSender,
...currentHistoryMsgList ...currentHistoryMsgList
]; ];
globalModel.setMessageList(conversationID, currentHistoryMsgList); globalModel.setMessageList(conversationID, currentHistoryMsgList);
@ -823,11 +807,11 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
return _sendMessage( return _sendMessage(
convID: convID, convID: convID,
id: textMessageInfo.id as String, id: faceMessageInfo.id as String,
convType: convType, convType: convType,
messageInfo: lifeCycleMsg ?? messageInfoWithSender, messageInfo: messageInfoWithSender,
offlinePushInfo: tools.buildMessagePushInfo( offlinePushInfo: tools.buildMessagePushInfo(
textMessageInfo.messageInfo!, convID, convType)); faceMessageInfo.messageInfo!, convID, convType));
} }
return null; return null;
} }
@ -845,18 +829,12 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = final messageInfoWithSender =
tools.setUserInfoForMessage(messageInfo, soundMessageInfo.id!); tools.setUserInfoForMessage(messageInfo, soundMessageInfo.id!);
V2TimMessage? lifeCycleMsg; messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
if (lifeCycle?.messageWillSend != null) { addSendingMessageID(messageInfo.id);
lifeCycleMsg = await lifeCycle?.messageWillSend(messageInfoWithSender);
if (lifeCycleMsg == null) {
return null;
}
}
if (globalModel.getMessageListPosition(conversationID) != if (globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) { HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [ currentHistoryMsgList = [
lifeCycleMsg ?? messageInfoWithSender, messageInfoWithSender,
...currentHistoryMsgList ...currentHistoryMsgList
]; ];
globalModel.setMessageList(conversationID, currentHistoryMsgList); globalModel.setMessageList(conversationID, currentHistoryMsgList);
@ -899,6 +877,8 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
if (messageInfo != null) { if (messageInfo != null) {
V2TimMessage messageInfoWithSender = V2TimMessage messageInfoWithSender =
tools.setUserInfoForMessage(messageInfo, textMessageInfo.id!); tools.setUserInfoForMessage(messageInfo, textMessageInfo.id!);
messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
addSendingMessageID(messageInfo.id);
final hasNickName = _repliedMessage?.nickName != null && final hasNickName = _repliedMessage?.nickName != null &&
_repliedMessage?.nickName != ""; _repliedMessage?.nickName != "";
final cloudCustomData = { final cloudCustomData = {
@ -914,17 +894,9 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
} }
}; };
messageInfoWithSender.cloudCustomData = json.encode(cloudCustomData); messageInfoWithSender.cloudCustomData = json.encode(cloudCustomData);
V2TimMessage? lifeCycleMsg;
if (lifeCycle?.messageWillSend != null) {
lifeCycleMsg = await lifeCycle?.messageWillSend(
messageInfoWithSender, repliedMessage);
if (lifeCycleMsg == null) {
return null;
}
}
List<V2TimMessage> currentHistoryMsgList = getOriginMessageList(); List<V2TimMessage> currentHistoryMsgList = getOriginMessageList();
currentHistoryMsgList = [ currentHistoryMsgList = [
lifeCycleMsg ?? messageInfoWithSender, messageInfoWithSender,
...currentHistoryMsgList ...currentHistoryMsgList
]; ];
globalModel.setMessageList(conversationID, currentHistoryMsgList); globalModel.setMessageList(conversationID, currentHistoryMsgList);
@ -932,7 +904,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
_repliedMessage = null; _repliedMessage = null;
final sendMsgRes = await _messageService.sendMessage( final sendMsgRes = await _messageService.sendMessage(
cloudCustomData: cloudCustomData:
TencentUtils.checkString(lifeCycleMsg?.cloudCustomData) ?? TencentUtils.checkString(messageInfoWithSender?.cloudCustomData) ??
json.encode(cloudCustomData), json.encode(cloudCustomData),
id: textMessageInfo.id as String, id: textMessageInfo.id as String,
offlinePushInfo: tools.buildMessagePushInfo( offlinePushInfo: tools.buildMessagePushInfo(
@ -1007,19 +979,12 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = final messageInfoWithSender =
tools.setUserInfoForMessage(messageInfo, imageMessageInfo.id); tools.setUserInfoForMessage(messageInfo, imageMessageInfo.id);
messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
V2TimMessage? lifeCycleMsg; addSendingMessageID(messageInfo.id);
if (lifeCycle?.messageWillSend != null) {
lifeCycleMsg = await lifeCycle?.messageWillSend(messageInfoWithSender);
if (lifeCycleMsg == null) {
return null;
}
}
if (globalModel.getMessageListPosition(conversationID) != if (globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) { HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [ currentHistoryMsgList = [
lifeCycleMsg ?? messageInfoWithSender, messageInfoWithSender,
...currentHistoryMsgList ...currentHistoryMsgList
]; ];
globalModel.setMessageList(conversationID, currentHistoryMsgList); globalModel.setMessageList(conversationID, currentHistoryMsgList);
@ -1028,7 +993,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
return _sendMessage( return _sendMessage(
convID: convID, convID: convID,
messageInfo: lifeCycleMsg ?? messageInfoWithSender, messageInfo: messageInfoWithSender,
id: imageMessageInfo.id as String, id: imageMessageInfo.id as String,
convType: convType, convType: convType,
offlinePushInfo: tools.buildMessagePushInfo( offlinePushInfo: tools.buildMessagePushInfo(
@ -1058,18 +1023,12 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = final messageInfoWithSender =
tools.setUserInfoForMessage(messageInfo, videoMessageInfo.id); tools.setUserInfoForMessage(messageInfo, videoMessageInfo.id);
V2TimMessage? lifeCycleMsg; messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
if (lifeCycle?.messageWillSend != null) { addSendingMessageID(messageInfo.id);
lifeCycleMsg = await lifeCycle?.messageWillSend(messageInfoWithSender);
if (lifeCycleMsg == null) {
return null;
}
}
if (globalModel.getMessageListPosition(conversationID) != if (globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) { HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [ currentHistoryMsgList = [
lifeCycleMsg ?? messageInfoWithSender, messageInfoWithSender,
...currentHistoryMsgList ...currentHistoryMsgList
]; ];
globalModel.setMessageList(conversationID, currentHistoryMsgList); globalModel.setMessageList(conversationID, currentHistoryMsgList);
@ -1078,7 +1037,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
return _sendMessage( return _sendMessage(
convID: convID, convID: convID,
messageInfo: lifeCycleMsg ?? messageInfoWithSender, messageInfo: messageInfoWithSender,
id: videoMessageInfo.id as String, id: videoMessageInfo.id as String,
convType: convType, convType: convType,
offlinePushInfo: tools.buildMessagePushInfo( offlinePushInfo: tools.buildMessagePushInfo(
@ -1112,19 +1071,13 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = final messageInfoWithSender =
tools.setUserInfoForMessage(messageInfo, fileMessageInfo.id); tools.setUserInfoForMessage(messageInfo, fileMessageInfo.id);
messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
addSendingMessageID(messageInfo.id);
messageInfoWithSender.fileElem!.fileSize = size; messageInfoWithSender.fileElem!.fileSize = size;
V2TimMessage? lifeCycleMsg;
if (lifeCycle?.messageWillSend != null) {
lifeCycleMsg = await lifeCycle?.messageWillSend(messageInfoWithSender);
if (lifeCycleMsg == null) {
return null;
}
}
if (globalModel.getMessageListPosition(conversationID) != if (globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) { HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [ currentHistoryMsgList = [
lifeCycleMsg ?? messageInfoWithSender, messageInfoWithSender,
...currentHistoryMsgList ...currentHistoryMsgList
]; ];
globalModel.setMessageList(conversationID, currentHistoryMsgList); globalModel.setMessageList(conversationID, currentHistoryMsgList);
@ -1133,7 +1086,7 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
return _sendMessage( return _sendMessage(
convID: convID, convID: convID,
messageInfo: lifeCycleMsg ?? messageInfoWithSender, messageInfo: messageInfoWithSender,
id: fileMessageInfo.id as String, id: fileMessageInfo.id as String,
convType: convType, convType: convType,
offlinePushInfo: tools.buildMessagePushInfo( offlinePushInfo: tools.buildMessagePushInfo(
@ -1156,18 +1109,12 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = final messageInfoWithSender =
tools.setUserInfoForMessage(messageInfo, locationMessageInfo.id); tools.setUserInfoForMessage(messageInfo, locationMessageInfo.id);
V2TimMessage? lifeCycleMsg; messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
if (lifeCycle?.messageWillSend != null) { addSendingMessageID(messageInfo.id);
lifeCycleMsg = await lifeCycle?.messageWillSend(messageInfoWithSender);
if (lifeCycleMsg == null) {
return null;
}
}
if (globalModel.getMessageListPosition(conversationID) != if (globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) { HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [ currentHistoryMsgList = [
lifeCycleMsg ?? messageInfoWithSender, messageInfoWithSender,
...currentHistoryMsgList ...currentHistoryMsgList
]; ];
globalModel.setMessageList(conversationID, currentHistoryMsgList); globalModel.setMessageList(conversationID, currentHistoryMsgList);
@ -1197,16 +1144,9 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
await _messageService.createForwardMessage(msgID: message.msgID!); await _messageService.createForwardMessage(msgID: message.msgID!);
final messageInfo = forwardMessageInfo!.messageInfo; final messageInfo = forwardMessageInfo!.messageInfo;
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = tools.setUserInfoForMessage(messageInfo, forwardMessageInfo.id);
tools.setUserInfoForMessage(messageInfo, forwardMessageInfo.id); messageInfo.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
V2TimMessage? lifeCycleMsg; addSendingMessageID(messageInfo.id);
if (lifeCycle?.messageWillSend != null) {
lifeCycleMsg =
await lifeCycle?.messageWillSend(messageInfoWithSender);
if (lifeCycleMsg == null) {
return null;
}
}
_sendMessage( _sendMessage(
id: forwardMessageInfo.id!, id: forwardMessageInfo.id!,
convID: convID, convID: convID,
@ -1242,17 +1182,9 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
compatibleText: TIM_t("该版本不支持此消息")); compatibleText: TIM_t("该版本不支持此消息"));
final messageInfo = mergerMessageInfo!.messageInfo; final messageInfo = mergerMessageInfo!.messageInfo;
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = tools.setUserInfoForMessage(messageInfo, mergerMessageInfo.id);
tools.setUserInfoForMessage(messageInfo, mergerMessageInfo.id); messageInfo.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
addSendingMessageID(messageInfo.id);
V2TimMessage? lifeCycleMsg;
if (lifeCycle?.messageWillSend != null) {
lifeCycleMsg =
await lifeCycle?.messageWillSend(messageInfoWithSender);
if (lifeCycleMsg == null) {
continue;
}
}
_sendMessage( _sendMessage(
id: mergerMessageInfo.id!, id: mergerMessageInfo.id!,
convID: convID, convID: convID,
@ -1267,96 +1199,34 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
return null; return null;
} }
Future<V2TimValueCallback<V2TimMessage>?> reSendMessage(
{required String msgID,
required String convID,
bool? onlineUserOnly}) async {
final res = await _messageService.reSendMessage(
msgID: msgID, onlineUserOnly: onlineUserOnly ?? false);
final messageInfo = res.data;
List<V2TimMessage> currentHistoryMsgList = getOriginMessageList();
// final messageInfo = textMessageInfo!.messageInfo;
if (messageInfo != null) {
final messageInfoWithSender =
tools.setUserInfoForMessage(messageInfo, messageInfo.id!);
V2TimMessage? lifeCycleMsg;
if (lifeCycle?.messageWillSend != null) {
lifeCycleMsg = await lifeCycle?.messageWillSend(messageInfoWithSender);
if (lifeCycleMsg == null) {
return null;
}
}
currentHistoryMsgList = [
lifeCycleMsg ?? messageInfoWithSender,
...currentHistoryMsgList
];
globalModel.setMessageList(convID, currentHistoryMsgList);
}
return res;
}
//
Future<V2TimValueCallback<V2TimMessage>?> reSendFailMessage({ Future<V2TimValueCallback<V2TimMessage>?> reSendFailMessage({
required V2TimMessage message, required V2TimMessage message,
required String convID, required String convID,
required ConvType convType, required ConvType convType,
List<String>? atUserIDList,
}) async { }) async {
await deleteMsg(message.msgID ?? "", List<V2TimMessage> currentHistoryMsgList = getOriginMessageList();
id: message.id, webMessageInstance: message.messageFromWeb); if (currentHistoryMsgList.isEmpty) {
int messageType = message.elemType; return null;
V2TimValueCallback<V2TimMessage>? res;
if (messageType == MessageElemType.V2TIM_ELEM_TYPE_TEXT) {
String text = message.textElem!.text!;
if (_repliedMessage != null) {
res = await sendReplyMessage(
text: text,
convID: convID,
convType: convType,
atUserIDList: atUserIDList,
);
} else {
res = await sendTextMessage(
text: text, convID: convID, convType: convType);
}
} }
if (messageType == MessageElemType.V2TIM_ELEM_TYPE_SOUND) {
String soundPath = message.soundElem!.path!; int messageIndex = currentHistoryMsgList.indexWhere((element) => element.msgID == message.msgID);
int duration = message.soundElem!.duration!; if (messageIndex != -1) {
res = await sendSoundMessage( // sending
soundPath: soundPath, currentHistoryMsgList[messageIndex].status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
duration: duration, addSendingMessageID(message.msgID);
convID: convID, globalModel.setMessageList(convID, currentHistoryMsgList);
convType: convType); //
final res = await _messageService.reSendMessage(
msgID: message.msgID ?? "", onlineUserOnly: false);
removeSendingMessageID(message.msgID ?? "");
final messageInfo = res.data;
//
currentHistoryMsgList[messageIndex] = messageInfo!;
globalModel.setMessageList(convID, currentHistoryMsgList);
return res;
} }
if (messageType == MessageElemType.V2TIM_ELEM_TYPE_IMAGE) {
String imagePath = message.imageElem!.path!; return null;
res = await sendImageMessage(
imagePath: imagePath, convID: convID, convType: convType);
}
if (messageType == MessageElemType.V2TIM_ELEM_TYPE_VIDEO) {
String videoPath = message.videoElem?.videoPath ?? "";
int duration = message.videoElem?.duration ?? 0;
String snapshotPath = message.videoElem?.snapshotPath ?? "";
res = await sendVideoMessage(
videoPath: videoPath,
duration: duration,
snapshotPath: snapshotPath,
convID: convID,
convType: convType);
}
if (messageType == MessageElemType.V2TIM_ELEM_TYPE_FILE) {
String filePath = message.fileElem?.path ?? "";
int size = message.fileElem?.fileSize ?? 0;
res = await sendFileMessage(
filePath: filePath, size: size, convID: convID, convType: convType);
}
if (messageType == MessageElemType.V2TIM_ELEM_TYPE_CUSTOM) {
String data = message.customElem?.data ?? "";
res = await sendCustomMessage(
convID: convID, convType: convType, data: data);
}
return res;
} }
Future<V2TimValueCallback<V2TimMessage>?> sendTextMessage( Future<V2TimValueCallback<V2TimMessage>?> sendTextMessage(
@ -1372,18 +1242,12 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = final messageInfoWithSender =
tools.setUserInfoForMessage(messageInfo, textMessageInfo.id!); tools.setUserInfoForMessage(messageInfo, textMessageInfo.id!);
V2TimMessage? lifeCycleMsg; messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
if (lifeCycle?.messageWillSend != null) { addSendingMessageID(messageInfo.id);
lifeCycleMsg = await lifeCycle?.messageWillSend(messageInfoWithSender);
if (lifeCycleMsg == null) {
return null;
}
}
if (globalModel.getMessageListPosition(conversationID) != if (globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) { HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [ currentHistoryMsgList = [
lifeCycleMsg ?? messageInfoWithSender, messageInfoWithSender,
...currentHistoryMsgList ...currentHistoryMsgList
]; ];
globalModel.setMessageList(conversationID, currentHistoryMsgList); globalModel.setMessageList(conversationID, currentHistoryMsgList);
@ -1417,7 +1281,8 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
final messageInfoWithSender = messageInfo.sender == null final messageInfoWithSender = messageInfo.sender == null
? tools.setUserInfoForMessage(messageInfo, messageInfo.id!) ? tools.setUserInfoForMessage(messageInfo, messageInfo.id!)
: messageInfo; : messageInfo;
messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
addSendingMessageID(messageInfo.id);
if (globalModel.getMessageListPosition(conversationID) != if (globalModel.getMessageListPosition(conversationID) !=
HistoryMessagePosition.notShowLatest) { HistoryMessagePosition.notShowLatest) {
currentHistoryMsgList = [ currentHistoryMsgList = [
@ -1574,6 +1439,26 @@ class TUIChatSeparateViewModel extends ChangeNotifier {
conversationID, HistoryMessagePosition.bottom); conversationID, HistoryMessagePosition.bottom);
} }
// id msgID(id 使 msgID)
void addSendingMessageID(String? id) {
if (id?.isNotEmpty == true) {
_sendingMessageIDList.add(id!);
}
}
// id msgID(id 使 msgID)
void removeSendingMessageID(String id) {
bool hasID = _sendingMessageIDList.contains(id);
if (hasID) {
_sendingMessageIDList.remove(id);
}
}
// id msgID(id 使 msgID)
bool hasSendingMessageID(String id) {
return _sendingMessageIDList.contains(id);
}
@override @override
void dispose() { void dispose() {
globalModel.clearCurrentConversation(); globalModel.clearCurrentConversation();

View File

@ -747,6 +747,7 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
List<V2TimMessage> currentHistoryMsgList = _messageListMap[convID] ?? []; List<V2TimMessage> currentHistoryMsgList = _messageListMap[convID] ?? [];
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = messageInfo.sender == null ? tools.setUserInfoForMessage(messageInfo, messageInfo.id!) : messageInfo; final messageInfoWithSender = messageInfo.sender == null ? tools.setUserInfoForMessage(messageInfo, messageInfo.id!) : messageInfo;
messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
currentHistoryMsgList = [messageInfoWithSender, ...currentHistoryMsgList]; currentHistoryMsgList = [messageInfoWithSender, ...currentHistoryMsgList];
setMessageList(convID, currentHistoryMsgList); setMessageList(convID, currentHistoryMsgList);
if (loadingMessage[convID] != null && loadingMessage[convID]!.isNotEmpty) { if (loadingMessage[convID] != null && loadingMessage[convID]!.isNotEmpty) {
@ -799,7 +800,7 @@ class TUIChatGlobalModel extends ChangeNotifier implements TIMUIKitClass {
if (messageInfo != null) { if (messageInfo != null) {
final messageInfoWithSender = messageInfo.sender == null ? tools.setUserInfoForMessage(messageInfo, messageInfo.id ?? textMessageInfo.id ?? "") : messageInfo; final messageInfoWithSender = messageInfo.sender == null ? tools.setUserInfoForMessage(messageInfo, messageInfo.id ?? textMessageInfo.id ?? "") : messageInfo;
messageInfoWithSender.status = MessageStatus.V2TIM_MSG_STATUS_SENDING;
final hasNickName = messageBeenReplied.nickName != null && messageBeenReplied.nickName != ""; final hasNickName = messageBeenReplied.nickName != null && messageBeenReplied.nickName != "";
final cloudCustomData = { final cloudCustomData = {
"messageReply": { "messageReply": {

View File

@ -265,7 +265,7 @@ class MessageServiceImpl extends MessageService {
@override @override
Future<V2TimValueCallback<V2TimMessage>> reSendMessage( Future<V2TimValueCallback<V2TimMessage>> reSendMessage(
{required String msgID, // ID {required String msgID,
bool? onlineUserOnly}) async { bool? onlineUserOnly}) async {
final res = await TencentImSDKPlugin.v2TIMManager final res = await TencentImSDKPlugin.v2TIMManager
.getMessageManager() .getMessageManager()

View File

@ -83,7 +83,7 @@ abstract class MessageService {
}); });
Future<V2TimValueCallback<V2TimMessage>> reSendMessage( Future<V2TimValueCallback<V2TimMessage>> reSendMessage(
{required String msgID, // ID {required String msgID,
bool onlineUserOnly}); bool onlineUserOnly});
Future<V2TimValueCallback<V2TimMessageChangeInfo>> modifyMessage( Future<V2TimValueCallback<V2TimMessageChangeInfo>> modifyMessage(

View File

@ -207,9 +207,6 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
/// Control avatar hide or show /// Control avatar hide or show
final bool showAvatar; final bool showAvatar;
/// message sending status
final bool showMessageSending;
/// message is read status /// message is read status
final bool showMessageReadRecipt; final bool showMessageReadRecipt;
@ -283,7 +280,6 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
this.messageItemBuilder, this.messageItemBuilder,
this.onLongPressForOthersHeadPortrait, this.onLongPressForOthersHeadPortrait,
this.showAvatar = true, this.showAvatar = true,
this.showMessageSending = true,
this.showMessageReadRecipt = true, this.showMessageReadRecipt = true,
this.allowLongPress = true, this.allowLongPress = true,
this.toolTipsConfig, this.toolTipsConfig,
@ -343,8 +339,9 @@ class TipsActionItem extends TIMUIKitStatelessWidget {
} }
} }
class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistoryMessageListItem> with TickerProviderStateMixin { class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistoryMessageListItem> with SingleTickerProviderStateMixin {
SuperTooltip? tooltip; SuperTooltip? tooltip;
late AnimationController _animationController;
// ignore: unused_field // ignore: unused_field
final MessageService _messageService = serviceLocator<MessageService>(); final MessageService _messageService = serviceLocator<MessageService>();
@ -356,6 +353,12 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
bool isShowWideToolTip = false; bool isShowWideToolTip = false;
TapDownDetails? _tapDetails; TapDownDetails? _tapDetails;
@override
void initState() {
super.initState();
_animationController = AnimationController(duration: const Duration(seconds: 1), vsync: this)..repeat();
}
closeTooltip() { closeTooltip() {
tooltip?.close(); tooltip?.close();
} }
@ -877,6 +880,7 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
@override @override
void dispose() { void dispose() {
_animationController.dispose();
super.dispose(); super.dispose();
if (tooltip?.isOpen ?? false) { if (tooltip?.isOpen ?? false) {
tooltip?.close(); tooltip?.close();
@ -1052,11 +1056,28 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
}, },
child: Icon(Icons.error, color: theme.cautionColor, size: 18), child: Icon(Icons.error, color: theme.cautionColor, size: 18),
)), )),
if (isSelf && message.status == MessageStatus.V2TIM_MSG_STATUS_SENDING && model.hasSendingMessageID(message.id ?? message.msgID!))
FutureBuilder(
future: Future.delayed(const Duration(seconds: 1)),
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
if (snapshot.connectionState == ConnectionState.done && model.hasSendingMessageID(message.id ?? message.msgID!)) {
return Container(
padding: const EdgeInsets.only(bottom: 3),
margin: const EdgeInsets.only(right: 6),
child: RotationTransition(
turns: Tween(begin: 0.0, end: 1.0).animate(_animationController),
child: Icon(Icons.rotate_right, color: theme.cautionColor, size: 18),
),
);
} else {
return Container();
}
},
),
if (model.chatConfig.isShowReadingStatus && if (model.chatConfig.isShowReadingStatus &&
widget.showMessageReadRecipt && widget.showMessageReadRecipt &&
model.conversationType == ConvType.c2c && model.conversationType == ConvType.c2c &&
isSelf && isSelf && message.status == MessageStatus.V2TIM_MSG_STATUS_SEND_SUCC)
(message.status == MessageStatus.V2TIM_MSG_STATUS_SEND_SUCC || message.status == MessageStatus.V2TIM_MSG_STATUS_SENDING))
Container( Container(
padding: const EdgeInsets.only(bottom: 3), padding: const EdgeInsets.only(bottom: 3),
margin: const EdgeInsets.only(right: 6), margin: const EdgeInsets.only(right: 6),
@ -1068,8 +1089,7 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
if (model.chatConfig.isShowGroupReadingStatus && if (model.chatConfig.isShowGroupReadingStatus &&
model.chatConfig.isShowGroupMessageReadReceipt && model.chatConfig.isShowGroupMessageReadReceipt &&
model.conversationType == ConvType.group && model.conversationType == ConvType.group &&
isSelf && isSelf && message.status == MessageStatus.V2TIM_MSG_STATUS_SEND_SUCC)
(message.status == MessageStatus.V2TIM_MSG_STATUS_SEND_SUCC || message.status == MessageStatus.V2TIM_MSG_STATUS_SENDING))
TIMUIKitMessageReadReceipt( TIMUIKitMessageReadReceipt(
messageItem: widget.message, messageItem: widget.message,
onTapAvatar: widget.onTapForOthersPortrait, onTapAvatar: widget.onTapForOthersPortrait,

View File

@ -622,9 +622,9 @@ class TIMUIKitMessageTooltipState
alignment: alignment:
TUIKitScreenUtils.getFormFactor(context) == TUIKitScreenUtils.getFormFactor(context) ==
DeviceType.Mobile DeviceType.Mobile
? WrapAlignment.spaceBetween ? WrapAlignment.start
: WrapAlignment.start, : WrapAlignment.start,
spacing: 4, spacing: 12,
runSpacing: 8, runSpacing: 8,
children: [ children: [
..._buildLongPressTipItem(theme, model, message), ..._buildLongPressTipItem(theme, model, message),

View File

@ -64,7 +64,6 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
final TUIChatGlobalModel model = serviceLocator<TUIChatGlobalModel>(); final TUIChatGlobalModel model = serviceLocator<TUIChatGlobalModel>();
final MessageService _messageService = serviceLocator<MessageService>(); final MessageService _messageService = serviceLocator<MessageService>();
Widget? imageItem; Widget? imageItem;
bool isSent = false;
@override @override
didUpdateWidget(oldWidget) { didUpdateWidget(oldWidget) {
@ -592,13 +591,6 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
initImages(); initImages();
} }
bool isNeedShowLocalPath() {
final current = (DateTime.now().millisecondsSinceEpoch / 1000).ceil();
final timeStamp = widget.message.timestamp ?? current;
return (widget.message.isSelf ?? true) &&
(isSent || current - timeStamp < 300);
}
Widget? _renderImage(dynamic heroTag, TUITheme theme, Widget? _renderImage(dynamic heroTag, TUITheme theme,
{V2TimImage? originalImg, V2TimImage? smallImg}) { {V2TimImage? originalImg, V2TimImage? smallImg}) {
@ -623,7 +615,7 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
} }
try { try {
if ((isNeedShowLocalPath() && if ((widget.message.isSelf! &&
widget.message.imageElem!.path != null && widget.message.imageElem!.path != null &&
widget.message.imageElem!.path!.isNotEmpty && widget.message.imageElem!.path!.isNotEmpty &&
File(widget.message.imageElem!.path!).existsSync())) { File(widget.message.imageElem!.path!).existsSync())) {
@ -680,9 +672,6 @@ class _TIMUIKitImageElem extends TIMUIKitState<TIMUIKitImageElem> {
@override @override
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
final theme = value.theme; final theme = value.theme;
if (widget.message.status == MessageStatus.V2TIM_MSG_STATUS_SENDING) {
isSent = true;
}
final isDesktopScreen = final isDesktopScreen =
TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop; TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
final heroTag = final heroTag =

View File

@ -210,9 +210,6 @@ class GroupProfileButtonArea extends TIMUIKitStatelessWidget {
actions: [ actions: [
CupertinoActionSheetAction( CupertinoActionSheetAction(
onPressed: () async { onPressed: () async {
Navigator.pop(
context,
);
final res = await sdkInstance.dismissGroup(groupID: groupID); final res = await sdkInstance.dismissGroup(groupID: groupID);
if (res.code == 0) { if (res.code == 0) {
await sdkInstance await sdkInstance

View File

@ -304,7 +304,7 @@ class TIMUIKitProfileWidget extends TIMUIKitClass {
border: border:
Border(bottom: BorderSide(color: theme.weakDividerColor))), Border(bottom: BorderSide(color: theme.weakDividerColor))),
child: Text( child: Text(
TIM_t("除好友"), TIM_t("除好友"),
style: TextStyle(color: theme.cautionColor, fontSize: 17), style: TextStyle(color: theme.cautionColor, fontSize: 17),
), ),
), ),
@ -392,7 +392,7 @@ class TIMUIKitProfileWidget extends TIMUIKitClass {
handleDeleteFriend(); handleDeleteFriend();
}, },
color: theme.cautionColor ?? Colors.red, color: theme.cautionColor ?? Colors.red,
text: TIM_t("除好友"), text: TIM_t("除好友"),
); );
} }

View File

@ -232,7 +232,7 @@ class _VideoScreenState extends TIMUIKitState<VideoScreen> {
: VideoPlayerController.networkUrl( : VideoPlayerController.networkUrl(
Uri.parse(widget.videoElement.localVideoUrl!), 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) && File(widget.videoElement.videoPath!).existsSync())
? VideoPlayerController.file(File(widget.videoElement.videoPath!)) ? VideoPlayerController.file(File(widget.videoElement.videoPath!))
: (TencentUtils.checkString(widget.videoElement.localVideoUrl) == null) : (TencentUtils.checkString(widget.videoElement.localVideoUrl) == null)
? VideoPlayerController.networkUrl( ? VideoPlayerController.networkUrl(

View File

@ -1,6 +1,6 @@
name: tencent_cloud_chat_uikit name: tencent_cloud_chat_uikit
description: A powerful chat UI component library and business logic for Tencent Cloud Chat, creating seamless in-app chat modules for delightful user experiences. description: A powerful chat UI component library and business logic for Tencent Cloud Chat, creating seamless in-app chat modules for delightful user experiences.
version: 2.7.1 version: 2.7.2
homepage: https://trtc.io/products/chat?utm_source=gfs&utm_medium=link&utm_campaign=%E6%B8%A0%E9%81%93&_channel_track_key=k6WgfCKn homepage: https://trtc.io/products/chat?utm_source=gfs&utm_medium=link&utm_campaign=%E6%B8%A0%E9%81%93&_channel_track_key=k6WgfCKn
repository: https://github.com/TencentCloud/chat-uikit-flutter repository: https://github.com/TencentCloud/chat-uikit-flutter
documentation: https://comm.qq.com/im/doc/flutter/en/TUIKit/readme.html documentation: https://comm.qq.com/im/doc/flutter/en/TUIKit/readme.html
@ -43,7 +43,7 @@ dependencies:
wechat_assets_picker: ^8.9.0-dev.1 wechat_assets_picker: ^8.9.0-dev.1
wechat_camera_picker: ^4.2.0-dev.2 wechat_camera_picker: ^4.2.0-dev.2
flutter_easyrefresh: ^2.2.1 flutter_easyrefresh: ^2.2.1
extended_image: ^8.2.0 extended_image: '>=8.2.0 <=8.2.4'
extended_text_field: ^15.0.0 extended_text_field: ^15.0.0
extended_text: ^13.0.0 extended_text: ^13.0.0
package_info_plus: ^4.0.1 package_info_plus: ^4.0.1