From ba97003ea0a38914272112ca903b8e3c914b6b76 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Fri, 23 Oct 2026 16:23:08 -0400 Subject: [PATCH] Android editor suggests existing tags while a #tag is typed The web editor's `#` suggestions, ported: with the caret in a `#tag`, a row of chips under the field offers the existing tags that finish it, prefix matches first and busiest first. A tap puts in the whole name and a space. The rules are the web's tags.ts, with the same test cases. Task #6316. Co-Authored-By: Claude Opus 5.5 --- .../com/fabledsword/inkwell/ui/BlockBody.kt | 99 ++++++++++++++++--- .../inkwell/ui/NoteEditorScreen.kt | 1 + .../com/fabledsword/inkwell/ui/TagSuggest.kt | 96 ++++++++++++++++++ .../fabledsword/inkwell/ui/TagSuggestTest.kt | 79 +++++++++++++++ 4 files changed, 264 insertions(+), 11 deletions(-) create mode 100644 android/app/src/main/java/com/fabledsword/inkwell/ui/TagSuggest.kt create mode 100644 android/app/src/test/java/com/fabledsword/inkwell/ui/TagSuggestTest.kt diff --git a/android/app/src/main/java/com/fabledsword/inkwell/ui/BlockBody.kt b/android/app/src/main/java/com/fabledsword/inkwell/ui/BlockBody.kt index 0a84038..04f0d9c 100644 --- a/android/app/src/main/java/com/fabledsword/inkwell/ui/BlockBody.kt +++ b/android/app/src/main/java/com/fabledsword/inkwell/ui/BlockBody.kt @@ -1,11 +1,14 @@ package com.fabledsword.inkwell.ui import androidx.annotation.StringRes +import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions @@ -16,6 +19,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LocalMinimumInteractiveComponentSize import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SuggestionChip import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -32,12 +36,14 @@ import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextLayoutResult +import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.dp import com.fabledsword.inkwell.R +import com.fabledsword.inkwell.core.Label /** * The note's body, as fields and checkboxes rather than as markup. @@ -50,6 +56,8 @@ fun BlockBody( blocks: List, readOnly: Boolean, focus: Long?, + /** Every tag there is, offered while a `#tag` is typed (see [TagSuggestions]). */ + tags: List