Go to file
Greg Pomerantz 58b203e4fa gtauri: event-driven watching + defense against stale VFS dir listings
Live watching is now event-driven, no tree polling:
- Android: MainActivity registers a MediaStore ContentObserver
  (Images, notifyForDescendants) and wakes the Rust watcher thread via
  a JNI call (Java_wow_gmp_gallery_MainActivity_nativeFsChange) — a
  single channel send, no main-thread work. Covers camera saves,
  media-scanner indexing, other apps' indexed writes.
- Desktop: inotify/FSEvents via notify on the scan roots.
- On wake: coalesce + debounce, diff dir mtimes, rescan only the
  changed subtrees. The 1 s recv timeout doubles as a cheap backstop
  (raw out-of-band copies the scanner hasn't indexed yet); a 5-minute
  full pass is the safety net. minSdk 30 (3-arg ContentObserver API).

Stale-listing truncation bug found and fixed (reproduced on the
emulator's 9p /sdcard; the phone's FUSE does the same): a readdir over
a large directory can return a SILENT early EOF — a stale cached
listing with NO error. The phone's 9961-file Camera dir truncated at
~8400 once and db::apply deleted ~1700 good rows. Three layers now:
1. scan::read_dir_full — retry whole-dir reads on mid-stream errors;
2. per-directory cross-check in walk_dir: if the enumeration is far
   below the DB's count for that dir, re-read up to 3x keeping the
   best listing; whole-walk re-check in rescan keeps the larger of two
   walks;
3. db::apply mass-delete guard: never delete >20% of the DB in one
   apply unless a previous walk already saw the low count (two-strike;
   a meta.walked row tracks it). Genuine gradual deletions still flow
   through (verified: a 4000-file mass move streams the grid down
   progressively), and a second consecutive low walk still deletes.

Emulator reliability suite (all pass): 3x launch count stability,
add +1 / remove -1 in ~2 s, 20-file burst, DB recovery from damage,
stale-listing refusal (0 rows lost), two-strike delete, live restore,
idle 0.0% dropped frames, deep fling loads thumbnails. A/B vs ttimg
(no-backend CSS-scroll control): adb-swipe drop deltas are at the
input-injection artifact level, idle identical (0.0%).
2026-11-01 20:24:01 -05:00
docs/BUGS 120Hz: jank_eval referee + slot-based wake guard + MISS ledger 2026-10-30 13:29:50 -04:00
harnesses gtauri: event-driven watching + defense against stale VFS dir listings 2026-11-01 20:24:01 -05:00
scripts Port the gallery from Slint to egui (egui 0.31 / egui_glow / winit 0.30 / glow 0.16) 2026-10-31 13:50:46 -04:00
shim/out Port the gallery from Slint to egui (egui 0.31 / egui_glow / winit 0.30 / glow 0.16) 2026-10-31 13:50:46 -04:00
src Port the gallery from Slint to egui (egui 0.31 / egui_glow / winit 0.30 / glow 0.16) 2026-10-31 13:50:46 -04:00
tools Port the gallery from Slint to egui (egui 0.31 / egui_glow / winit 0.30 / glow 0.16) 2026-10-31 13:50:46 -04:00
.gitignore Port the gallery from Slint to egui (egui 0.31 / egui_glow / winit 0.30 / glow 0.16) 2026-10-31 13:50:46 -04:00
Cargo.lock Port the gallery from Slint to egui (egui 0.31 / egui_glow / winit 0.30 / glow 0.16) 2026-10-31 13:50:46 -04:00
Cargo.toml Port the gallery from Slint to egui (egui 0.31 / egui_glow / winit 0.30 / glow 0.16) 2026-10-31 13:50:46 -04:00
HANDOFF.md docs: HANDOFF §8.12 (egui port + tttest harness), README reflects the egui stack 2026-10-31 13:54:56 -04:00
LICENSE Initial commit 2026-10-27 12:13:22 -04:00
README.md docs: HANDOFF §8.12 (egui port + tttest harness), README reflects the egui stack 2026-10-31 13:54:56 -04:00

gallery

A high-performance image gallery for Android (primary), Linux and macOS — Rust + egui 0.31 (egui_glow / winit 0.30 / glow 0.16). Ported from Slint 1.18 after the zero-jank campaign showed Slint-on-Mali janky at its base level while egui measured 3–7× cleaner (HANDOFF.md §8.11–8.12). The Slint tree is preserved in git history and docs/BUGS/.

Status: M0–M4 ported to egui, zero-jank tuning in progress. See HANDOFF.md — the development hand-off: architecture, thumbnail pipeline, milestones M1–M7, the Slint jank campaign, the egui port, and the sltest/egtest/tttest harnesses (A/B/C: Slint/egui/WebView).

Build

./scripts/build.sh debug     # debug x86_64 APK + install on emulator
./scripts/build.sh           # release x86_64 (emulator)
./scripts/build.sh aarch64   # release aarch64 (device)
cargo run                    # desktop (Linux needs libfontconfig1 + pkg-config)

Requires: Rust (rustup), cargo-apk2, Android SDK + NDK 27 (see HANDOFF.md §3 for exact paths/env).

License

GPL-3.0 (see LICENSE). Built on egui (MIT/Apache-2.0).