android: detekt caught a callback that never reached the cards
Not a style finding. `onToggleItem` was added to BoardScreen's signature and read
inside NoteBoard — which is a separate top-level composable, not a nested one, so
the two were never connected. detekt reported it as an unused parameter; the
compiler would have called it an unresolved reference. Neither had run: Kotlin is
compiled at the "Unit tests" step, which is gated behind detekt, so nothing in this
lane had type-checked the Android changes yet.
Threaded properly now, which is what makes ticking a box from the board actually
work rather than merely appear to.
Two more from reading it again with that in mind:
* `when { item != null -> … onToggleItem(index, …) }` would not have compiled.
Kotlin does not infer that a non-null item implies a non-null index, so the
index stayed `Int?` against an `Int` parameter. Both are in the condition now.
* continueChecklist had six returns against detekt's limit of two. Collapsed to
one `when`, with the two intermediate values guarded on `typedNewline` —
`caret - 1` is only a real index once it is known to be the newline just typed.
This commit is contained in:
@@ -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<Note>,
|
||||
onOpenNote: (Note) -> Unit,
|
||||
onToggleItem: (Note, Int, Boolean) -> Unit,
|
||||
) {
|
||||
LazyVerticalStaggeredGrid(
|
||||
columns = StaggeredGridCells.Fixed(BOARD_COLUMNS),
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 = "- [ ] "
|
||||
|
||||
Reference in New Issue
Block a user