Skip to content

Add close button to info card for classic 3-button nav users#932

Merged
jaydeetay merged 2 commits into
masterfrom
feature/info-card-close-button
Jun 20, 2026
Merged

Add close button to info card for classic 3-button nav users#932
jaydeetay merged 2 commits into
masterfrom
feature/info-card-close-button

Conversation

@jaydeetay

Copy link
Copy Markdown
Member

Summary

  • Users on classic 2/3-button on-screen navigation have no visible Back button to dismiss the info card, since Sky Map runs full screen — they previously had to swipe up to reveal the hidden nav bar.
  • Adds NavigationModeUtil.isGestureNavigationEnabled(), which reads the navigation_mode system setting to detect classic vs. gesture navigation.
  • ObjectInfoDialogFragment now adds a negative "OK" button to the info card's AlertDialog only when classic navigation is detected. Gesture-nav users see no change.

Test plan

  • ./gradlew :app:compileGmsDebugKotlin passes
  • Manually verify on a device/emulator set to 3-button nav: info card shows an OK button that dismisses it
  • Manually verify on a device/emulator set to gesture nav: info card looks unchanged (no extra button)

🤖 Generated with Claude Code

@jaydeetay

Copy link
Copy Markdown
Member Author

@gemini-code-assist review

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces several changes, including adding an explicit close button to the object info dialog for users on classic 2/3-button navigation, implementing a 15-second startup grace period in SensorAccuracyMonitor before displaying compass accuracy warnings, updating dependencies, and adding troubleshooting documentation. The reviewer feedback suggests wrapping the system settings read in NavigationModeUtil with a try-catch block to prevent potential SecurityException crashes on custom ROMs, and using monotonic SystemClock.elapsedRealtime() instead of System.currentTimeMillis() to robustly measure the startup grace period.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +27 to +29
fun isGestureNavigationEnabled(context: Context): Boolean {
return Settings.Secure.getInt(context.contentResolver, "navigation_mode", 0) == 2
}

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.

medium

Reading system settings from Settings.Secure can occasionally throw a SecurityException or other runtime exceptions on highly customized Android ROMs, restricted user profiles (e.g., guest mode, work profiles), or in certain testing environments. Wrapping this in a try-catch block and falling back to false (classic navigation) is a safer, defensive approach. Falling back to false is safe because it will simply show the close button, which is harmless, whereas a crash would be critical.

    fun isGestureNavigationEnabled(context: Context): Boolean {
        return try {
            Settings.Secure.getInt(context.contentResolver, "navigation_mode", 0) == 2
        } catch (e: Exception) {
            false
        }
    }

private val toaster: Toaster
private var started = false
private var hasReading = false
private var startedAtMillis = 0L

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.

medium

Using System.currentTimeMillis() to measure elapsed time intervals can lead to bugs if the system clock is adjusted (e.g., via network time synchronization or manual user changes) during the grace period. Using SystemClock.elapsedRealtime() is monotonic and guaranteed to be unaffected by clock adjustments, making it the standard and robust choice for measuring intervals in Android.

Let's update startedAtMillis to use elapsed realtime.

Suggested change
private var startedAtMillis = 0L
private var startedAtElapsedMillis = 0L

return
}
Log.d(TAG, "Starting monitoring compass accuracy")
startedAtMillis = System.currentTimeMillis()

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.

medium

Record the start time using SystemClock.elapsedRealtime() instead of System.currentTimeMillis().

Suggested change
startedAtMillis = System.currentTimeMillis()
startedAtElapsedMillis = android.os.SystemClock.elapsedRealtime()

Comment on lines +77 to +81
val nowMillis = System.currentTimeMillis()
if (nowMillis - startedAtMillis < STARTUP_GRACE_PERIOD_MILLIS) {
Log.d(TAG, "...but still within startup grace period, letting the user settle in first")
return
}

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.

medium

Perform the startup grace period check using monotonic elapsed realtime, while keeping the wall-clock time for the persisted warning interval check.

Suggested change
val nowMillis = System.currentTimeMillis()
if (nowMillis - startedAtMillis < STARTUP_GRACE_PERIOD_MILLIS) {
Log.d(TAG, "...but still within startup grace period, letting the user settle in first")
return
}
val nowElapsedMillis = android.os.SystemClock.elapsedRealtime()
if (nowElapsedMillis - startedAtElapsedMillis < STARTUP_GRACE_PERIOD_MILLIS) {
Log.d(TAG, "...but still within startup grace period, letting the user settle in first")
return
}
val nowMillis = System.currentTimeMillis()

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces several updates, including a startup grace period for the compass accuracy monitor to prevent premature warnings, an explicit close button on the object info dialog for users not using gesture navigation, and corresponding troubleshooting documentation updates. Feedback on the code changes suggests using monotonic SystemClock.elapsedRealtime() instead of System.currentTimeMillis() for measuring the grace period, always showing the dismiss button on the info dialog to avoid relying on undocumented settings, and updating the troubleshooting guides to mention the new close button.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

private val toaster: Toaster
private var started = false
private var hasReading = false
private var startedAtMillis = 0L

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.

medium

Rename startedAtMillis to startedAtElapsedRealtime to reflect that it stores monotonic elapsed realtime instead of wall-clock time.

Suggested change
private var startedAtMillis = 0L
private var startedAtElapsedRealtime = 0L

return
}
Log.d(TAG, "Starting monitoring compass accuracy")
startedAtMillis = System.currentTimeMillis()

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.

medium

Using System.currentTimeMillis() to measure elapsed time (such as the startup grace period) is susceptible to issues if the system clock is adjusted (e.g., via network time sync or manual user changes). For monotonic elapsed time measurements, it is highly recommended to use SystemClock.elapsedRealtime() instead.

Suggested change
startedAtMillis = System.currentTimeMillis()
startedAtElapsedRealtime = android.os.SystemClock.elapsedRealtime()

Comment on lines +78 to +81
if (nowMillis - startedAtMillis < STARTUP_GRACE_PERIOD_MILLIS) {
Log.d(TAG, "...but still within startup grace period, letting the user settle in first")
return
}

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.

medium

Use the monotonic SystemClock.elapsedRealtime() to check if the startup grace period has elapsed.

Suggested change
if (nowMillis - startedAtMillis < STARTUP_GRACE_PERIOD_MILLIS) {
Log.d(TAG, "...but still within startup grace period, letting the user settle in first")
return
}
if (android.os.SystemClock.elapsedRealtime() - startedAtElapsedRealtime < STARTUP_GRACE_PERIOD_MILLIS) {
Log.d(TAG, "...but still within startup grace period, letting the user settle in first")
return
}

Comment on lines +220 to +224
// Users on classic 2/3-button navigation have no visible Back button to dismiss the
// card with, since the app runs full screen. Give them an explicit close button.
if (!NavigationModeUtil.isGestureNavigationEnabled(parentActivity)) {
builder.setNegativeButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() }
}

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.

medium

Relying on the undocumented "navigation_mode" setting in Settings.Secure is fragile, as it is an internal API that is not guaranteed to be present or behave consistently across all Android OEMs and custom ROMs.

Additionally, even for gesture-navigation users, performing a back gesture in a full-screen interactive app like Sky Map can be finicky (as it can conflict with map dragging gestures or require an extra swipe to reveal the gesture area).

Recommendation:
Consider always showing a dismiss button (using android.R.string.cancel or a "Close" resource) for all users, regardless of their navigation mode. This simplifies the codebase by eliminating the need for NavigationModeUtil entirely and provides a consistent, reliable, and intuitive way to dismiss the dialog for all users.

Suggested change
// Users on classic 2/3-button navigation have no visible Back button to dismiss the
// card with, since the app runs full screen. Give them an explicit close button.
if (!NavigationModeUtil.isGestureNavigationEnabled(parentActivity)) {
builder.setNegativeButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() }
}
builder.setNegativeButton(android.R.string.cancel) { dialog, _ -> dialog.dismiss() }

Comment thread troubleshooting.md Outdated
Comment on lines +143 to +146
If you're using the older "classic" 3-button Android navigation (rather than gesture navigation),
Sky Map runs full screen, so the on-screen Back/Home/Recents buttons aren't rendered at all. Swipe
up from the very bottom of the screen to bring the navigation bar into view, then tap Back to
close the card.

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.

medium

Since this PR introduces an explicit close button on the info card for classic 3-button navigation users, they no longer have to swipe up to reveal the navigation bar to close the card. The troubleshooting text should be updated to reflect this new capability.

Suggested change
If you're using the older "classic" 3-button Android navigation (rather than gesture navigation),
Sky Map runs full screen, so the on-screen Back/Home/Recents buttons aren't rendered at all. Swipe
up from the very bottom of the screen to bring the navigation bar into view, then tap Back to
close the card.
If you're using the older "classic" 3-button Android navigation (rather than gesture navigation),
an explicit close button is provided on the card. Alternatively, you can swipe up from the very
bottom of the screen to bring the navigation bar into view, then tap Back.

Comment thread troubleshooting-llm.md Outdated
Comment on lines +156 to +157
3. If using classic 3-button navigation, swipe up from the very bottom of the screen to bring the
navigation bar into view, then tap Back

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.

medium

Update the suggested steps for LLM responses to mention the new close button on the card for classic 3-button navigation users.

Suggested change
3. If using classic 3-button navigation, swipe up from the very bottom of the screen to bring the
navigation bar into view, then tap Back
3. If using classic 3-button navigation, tap the close button on the card, or swipe up from the
very bottom of the screen to bring the navigation bar into view and tap Back

Sky Map runs full screen, so users on classic 2/3-button on-screen
navigation have no visible Back button to dismiss the info card and
must swipe up to reveal the nav bar. Detect classic nav via the
navigation_mode system setting and add an explicit close button in
that case only; gesture-nav users see no change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jaydeetay jaydeetay force-pushed the feature/info-card-close-button branch from ece45ef to 8744096 Compare June 20, 2026 16:17
Settings.Secure reads can throw on restricted profiles or customized
ROMs; fall back to classic-nav (false) on failure since that's the
safe direction (an extra harmless button, not a crash).
@jaydeetay

Copy link
Copy Markdown
Member Author

@gemini-code-assist review

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces a new utility, NavigationModeUtil, to detect whether the device is using gesture or classic 2/3-button navigation. In ObjectInfoDialogFragment, this utility is used to conditionally add an explicit close button for users on classic navigation, ensuring they can dismiss the dialog when running in full screen. There are no review comments, so I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@jaydeetay jaydeetay merged commit f38268d into master Jun 20, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant