Catalogue a merged panorama the moment it is written
A finished merge drained the outbox and started a rescan beside it. The scan raced the upload: on a folder library the 800 MB copy was still running when the folder was listed, on Nextcloud the upload takes minutes, and either way the listing lacked the composite, recorded the folder's validator, and nothing looked again until the next sync pass. The job now reports what the catalog needs (the name, the size of the picture it opens on, the capture time it wrote into the DNG) and the library writes the row at once, in one transaction, keyed where the scan will list the file; a composite with no time of its own takes its sources' earliest. The grid reloads and shows it beside its sources. The upload then gives the row what only the server knows: after sending a file the catalog already has a row for, it lists the folder once, takes the file id the server assigned, and records it (and, once the merge makes them, the thumbnails waiting beside the payload) under that id. Every drain now rescans when something landed in the library, after the upload rather than beside it. A second merge of the same frames is no longer named over the first: the name is checked against the catalog's names in that folder, which is all that knows it once the outbox is empty.
This commit is contained in:
@@ -48,8 +48,8 @@ mod window;
|
||||
|
||||
pub use controller::LibraryController;
|
||||
pub use grid::wire;
|
||||
pub use open::{catalogue_composite, open, reload};
|
||||
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;
|
||||
|
||||
@@ -41,6 +41,52 @@ pub fn reload(window: &AppWindow, ctl: &Rc<LibraryController>) {
|
||||
note_place(window, ctl);
|
||||
}
|
||||
|
||||
/// TRACES: FR-MRG-6
|
||||
/// Put a composite the merge has just staged into the catalog and the grid,
|
||||
/// before its upload has finished and before any scan could find it.
|
||||
///
|
||||
/// See `library::composite` for why this does not wait for the scan. The
|
||||
/// row is keyed where the scan will list the file, so the scan after the
|
||||
/// upload updates it rather than adding a second.
|
||||
pub fn catalogue_composite(
|
||||
window: &AppWindow,
|
||||
ctl: &Rc<LibraryController>,
|
||||
placed: &crate::merge_ui::Placed,
|
||||
) {
|
||||
let Some((conn, _)) = ctl.session.borrow().clone() else {
|
||||
return;
|
||||
};
|
||||
let root = conn.account.root.clone();
|
||||
let c = &placed.composite;
|
||||
let source_ref = crate::export::staged_remote_path(&root, &placed.remote_dir, &c.name);
|
||||
let row = library::CompositeRow {
|
||||
source_ref: source_ref.as_str().to_string(),
|
||||
width: c.width,
|
||||
height: c.height,
|
||||
captured_at: c.captured_at,
|
||||
captured_offset: c.captured_offset,
|
||||
camera: c.camera.clone(),
|
||||
lens: c.lens.clone(),
|
||||
iso: c.iso,
|
||||
file_size: c.file_size,
|
||||
sources: placed.sources.clone(),
|
||||
};
|
||||
let written = {
|
||||
let borrow = ctl.catalog.borrow();
|
||||
let Some(catalog) = borrow.as_ref() else {
|
||||
return;
|
||||
};
|
||||
library::catalogue_composite(catalog, &root, &row)
|
||||
};
|
||||
match written {
|
||||
Ok(image) => {
|
||||
log::info!("merge: {} catalogued as image {image}", row.source_ref);
|
||||
reload(window, ctl);
|
||||
}
|
||||
Err(e) => log::warn!("merge: cataloguing {}: {e}", row.source_ref),
|
||||
}
|
||||
}
|
||||
|
||||
/// Open a library: show the grid, start a scan, then fill in thumbnails.
|
||||
///
|
||||
/// Called from the launch screen's "Open library" button — the callback that
|
||||
|
||||
@@ -112,23 +112,7 @@ pub(super) fn start_derived_sync(window: &AppWindow, ctl: &Rc<LibraryController>
|
||||
let outbox = crate::export::outbox_dir(&conn.account);
|
||||
if crate::export::pending_count(&outbox) > 0 {
|
||||
let rx = crate::export::spawn_upload(conn.clone(), conn.account.root.clone(), outbox);
|
||||
executors::spawn(Executor::Io, "upload-log", move || {
|
||||
while let Ok(msg) = rx.recv() {
|
||||
match msg {
|
||||
crate::export::UploadMessage::Status(s) => log::info!("export: {s}"),
|
||||
crate::export::UploadMessage::Finished {
|
||||
uploaded,
|
||||
remaining,
|
||||
error,
|
||||
} => {
|
||||
log::info!("export: {uploaded} uploaded, {remaining} still queued");
|
||||
if let Some(e) = error {
|
||||
log::warn!("export upload stopped: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
crate::export::watch_upload(rx, window.as_weak());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user