Files
DarkRoom/ui/dr-ui/src/library_ui/mod.rs
T
dtourolle 220e9af222 Add the duplicate originals review, from the sidebar and from Settings
"Duplicate originals" appears under the trash in the collections
sidebar while the catalog holds any, and Settings says how many there
are beside the other whole-library passes. Both open one page: every
group with its picture and paths, the copy that stays (tap another path
to change it), a per-group Include box, what the survivor will gain and
any flag, label or face conflict, and why a group was skipped.

The summary is the dry run -- "N groups, M files to trash, K skipped" --
and nothing moves until "Check" has read the copies and "Move M copies
to trash" is pressed. Both run on workers with progress on the page, in
the activity register and, for the move, on the library status line;
Stop ends a job between groups. When it ends the grid, the sidebar and
the trash are refreshed and the survivors' judgements are written to
their sidecars and XMP the way a rating keystroke writes them.

The page is paginated at 30 groups, so a redraw decodes 30 thumbnails
and previews 30 merges whatever the size of the library. Back and
Escape leave it like its own Back button.
2026-09-26 07:19:13 -04:00

57 lines
2.6 KiB
Rust

//! TRACES: FR-CAT-4 | FR-NC-3 | NFR-P9
//! Drives the library grid from scan and thumbnail workers.
//!
//! Owns the bridge between three background activities and one single-threaded
//! event loop:
//!
//! - a **scan** worker walking the remote tree into the catalog
//! - a **thumbnail** worker range-fetching previews for visible cells
//! - the **grid model** Slint renders
//!
//! Nothing here blocks. Workers post through mpsc channels drained by Slint
//! timers, which is the same shape [`crate::launch_ui`] uses for login.
//!
//! # Why thumbnails are fetched, not derived from the scan
//!
//! A scan yields paths and sizes, nothing visual. Each thumbnail costs its own
//! range request, so they are fetched **only for cells the grid actually
//! wants** — never for the whole library up front. On the reference library
//! that is the difference between a few MB and ~370 GB (ARCH §6.7).
//!
//! Split into one module per area of behaviour (docs/dev/code-health.md CH-1):
//! `controller` holds the running state every other module reads and writes
//! through `pub(super)` fields; `open` is the launch-to-scan cycle and the
//! worker that checks the catalog file before either touches it; `offline`
//! is what of a collection is on this device and the prompt that offers to
//! change it; `window` fills the grid model from the catalog and drains the
//! thumbnail fetch; `sync` is the background passes that reach beyond the
//! loaded window — the metadata sweep, the whole-library thumbnail pass, and
//! the exchange with the server; `ratings_keywords` applies a judgement or a
//! keyword to a selection and queues the sidecar and XMP writes behind it;
//! `timeline` is the capture-time sidebar and the photographer's place,
//! which move together closely enough to live in one file; `grid` wires the
//! grid's own callbacks — the keyboard cursor, cell-size zoom, the routes
//! into and out of develop; `filter_bar` wires the rating, people, date and
//! offline-scope filters. `mod.rs` re-exports what the rest of the crate
//! calls by `library_ui::` path, so nothing outside this module needs to
//! change.
mod controller;
mod filter_bar;
mod grid;
mod offline;
mod open;
mod ratings_keywords;
mod sync;
mod timeline;
mod window;
pub use controller::LibraryController;
pub use grid::wire;
pub(crate) use open::{forget_catalog, show_catalog_now, start_rescan};
pub use open::{open, reload};
pub use ratings_keywords::paste_settings_to_selection;
pub(crate) use ratings_keywords::{save_judgements, start_sidecar_writes};
pub use timeline::format_date;
pub use window::refresh_thumbnail;