Skip to content

fix(settings): crash opening Position radio-config screen#5862

Merged
jamesarich merged 1 commit into
mainfrom
claude/heuristic-almeida-c7fd95
Jun 19, 2026
Merged

fix(settings): crash opening Position radio-config screen#5862
jamesarich merged 1 commit into
mainfrom
claude/heuristic-almeida-c7fd95

Conversation

@jamesarich

Copy link
Copy Markdown
Collaborator

Why

Tapping Location in radio config crashed the app instantly (reproduced on a Pixel 9 Pro via logcat):

java.lang.IllegalArgumentException: MutableState containing Position(lat=…, lon=…, alt=…, time=1)
cannot be saved using the current SaveableStateRegistry. The default implementation only
supports types which can be stored inside the Bundle.
    at androidx.compose.runtime.saveable.RememberSaveableKt.requireCanBeSaved(RememberSaveable.kt:355)

PositionConfigScreen used rememberSaveable { mutableStateOf(currentPosition) } with no stateSaver. Position is a plain core.model data class (not Parcelable/Bundle-storable), so rememberSaveable fell back to the default Bundle saver and threw on the main thread the moment the screen composed — the crash happened on entry, not on any interaction.

What changed

  • Added a listSaver over Position's primitive fields and passed it as stateSaver to the rememberSaveable. All fields are Double/Int, so the saver is KMP/Bundle-safe.
  • All eight fields are round-tripped so the additionalDirtyCheck { locationInput != currentPosition } equality comparison stays correct.

Testing Performed

  • ./gradlew :feature:settings:assemble spotlessCheck detekt — all pass.
  • Crash confirmed in device logcat before the fix.

🤖 Generated with Claude Code

Opening the Position radio-config screen crashed instantly with
IllegalArgumentException: a `rememberSaveable { mutableStateOf(currentPosition) }`
had no stateSaver, so it fell back to the default Bundle saver. `Position` is a
plain core.model data class (not Parcelable/Bundle-storable), so the saveable
registration threw on the main thread as soon as the screen composed.

Provide a listSaver over Position's primitive fields and pass it as stateSaver.
All eight fields are round-tripped so the `locationInput != currentPosition`
dirty check stays correct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added the bugfix PR tag label Jun 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📄 Docs staleness check — advisory

This PR modifies user-facing UI source files but does not update any page under docs/en/user/ or docs/en/developer/.

⚠️ Doc changes propagate to 3 consumers: in-app docs browser, Jekyll site (GitHub Pages), and meshtastic.org (Docusaurus sync). Updating a page in docs/en/ automatically flows to all three.

Changed source files:

feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/component/PositionConfigScreen.kt

What to check:

Changed area Likely doc page
feature/messaging/ docs/en/user/messages-and-channels.md
feature/node/ docs/en/user/nodes.md or docs/en/user/node-metrics.md
feature/map/ docs/en/user/map-and-waypoints.md
feature/connections/ docs/en/user/connections.md
feature/settings/ docs/en/user/settings-radio-user.md or docs/en/user/settings-module-admin.md
feature/firmware/ docs/en/user/firmware.md
feature/intro/ docs/en/user/onboarding.md
feature/discovery/ docs/en/user/discovery.md
feature/docs/ Internal docs infrastructure
core/ui/ docs/en/developer/codebase.md or component-specific user pages

New page checklist (if adding a new doc page):

  1. Create the .md file in docs/en/user/ or docs/en/developer/ with last_updated frontmatter
  2. Register in DocBundleLoader.kt with string resources (in-app browser)
  3. Jekyll and Docusaurus sync pick up new pages automatically — no config change needed

If this PR does not require a doc update (e.g., internal refactor, bug fix, test change), add the skip-docs-check label to dismiss this check.

Cross-platform note: This check is advisory while doc coverage matures. Both Android and Apple repos use the same skip-docs-check label and advisory severity. See meshtastic/design standards for shared conventions.

@github-actions

Copy link
Copy Markdown
Contributor

🖼️ Preview staleness check — advisory

This PR modifies UI composables but does not update any *Previews.kt files.

Previews power screenshot tests and in-app docs screenshots. Keeping them current ensures visual regression coverage stays accurate.

Changed UI files:

feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/component/PositionConfigScreen.kt

What to check:

Pattern Preview file convention
feature/{name}/…/ui/ or component/ feature/{name}/…/*Previews.kt
core/ui/…/ core/ui/…/ (previews colocated)

Adding previews checklist:

  1. Create or update a *Previews.kt file in the same module with @PreviewLightDark
  2. Add @Suppress("PreviewPublic") if the preview is consumed by screenshot-tests
  3. Add corresponding @PreviewTest function in screenshot-tests/src/screenshotTest/
  4. Run ./gradlew :screenshot-tests:updateDebugScreenshotTest to generate reference images

If this PR does not require preview updates (e.g., logic-only change, non-visual refactor), add the skip-preview-check label to dismiss.

@jamesarich jamesarich enabled auto-merge June 19, 2026 01:05
@jamesarich jamesarich added this pull request to the merge queue Jun 19, 2026
Merged via the queue into main with commit 5dd9d57 Jun 19, 2026
19 checks passed
@jamesarich jamesarich deleted the claude/heuristic-almeida-c7fd95 branch June 19, 2026 01:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix PR tag

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant