Commit Graph

9 Commits

Author SHA1 Message Date
ebb4023955 Fix scroll-back-to-top shimmer: prepend-on-submit job queue
Root cause: the worker job queue was FIFO (mpsc). Scrolling down filled it
with slow cold decodes of far cells; scrolling back up re-submitted the top
cells as fast disk-cache hits that then waited behind the whole backlog —
seconds of shimmer. Deterministic repro measured 6.3 s behind a 180-cold
backlog (emulator UI showed the same while 220 cold jobs waited 0.5-0.9 s).

Fix: job queue is now Mutex<VecDeque> + Condvar; Engine::submit prepends
each new batch so the most-recent intent (the viewport, or what you scrolled
back to) is decoded before stale far-away prefetch. Cold backlog keeps
warming the disk cache in the background (total work unchanged).

- regression: thumb::tests::scroll_back_cache_hit_not_starved (6.3 s -> 130 ms)
- dispatcher exits via a closed flag set in Engine::drop (replaces the
  mpsc channel-close shutdown)
- HANDOFF: M3 fix note, prepend rationale, emulator realtest_extra dataset
2026-10-27 19:38:45 -04:00
c9a6066ace HANDOFF: M3 real-device scroll-FPS result + SurfaceFlinger latency method
Pixel 9 Pro (release aarch64, 8,577 photos): sustained 60 fps, 0 display
hitches while scrolling, cold and warm cache. dumpsys gfxinfo reports 0
frames for Slint's NativeActivity window on Android 15 — document the
dumpsys SurfaceFlinger --latency <layer> method instead.
2026-10-27 18:45:46 -04:00
59787f1d3f M3: 3-column grid UI with shimmer, scroll prefetch, bounded retention
- main.slint: ListView of GridRows (3 square CellViews each); Cell struct
  {path, image, loaded}; shimmer placeholder via animation-tick()
  expression (1.18 has no from:/to: animation objects); scroll-changed
  callback feeds Rust.
- lib.rs: active-range model (visible rows ± 4-row margin); on_scroll is
  cheap (re-anchor + submit prefetch only); a 10 Hz drain timer owns ALL
  model mutation, capped at 16 row-replacements/tick (ANR guard);
  apply_row_batch replaces each affected outer row once — the only update
  path that reaches ListView rows recycled while off-screen; clearing a
  cell releases its dedupe entry so re-entry re-submits (disk-cache hit).
- thumb.rs: LIST_TARGET(64) -> GRID_TARGET(500); cache key includes target.
- Verified on emulator (150 real JPEGs + 5k stubs): first paint 0.6 s
  cold, warm relaunch from disk cache, 0 ANRs through 16 fast swipes,
  backlog drains to 0. 13 unit tests + 5k engine test pass.
- HANDOFF: M3 status, Slint gotchas 11-13 (in-property binding, nested
  model updates vs row recycling, ListView spacing), emulator test-data
  notes.
2026-10-27 18:13:28 -04:00
572409b702 M2: thumbnail engine — turbojpeg DCT-shrink decode, worker pool, disk cache
- images.rs: libjpeg-turbo 1/2..1/8 shrink decode (48MP @1/8 ~2.3MB peak),
  all 8 EXIF orientations, imageops::resize final fit, PNG via image crate,
  q85 re-encode for the disk cache
- thumb.rs: dispatcher + N=cores/2 workers (2..8), cache
  thumbs/{sha1(path|mtime|size|target)}.jpg (target in key: list 64px and
  grid 500px coexist), atomic rename, generation-based cancellation,
  per-worker sqlite set_thumb, 256-job cadence logs
- lib.rs: AppState OnceLock, 10Hz drain timer (leaked !Send Timer),
  scroll prefetch (50-row margin), do_prefetch gating for scan batches
- main.slint/db.rs: rows carry images; list_entries + set_thumb
- build.sh: NDK CMake toolchain env for turbojpeg-sys (ANDROID_JAR vs
  ANDROID_PLATFORM conflict), nasm on PATH, ADB_SERIAL, debug-aarch64
- HANDOFF: M2 done + acceptance data; HEIC deferred (0 HEIC on device);
  transient first-launch black screen parked as §10.7 (unreproducible)

Verified: 12 unit tests + 5k engine test; Pixel 9 Pro 8577 photos —
cold scan ~5s streaming, warm relaunch instant, thumbnails in every row,
~100% cache hits on relaunch; release aarch64 APK 9.8 MB.
2026-10-27 16:32:12 -04:00
c72b00f7ec M1: instant list paint + streaming first scan
- relaunch: DB list paints immediately ('N files (cached)'), background
  walk refreshes ('Updating… N') — no more 5.5 s blank list on warm start
- first launch: walk_stream() feeds the list in 512-file batches while
  scanning; UI never waits for the full DB build
- skip hidden dirs (.thumbnails/.trash/…): -559 entries on the phone
- db.rs: cfg-gate ANDROID_PACKAGE (dead-code warning on desktop)

Phone (8.5k photos): cold scan 4.2 s with live list; warm relaunch
paints instantly, rescan 4.2 s in background.
2026-10-27 13:45:37 -04:00
e1982eade4 M1: metadata scan + sqlite DB + placeholder list
- scan.rs: recursive walk of Pictures/DCIM (GALLERY_SCAN_DIRS override),
  image-ext detection, mtime/size capture, no symlink-dir following
- db.rs: rusqlite(bundled) store; incremental apply (insert/update/delete)
  keyed on path with mtime/size change detection; derived columns reset on
  change; Android DB path in Android/data/<pkg>/files (EXTERNAL_DATA_DIR is
  unset in this NativeActivity setup)
- lib.rs: start_scan() background thread -> invoke_from_event_loop ->
  VecModel + status line; called from desktop and Android entry points
- main.slint: ListView of paths (M1), status line with scan stats
- main.rs: fix desktop bin for 1.18.1 (no slint::Result; ComponentHandle)
- build.sh: export NDK clang CC_/CXX_/AR_ per target (bundled sqlite)
- tests: 5k-file scan < 2s, incremental apply, roundtrip

Verified on emulator: 5002 files in 153-226 ms; relaunch 0+ 0~ 0-;
touch -> 1~, delete -> 1-.
2026-10-27 13:28:33 -04:00
53ba74747d README: point at HANDOFF.md, build instructions, license note 2026-10-27 12:23:12 -04:00
4863e42bae M0: Slint gallery scaffold + development hand-off
- Slint 1.18.1 (backend-android-activity-06), cargo-apk2 packaging
- Manifest permissions: READ_MEDIA_IMAGES, READ_EXTERNAL_STORAGE (maxSdk 32),
  MANAGE_EXTERNAL_STORAGE
- android_main with permission-aware init_with_event_listener hook and
  AndroidApp clone stash for JNI (storage flow, later BLE/etc.)
- scripts/build.sh: release/debug x86_64 + aarch64, sign, adb install
- HANDOFF.md: full dev plan (architecture, thumbnail pipeline, milestones,
  gotchas, perf targets) from the Slint/eframe evaluation
- Verified: builds, installs, runs on pad_avd emulator (API 35)
2026-10-27 12:22:59 -04:00
gmp
2fe5f5917a Initial commit 2026-10-27 12:13:22 -04:00