# 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