diff --git a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/BoardScreen.kt b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/BoardScreen.kt index ed226ee..0c3fe20 100644 --- a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/BoardScreen.kt +++ b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/BoardScreen.kt @@ -141,7 +141,12 @@ fun BoardScreen( when { state.loading -> LoadingBoard() state.notes.isEmpty() -> EmptyBoard(state) - else -> NoteBoard(notes = state.notes, onOpenNote = onOpenNote) + else -> + NoteBoard( + notes = state.notes, + onOpenNote = onOpenNote, + onToggleItem = onToggleItem, + ) } // `PullToRefreshBox` would be less code, but it takes no // `enabled`, so the modifier and the indicator are wired by @@ -324,6 +329,7 @@ private fun DrawerRow( private fun NoteBoard( notes: List, onOpenNote: (Note) -> Unit, + onToggleItem: (Note, Int, Boolean) -> Unit, ) { LazyVerticalStaggeredGrid( columns = StaggeredGridCells.Fixed(BOARD_COLUMNS), diff --git a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteCard.kt b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteCard.kt index f87a10b..3b92d66 100644 --- a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteCard.kt +++ b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteCard.kt @@ -109,7 +109,11 @@ private fun NoteBody( val index = itemAtLine[n] val item = index?.let { note.items.getOrNull(it) } when { - item != null -> ChecklistRow(item) { onToggleItem(index, !item.checked) } + // Both in the condition, not just `item`: Kotlin will not infer that a + // non-null item implies a non-null index, and `onToggleItem` needs the + // index smart-cast to act on it. + index != null && item != null -> + ChecklistRow(item) { onToggleItem(index, !item.checked) } // Kept as a gap rather than dropped: it is the paragraph break // somebody typed, and the card reads as a wall without it. line.isBlank() -> Spacer(Modifier.height(4.dp)) diff --git a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteEditorScreen.kt b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteEditorScreen.kt index f1e6d74..4c39129 100644 --- a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteEditorScreen.kt +++ b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteEditorScreen.kt @@ -396,21 +396,31 @@ private fun continueChecklist( new: TextFieldValue, ): TextFieldValue { val caret = new.selection.start - if (new.selection.length != 0) return new - if (new.text.length != old.text.length + 1) return new - if (caret == 0 || new.text[caret - 1] != '\n') return new + val typedNewline = + new.selection.length == 0 && + new.text.length == old.text.length + 1 && + caret > 0 && + new.text[caret - 1] == '\n' + // Both guarded on `typedNewline`, because caret - 1 is only a real index once it + // is known to be the newline that was just typed. + val lineStart = if (typedNewline) new.text.take(caret - 1).lastIndexOf('\n') + 1 else 0 + val marker = + if (typedNewline) checklistContinuation(new.text.substring(lineStart, caret - 1)) else null - val before = new.text.take(caret - 1) - val lineStart = before.lastIndexOf('\n') + 1 - val marker = checklistContinuation(before.substring(lineStart)) ?: return new - - if (marker.isEmpty()) { + return when { + marker == null -> new // An empty item: take the marker line away rather than adding another. - val text = new.text.take(lineStart) + new.text.substring(caret) - return TextFieldValue(text, TextRange(lineStart)) + marker.isEmpty() -> + TextFieldValue( + new.text.take(lineStart) + new.text.substring(caret), + TextRange(lineStart), + ) + else -> + TextFieldValue( + new.text.take(caret) + marker + new.text.substring(caret), + TextRange(caret + marker.length), + ) } - val text = new.text.take(caret) + marker + new.text.substring(caret) - return TextFieldValue(text, TextRange(caret + marker.length)) } private const val CHECKLIST_MARKER = "- [ ] "