Skip to content

feat: Port “Compass view” bottom sheet from Meshtastic-Apple PR #1504#3896

Merged
jamesarich merged 16 commits into
meshtastic:mainfrom
jakevis:main
Dec 12, 2025
Merged

feat: Port “Compass view” bottom sheet from Meshtastic-Apple PR #1504#3896
jamesarich merged 16 commits into
meshtastic:mainfrom
jakevis:main

Conversation

@jakevis

@jakevis jakevis commented Dec 3, 2025

Copy link
Copy Markdown
Contributor

This ports the “Compass view” from Meshtastic-Apple PR pull/1504 (thanks @RCGV1) to Android. It keeps the phone’s location as origin and guides you to the selected node via a modal bottom sheet on Node Detail → Position → “Open Compass.”

What changed

  • Add localized strings for compass title/action, distance/bearing display, and sensor/permission/location warnings.
  • New providers: CompassHeadingProvider (rotation vector with accel+mag fallback) and PhoneLocationProvider (LocationManager flow with permission/provider state).
  • CompassViewModel/CompassUiState combine heading + phone location with the target node, computing distance, bearing, alignment, and elapsed “last position update.”
  • Compose CompassSheetContent: dial ~2/3 width, red north reference, black target bearing, larger cardinal labels + quarter/eighth ticks, distance/bearing rows, elapsed time, and warnings with CTAs (request permission, open location settings, request position).
  • Node Detail integration: Position section gets “Open Compass”; sheet starts/stops providers with visibility, caches target node, and includes “Request Position” inside the sheet.

Why
Per the iOS PR: adds a compass view to quickly navigate to a node—useful off-grid when locating a friend, dog, or tracker.

Testing

  • Built and ran on Android emulator (API 35); opened Node Detail → Position → Open Compass; verified sheet renders and warnings appear when sensors/permissions are missing. (No automated tests run in this PR.)

@CLAassistant

CLAassistant commented Dec 3, 2025

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@jakevis

jakevis commented Dec 3, 2025

Copy link
Copy Markdown
Contributor Author

Screenshots of the changes:

Screenshot_1764802949 Screenshot_1764802956 Screenshot_1764802954

@DaneEvans

Copy link
Copy Markdown
Collaborator

Why lines not a compass rose? And why are there 3 lines for a single bearing?

@jakevis

jakevis commented Dec 4, 2025

Copy link
Copy Markdown
Contributor Author

Why lines not a compass rose? And why are there 3 lines for a single bearing?

Personal preference and re-using some old code I had from another project. Red is fixed line on the N marker; the thin under it is a heading line. Align the black lines and your walking directly to the node (accessibility feature mostly from the old project).

Orignal code and design I was playing with had support for multiple nodes on the rose (and that might a future PR - with a rose accessible from somewhere else). Totem Compass style - show where you stared nodes are both distance and direction from you.

For the moment; happy to drop the heading and red lines if folks prefer.

@mdecourcy

Copy link
Copy Markdown
Contributor

Should there perhaps be a message displayed when the target node has a high degree of precision bits? So we don't send the users on a wild goosechase

@jakevis

jakevis commented Dec 4, 2025

Copy link
Copy Markdown
Contributor Author

Should there perhaps be a message displayed when the target node has a high degree of precision bits? So we don't send the users on a wild goosechase

Let me see how hard it would be to tell the user the degree of error on the screen.. if its communicated somewhere..

@jakevis

jakevis commented Dec 4, 2025

Copy link
Copy Markdown
Contributor Author

@DaneEvans @mdecourcy - ok simplified the rose and did implement an accuracy cone-

  • Data source: We use gps_accuracy (mm) and DOP (PDOP, or HDOP/VDOP fallback) from the node’s Position. If these are missing, uncertainty is “unknown.”
  • Visual: A translucent blue wedge around the bearing shows ±angular error (error radius vs. your distance). Close range + poor accuracy = wide wedge; good accuracy or long distance = narrow wedge.
  • Messaging (beneath the dial, next to distance/bearing):
    • Known: “Estimated area: ±X (±Y°)” — rendered from compass_uncertainty.
    • Unknown: “Estimated area: unknown accuracy” — rendered from compass_uncertainty_unknown.

I need to test this on some more physical devices though- only tested this in the emulator right now- but would love feedback.

Screenshot_1764870764

@jakevis jakevis marked this pull request as draft December 4, 2025 22:16
@jakevis

jakevis commented Dec 4, 2025

Copy link
Copy Markdown
Contributor Author

Converting to draft pending physical device testing of the error cone.

@RCGV1

RCGV1 commented Dec 7, 2025

Copy link
Copy Markdown
Member

@jakevis I made a pr into your fork repo to improve the view of the compass.

@jakevis

jakevis commented Dec 7, 2025

