mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
feat: Enhance message handling with recipient public key and delivery status for improved retry support
This commit is contained in:
@@ -170,7 +170,7 @@ class _MessagesTabState extends State<MessagesTab> {
|
|||||||
final devicePublicKey = connectionProvider.deviceInfo.publicKey;
|
final devicePublicKey = connectionProvider.deviceInfo.publicKey;
|
||||||
final senderPublicKeyPrefix = devicePublicKey?.sublist(0, 6);
|
final senderPublicKeyPrefix = devicePublicKey?.sublist(0, 6);
|
||||||
|
|
||||||
// Create sent message object
|
// Create sent message object with recipient public key for retry support
|
||||||
final sentMessage = Message(
|
final sentMessage = Message(
|
||||||
id: messageId,
|
id: messageId,
|
||||||
messageType: MessageType.contact,
|
messageType: MessageType.contact,
|
||||||
@@ -181,6 +181,7 @@ class _MessagesTabState extends State<MessagesTab> {
|
|||||||
text: fullMessage,
|
text: fullMessage,
|
||||||
receivedAt: DateTime.now(),
|
receivedAt: DateTime.now(),
|
||||||
deliveryStatus: MessageDeliveryStatus.sending,
|
deliveryStatus: MessageDeliveryStatus.sending,
|
||||||
|
recipientPublicKey: roomPublicKey, // Store recipient for retry
|
||||||
// SAR marker data is automatically added by SarMessageParser.enhanceMessage in MessagesProvider
|
// SAR marker data is automatically added by SarMessageParser.enhanceMessage in MessagesProvider
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -408,15 +409,42 @@ class _MessageBubble extends StatelessWidget {
|
|||||||
|
|
||||||
// Resend the message
|
// Resend the message
|
||||||
if (failedMessage.messageType == MessageType.contact) {
|
if (failedMessage.messageType == MessageType.contact) {
|
||||||
// Direct message retry - NOT YET IMPLEMENTED
|
// Direct message retry (for SAR markers sent to rooms)
|
||||||
// Would need to look up contact's full public key by senderKeyShort
|
if (failedMessage.recipientPublicKey == null) {
|
||||||
messagesProvider.markMessageFailed(retryMessageId);
|
messagesProvider.markMessageFailed(retryMessageId);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
const SnackBar(
|
||||||
content: Text('Direct message retry not yet implemented'),
|
content: Text('Cannot retry: recipient information missing'),
|
||||||
backgroundColor: Colors.orange,
|
backgroundColor: Colors.red,
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resend to the same room
|
||||||
|
final sentSuccessfully = await connectionProvider.sendTextMessage(
|
||||||
|
contactPublicKey: failedMessage.recipientPublicKey!,
|
||||||
|
text: failedMessage.text,
|
||||||
|
messageId: retryMessageId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!sentSuccessfully) {
|
||||||
|
messagesProvider.markMessageFailed(retryMessageId);
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('Failed to resend message'),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('Retrying message...'),
|
||||||
|
backgroundColor: Colors.orange,
|
||||||
|
duration: Duration(seconds: 2),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if (failedMessage.messageType == MessageType.channel) {
|
} else if (failedMessage.messageType == MessageType.channel) {
|
||||||
// Channel message retry
|
// Channel message retry
|
||||||
await connectionProvider.sendChannelMessage(
|
await connectionProvider.sendChannelMessage(
|
||||||
|
|||||||
@@ -120,6 +120,14 @@ class MessageStorageService {
|
|||||||
'sarGpsLon': message.sarGpsCoordinates?.longitude,
|
'sarGpsLon': message.sarGpsCoordinates?.longitude,
|
||||||
'receivedAtMillis': message.receivedAt.millisecondsSinceEpoch,
|
'receivedAtMillis': message.receivedAt.millisecondsSinceEpoch,
|
||||||
'senderName': message.senderName,
|
'senderName': message.senderName,
|
||||||
|
'deliveryStatus': message.deliveryStatus.name,
|
||||||
|
'expectedAckTag': message.expectedAckTag,
|
||||||
|
'suggestedTimeoutMs': message.suggestedTimeoutMs,
|
||||||
|
'roundTripTimeMs': message.roundTripTimeMs,
|
||||||
|
'deliveredAtMillis': message.deliveredAt?.millisecondsSinceEpoch,
|
||||||
|
'recipientPublicKey': message.recipientPublicKey != null
|
||||||
|
? base64Encode(message.recipientPublicKey!)
|
||||||
|
: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,6 +163,23 @@ class MessageStorageService {
|
|||||||
receivedAt: DateTime.fromMillisecondsSinceEpoch(
|
receivedAt: DateTime.fromMillisecondsSinceEpoch(
|
||||||
json['receivedAtMillis'] as int),
|
json['receivedAtMillis'] as int),
|
||||||
senderName: json['senderName'] as String?,
|
senderName: json['senderName'] as String?,
|
||||||
|
deliveryStatus: json['deliveryStatus'] != null
|
||||||
|
? MessageDeliveryStatus.values.firstWhere(
|
||||||
|
(e) => e.name == json['deliveryStatus'],
|
||||||
|
orElse: () => MessageDeliveryStatus.received,
|
||||||
|
)
|
||||||
|
: MessageDeliveryStatus.received,
|
||||||
|
expectedAckTag: json['expectedAckTag'] as int?,
|
||||||
|
suggestedTimeoutMs: json['suggestedTimeoutMs'] as int?,
|
||||||
|
roundTripTimeMs: json['roundTripTimeMs'] as int?,
|
||||||
|
deliveredAt: json['deliveredAtMillis'] != null
|
||||||
|
? DateTime.fromMillisecondsSinceEpoch(
|
||||||
|
json['deliveredAtMillis'] as int)
|
||||||
|
: null,
|
||||||
|
recipientPublicKey: json['recipientPublicKey'] != null
|
||||||
|
? Uint8List.fromList(
|
||||||
|
base64Decode(json['recipientPublicKey'] as String))
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('❌ [MessageStorage] Error parsing message from JSON: $e');
|
print('❌ [MessageStorage] Error parsing message from JSON: $e');
|
||||||
|
|||||||
Reference in New Issue
Block a user