From 79a45c527b7293d393d37160049c17ff78b56d03 Mon Sep 17 00:00:00 2001 From: Winston Lowe Date: Sat, 14 Mar 2026 11:45:47 -0700 Subject: [PATCH] Unify contact retrieval by introducing allContacts getter --- lib/connector/meshcore_connector.dart | 17 +++++++++++++++-- lib/screens/channel_message_path_screen.dart | 10 ++-------- lib/screens/chat_screen.dart | 2 +- lib/screens/map_screen.dart | 5 +---- lib/screens/neighbors_screen.dart | 5 +---- lib/screens/path_trace_map.dart | 5 +---- lib/widgets/path_management_dialog.dart | 2 +- lib/widgets/path_selection_dialog.dart | 3 ++- lib/widgets/snr_indicator.dart | 5 +---- 9 files changed, 25 insertions(+), 29 deletions(-) diff --git a/lib/connector/meshcore_connector.dart b/lib/connector/meshcore_connector.dart index 7cf32ef0..dad5ed13 100644 --- a/lib/connector/meshcore_connector.dart +++ b/lib/connector/meshcore_connector.dart @@ -289,6 +289,10 @@ class MeshCoreConnector extends ChangeNotifier { ); } + List get allContacts => List.unmodifiable([ + ..._contacts, + ..._discoveredContacts.where((c) => !c.isActive), + ]); List get discoveredContacts { return List.unmodifiable(_discoveredContacts); } @@ -2909,6 +2913,8 @@ class MeshCoreConnector extends ChangeNotifier { void _handleContact(Uint8List frame, {bool isContact = true}) { final contact = Contact.fromFrame(frame); if (contact != null) { + _handleDiscovery(contact, frame, noNotify: true, addActive: true); + if (contact.type == advTypeRepeater) { _contactUnreadCount.remove(contact.publicKeyHex); _unreadStore.saveContactUnreadCount( @@ -4717,6 +4723,12 @@ class MeshCoreConnector extends ChangeNotifier { (_autoAddRoomServers && type == advTypeRoom) || (_autoAddSensors && type == advTypeSensor)) { _handleContactAdvert(newContact); + _handleDiscovery( + newContact, + rawPacket, + noNotify: true, + addActive: true, + ); } else { _handleDiscovery(newContact, rawPacket); } @@ -4827,6 +4839,7 @@ class MeshCoreConnector extends ChangeNotifier { Contact contact, Uint8List rawPacket, { bool noNotify = false, + bool addActive = false, }) { appLogger.info('Discovered new contact: ${contact.name}', tag: 'Connector'); @@ -4847,7 +4860,7 @@ class MeshCoreConnector extends ChangeNotifier { longitude: contact.longitude, lastSeen: contact.lastSeen, flags: 0, - isActive: false, + isActive: addActive, ); notifyListeners(); unawaited(_persistDiscoveredContacts()); @@ -4865,7 +4878,7 @@ class MeshCoreConnector extends ChangeNotifier { longitude: contact.longitude, lastSeen: contact.lastSeen, lastMessageAt: contact.lastMessageAt, - isActive: false, + isActive: addActive, flags: 0, ); _discoveredContacts.add(disContact); diff --git a/lib/screens/channel_message_path_screen.dart b/lib/screens/channel_message_path_screen.dart index c2c57f0d..32eadef0 100644 --- a/lib/screens/channel_message_path_screen.dart +++ b/lib/screens/channel_message_path_screen.dart @@ -40,10 +40,7 @@ class ChannelMessagePathScreen extends StatelessWidget { final primaryPath = !channelMessage && !message.isOutgoing ? Uint8List.fromList(primaryPathTmp.reversed.toList()) : primaryPathTmp; - final contacts = [ - ...connector.contacts, - ...connector.discoveredContacts, - ]; + final contacts = connector.allContacts; final hops = _buildPathHops(primaryPath, contacts, l10n); final hasHopDetails = primaryPath.isNotEmpty; final observedLabel = _formatObservedHops( @@ -367,10 +364,7 @@ class _ChannelMessagePathMapScreenState : selectedPathTmp; final selectedIndex = _indexForPath(selectedPath, observedPaths); - final contacts = [ - ...connector.contacts, - ...connector.discoveredContacts, - ]; + final contacts = connector.allContacts; final hops = _buildPathHops(selectedPath, contacts, context.l10n); final points = []; diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart index 96203ea7..6558ecde 100644 --- a/lib/screens/chat_screen.dart +++ b/lib/screens/chat_screen.dart @@ -1027,7 +1027,7 @@ class _ChatScreenState extends State { final currentPathLabel = _currentPathLabel(currentContact); // Filter out the current contact from available contacts - final availableContacts = connector.contacts + final availableContacts = connector.allContacts .where((c) => c != widget.contact) .toList(); diff --git a/lib/screens/map_screen.dart b/lib/screens/map_screen.dart index 1dd3a5fe..497c05f6 100644 --- a/lib/screens/map_screen.dart +++ b/lib/screens/map_screen.dart @@ -137,10 +137,7 @@ class _MapScreenState extends State { builder: (context, connector, settingsService, pathHistory, child) { final tileCache = context.read(); final settings = settingsService.settings; - final allContacts = [ - ...connector.contacts, - ...connector.discoveredContacts.where((c) => !c.isActive), - ]; + final allContacts = connector.allContacts; final contacts = settings.mapShowDiscoveryContacts ? allContacts diff --git a/lib/screens/neighbors_screen.dart b/lib/screens/neighbors_screen.dart index 5cb8e45a..5afeda41 100644 --- a/lib/screens/neighbors_screen.dart +++ b/lib/screens/neighbors_screen.dart @@ -124,10 +124,7 @@ class _NeighborsScreenState extends State { void _handleNeighborsResponse(MeshCoreConnector connector, Uint8List frame) { final buffer = BufferReader(frame); - final contacts = [ - ...connector.contacts, - ...connector.discoveredContacts, - ]; + final contacts = connector.allContacts; try { final neighborCount = buffer.readUInt16LE(); final parsedNeighbors = parseNeighborsData(buffer, buffer.readUInt16LE()); diff --git a/lib/screens/path_trace_map.dart b/lib/screens/path_trace_map.dart index ceb60a65..62778867 100644 --- a/lib/screens/path_trace_map.dart +++ b/lib/screens/path_trace_map.dart @@ -263,10 +263,7 @@ class _PathTraceMapScreenState extends State { .toList(); Map pathContacts = {}; - final contacts = [ - ...connector.contacts, - ...connector.discoveredContacts, - ]; + final contacts = connector.allContacts; contacts.where((c) => c.type != advTypeChat).forEach((repeater) { for (var repeaterData in pathData) { if (listEquals( diff --git a/lib/widgets/path_management_dialog.dart b/lib/widgets/path_management_dialog.dart index 384f92b2..0233b430 100644 --- a/lib/widgets/path_management_dialog.dart +++ b/lib/widgets/path_management_dialog.dart @@ -107,7 +107,7 @@ class _PathManagementDialogState extends State<_PathManagementDialog> { } final pathForInput = currentContact.pathIdList; - final availableContacts = connector.contacts + final availableContacts = connector.allContacts .where((c) => c.publicKeyHex != currentContact.publicKeyHex) .toList(); diff --git a/lib/widgets/path_selection_dialog.dart b/lib/widgets/path_selection_dialog.dart index 4e6cfe55..b1733fcd 100644 --- a/lib/widgets/path_selection_dialog.dart +++ b/lib/widgets/path_selection_dialog.dart @@ -1,5 +1,6 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; +import 'package:meshcore_open/connector/meshcore_protocol.dart'; import '../l10n/l10n.dart'; import '../models/contact.dart'; @@ -65,7 +66,7 @@ class _PathSelectionDialogState extends State { void _filterValidContacts() { _validContacts = widget.availableContacts - .where((c) => c.type == 2 || c.type == 3) + .where((c) => c.type == advTypeRepeater || c.type == advTypeRoom) .toList(); } diff --git a/lib/widgets/snr_indicator.dart b/lib/widgets/snr_indicator.dart index f122836b..30956e22 100644 --- a/lib/widgets/snr_indicator.dart +++ b/lib/widgets/snr_indicator.dart @@ -157,10 +157,7 @@ class _SNRIndicatorState extends State { repeater.snr, widget.connector.currentSf, ); - final allContacts = [ - ...widget.connector.contacts, - ...widget.connector.discoveredContacts, - ]; + final allContacts = widget.connector.allContacts; final name = allContacts .where((c) => c.publicKey.first == repeater.pubkeyFirstByte) .map((c) => c.name)