Files
music_library/backlog/completed/ml-176.2 - Presto-add-splash-screen-search-views-and-on-screen-keyboard.md
T
Claudio Ortolina 8ece3ba891 Backlog cleanup
2026-05-12 11:30:59 +01:00

176 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: ML-176.2
title: "Presto: add splash screen, search views, and on-screen keyboard"
status: Done
assignee: []
created_date: "2026-05-10 13:35"
updated_date: "2026-05-11 06:47"
labels:
- presto
milestone: m-0
dependencies:
- ML-176.1
references:
- presto/AGENTS.md
- presto/README.md
- >-
doc-17 -
Implementation-Plan-ML-176.2-—-Presto-splash-screen-search-views-and-on-screen-keyboard
modified_files:
- presto/records_on_the_day.py
parent_task_id: ML-176
priority: medium
ordinal: 2000
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Refactor `presto/records_on_the_day.py` into a unified app with a splash screen, search capability, and the existing calendar. All work is in the single MicroPython file.
## New states
- `STATE_HOME` (new, default on boot/wake)
- `STATE_SEARCH_INPUT` (new — search box + on-screen keyboard)
- `STATE_SEARCH_RESULTS` (new — results list, reuses day-view rendering)
- `STATE_MONTH` / `STATE_DAY` / `STATE_RECORD` (existing, unchanged logic)
## Splash screen (STATE_HOME)
- Two large touch targets: "Search Collection" and "Today's Records"
- "Today's Records" → transitions to existing `STATE_MONTH` / today's records flow
- "Search Collection" → transitions to `STATE_SEARCH_INPUT`
- On boot and display wake: always show `STATE_HOME`
## On-screen keyboard (part of STATE_SEARCH_INPUT)
- 3-row QWERTY layout: qwertyuiop / asdfghjkl / zxcvbnm
- Bottom row: [123 toggle] [space] [⌫ backspace] [OK]
- Numbers keyboard: 1234567890 / symbols row / [ABC toggle] [space] [⌫] [OK]
- Space and ⌫ are shared between both layouts
- Lowercase only, no shift/caps
- OK button disabled (dimmed) when query is empty
- Each key is a rounded rectangle, touch-mapped to append/delete chars
- Visual feedback on key press (brief highlight)
- Query buffer displayed in a text field area above the keyboard, max ~50 chars
## Search triggering
- User types query, presses OK
- OK calls `fetch_search_results(query)` → API
- Transitions to `STATE_SEARCH_RESULTS`
## Search results (STATE_SEARCH_RESULTS)
- Reuses existing `_draw_record_list()`, scroll, and row rendering from day view
- Header shows "Search: <query>" with Back button
- Back returns to `STATE_SEARCH_INPUT` (preserving query so user can refine)
- Tapping a record → `STATE_RECORD` (detail view, unchanged)
- Back from detail → returns to search results
- Empty results: "No records found" full-screen message
- Error: "Could not reach server" with retry-on-tap (same as day view)
- 20 results per page, no infinite scroll
## API client
- New `fetch_search_results(query)` function
- Calls `GET /api/v1/collection?q=<url-encoded-query>&limit=20`
- Parses `{total, records, ...}` response
- Returns `(records_list, error_flag)` tuple (same shape as `fetch_records`)
## Navigation state
- Track previous state to know where "Back" in detail view should go
- Detail Back → search results when entered from search
- Detail Back → day view when entered from day
- Month view and search views both have "Back to Home"
## Constraints
- Must reuse existing record row rendering (`_draw_record_row`), detail view (`draw_record_detail`), thumbnail fetching, WiFi, NTP, display sleep logic
- Scroll performance rules from AGENTS.md still apply
- Memory: no large buffers, keep GC pressure low
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 On boot, splash screen shows with 'Search Collection' and 'Today's Records' buttons
- [ ] #2 Tapping 'Today's Records' opens the existing month calendar (unchanged behavior)
- [ ] #3 Tapping 'Search Collection' opens search input view with on-screen QWERTY keyboard
- [ ] #4 Keyboard: tapping letter keys builds query string shown in input field
- [ ] #5 Keyboard: backspace removes last character
- [ ] #6 Keyboard: 123/ABC toggle switches between QWERTY and numbers keyboard layouts
- [ ] #7 Keyboard: OK button is visually disabled (dimmed) when query is empty
- [ ] #8 Keyboard: OK button triggers API search when query is non-empty
- [ ] #9 Search results display using same record row layout as day view (cover, title, artist, format, year)
- [ ] #10 Search results: Back button returns to search input view with query preserved
- [ ] #11 Search results: tapping a record opens detail view
- [ ] #12 Detail view Back returns to search results when entered from search
- [ ] #13 Detail view Back returns to day view when entered from day
- [ ] #14 Empty results show 'No records found' full-screen message
- [ ] #15 API error shows 'Could not reach server' with retry-on-tap
- [ ] #16 Display sleep/wake always returns to splash screen
- [ ] #17 Scroll in search results works identically to day view scroll
- [ ] #18 Keyboard renders correctly at 720×720: all keys visible and tappable
- [ ] #19 Back-to-Home navigation available from month view and search views
<!-- AC:END -->
## Implementation Notes
<!-- SECTION:NOTES:BEGIN -->
## Implementation complete (~617 new lines, 2450 total)
### State constants + globals
- Renumbered STATE_MONTH=0, STATE_DAY=1, STATE_RECORD=2. Added STATE_HOME=3, STATE_SEARCH_INPUT=4, STATE_SEARCH_RESULTS=5. Removed STATE_STARTUP.
- New globals: `search_query`, `search_results`, `search_results_error`, `search_scroll_offset`, `_search_content_height`, `keyboard_mode`, `previous_state`.
### Splash screen (STATE_HOME)
- `draw_home_screen()` with "Search Collection" and "Today's Records" buttons. Tapping "Today's Records" → month view with today highlighted. Tapping "Search Collection" → search input.
### On-screen keyboard (STATE_SEARCH_INPUT)
- QWERTY layout (3 rows) + numbers/symbols. Bottom row: [123/ABC] [Space] [Backspace] [OK]. OK dimmed when query empty. `_keyboard_hit_test()` maps touch to action. `handle_search_input_touch()` dispatches all actions. Visual feedback via `_flash_key()`.
### Search results (STATE_SEARCH_RESULTS)
- Reuses `_draw_record_row()`. Own scroll state (`search_scroll_offset`, `_search_content_height`). Header: "Search: <query>" with truncation. Empty: "No records found". Error: "Could not reach server" with retry-on-tap.
### API client
- `fetch_search_results(query)``GET /api/v1/collection?q=<encoded>&limit=20`. Returns `(records_list, error_flag)`.
### Generic display pipeline
- `prepare_records_for_display(recs=None)` and `preload_record_thumbnails(recs=None)` accept optional list. Height cache tracked per source.
### Navigation tracking
- `previous_state` tracks detail origin (STATE_DAY / STATE_SEARCH_RESULTS). Back → correct origin. `draw_record_detail()` reads from `search_results` or `records`.
### Back-to-Home
- Month header gains "H" Home button. `wake_display()` always sets `state = STATE_HOME`. Search input header Back → Home.
### Boot flow
- Starts at `draw_home_screen()`, no auto-fetch. User taps a button.
### Main loop
- New dispatches for STATE_HOME, STATE_SEARCH_INPUT, STATE_SEARCH_RESULTS (drag scroll mirrors day view).
### Touch helpers
- `touch_to_record_index()` accepts optional `recs` and `offset` params.
### Verification
- Syntax check passes (`python3 py_compile`). No `STATE_STARTUP` references remain.
<!-- SECTION:NOTES:END -->