feat: Enhance contact telemetry updates with last seen timestamp and improve message bubble UI for SAR and drawing indicators

This commit is contained in:
Janez T
2025-10-26 17:04:25 +01:00
parent b8147e904c
commit a6fbc10221
3 changed files with 158 additions and 130 deletions

View File

@@ -304,10 +304,19 @@ class ContactsProvider with ChangeNotifier {
debugPrint(' ✅ Parsed new telemetry'); debugPrint(' ✅ Parsed new telemetry');
debugPrint(' New telemetry timestamp: ${telemetry.timestamp}'); debugPrint(' New telemetry timestamp: ${telemetry.timestamp}');
// Update contact with new telemetry // Update contact with new telemetry AND last seen time
final updatedContact = contact.copyWith(telemetry: telemetry); // lastAdvert is Unix timestamp in seconds
final currentTimestamp =
(DateTime.now().millisecondsSinceEpoch / 1000).round();
debugPrint(' Old lastAdvert: ${contact.lastAdvert}');
debugPrint(' New lastAdvert: $currentTimestamp');
final updatedContact = contact.copyWith(
telemetry: telemetry,
lastAdvert: currentTimestamp, // Update last seen time
);
_contacts[contact.publicKeyHex] = updatedContact; _contacts[contact.publicKeyHex] = updatedContact;
debugPrint(' ✅ Updated contact in map'); debugPrint(' ✅ Updated contact in map (with new lastAdvert)');
_persistContacts(); _persistContacts();
debugPrint(' ✅ Persisted contacts to storage'); debugPrint(' ✅ Persisted contacts to storage');

View File

@@ -1413,7 +1413,8 @@ class _MessageBubble extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Header: Sender and time // Header: Badge (if SAR or drawing) and time
if (isSarMarker || message.isDrawing)
Row( Row(
children: [ children: [
// Unread indicator badge // Unread indicator badge
@@ -1491,8 +1492,37 @@ class _MessageBubble extends StatelessWidget {
), ),
], ],
), ),
) ),
else ...[ const Spacer(),
Text(
message.getLocalizedTimeAgo(context),
style: Theme.of(context).textTheme.labelSmall?.copyWith(
fontWeight: isSarMarker
? FontWeight.w600
: FontWeight.normal,
),
),
],
),
// Sender info row (shown for all messages)
Row(
children: [
// Unread indicator badge (only for regular messages, not SAR/drawing)
if (!message.isRead &&
!message.isSentMessage &&
!message.isSystemMessage &&
!isSarMarker &&
!message.isDrawing)
Container(
width: 8,
height: 8,
margin: const EdgeInsets.only(right: 8),
decoration: const BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
),
if (isOwnMessage) if (isOwnMessage)
Icon( Icon(
Icons.account_circle, Icons.account_circle,
@@ -1536,15 +1566,12 @@ class _MessageBubble extends StatelessWidget {
), ),
), ),
], ],
],
const Spacer(), const Spacer(),
// Time for regular messages (not shown for SAR/drawing as it's already above)
if (!isSarMarker && !message.isDrawing)
Text( Text(
message.getLocalizedTimeAgo(context), message.getLocalizedTimeAgo(context),
style: Theme.of(context).textTheme.labelSmall?.copyWith( style: Theme.of(context).textTheme.labelSmall,
fontWeight: isSarMarker
? FontWeight.w600
: FontWeight.normal,
),
), ),
], ],
), ),
@@ -1663,14 +1690,6 @@ class _MessageBubble extends StatelessWidget {
), ),
], ],
), ),
if (drawing.senderName != null) ...[
const SizedBox(height: 4),
Text(
'From: ${drawing.senderName}',
style: Theme.of(context).textTheme.labelSmall
?.copyWith(fontStyle: FontStyle.italic),
),
],
], ],
), ),
), ),

View File

@@ -148,16 +148,16 @@ void main() {
// Verify 3-byte signed encoding // Verify 3-byte signed encoding
// Lat: -33.8688 * 10000 = -338688 // Lat: -33.8688 * 10000 = -338688
// In 24-bit two's complement: -338688 + 0x1000000 = 16438608 = 0xFAD4E0 // In 24-bit two's complement: -338688 + 0x1000000 = 16438528 = 0xFAD500
final latEncoded = final latEncoded =
(encoded[2] << 16) | (encoded[3] << 8) | encoded[4]; (encoded[2] << 16) | (encoded[3] << 8) | encoded[4];
// Lon: -151.2093 * 10000 = -1512093 // Lon: -151.2093 * 10000 = -1512093
// In 24-bit two's complement: -1512093 + 0x1000000 = 15265123 = 0xE8E963 // In 24-bit two's complement: -1512093 + 0x1000000 = 15265123 = 0xE8ED63
final lonEncoded = final lonEncoded =
(encoded[5] << 16) | (encoded[6] << 8) | encoded[7]; (encoded[5] << 16) | (encoded[6] << 8) | encoded[7];
expect(latEncoded, equals(0xFAD4E0)); // Verify two's complement expect(latEncoded, equals(0xFAD500)); // Verify two's complement
expect(lonEncoded, equals(0xE8E963)); expect(lonEncoded, equals(0xE8ED63));
// Verify decoding // Verify decoding
final decoded = CayenneLppParser.parse(encoded); final decoded = CayenneLppParser.parse(encoded);