diff --git a/presto/AGENTS.md b/presto/AGENTS.md new file mode 100644 index 00000000..fe8c6c4f --- /dev/null +++ b/presto/AGENTS.md @@ -0,0 +1,109 @@ +# Presto App Guidance + +This directory contains MicroPython apps for the Pimoroni Presto. The main app is +`records_on_the_day.py`, deployed to the device as `main.py`. + +## Context To Read First + +- Read `README.md` before changing setup, deployment, user-facing behavior, or API response assumptions. +- Read `records_on_the_day.py` before changing layout, touch handling, networking, display sleep, or performance-sensitive code. +- The root project conventions still apply, but most Phoenix/Elixir conventions are not relevant inside `presto/`. + +## Deployment And Verification + +- The project task deploys the records app: + + ```bash + mise run presto + ``` + +- Manual deployment copies `records_on_the_day.py` to the device as `main.py`: + + ```bash + mpremote fs cp records_on_the_day.py :main.py + mpremote fs cp secrets.py :secrets.py + mpremote reset + ``` + +- Before finishing Python edits, run a syntax-only check that does not leave `__pycache__` behind: + + ```bash + python3 -c "import py_compile; py_compile.compile('records_on_the_day.py', cfile='/tmp/records_on_the_day.pyc', doraise=True)" + ``` + +- Do not claim device behavior is verified unless it was tested on the physical Presto. + +## Hardware And Runtime Constraints + +- Target stock Pimoroni Presto firmware: MicroPython, PicoGraphics, touch driver, `urequests`, `ntptime`, and usually `jpegdec`. +- Presto hardware is RP2350B, but stock firmware should be treated as a single Python runtime. Do not assume `_thread` or user-accessible multicore support. +- Keep memory pressure low. Avoid large in-memory image buffers, aggressive caching of large responses, and repeated `gc.collect()` in hot render paths. +- Network calls are blocking. Avoid doing HTTP requests during drag scrolling or repeated redraw loops. + +## Records App Behavior + +- Boot should land on today's records, not the month calendar. +- The Back button returns from day view to month view. +- Month and day headers should share the same header geometry: height, button dimensions, side margins, and centered title/date positioning. +- Day rows show cover art, title, artists, and a dim metadata line of `format | year`. +- `release_date` is displayed as year only. +- Text shown with bitmap fonts should pass through `display_text()` to replace unsupported punctuation such as smart dashes and quotes. Do not strip diacritics; the font can render them. + +## Image Handling + +- Prefer `micro_cover_url`, then `mini_cover_url`, then `thumb_url`. +- Keep `THUMB_SIZE` aligned with the micro image size when possible. +- Cache downloaded thumbnail bytes on the record dict as `_thumb_data`. +- Keep the placeholder-while-dragging behavior. Decoding JPEGs during drag was too slow on device, even with micro covers. +- Repaint real covers after the finger is released. +- Do not call `gc.collect()` per row draw. Collect after record preparation, after API fetches, or at other non-hot-path points. +- JPEG is the practical default on stock firmware. PNG generally has worse memory characteristics, and raw/RGB565 should only be attempted after confirming a stable on-device blit API. + +## Scroll Performance + +- The scroll hot path must not measure text, join artist lists, sanitize strings, calculate full content height, or fetch images. +- After fetching records, call the preparation path that caches: + - `_display_title` + - `_display_artists` + - `_display_meta` + - `_thumb_url` + - `_row_height` + - total `_content_height` +- Preload only `micro_cover_url` thumbnails before the first day-view draw. Do not eagerly fetch larger fallback images. +- Drag scrolling should remain pixel-based, but redraws should be throttled by both time and pixel delta (`DRAG_REDRAW_MS`, `DRAG_REDRAW_PX`). +- Preserve any pending drag delta on touch release and redraw once with real covers if the view moved. + +## Layout Details + +- Use named constants for pixel geometry instead of scattered literals. +- For record rows, keep cover top and bottom spacing visually symmetric: + - `ROW_PAD_Y` is the padding above and below the cover. + - `ROW_SEPARATOR_H` is the separator line height after the bottom padding. +- If row spacing looks wrong on device, reason in terms of inclusive pixel drawing: a separator drawn inside the padding visually consumes that padding. + +## Display Sleep + +- The display sleeps by setting the backlight to `0.0`; the app and WiFi stay running. +- The first touch after sleep should wake the backlight and be consumed so it does not also activate a control. +- On wake, check WiFi and reconnect only if it dropped. + +## API Contract + +The records endpoint is: + +```text +GET https://music-library.claudio-ortolina.org/api/v1/collection/on_this_day?date=YYYY-MM-DD +Authorization: Bearer +``` + +Expected record fields used by the app: + +- `title` +- `artists` +- `format` +- `release_date` +- `micro_cover_url` +- `mini_cover_url` +- `thumb_url` + +When adding or changing API assumptions, update `README.md`.