board: ktlint on the long-press menu — a named modifier, three dead imports
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 2m49s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 5m0s
Desktop (Tauri) / Update manifest (push) Successful in 3s
Android / Kotlin + Rust (APK) (push) Successful in 7m55s

Two failures on `3f0eef1`, both ktlint, both mine.

`chain-method-continuation`: a multiline element in a Modifier chain wants the
next `.` glued to its closing paren — `).background(…)`. Every other multiline
chain element in this codebase happens to be LAST in its chain, so nothing had
exercised the rule before. `combinedClickable` is now a named `opening`
modifier applied with `.then(…)`, which keeps the chain single-line per element
and reads better than the shape ktlint was asking for.

`no-unused-imports`: lifting the delete-forever dialog into Panel.kt took the
last use of `Text`, `stringResource` and `R` out of NoteEditorScreen.kt with
it. I had checked AlertDialog and TextButton and stopped there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-27 07:49:57 -04:00
co-authored by Claude Opus 5
parent 3f0eef145b
commit 396e91e609
2 changed files with 26 additions and 20 deletions
@@ -57,6 +57,28 @@ fun NoteCard(
val haptics = LocalHapticFeedback.current val haptics = LocalHapticFeedback.current
var menuOpen by remember { mutableStateOf(false) } var menuOpen by remember { mutableStateOf(false) }
// NAMED rather than written inline in the chain below, and not for taste: ktlint's
// chain-method-continuation wants the next `.` glued to the closing paren of a
// multiline element — `).background(…)` — which is worse to read than a modifier
// with a name. Every other multiline element in this codebase happens to be last
// in its chain, so this is the first place the rule bites.
val opening =
Modifier.combinedClickable(
onClickLabel = stringResource(R.string.board_open_note),
onLongClickLabel = stringResource(R.string.board_note_actions),
onLongClick = {
// Fired HERE rather than when the menu appears. A long press is
// confirmed by the system before the popup has laid out, and the whole
// point of the buzz is to say "that registered" at the moment your
// finger has been still long enough — a menu that arrives with no tick
// under it reads as a phone that missed the gesture and then changed
// its mind.
haptics.performHapticFeedback(HapticFeedbackType.LongPress)
menuOpen = true
},
onClick = onOpen,
)
// The Box exists only to anchor the menu. A DropdownMenu is a popup and takes no // The Box exists only to anchor the menu. A DropdownMenu is a popup and takes no
// space, so the card's size is still the Column's. // space, so the card's size is still the Column's.
Box { Box {
@@ -68,24 +90,11 @@ fun NoteCard(
// separate a white card from a #fafafa board, and the web's own // separate a white card from a #fafafa board, and the web's own
// `shadow-sm` is the value it is matching. // `shadow-sm` is the value it is matching.
.shadow(CARD_ELEVATION, RoundedCornerShape(CARD_RADIUS)) .shadow(CARD_ELEVATION, RoundedCornerShape(CARD_RADIUS))
// Clipped BEFORE clickable, so the ripple is bounded by the card's // Clipped BEFORE the click modifier, so the ripple is bounded by the
// rounded corners instead of a rectangle overhanging them. // card's rounded corners instead of a rectangle overhanging them
// and BEFORE padding, so the padded edge is still a tap target.
.clip(RoundedCornerShape(CARD_RADIUS)) .clip(RoundedCornerShape(CARD_RADIUS))
.combinedClickable( .then(opening)
onClickLabel = stringResource(R.string.board_open_note),
onLongClickLabel = stringResource(R.string.board_note_actions),
onLongClick = {
// Fired HERE rather than when the menu appears. A long press
// is confirmed by the system before the popup has laid out,
// and the whole point of the buzz is to say "that registered"
// at the moment your finger has been still long enough — a
// menu that arrives with no tick under it reads as a phone
// that missed the gesture and then changed its mind.
haptics.performHapticFeedback(HapticFeedbackType.LongPress)
menuOpen = true
},
onClick = onOpen,
)
.background(noteCardColor(note, dark)) .background(noteCardColor(note, dark))
// ONE grey edge on every card, regardless of its colour — the tint is // ONE grey edge on every card, regardless of its colour — the tint is
// deliberately not consulted here. See CARD_EDGE_DARK. // deliberately not consulted here. See CARD_EDGE_DARK.
@@ -16,7 +16,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@@ -25,9 +24,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.fabledsword.thoughtsync.R
import com.fabledsword.thoughtsync.core.Label import com.fabledsword.thoughtsync.core.Label
import com.fabledsword.thoughtsync.core.Note import com.fabledsword.thoughtsync.core.Note
import kotlinx.coroutines.delay import kotlinx.coroutines.delay