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:
@@ -2,15 +2,41 @@
|
||||
<resources>
|
||||
<string name="app_name">ThoughtSync</string>
|
||||
|
||||
<!-- Capture -->
|
||||
<string name="capture_hint">Take a note…</string>
|
||||
<string name="capture_action">Save</string>
|
||||
<!-- Search bar -->
|
||||
<string name="search_hint">Search your notes</string>
|
||||
<string name="search_clear">Clear search</string>
|
||||
<string name="nav_open">Open navigation</string>
|
||||
<string name="nav_labels">Labels</string>
|
||||
|
||||
<!-- Compose sheet -->
|
||||
<string name="compose_open">New note</string>
|
||||
<string name="compose_kind_note">Note</string>
|
||||
<string name="compose_kind_list">List</string>
|
||||
<string name="compose_title_hint">Title</string>
|
||||
<string name="compose_body_hint">Take a note…</string>
|
||||
<string name="compose_list_hint">One item per line</string>
|
||||
<string name="compose_cancel">Cancel</string>
|
||||
<string name="compose_save">Save</string>
|
||||
|
||||
<!-- Board -->
|
||||
<string name="board_title">Notes</string>
|
||||
<string name="board_empty_note">Empty note</string>
|
||||
<plurals name="board_more_items">
|
||||
<item quantity="one">+%d more item</item>
|
||||
<item quantity="other">+%d more items</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Empty states. Each destination says something true of ITSELF; a single
|
||||
"nothing here" reads as encouragement on the board and as a fault in Trash. -->
|
||||
<string name="board_empty_title">Nothing here yet</string>
|
||||
<string name="board_empty_body">Your notes stay on this device. Connect a server later if you want them everywhere.</string>
|
||||
<string name="board_untitled">Untitled</string>
|
||||
<string name="board_empty_body">Tap + to start a note or a list. Everything stays on this device until you connect a server.</string>
|
||||
<string name="empty_search_title">No matches</string>
|
||||
<string name="empty_search_body">Nothing matched “%1$s”.</string>
|
||||
<string name="empty_trash_title">Trash is empty</string>
|
||||
<string name="empty_trash_body">Deleted notes wait here before they are removed for good.</string>
|
||||
<string name="empty_archive_title">Nothing archived</string>
|
||||
<string name="empty_archive_body">Archived notes leave the board but stay searchable.</string>
|
||||
<string name="empty_reminders_title">No reminders</string>
|
||||
<string name="empty_reminders_body">Notes with a reminder set will appear here.</string>
|
||||
|
||||
<!-- Store failure -->
|
||||
<string name="store_unavailable_title">Your notes couldn\'t be opened</string>
|
||||
@@ -18,5 +44,4 @@
|
||||
|
||||
<!-- Errors -->
|
||||
<string name="error_dismiss">Dismiss</string>
|
||||
<string name="error_retry">Try again</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user