feat(connections): unified device list + USB address stabilization#5208
Closed
jamesarich wants to merge 5 commits intomainfrom
Closed
feat(connections): unified device list + USB address stabilization#5208jamesarich wants to merge 5 commits intomainfrom
jamesarich wants to merge 5 commits intomainfrom
Conversation
…r instead of Accompanist - Remove global ACCESS_LOCAL_NETWORK declaration from manifest (only needed for TAK localhost binding) - Add rememberRequestLocalNetworkPermission to core/ui PlatformUtils API - Implement for Android (gated to API 31+), iOS/JVM (no-ops) - Replace Accompanist in TAK permission handler with core/ui helper - Reduces per-reinstall permission prompts; users only see dialog when enabling TAK - Consistent with project's existing permission pattern (location/BLE/notifications) - Net -18 LOC Fixes unnecessary LOCAL_NETWORK permission dialog on app reinstall when TAK Server is disabled. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…s NSD picker On Android 17 (API 37) with targetSdk=37, the platform falls back to the system 'Choose a device to connect' picker on every NsdManager.discoverServices() call when ACCESS_LOCAL_NETWORK isn't granted. Removing the manifest entry in the previous commit only suppressed the runtime grant flavor of the prompt — the picker still fires as the platform's mediated fallback. This restores the manifest declaration and adds an isLocalNetworkPermissionGranted() helper plus the rememberRequestLocalNetworkPermission Compose helper to core/ui, ready to be wired into the connections UI. Because ACCESS_LOCAL_NETWORK is in the NEARBY_DEVICES permission group, users who have already granted Bluetooth permissions are silently auto-granted with no UI shown. - Re-add ACCESS_LOCAL_NETWORK to AndroidManifest.xml with comment explaining the Android 17 LNP enforcement and dual TAK/NSD use case. - Add isLocalNetworkPermissionGranted() expect/actual helper to core/ui. - Update TakPermissionUtil comment — pre-existing comment claimed the permission was 'NOT required for NSD', which was true on Android 16 but false on Android 17 with targetSdk=37. The ConnectionsScreen wiring that consumes these helpers is part of the separate unified-device-list PR (#5208). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Apr 22, 2026
…rhaul
Replaces the tabbed Bluetooth/Network/USB picker with a single Connections
screen that ranks bonded BLE, USB (OTG), discovered NSD, and recently-used
TCP devices in one adaptive list. Gates NSD scanning behind a user pref to
avoid chatty discovery, and makes device recognition work cross-transport.
UI / UX
- New adaptive DeviceList with M3 section headers and a stable, sticky
"currently connected" card at the top of the screen.
- Per-transport inline empty states with actionable hints instead of one
generic empty message.
- Device rows now show the NodeChip for recognized devices, BLE RSSI when
seen, and animated list reordering as RSSI updates.
- New ConnectionActionButton + DisconnectButton components replace ad-hoc
buttons; new DeviceSectionHeader replaces the old segmented bar.
- Nodes screen gets its own empty state ("no device connected" /
"searching for nodes") and the initial tab is gated on whether a device
is currently selected so first-run users land on Connections.
- Android DB detection (DatabaseManager.hasDatabaseFor) now matches files
without a `.db` extension so USB/serial-keyed DBs are recognized.
Preferences
- AppPreferences gains auto-scan toggles (BLE / NSD) persisted via
UiPrefsImpl; scanner VM honours them so scanning only runs when the user
wants it.
Refactors
- Scanner VM + discovery use cases split into Common / Android / JVM
variants with DRY flow composition; JvmGetDiscoveredDevicesUseCase added
so desktop compiles without Android scaffolding.
- OTG-attached serial devices now surface immediately in the list via
UsbBroadcastReceiver plumbing.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
USB device paths (`/dev/bus/usb/NNN/MMM`) change on every replug and after every reboot, which made the per-device Room database and DeviceListItem subtitle churn. Switch the internal USB address to a stable `usb:VID:PID:SERIAL` id (falling back to `usb:VID:PID` when the platform denies serial access pre-permission on Android 10+), keyed in UsbRepository and threaded through stableUsbId(). UI keeps the volatile port path visible as the row subtitle via a new DeviceListEntry.displayAddress override, while the stable id is used internally for DB/recognition lookups. Title is rendered as `Meshtastic · VVVV:PPPP` (4-digit upper-case hex). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… screen On Android 17 (API 37) with targetSdk=37, NsdManager.discoverServices() falls back to the system 'Choose a device to connect' picker on every call when ACCESS_LOCAL_NETWORK isn't granted. Wire the new core/ui permission helpers into ConnectionsScreen so users get a proper one-time grant prompt instead of a per-scan picker. Because ACCESS_LOCAL_NETWORK is in the NEARBY_DEVICES permission group, users who have already granted Bluetooth permissions are silently auto-granted with no UI shown. - Gate ConnectionsScreen network auto-start on the runtime grant so a previously-persisted networkAutoScan=true does not surface the picker for users who haven't granted the permission. - Manual scan toggle now requests the permission before starting and persists the user's intent so the launcher's onGranted callback can start the scan. - Add ScannerViewModel.persistNetworkAutoScanIntent for the deferred-start path. The manifest declaration and core/ui helpers consumed here ship in the separate permission-gating PR (#5211). Verified on Pixel 6a / Android 17 / API 37: NSD discovery now runs without the picker, and the permission is silently auto-granted via the NEARBY_DEVICES group when Bluetooth perms are already held. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
901cff4 to
fda0e07
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Connections UI overhaul:
usb:VID:PID:SERIALidentifiers so reconnects, recognition, and DB lookups survive replug/reboot.ACCESS_LOCAL_NETWORKruntime request into the Connections screen so Android 17 NSD discovery doesn't fall back to the system "Choose a device" picker.Changes by Commit
feat(connections): unified device list + cross-platform discovery overhaul
feat(network): stabilize USB addresses by VID:PID[:SERIAL]
usb:VID:PID:SERIALid.usb:VID:PIDwhen platform denies serial access (Android <11).Meshtastic · VVVV:PPPP(4-digit upper-case hex).feat(connections): wire ACCESS_LOCAL_NETWORK request into Connections screen
ScannerViewModel.persistNetworkAutoScanIntent.Splits
The polite-disconnect and permission-gating work originally bundled here was moved to:
feat(service): send polite ToRadio(disconnect=true) before transport closefix(permissions): gate ACCESS_LOCAL_NETWORK and migrate TAK off Accompanist(provides thecore/uihelpers and manifest declaration consumed by the wiring commit above; this PR depends on refactor: eliminate Accompanist permissions library #5211)