mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
feat: Add new contact and message tracking features, including unread status and removal functionality
This commit is contained in:
@@ -1098,6 +1098,26 @@ class ConnectionProvider with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove a contact from the companion radio
|
||||
///
|
||||
/// Deletes the contact from the device's internal contact table.
|
||||
/// The contact will no longer appear in the contact list and all
|
||||
/// routing information will be cleared.
|
||||
Future<void> removeContact(Uint8List contactPublicKey) async {
|
||||
if (!_bleService.isConnected) {
|
||||
_error = 'Not connected to device';
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await _bleService.removeContact(contactPublicKey);
|
||||
} catch (e) {
|
||||
_error = 'Failed to remove contact: $e';
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear error message
|
||||
void clearError() {
|
||||
_error = null;
|
||||
|
||||
@@ -125,7 +125,18 @@ class ContactsProvider with ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
|
||||
_contacts[contact.publicKeyHex] = contact;
|
||||
// Check if this is a new contact
|
||||
final isNewContact = !_contacts.containsKey(contact.publicKeyHex);
|
||||
|
||||
// If it's a new contact, mark it as new
|
||||
if (isNewContact) {
|
||||
_contacts[contact.publicKeyHex] = contact.copyWith(isNew: true);
|
||||
} else {
|
||||
// Keep existing isNew status when updating
|
||||
final existingContact = _contacts[contact.publicKeyHex]!;
|
||||
_contacts[contact.publicKeyHex] = contact.copyWith(isNew: existingContact.isNew);
|
||||
}
|
||||
|
||||
_persistContacts();
|
||||
notifyListeners();
|
||||
}
|
||||
@@ -242,6 +253,35 @@ class ContactsProvider with ChangeNotifier {
|
||||
return contacts.where((c) => c.isRecentlySeen).toList();
|
||||
}
|
||||
|
||||
/// Get count of new contacts (not yet viewed)
|
||||
int get newContactsCount =>
|
||||
contacts.where((c) => c.isNew && !c.isChannel).length;
|
||||
|
||||
/// Mark all contacts as viewed (not new)
|
||||
void markAllAsViewed() {
|
||||
bool hasChanges = false;
|
||||
_contacts.forEach((key, contact) {
|
||||
if (contact.isNew && !contact.isChannel) {
|
||||
_contacts[key] = contact.copyWith(isNew: false);
|
||||
hasChanges = true;
|
||||
}
|
||||
});
|
||||
if (hasChanges) {
|
||||
_persistContacts();
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark a specific contact as viewed (not new)
|
||||
void markAsViewed(String publicKeyHex) {
|
||||
final contact = _contacts[publicKeyHex];
|
||||
if (contact != null && contact.isNew) {
|
||||
_contacts[publicKeyHex] = contact.copyWith(isNew: false);
|
||||
_persistContacts();
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear all contacts
|
||||
void clearContacts() {
|
||||
_contacts.clear();
|
||||
@@ -250,7 +290,21 @@ class ContactsProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
/// Remove a contact
|
||||
void removeContact(String publicKeyHex) {
|
||||
/// [onRemoveFromDevice] - Optional callback to remove contact from BLE device
|
||||
Future<void> removeContact(
|
||||
String publicKeyHex, {
|
||||
Future<void> Function(Uint8List)? onRemoveFromDevice,
|
||||
}) async {
|
||||
// Get the contact before removing
|
||||
final contact = _contacts[publicKeyHex];
|
||||
if (contact == null) return;
|
||||
|
||||
// Remove from device first if callback provided
|
||||
if (onRemoveFromDevice != null) {
|
||||
await onRemoveFromDevice(contact.publicKey);
|
||||
}
|
||||
|
||||
// Then remove from local storage
|
||||
_contacts.remove(publicKeyHex);
|
||||
_persistContacts();
|
||||
notifyListeners();
|
||||
|
||||
@@ -49,6 +49,14 @@ class MessagesProvider with ChangeNotifier {
|
||||
|
||||
bool get isInitialized => _isInitialized;
|
||||
|
||||
/// Get count of unread messages (excluding sent messages and system messages)
|
||||
int get unreadCount => _messages
|
||||
.where((m) =>
|
||||
!m.isRead &&
|
||||
!m.isSentMessage &&
|
||||
!m.isSystemMessage)
|
||||
.length;
|
||||
|
||||
/// Initialize and load persisted messages
|
||||
Future<void> initialize() async {
|
||||
if (_isInitialized) return;
|
||||
@@ -287,6 +295,31 @@ class MessagesProvider with ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Mark all messages as read
|
||||
void markAllAsRead() {
|
||||
bool hasChanges = false;
|
||||
for (int i = 0; i < _messages.length; i++) {
|
||||
if (!_messages[i].isRead && !_messages[i].isSentMessage && !_messages[i].isSystemMessage) {
|
||||
_messages[i] = _messages[i].copyWith(isRead: true);
|
||||
hasChanges = true;
|
||||
}
|
||||
}
|
||||
if (hasChanges) {
|
||||
_persistMessages();
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark a specific message as read
|
||||
void markAsRead(String messageId) {
|
||||
final index = _messages.indexWhere((m) => m.id == messageId);
|
||||
if (index != -1 && !_messages[index].isRead) {
|
||||
_messages[index] = _messages[index].copyWith(isRead: true);
|
||||
_persistMessages();
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete a specific message by ID
|
||||
void deleteMessage(String messageId) {
|
||||
final index = _messages.indexWhere((m) => m.id == messageId);
|
||||
@@ -412,9 +445,10 @@ class MessagesProvider with ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add message with sending status
|
||||
// Add message with sending status and mark as read (sent messages are always read)
|
||||
final sendingMessage = enhancedMessage.copyWith(
|
||||
deliveryStatus: MessageDeliveryStatus.sending,
|
||||
isRead: true, // Sent messages are always marked as read
|
||||
);
|
||||
_messages.add(sendingMessage);
|
||||
print(' ✅ Message added to list at index ${_messages.length - 1}');
|
||||
|
||||
Reference in New Issue
Block a user