Files
DarkRoom/docs
dtourolle 38819da222 Replace the six view booleans with View and Page enums
app.slint carried show-launch, show-library, show-identity, show-settings,
show-import and show-merge as separate booleans, so the root component chose
what to draw with five- and six-term conjunctions and nothing stopped two of
them being true at once. Replaced with two enums: View { develop, library,
identity, launch } for which top-level screen is showing, and Page { none,
settings, import, merge } for which page, if any, is drawn over it.

Two values rather than one, because the two questions are genuinely
different. Settings, Import and Merge are reachable from more than one View
and are drawn outermost without touching it — closing one has to return to
whichever View was already current, and today that works because the
underlying property is left alone while the page sits over it. A single
View with five or more variants would need a second field remembering what
to return to; Page needs nothing to remember, since View was never
overwritten in the first place. Identity, by contrast, genuinely replaces
the window the way Launch and Library do (see the existing "like the launch
screen" comment on its `if`), so it is a View variant, not a Page.

Every `if` chain in app.slint that used to compare four, five or six
booleans now compares active-view and active-page to at most one variant
each. library-visible collapsed from a six-term conjunction to
`active-page == Page.none && active-view == View.library`.

The Rust side follows: every set_show_*/get_show_* call in library_ui.rs,
identity_ui.rs, settings_ui.rs, merge_ui.rs, import_ui.rs, launch_ui.rs and
lib.rs now reads or writes active-view or active-page instead, including
lib.rs's startup match (View.launch vs View.develop, since a Startup that
skips the launch screen used to leave both old booleans false and fall
through the chain to develop) and identity_ui's close handler, which now
writes View.library or View.develop in one call where it used to write
show-library then show-identity separately.

back_one_step needed one deliberate adjustment beyond the mechanical
rename. Identity was never represented in NavState: back had nothing to do
when Identity was opened from the library (show-library stayed true,
unread by IdentityScreen's own condition) and could only reach ToLibrary
when opened from develop, which likewise wrote a property IdentityScreen
never read — so escaping out of Identity was invisible in both cases before
this change. With a single active-view, falling into the general case
would instead overwrite the value IdentityScreen's `if` does read and close
it as an unintended side effect. back_one_step now swallows the gesture
while View.identity is current, reproducing the same "nothing visible
happens" outcome for both origins without threading identity_ui's private
came-from-library state through lib.rs for one screen.

Verified with tools/manual/drive.py against a private Xvfb and the debug
build: launch screen to library, Settings opened and closed, Identity
opened and closed (including Escape doing nothing while it is open),
develop opened from a cell and closed both by the back button and by
Escape. Screenshots under verify/.
2026-09-20 20:30:56 +02:00
..

Documentation

Two audiences, two folders. Most people want the first table and never the second.

Using DarkRoom

The manual Every feature, pictured from the application itself — opening a library, rating and filing, developing, local masks, repair, film, panoramas, export
How it is driven Every gesture and shortcut, by screen. Generated from the code, so it cannot describe one the application does not have

The top-level README says what DarkRoom is, how to get it on each platform, and what is still missing.

Changing DarkRoom

Everything under dev/ is for someone working on the code. Start with CONTRIBUTING.md, which says how to land a first change without reading the rest.

The register and the record. What must be built, how it is built, and how far along it is.

requirements.md What the software must do — the numbered register, the decisions (D-numbers) and the spikes (S-numbers)
architecture.md How it is built — crates, the GPU pipeline, the data model, sync
traceability.md Generated: which requirement is claimed by which file. Never edited by hand
outstanding.md What is specified and not built, and whether that is a decision or a gap
technical-debt.md Compromises taken deliberately, each with the condition that retires it
code-health.md What a contribution costs, per seam, measured

Designs, one per subsystem. Each is the specification the code was built to, kept current as the code moved.

catalog.md The index, the library view, incremental scan, the job queue
storage.md Storage backends: the seam a folder, a sync client and a Nextcloud account share
faces.md Face detection, identity, clustering and the eye-state models
segmentation.md How the application finds the regions a local mask snaps to
mask-editing.md Painting, erasing and combining masks
spot-removal.md Clone and heal as parameters in the edit graph
panorama.md Alignment, projection, the chunked composite and the border fill
inference.md The neural runtime and model chosen per device, with the measurements
display-and-extension.md The display contract, and why the fused pipeline is already most of a plugin format
view-composition.md A controller for the display layer
ui-navigation.md Finding things in the interface once there are many

Measurements. Numbers committed so a regression is a diff rather than a recollection.

benchmarks.md The per-commit suite: what it covers, what it does not, how to read a failure
bench-baseline.json The committed numbers the suite checks against
frame-budget.md What a frame costs on each device, and the decision those figures settled

Platforms and distribution.

distribution.md Which channels v1 targets and what each one constrains
windows.md The Windows installer, cross-built from the Linux CI
android-signing.md Which key signs the APK, and keeping it

Archive. Kept as the record of what was asked for, not as plans.

milestone-v0.1.md The first milestone, delivered 2026-08-30 and superseded
ui-refinement.md How the interface should look; succeeded by ui-navigation.md

Conventions

Two files here are generated and must not be edited by hand: gestures.md and dev/traceability.md. Both come from cargo run -p traceability and the pre-commit hook keeps them in step with the tree. The manual's pictures are recorded by tools/manual and live in LFS.

A design document links to the requirements it satisfies and to the code that satisfies them. When the code moves, the link moves with it; a document that has stopped being true goes to dev/archive/ with a note saying what replaced it, rather than being deleted.