Remember where the photographer was
Opening the application was always a fresh arrival at the beginning of the library, whatever you had been doing when you closed it. What is written down is the view, the scope, the rating filter and the photograph on screen -- the open one in develop, the first visible one in the grid. Not just a scroll position: a position without the filter that produced it names a row of a list that no longer exists. Restoring them has an order for the same reason -- scope, then filter, then position, then the view -- because each step changes what an ordinal *means*. Addressed by remote path and collection UUID, never by an ordinal or a row id. `images.id` and `collections.id` are local to one catalog, and a grid ordinal is local to one ordering; a record naming either would land somewhere arbitrary on a second device and after any filter change on this one. Where the ordinal is needed, `library::ordinal_of_path` computes it through the grid's own `ORDER BY`, taken verbatim by a window function rather than spelled a second time as an inequality -- which is the mistake `grid_order_for` already warns about, and which a manually ordered collection would make unreadable. Every failure degrades rather than reports. A collection this device has not merged leaves the scope at the whole library; a photograph that has since been deleted falls back to when it was taken, which puts the grid in the right week; a torn file yields no place and the library opens at the top. Reopening develop is the one thing that requires an exact match, because a canvas on a path that no longer resolves is a filename over an empty frame. The record lives in `dr-types` beside `Settings` and the store lives here beside `SettingsStore`, for the reason `dr-types`' manifest gives: a JSON serialiser in `core/` would be paid for by every crate there. Two files and two lifetimes, though -- resetting preferences must not forget where you were. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -552,6 +552,44 @@ pub fn kind(conn: &Connection, id: CollectionId) -> Result<Option<CollectionKind
|
||||
Ok(found.map(CollectionKind::from_i64))
|
||||
}
|
||||
|
||||
/// TRACES: FR-UI-8
|
||||
/// The device-independent name of a collection, from its local id.
|
||||
///
|
||||
/// The pair to [`id_for_uuid`], and the reason both exist: `collections.id` is
|
||||
/// an autoincrement local to one catalog, so anything that travels between
|
||||
/// devices — a place, a merge — has to say which collection it means in the
|
||||
/// only vocabulary they share.
|
||||
///
|
||||
/// `None` for a collection that is not there, or has been tombstoned. A caller
|
||||
/// writing down a scope treats that as "the whole library", which is the
|
||||
/// harmless direction: the alternative is recording a name nothing can resolve.
|
||||
pub fn uuid_of(conn: &Connection, id: CollectionId) -> Result<Option<String>, CatalogError> {
|
||||
Ok(conn
|
||||
.query_row(
|
||||
"SELECT uuid FROM collections WHERE id = ?1 AND deleted = 0",
|
||||
[id.0 as i64],
|
||||
|r| r.get::<_, String>(0),
|
||||
)
|
||||
.optional()?)
|
||||
}
|
||||
|
||||
/// TRACES: FR-UI-8
|
||||
/// The local id of a collection, from the name every device knows it by.
|
||||
///
|
||||
/// `None` where this device has never heard of it, or has deleted it — a place
|
||||
/// recorded on the tablet inside a collection this machine has not yet merged.
|
||||
/// The caller falls back to the whole library rather than to an empty grid.
|
||||
pub fn id_for_uuid(conn: &Connection, uuid: &str) -> Result<Option<CollectionId>, CatalogError> {
|
||||
Ok(conn
|
||||
.query_row(
|
||||
"SELECT id FROM collections WHERE uuid = ?1 AND deleted = 0",
|
||||
[uuid],
|
||||
|r| r.get::<_, i64>(0),
|
||||
)
|
||||
.optional()?
|
||||
.map(|id| CollectionId(id as u64)))
|
||||
}
|
||||
|
||||
/// A collection and everything beneath it, including itself.
|
||||
///
|
||||
/// Used for cycle checks and for scoping the grid to a parent: selecting a
|
||||
|
||||
Reference in New Issue
Block a user