Compare commits

...

2 Commits

Author SHA1 Message Date
75deb04a2b ♻️ Better resend message 2025-10-10 22:34:34 +08:00
7c7ed21a96 💄 Optimize message delete when failed to send 2025-10-10 21:50:52 +08:00
4 changed files with 41 additions and 3 deletions

View File

@@ -1208,5 +1208,6 @@
"enterPinToConfirmTransfer": "Enter your 6-digit PIN to confirm transfer",
"transferCreatedSuccessfully": "Transfer created successfully!",
"postUpdate": "Update",
"fileMetadata": "File Metadata"
"fileMetadata": "File Metadata",
"resend": "Resend"
}

View File

@@ -765,13 +765,34 @@ class MessagesNotifier extends _$MessagesNotifier {
Future<void> deleteMessage(String messageId) async {
talker.log('Deleting message $messageId');
// Fetch message to check its status before attempting server delete
final message = await fetchMessageById(messageId);
if (message == null) {
talker.log('Message $messageId not found for deletion');
return;
}
// Skip server delete for failed messages (never successfully sent)
if (message.status == MessageStatus.failed) {
talker.log('Skipping server delete for failed message $messageId');
// For failed messages, remove them completely from the active list
_pendingMessages.remove(messageId);
await _database.deleteMessage(messageId);
final currentMessages = state.value ?? [];
final newMessages =
currentMessages.where((m) => m.id != messageId).toList();
state = AsyncValue.data(newMessages);
return;
}
try {
await _apiClient.delete('/sphere/chat/$_roomId/messages/$messageId');
await receiveMessageDeletion(messageId);
} catch (err, stackTrace) {
talker.log(
'Error deleting message $messageId',
exception: err,
stackTrace: stackTrace,
);

View File

@@ -586,6 +586,8 @@ class ChatRoomScreen extends HookConsumerWidget {
messageForwardingTo.value = message.toRemoteMessage();
case MessageItemAction.reply:
messageReplyingTo.value = message.toRemoteMessage();
case MessageItemAction.resend:
messagesNotifier.retryMessage(message.id);
}
},
onJump: (messageId) {

View File

@@ -34,6 +34,7 @@ class MessageItemAction {
static const String delete = "delete";
static const String reply = "reply";
static const String forward = "forward";
static const String resend = "resend";
}
class MessageItem extends HookConsumerWidget {
@@ -117,6 +118,7 @@ class MessageItem extends HookConsumerWidget {
translate: translate,
isMobile: isMobile,
remoteMessage: remoteMessage,
message: message,
),
);
}
@@ -254,6 +256,7 @@ class MessageActionSheet extends StatefulWidget {
final VoidCallback translate;
final bool isMobile;
final dynamic remoteMessage;
final LocalChatMessage message;
const MessageActionSheet({
super.key,
@@ -265,6 +268,7 @@ class MessageActionSheet extends StatefulWidget {
required this.translate,
required this.isMobile,
required this.remoteMessage,
required this.message,
});
@override
@@ -390,6 +394,16 @@ class _MessageActionSheetState extends State<MessageActionSheet> {
Navigator.pop(context);
},
),
if (widget.isCurrentUser &&
widget.message.status == MessageStatus.failed)
_ActionListTile(
leading: Icon(Symbols.refresh),
title: Text('resend'.tr()),
onTap: () {
widget.onAction!.call(MessageItemAction.resend);
Navigator.pop(context);
},
),
if (widget.isCurrentUser)
_ActionListTile(
leading: Icon(Symbols.delete),
@@ -1188,7 +1202,7 @@ class FileUploadProgressWidget extends StatelessWidget {
'fileUploadingProgress'.tr(
args: [
(entry.key + 1).toString(),
entry.value.toStringAsFixed(1),
(entry.value * 100).toStringAsFixed(1),
],
),
style: TextStyle(