Copy link
Copy Markdown
Contributor Author

@jakevis I made a pr into your fork repo to improve the view of the compass.

Looks amazing! Thank you!

@jamesarich

Copy link
Copy Markdown
Collaborator

How y'all feeling about this, @jakevis @RCGV1 ?

Should we let copilot do a review pass?

@RCGV1

RCGV1 commented Dec 7, 2025

Copy link
Copy Markdown
Member

The only thing I have not fully tested is the uncertainty feature, also I did not figure out how to localize distance since right now it only shows km

@jakevis

jakevis commented Dec 8, 2025

Copy link
Copy Markdown
Contributor Author

I have a todo item tomorrow to test this on a couple physical devices now I'm back from the weekend. I want to check the uncertainty cone some more- it's a tad hard to do in the emulator.

I have ran codex-max over it before I pushed to my branch; but yes - I would certainly say copilot should triple check 😀 - I can ask codex to take a pass at the localization as well.

- fix compass cone math by drawing in canvas space (0°=east) without double heading adjustment so wedge/dot rotate with device heading
- normalize cone start angle to prevent wraparound artifacts and keep shading aligned
- rebuild compass shading (filled wedge + edges) using marker color for consistent visual cues
- include angle normalization helper for safer bearing math

@jakevis jakevis left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok a few things tested and everything seems to be functional.

I just pushed a fix for the cone alignment (wedge now tracks heading and target dot), and some changes around when to show time since update and accuracy. Localization of miles vs km also seems to function fine (based on your app settings).

Happy for copilot to have at it and see how we go.

@jakevis jakevis marked this pull request as ready for review December 9, 2025 21:36
@jakevis

jakevis commented Dec 9, 2025

Copy link
Copy Markdown
Contributor Author

4E68B13F-F422-4D48-B9AD-132394896253_1_102_o
EAEAD6AD-A1CF-4AA7-9E30-6A827387F94C_1_102_o

Signed-off-by: Jake Vis <github@jv.ag>
@jamesarich jamesarich requested a review from Copilot December 9, 2025 22:31
@jamesarich

Copy link
Copy Markdown
Collaborator

@jakevis you'll need to run ./gradlew spotlessApply detekt and clean up any errors

@jakevis

jakevis commented Dec 9, 2025

Copy link
Copy Markdown
Contributor Author

🤦‍♂️ Will do, sorry about that.

@jamesarich

Copy link
Copy Markdown
Collaborator

🤦‍♂️ Will do, sorry about that.

no worries, it's a common gotcha most new contribs miss - so much so that we thought about scripting an action to remind folks when detekt or spotless fail on ci 😂

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR ports the compass view feature from Meshtastic-Apple to Android, enabling users to navigate to mesh nodes using a visual compass interface with distance and bearing information. The implementation provides a modal bottom sheet accessible from the Node Detail screen's Position section.

Key Changes:

  • New compass providers for device heading (sensors) and phone location (GPS/Network)
  • CompassViewModel that combines heading, location, and target node data to compute bearing, distance, and alignment
  • Compose-based UI with rotating compass dial, cardinal markers, and uncertainty cone visualization
  • Integration with Node Detail screen via modal bottom sheet with proper permission handling

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
NodeDetailAction.kt Adds OpenCompass action to open compass sheet with target node and display units
NodeDetailScreen.kt Adds action handler stub for compass (actual handling in NodeDetailList)
NodeDetailList.kt Integrates compass sheet with lifecycle management, permission launchers, and ViewModel
PositionSection.kt Adds "Open Compass" button when node has valid position
CompassBottomSheet.kt Implements compass UI with rotating dial, warnings, distance/bearing display, and uncertainty visualization
PhoneLocationProvider.kt Provides location updates via LocationManager with permission/provider state tracking
CompassHeadingProvider.kt Provides device heading from rotation vector or accelerometer+magnetometer sensors
CompassViewModel.kt Coordinates heading and location streams, computes bearing/distance, manages state
CompassUiState.kt Defines render-ready state and warning enum for compass UI
strings.xml Adds localized strings for compass title, actions, distances, bearings, and warnings

*
* @param location Optional Location from the phone's location provider.
*/
fun headingUpdates(location: Location? = null): Flow<HeadingState> = callbackFlow {

Copilot AI Dec 9, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The headingUpdates function accepts a location parameter but never uses it because it's captured once at function creation time. However, the location needs to be continuously updated for accurate true north correction as the phone moves. Consider either removing the parameter and obtaining location dynamically, or restructuring to accept a Flow<Location?> that can be combined with sensor updates.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had codex implement a suggested fix (on next push)

}
}

LaunchedEffect(showCompassSheet) { if (!showCompassSheet) compassViewModel?.stop() }

