location aware channel_message_path#307
Conversation
There was a problem hiding this comment.
Pull request overview
Reimplements the “location aware” hop trace resolution for channel_message_path by selecting hop contacts based on proximity (when location is available) rather than a simple first-match strategy.
Changes:
- Update hop-building logic to group repeater/room contacts by 1-byte public key prefix and choose the “best” candidate per hop (location-aware when possible).
- Change
_buildPathHopsto take aMeshCoreConnectorinstead of a precomputed contact list. - Update
.gitignoreto ignore macOS GeneratedPluginRegistrant and normalize the.wranglerentry.
Reviewed changes
Copilot reviewed 1 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| lib/screens/channel_message_path_screen.dart | Implements prefix-candidate grouping + distance-based selection for hop resolution and updates call sites accordingly. |
| .gitignore | Ignores a generated macOS Swift file and fixes .wrangler line formatting. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Reimplements the channel message path trace UI to resolve hop prefixes using nearby discovered repeaters/rooms (location-aware matching), aiming for more realistic hop paths after alpha7.
Changes:
- Update hop resolution to pick the best candidate per prefix using proximity to the previous hop (and/or self location) rather than first/oldest match.
- Refactor
_buildPathHopsto take aMeshCoreConnectordirectly (so it can use self location +allContacts) and remove the old_matchContactForPrefix/_hasValidLocationhelpers. - Ignore
macos/Flutter/GeneratedPluginRegistrant.swiftvia.gitignore.
Reviewed changes
Copilot reviewed 1 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| lib/screens/channel_message_path_screen.dart | Location-aware hop matching based on nearest candidate per prefix and connector self position. |
| .gitignore | Adds macOS GeneratedPluginRegistrant.swift to ignored files (and normalizes .wrangler line). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| final candidate = candidates[j]; | ||
| if (!candidate.hasLocation) continue; | ||
| final currentDistance = distance( | ||
| searchPoint, | ||
| LatLng(candidate.latitude!, candidate.longitude!), | ||
| ); |
| LatLng? _resolvePosition(Contact? contact) { | ||
| if (contact == null) return null; | ||
| if (!_hasValidLocation(contact)) return null; | ||
| if (!contact.hasLocation) return null; | ||
| return LatLng(contact.latitude!, contact.longitude!); | ||
| } |
There was a problem hiding this comment.
Pull request overview
Reimplements the channel message hop path trace to be location-aware, aiming to produce more realistic hop sequences by selecting the nearest matching next-hop candidate (by prefix) when location data is available.
Changes:
- Updates hop resolution to group repeaters/rooms by 1-byte prefix, then pick the nearest candidate (or fall back by recency) while avoiding reusing the same candidate multiple times.
- Enhances the map UI with hop focusing: tapping a hop centers/zooms the map and highlights the selected hop in the legend list.
- Updates macOS plugin registration (Path Provider) and adjusts
.gitignore.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
lib/screens/channel_message_path_screen.dart |
Implements location-aware hop matching and adds hop focus/selection behavior on the map screen. |
macos/Flutter/GeneratedPluginRegistrant.swift |
Registers the Path Provider macOS plugin (generated file). |
.gitignore |
Adds the macOS generated plugin registrant to ignored files and fixes .wrangler formatting. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Reimplements the “location-aware” channel message hop-path trace so that prefix collisions are resolved by selecting the nearest plausible repeater/room candidate (using available location data), and adds UI interactions to focus the map on a tapped hop.
Changes:
- Update hop resolution to group candidates by prefix and pick nearest-by-distance (falling back to most-recent by
lastSeen). - Add hop focusing/selection behavior in the map view (tap a hop to move/zoom the map and highlight the focused row).
- macOS plugin registrant updated for
path_provider_foundation, and generated registrant is added to.gitignore.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| macos/Flutter/GeneratedPluginRegistrant.swift | Registers path_provider_foundation on macOS. |
| lib/screens/channel_message_path_screen.dart | Implements new hop-selection algorithm and hop-to-map focus UI. |
| .gitignore | Ignores macOS GeneratedPluginRegistrant and normalizes .wrangler entry. |
Comments suppressed due to low confidence (1)
lib/screens/channel_message_path_screen.dart:316
- A
MapControlleris created and held for the lifetime of the state, but it is never disposed. Other screens in this repo (e.g.MapCacheScreen) call_mapController.dispose()indispose(). Please add adispose()override to dispose the controller to avoid leaking listeners/resources.
final MapController _mapController = MapController();
Uint8List? _selectedPath;
double _pathDistance = 0.0;
bool _showNodeLabels = true;
bool _didReceivePositionUpdate = false;
int? _focusedHopIndex;
@override
void initState() {
super.initState();
_selectedPath = widget.initialPath;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| List<_PathHop> _buildPathHops( | ||
| Uint8List pathBytes, | ||
| List<Contact> contacts, | ||
| MeshCoreConnector connector, | ||
| AppLocalizations l10n, | ||
| ) { | ||
| if (pathBytes.isEmpty) return const []; | ||
| final candidatesByPrefix = <int, List<Contact>>{}; | ||
| for (final contact in connector.allContacts) { | ||
| if (contact.publicKey.isEmpty) continue; | ||
| if (contact.type != advTypeRepeater && contact.type != advTypeRoom) { | ||
| continue; | ||
| } | ||
| final prefix = contact.publicKey.first; | ||
| candidatesByPrefix.putIfAbsent(prefix, () => <Contact>[]).add(contact); | ||
| } | ||
| for (final candidates in candidatesByPrefix.values) { | ||
| candidates.sort((a, b) => b.lastSeen.compareTo(a.lastSeen)); | ||
| } | ||
| final startPoint = | ||
| (connector.selfLatitude != null && connector.selfLongitude != null) | ||
| ? LatLng(connector.selfLatitude!, connector.selfLongitude!) | ||
| : null; | ||
| var previousPosition = startPoint; | ||
| final distance = Distance(); | ||
|
|
||
| final hops = <_PathHop>[]; | ||
| for (var i = 0; i < pathBytes.length; i++) { | ||
| final prefix = pathBytes[i]; | ||
| final contact = _matchContactForPrefix(contacts, prefix); | ||
| final searchPoint = i == 0 ? startPoint : previousPosition; | ||
| final candidates = candidatesByPrefix[pathBytes[i]]; | ||
| Contact? contact; | ||
| if (candidates != null && candidates.isNotEmpty) { | ||
| var bestIndex = 0; | ||
| if (searchPoint != null) { | ||
| var bestDistance = double.infinity; | ||
| for (var j = 0; j < candidates.length; j++) { | ||
| final candidate = candidates[j]; | ||
| if (!candidate.hasLocation || | ||
| candidate.latitude == null || | ||
| candidate.longitude == null) { | ||
| continue; | ||
| } | ||
| final currentDistance = distance( | ||
| searchPoint, | ||
| LatLng(candidate.latitude!, candidate.longitude!), | ||
| ); | ||
| if (currentDistance < bestDistance) { | ||
| bestDistance = currentDistance; | ||
| bestIndex = j; | ||
| } | ||
| } | ||
| } | ||
| contact = candidates.removeAt(bestIndex); | ||
| if (candidates.isEmpty) { | ||
| candidatesByPrefix.remove(pathBytes[i]); | ||
| } | ||
| } |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Reimplements the “location aware” channel_message_path hop trace by selecting, for each hop prefix, the nearest matching discovered repeater/room based on the previous hop (or self) location to produce a more realistic path trace and map visualization.
Changes:
- Update hop resolution to choose nearest candidate per prefix (distance-based) and avoid reusing the same candidate for repeated prefixes.
- Add map hop focusing via list-tap (centers/zooms the map on the tapped hop and highlights it).
- Update macOS plugin registrant for
path_providerand add the registrant file to.gitignore.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
lib/screens/channel_message_path_screen.dart |
Implements nearest-prefix hop matching and adds hop focus/highlight behavior in the map UI. |
macos/Flutter/GeneratedPluginRegistrant.swift |
Adds path_provider_foundation registration (generated file). |
.gitignore |
Attempts to ignore the generated macOS plugin registrant file. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| final MapController _mapController = MapController(); | ||
| Uint8List? _selectedPath; | ||
| double _pathDistance = 0.0; | ||
| bool _showNodeLabels = true; | ||
| bool _didReceivePositionUpdate = false; | ||
| int? _focusedHopIndex; |
| @@ -20,6 +21,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { | |||
| FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) | |||
| MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin")) | |||
| FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) | |||
| PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) | |||
| SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) | |||
Reimplementation of the location aware channel_message_path trace (after alpha7 release)
It searches for the nearest match for the prefix of the next hop to build the Hop path trace.
I tried more complex search algorithm including a full graph search with custom scoring to try to make a more plausible path. But the Results did not improve much, but with a high cost in calculating time.
An implementation for inspection can be seen at my branch ez_channel_message_path2.
It gets more realistic if a lot of Repeaters are discovered (see for that #298) and the hopLength is small.
But the real solution would be multibyte prefixes. But even than collision could occour (even if very unlikely) where it is better to match to the nearest Prefix instead of the first (mostly oldest) entry in the list.