From 9a3c4ec377dce6c237850c7c4762941133acb9af Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Mon, 24 Aug 2026 09:59:00 -0400 Subject: [PATCH] android: ticking a box on a card threw the editor open on top of it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .../fabledsword/thoughtsync/ui/BoardViewModel.kt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/BoardViewModel.kt b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/BoardViewModel.kt index dece4d3..6d3e2ac 100644 --- a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/BoardViewModel.kt +++ b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/BoardViewModel.kt @@ -413,9 +413,10 @@ class BoardViewModel( /** * The one path every store mutation takes. * - * Each core mutation returns the reloaded note, which goes straight into - * [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: + * Each core mutation returns the reloaded note, which refreshes + * [BoardState.editing] so an OPEN editor shows its own change without a + * 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 * 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. @@ -451,7 +452,12 @@ class BoardViewModel( withContext(Dispatchers.IO) { onRemindersChanged() } state.copy( 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, error = null, )