Copilot AI Dec 9, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LaunchedEffect that calls compassViewModel?.stop() should be placed inside the if (showCompassSheet && compassViewModel != null) block to ensure it's properly tied to the sheet's lifecycle. Currently, it's outside the conditional, which means the effect will run even when the sheet is never shown. Additionally, calling stop() when the sheet is dismissed should happen in the onDismiss callback to ensure immediate cleanup, not in LaunchedEffect which may have a delay.

Copilot uses AI. Check for mistakes.
@jamesarich jamesarich added this to the 2.7.10 milestone Dec 10, 2025
jakevis and others added 5 commits December 11, 2025 22:08
…nent/CompassBottomSheet.kt

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Jake Vis <github@jv.ag>
…nent/CompassBottomSheet.kt

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Jake Vis <github@jv.ag>
…nent/CompassBottomSheet.kt

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Jake Vis <github@jv.ag>
@jakevis

jakevis commented Dec 12, 2025

Copy link
Copy Markdown
Contributor Author

@jakevis you'll need to run ./gradlew spotlessApply detekt and clean up any errors

Ok - we should be set here; and I think all the copilot fixes are implemented

Signed-off-by: Jake Vis <github@jv.ag>
@jamesarich

jamesarich commented Dec 12, 2025

Copy link
Copy Markdown
Collaborator

@jakevis
Instead of suppressing the Detekt warnings, let's actually clean up the code.

The errors are pretty descriptive of what needs to happen.

@jamesarich

Copy link
Copy Markdown
Collaborator

@jakevis Instead of suppressing the Detekt warnings, let's actually clean up the code.

The errors are pretty descriptive of what needs to happen.

I usually try to let a dev resolve their own PR feedback as they are able - but def reach out if you need a hand.

@jakevis

jakevis commented Dec 12, 2025

Copy link
Copy Markdown
Contributor Author

Yes let me take another look - sorry be another day or two. I think I know what happened.. I gave codex some leeway and for it to do a code review, it refactored some stuff and broke it, I reverted; but my prompt now has "always run and fix" before commit - so apparently that's how it likes to fix things..... time to do it by hand.

@jamesarich

Copy link
Copy Markdown
Collaborator

so apparently that's how it likes to fix things

dang ol' robots

@jamesarich

Copy link
Copy Markdown
Collaborator

If you don't mind I might take a whack at it this afternoon - @RCGV1 is begging me to get an internal build up for his 🎈 launch this weekend.

@jakevis

jakevis commented Dec 12, 2025

Copy link
Copy Markdown
Contributor Author

Go for it 😀 - if I get a break here before then, I'll certainly try; but don't block on me- please feel free to fix away.

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
@codecov

codecov Bot commented Dec 12, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 515 lines in your changes missing coverage. Please review.
✅ Project coverage is 0.51%. Comparing base (1a78745) to head (a3c51cf).
⚠️ Report is 12 commits behind head on main.

Files with missing lines Patch % Lines
...astic/feature/node/component/CompassBottomSheet.kt 0.00% 225 Missing ⚠️
...eshtastic/feature/node/compass/CompassViewModel.kt 0.00% 117 Missing ⚠️
...g/meshtastic/feature/node/detail/NodeDetailList.kt 0.00% 55 Missing ⚠️
...stic/feature/node/compass/PhoneLocationProvider.kt 0.00% 48 Missing ⚠️
...tic/feature/node/compass/CompassHeadingProvider.kt 0.00% 42 Missing ⚠️
.../meshtastic/feature/node/compass/CompassUiState.kt 0.00% 19 Missing ⚠️
...shtastic/feature/node/component/PositionSection.kt 0.00% 7 Missing ⚠️
...meshtastic/feature/node/detail/NodeDetailScreen.kt 0.00% 1 Missing ⚠️
.../meshtastic/feature/node/model/NodeDetailAction.kt 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##            main   #3896      +/-   ##
========================================
- Coverage   0.52%   0.51%   -0.02%     
========================================
  Files        395     400       +5     
  Lines      23172   23682     +510     
  Branches    2944    3042      +98     
========================================
  Hits         122     122              
- Misses     23029   23539     +510     
  Partials      21      21              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@jamesarich

Copy link
Copy Markdown
Collaborator

This is good enough to get in and try out, we can iterate from here. Thanks for the 🧭 @jakevis !

@jamesarich jamesarich added this pull request to the merge queue Dec 12, 2025
Merged via the queue into meshtastic:main with commit d3cd967 Dec 12, 2025
5 of 6 checks passed
@jamesarich jamesarich changed the title Port “Compass view” bottom sheet from Meshtastic-Apple PR #1504 feat: Port “Compass view” bottom sheet from Meshtastic-Apple PR #1504 Dec 13, 2025
@jamesarich jamesarich added the enhancement New feature or request label Dec 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants