android: phone-shaped chrome and the real note card (M12 step 6)
Two things at once, because they answer one question: what should this look like,
and what should it look like ON A PHONE.
IDENTITY IS SHARED, INTERACTION IS NOT. The card now renders exactly what the web
and desktop render — note colour, checklists, label chips, reminders — using the
same palette values, so a note looks like your note on every surface. The chrome
does not: the desktop's title bar and sidebar are wrong for a thumb.
* NoteTint.kt carries the Tailwind colours from frontend/src/notes/colors.ts
VALUE FOR VALUE, generated from tailwindcss 3.4 rather than eyeballed. Dark
tints keep the web's alpha (dark:bg-*-950/40) instead of a precomputed blend,
because Compose composites translucency over the background exactly as CSS
does.
* Dynamic colour is GONE. It was the more Android-native choice and it made the
app look like a different product — on a stock emulator with no wallpaper it
renders as undifferentiated grey, which is what the operator saw. Three peer
surfaces share one identity; the brand #F5C518 is the same value the web
manifest and the launcher icon already use.
* The board is a two-column staggered grid, the Compose equivalent of the CSS
multi-column NoteGrid.vue uses.
PHONE ERGONOMICS, chosen with the operator:
* Search IS the top bar. After writing a note, finding one is the most common
thing you do, and burying it behind an icon costs a tap every time. Debounced
180ms and cancelled per keystroke — without that a fast typist queues one
full-text query per character and results land out of order.
* A + button is the only way in. One obvious target beat a capture bar and a
button competing for the same job.
* Navigation moved into a drawer behind the search bar's menu icon, which is
where archive/trash/labels/reminders now live. They had nowhere to go once
search took the top bar, and would otherwise have been unreachable.
* The compose sheet asks note-or-list up front. On a phone those are different
typing tasks and switching halfway is worse than choosing at the start. A
list takes one item per line — fast to type, versus a tap per row.
Three new bindings the UI needed: search_notes, reminder_notes, list_labels.
Search goes through the CORE so "what matches" cannot drift between surfaces;
filtering the loaded list in Kotlin would have been less code and a different
product. reminder_notes is its own call because the core models it that way —
"has a reminder" cuts across archived and active alike.
Empty states are per-destination. "Nothing here yet" is encouraging on an empty
board, wrong in Trash, and misleading after a search where the notes exist but
did not match.
Verified locally before pushing: bindings generated from a host .so and read back,
ktlint and detekt clean from the image's pinned CLIs, cargo fmt/clippy/test green
(107 tests). Two detekt findings were fixed by extraction rather than by relaxing
the rules — this is the first Compose code in the repo and the thresholds should
have to earn their exceptions.
Still unbuilt: tapping a card does nothing. The editor is next.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,10 @@ compose-ui-graphics = { module = "androidx.compose.ui:ui-graphics" }
|
||||
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
|
||||
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
|
||||
compose-material3 = { module = "androidx.compose.material3:material3" }
|
||||
# Icons only from -core, deliberately: it carries the common set (Menu, Search,
|
||||
# Close, Add) and is already on the material3 path. -extended adds ~1,000 vectors
|
||||
# for the handful the drawer would use.
|
||||
compose-material-icons-core = { module = "androidx.compose.material:material-icons-core" }
|
||||
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" }
|
||||
jna = { module = "net.java.dev.jna:jna", version.ref = "jna" }
|
||||
junit = { module = "junit:junit", version.ref = "junit" }
|
||||
|
||||
Reference in New Issue
Block a user