The slow pop-in (warm and cold) had two root causes, both in the drain tick / scan pipeline: 1. Paint-cap drop bug: finished decodes beyond MAX_PAINT_CELLS_PER_TICK were silently dropped (out of inflight, not in painted) so FILL re-submitted them — the same cell re-decoded 3-6x per viewport and a new viewport took 500-850ms to fill after a flick. Now excess results hold in app.ready (bounded READY_CAP=48) and paint on a later tick at zero re-decode cost; FILL skips ready_paths. The cap is adaptive: 2 during grid motion (frame budget), 4 when settled (fast pop-in). 2. Cold-start scan storm: every 512-entry scan batch re-sorted the WHOLE list and set_list did a full model reset + generation bump, orphaning every queued decode (arrived marked stale, dropped, re-submitted) — a 17x re-decode storm (max observed dups = 18 = batch count) plus full row churn per batch. Streaming now appends (each 512 group mtime-sorted, groups concatenated = stable prefix), and set_list detects appends (prefix match) to extend the model in place (extend_from_slice) with NO reset/generation-bump. The final global sort is ONE reset at scan end; viewport re-fills from the disk cache (~2ms/cell). Measured: scan 7637ms -> ~4.3-4.9s, decode dups 18 -> 2-3. Window black after pause (regression found while testing): the OS can invalidate our surface (system dialog, app switch) with NO window event and no pending model change -> the window returned black and stayed black (nothing ever set pending_redraw). Fixes: - request_redraw() unconditionally in RenderingSetup - drain-tick watchdog: window visible but no frame completed for >2.5s -> one forced redraw (LAST_PRESENT_US, updated in AfterRendering; now_us/NOW_T0 no longer perf-gated) Also: debuggable=false — the system 16KB-compat dialog (debuggable apps only) is its own activity, it paused us on every cold launch, and its inconsistent lifecycle (TermWin or not) was the main black- window trigger in testing. Phone-verified (cold, 8580 files, fresh DB): clean launch, grid streams in with thumbnails, flicks render 120Hz (median 8.3-8.5ms, 0-2 late frames), viewport fully painted after flick, grid intact after an app switch (no black window). |
||
|---|---|---|
| docs/BUGS | ||
| scripts | ||
| shim | ||
| src | ||
| vendor | ||
| .gitignore | ||
| build.rs | ||
| Cargo.lock | ||
| Cargo.toml | ||
| HANDOFF.md | ||
| LICENSE | ||
| README.md | ||
gallery
A high-performance image gallery for Android (primary), Linux and macOS — Rust + Slint 1.18.
Status: M1 (metadata scan + DB) done. See HANDOFF.md — the development hand-off with the full plan: architecture, thumbnail pipeline, milestones M1–M7, Slint gotchas, permission flow, and performance targets. Next: M2 (thumbnail engine).
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 Slint, used under the Slint royalty-free license for proprietary apps (see HANDOFF.md §10.4).