android: ticking a box on a card threw the editor open on top of it
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 2m45s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 5m18s
Desktop (Tauri) / Update manifest (push) Successful in 4s
Android / Kotlin + Rust (APK) (push) Successful in 7m31s

Reported from the device: tapping a checkbox on the board checks it AND opens the
note. The "and" is the tell — both things happened, so this was never a tap landing
on the wrong target.

`mutate` ends with `editing = updated ?: state.editing`. That is right for an editor
action, where the reloaded note refreshes a screen already on display. But
`editing != null` IS "the editor is up" — it is what MainActivity's `when` selects
on — so calling `mutate` from the BOARD, where editing is null, wrote the mutated
note into it and opened the editor as a side effect of saving.

Fixed at `mutate` rather than at the caller, because the caller was not wrong: any
board-initiated mutation would have done this, and toggleItem is simply the first
one to exist. It now refreshes an open editor and cannot open a closed one.

The comment claimed the narrower behaviour all along — "so an open editor shows its
own change" — which is what the code should have been doing and wasn't.
This commit is contained in:
2026-08-24 09:59:00 -04:00
parent 315c5f19e6
commit 9a3c4ec377
@@ -413,9 +413,10 @@ class BoardViewModel(
/** /**
* The one path every store mutation takes. * The one path every store mutation takes.
* *
* Each core mutation returns the reloaded note, which goes straight into * Each core mutation returns the reloaded note, which refreshes
* [BoardState.editing] so an open editor shows its own change without a * [BoardState.editing] so an OPEN editor shows its own change without a
* re-query. The BOARD list is then reloaded rather than patched in place: * re-query — and does nothing at all when the editor is closed, because that
* field doubles as "which screen is up". The BOARD list is then reloaded rather than patched in place:
* pinning re-sorts it, archiving removes the note from it, and adding a label * pinning re-sorts it, archiving removes the note from it, and adding a label
* can move it in or out of a label view — a splice would have to reimplement * can move it in or out of a label view — a splice would have to reimplement
* the core's ordering and membership rules in Kotlin to get any of that right. * the core's ordering and membership rules in Kotlin to get any of that right.
@@ -451,7 +452,12 @@ class BoardViewModel(
withContext(Dispatchers.IO) { onRemindersChanged() } withContext(Dispatchers.IO) { onRemindersChanged() }
state.copy( state.copy(
notes = notes, notes = notes,
editing = if (closeEditor) null else updated ?: state.editing, // Only REFRESHES an open editor; it must never open one.
// `editing != null` IS "the editor is on screen", so writing
// the reloaded note in unconditionally meant any mutation
// started from the BOARD threw the editor open on top of it —
// which is exactly what ticking a checkbox on a card did.
editing = if (closeEditor) null else state.editing?.let { updated ?: it },
saving = false, saving = false,
error = null, error = null,
) )