54f9cb54fbee28b08d74506790b9f958e75ec31a
Shift-clicking two photographs selected only the cells between them that were in the loaded window. The grid is a window of a hundred or so over a library of twenty thousand, and `apply_press` resolved the range against that window — `ids[lo_row..=hi_row]`, clamped to what was there. Everything else in the run had no id anywhere in the UI, so it was silently dropped. The user cannot see that: the selection count is off screen along with the photographs, and the gesture only announces itself when the drop files a dozen images instead of two hundred. The two ends are *ordinals*, and only the catalog knows what lies between them. `read_ids_span` asks it, through the same predicates, the same rating filter and the same ordering the window itself is read with — an ordinal names a photograph only relative to an ordering, so a run taken through any other one is a run through a different library. That ordering is now a constant, `GRID_ORDER`, shared by the window, the trash's own order beside it, and the run: capture time first, with the file name breaking ties and nothing more. A card written by two cameras interleaves names that have nothing to do with each other, and what "everything between these two" means to a photographer is a stretch of an afternoon. The query is reached through a closure handed to `CollectionsController` at wiring time rather than a catalog handle, because the scope and the filter that bound the run belong to the grid's controller. `apply_press` stays a pure function of what it is given, which is what keeps the selection rules testable with no library open — and the tests pass a run that reads a plain slice. Where there is nothing to ask, the loaded window is still used: a poorer answer than the catalog's and a far better one than a gesture that appears to do nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…
DarkRoom
A cross-platform, non-destructive RAW photo editor for Linux and Android.
Status: early. v0.1 is a remote library viewer — see docs/milestone-v0.1.md.
Documentation
| Document | Contents |
|---|---|
| requirements.md | What the software must do — 122 numbered requirements |
| architecture.md | How it is built — crates, GPU pipeline, data model, sync |
| milestone-v0.1.md | The first buildable milestone |
Building
Desktop:
cargo run -p darkroom-desktop
Android (containerised toolchain, see docker/android):
./docker/android/build.sh cargo ndk -t arm64-v8a build --release
Current state
Working: workspace, GPU context and compute pass, adaptive Slint shell, Android cross-compilation of the core crates.
Not yet working: the zero-copy display path. The build currently uploads frames through the CPU, which is exactly what ARCH §6.1 forbids — measured at 96% of frame time at 4K. Replacing it is spike S1, the project's highest priority.
cargo run -p dr-gpu --example bench --features readback
reproduces that measurement.
Licence
GPL-3.0-or-later.
Releases
20
DarkRoom 0.24.0
Latest
Languages
Rust
86.1%
Slint
10.3%
Python
1.1%
Shell
1%
WGSL
0.9%
Other
0.6%