e68909d64d
Main / Build (BookPlayer) (push) Has been cancelled
Main / Build (Brainfuck) (push) Has been cancelled
Main / Build (Breakout) (push) Has been cancelled
Main / Build (Calculator) (push) Has been cancelled
Main / Build (Diceware) (push) Has been cancelled
Main / Build (EpubReader) (push) Has been cancelled
Main / Build (GPIO) (push) Has been cancelled
Main / Build (GraphicsDemo) (push) Has been cancelled
Main / Build (HelloWorld) (push) Has been cancelled
Main / Build (M5UnitTest) (push) Has been cancelled
Main / Build (Magic8Ball) (push) Has been cancelled
Main / Build (MediaKeys) (push) Has been cancelled
Main / Build (MystifyDemo) (push) Has been cancelled
Main / Build (SerialConsole) (push) Has been cancelled
Main / Build (Snake) (push) Has been cancelled
Main / Build (TamaTac) (push) Has been cancelled
Main / Build (TodoList) (push) Has been cancelled
Main / Build (TwoEleven) (push) Has been cancelled
Main / Bundle (push) Has been cancelled
- Migrates tactility-app-development from ~/.hermes/skills/ into .claude/skills/ for repo co-location - Adds AGENTS.md with local workstation context, hardware table, board-direct build/env wrapper (PYTHONPATH fix), ELF missing-symbol triage, app patterns (immersive, QVGA rail, tutorial 2-row, GameKit bubbling, screenshot rate-limit), and skill index Refs: personal Gitea mirror
103 lines
6.1 KiB
Markdown
103 lines
6.1 KiB
Markdown
# Book Browser — Horizontal Slide + Clean v4 + Animated v6 Final (arc-free, low-RAM, beautiful)
|
||
|
||
## Problem history
|
||
|
||
1. **66-button list** — 66× `lv_button_create` + flex rows + labels = 132-264 LVGL objs.
|
||
- `GET /api/sysinfo`: `heap free 275B total 310KB min_free 23 largest_block 23` → OOM.
|
||
- Symptom: `PUT /api/apps/install 500 failed to create temp directory`, screenshot `500 25`.
|
||
- After self-crash: heap 33KB, install `200 ok` again.
|
||
|
||
2. **`lv_arc` rotary** — center name changes rotating ring, 6 objs ideal.
|
||
- Build 0 missing on 0.8.0-dev SDK (`symbols.c` PR #496 `dff93cb6`), but device `0.7.0-dev` (192.168.68.112) missing: blue dialog `Error / missing symbol / OK`, heap `31779` healthy → loader failure not OOM.
|
||
- `git log -S lv_arc_create` → added after 0.7 release. Must be arc-free for 0.7 fleet.
|
||
- `lv_roller` not exported on 0.7/0.8.
|
||
|
||
3. **v3 horizontal slide + slider** — works on 0.7, ~12 objs, heap `10943 free largest 7168` (112), `54355 free` on 129 0.8.0-dev after editorial.
|
||
|
||
## v4 Clean (July 12) — User: remove Go, card, top bar; larger 50% name; number 39/66 right of slider; cancel left of slide
|
||
|
||
- Removed: top header `Books — swipe`, Go button 200x36, card bg `15151F` radius 18
|
||
- New layout:
|
||
- `center_wrap` full-screen `PCT(100)` pad_top 0 pad_bottom 64 (was 52/88), transparent, CLICKABLE + swipe `PRESSED/PRESSING/RELEASED/PRESS_LOST`
|
||
- Left arrow 44x44 radius22 `1E1E2E` at `LEFT_MID 8,0`, right arrow same `RIGHT_MID -8,0`, click steps ±1
|
||
- Center `mid_wrap` 68% width `SIZE_CONTENT`, transparent, gap 10, flex column center, CLICKABLE → `on_book_center_click` jumps (tap name does Go)
|
||
- `book_center_name` `LARGE` (was DEFAULT, 50% bigger), width `100%`, `DOTS`, center aligned, pretty `georgia_regular_24` serif
|
||
- `book_center_verses` small dim `5A5A78`
|
||
- Bottom bar `100%x56` `15151F` top border `232338`, row `SPACE_BETWEEN` center, gap 10, pad hor10 ver8
|
||
- `[X cancel 36x32 radius8 252538 left] [slider flex_grow 1 height8 range 0..65 bg 232338 ind 4A4A6E knob E8E6E0] [num label 1/66 right 8A8AAA small]`
|
||
- Object count ~10 (vs 12 v3, vs 264 v1) → heap `54471→54355` stable on 129, `PSRAM 4.9MB`
|
||
|
||
## v6 Final Animated (July 12 beautiful build 2142871) — User: "add animation to the bible book selection. Also let's start the app with the menu showing, but make the menu UI auto hide after 10s." + lift correction 30→15px + beautiful approval
|
||
|
||
**Animation added**:
|
||
```c
|
||
static void book_y_anim_cb(void* var,int32_t v){ lv_obj_set_y((lv_obj_t*)var,v); }
|
||
static void book_fade_anim_cb(void* var,int32_t v){ lv_obj_set_style_text_opa((lv_obj_t*)var,v,0); }
|
||
|
||
set_book_browser_visible(true):
|
||
ctx->book_dial_idx = cur_book_idx; book_dial_update_center(ctx);
|
||
remove FLAG_HIDDEN
|
||
// pop center mid_wrap y 20->0 260ms ease_out
|
||
mid_wrap y = 20; lv_anim 20->0 260ms ease_out via book_y_anim_cb
|
||
// fade name OPA_20->COVER 220ms ease_out via book_fade_anim_cb
|
||
book_dial_update_center: on swipe/slider change name fade 60->255 180ms ease_out
|
||
```
|
||
|
||
**Menu auto-show 10s** (see immersive-ui.md): `chrome_auto_hide_timer` field + `chrome_auto_hide_cb` uses `lv_timer_get_user_data` not `t->user_data` (incomplete typedef error), `onShowApp` `set_chrome_visible(true)` + `schedule 10000`, `toggle_ui` re-arms 10s, `toggle_book_browser` deletes timer, `onHide` deletes. Verified 8683 bytes menu visible `Zephaniah 1:3 / 31094` + bottom pills X/List/Prev/Pause/Next at 0.8s after run, 6882 immersive hidden at ~2s (configured 10s, screenshot race). "This is beatiful, well done."
|
||
|
||
**Lift correction**: `CENTER 0,8` too low → `0,-22` 30px up → user corrected "should had been 15" → `0,-7` = `+8 base -15` = 15px up balanced, vision "optical center correct, prevents sitting on buttons".
|
||
|
||
## AppCtx fields v6 final
|
||
```c
|
||
lv_obj_t* book_browser;
|
||
lv_obj_t* book_center_name; // LARGE 50% bigger, directly on bg, tappable jumps, georgia_regular_24
|
||
lv_obj_t* book_center_num; // bottom right 39/66
|
||
lv_obj_t* book_center_verses;
|
||
lv_obj_t* book_slider;
|
||
int book_dial_idx;
|
||
int book_drag_start_x;
|
||
bool book_dragging;
|
||
bool book_browser_visible;
|
||
lv_timer_t* chrome_auto_hide_timer; // v6 auto-hide
|
||
bool ui_visible;
|
||
```
|
||
|
||
Center update syncs slider + number + fade:
|
||
```c
|
||
static void book_dial_update_center(AppCtx* ctx){
|
||
BookInfo* b=&ctx->books[ctx->book_dial_idx];
|
||
// fade anim 60->255 180ms
|
||
lv_obj_set_style_text_opa(center_name,100,0);
|
||
lv_anim_t an; lv_anim_init(&an); lv_anim_set_var(&an,center_name); lv_anim_set_values(&an,60,255); lv_anim_set_duration(&an,180);
|
||
lv_anim_set_exec_cb(&an,book_fade_anim_cb); lv_anim_set_path_cb(&an,lv_anim_path_ease_out); lv_anim_start(&an);
|
||
lv_label_set_text(book_center_name,b->bname);
|
||
lv_obj_set_style_text_font(book_center_name,resolve_book_font(ctx),0); // georgia_regular_24 50% bigger
|
||
snprintf(num,"%2d / %d",b->bnumber,book_count); lv_label_set_text(book_center_num,num);
|
||
snprintf(vers,"%d verses",b->verse_count); lv_label_set_text(book_center_verses,vers);
|
||
lv_slider_set_value(slider,dial,LV_ANIM_OFF);
|
||
}
|
||
```
|
||
|
||
Swipe 28px per book via `lv_indev_get_point/active`.
|
||
|
||
## PSRAM vs heap
|
||
- `CONFIG_ELF_LOADER_LOAD_PSRAM=y` → app `.text/.rodata` SPIRAM 4.2-4.3MB ELF, free 4.8-5.2MB
|
||
- LVGL objects internal heap 310KB only. 264 objs OOM, 10 objs safe, 13 objs with anim safe 46-47KB
|
||
|
||
## Compat table v6 final
|
||
| widget | 0.7.0-dev .112 | 0.8.0-dev .129 | notes |
|
||
|---|---|---|---|
|
||
| `lv_arc_*` | MISSING | exported PR #496 | true rotary if fleet 0.8+ |
|
||
| `lv_roller_*` | MISSING | MISSING | not exported |
|
||
| `lv_slider_*` | OK | OK | scrub |
|
||
| `lv_indev_get_point/active` | OK | OK | swipe 28px |
|
||
| `lv_anim_*` | OK | OK | fade 220/300, book slide 260ms |
|
||
| `lv_timer_get_user_data` | OK | OK | auto-hide timer, need getter not direct access |
|
||
| `georgia_italic_*` embedded | OK via fallback | OK 4.3M PSRAM | pretty serif |
|
||
|
||
## Verification v6 final beautiful
|
||
- Heap 275B OOM → 10943 .112 → 54471→46215 .129 stable with fonts+anim
|
||
- Screenshots: reading 3756-4347, editorial fade 3991, menu show 8683, immersive 6882, error dialog 2755 missing symbol
|
||
- Boards .112 0.7.0 33KB, .129 0.8.0 46-54KB
|
||
- Build 2142871 editorial v6 beautiful approved
|