web: ?bench runs on demo photos in an unsaved library, never the stored one (#3646)

A navigation link with ?bench opened the first photo of the library in
browser storage and committed Exposure edits to it, finishing at 0 instead
of the photo's own value. ?bench now implies ?store=memory and loads the
generated demo photos, so the benchmark cannot edit stored photos.
This commit is contained in:
Dylan M. Taylor
2026-11-02 22:50:58 -05:00
committed by GitHub
parent 06c1b9ae07
commit ac1799db38
4 changed files with 16 additions and 4 deletions
+3
View File
@@ -2,6 +2,9 @@
//! control exactly like a slider drag (begin interaction → N `develop.set` → end) and time each
//! step from the command to the moment the new loupe texture is ready. Results go to the log
//! (the browser console on the web) as one `lightcraft-bench {…json…}` line.
//!
//! The web host runs it only on the generated demo photos in an unsaved library (`?bench` implies `?store=memory`): it
//! commits edits to the photo it opens, which must never be one in the user's stored library.
use lightcraft_ui_egui::LightcraftApp;
use lightcraft_ui_egui::render::Slot;
+2 -1
View File
@@ -11,7 +11,8 @@
//! - export downloads the file through the browser.
//!
//! `?bench` in the URL runs a scripted first-paint / slider-latency measurement and logs it to the
//! console (see [`bench`]); `?store=idb` forces the IndexedDB backend, `?store=memory` disables
//! console (see [`bench`]) on the generated demo photos in an unsaved library (it implies `?store=memory`, so it never edits
//! the library in browser storage); `?store=idb` forces the IndexedDB backend, `?store=memory` disables
//! persistence and `?workers=0` renders on the main thread.
#![forbid(unsafe_code)]
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
+9 -2
View File
@@ -90,9 +90,12 @@ impl Options {
})
.collect();
let get = |k: &str| params.iter().find(|(n, _)| n == k).map(|(_, v)| v.clone());
let bench = get("bench").is_some();
Options {
bench: get("bench").is_some(),
store: get("store").filter(|s| s == "idb" || s == "memory").unwrap_or_else(|| "opfs".into()),
bench,
// the benchmark edits the first photo it finds: a link with `?bench` must never reach
// the library in browser storage, so it always runs on the demo photos in an unsaved library
store: if bench { "memory".into() } else { get("store").filter(|s| s == "idb" || s == "memory").unwrap_or_else(|| "opfs".into()) },
workers: get("workers").and_then(|v| v.parse().ok()),
reset: get("reset").is_some(),
}
@@ -496,6 +499,10 @@ impl WebApp {
});
}
}
// `?bench` never has storage (see `Options::from_url`): it measures the generated demo photos
if opts.bench && backend.is_none() && session.catalog.len() == 0 {
lightcraft_engine::demo::load(&mut session);
}
if backend.is_some() {
notice(
"LightCraft in the browser is experimental. Your library is kept in this browser's storage: keep your original photos \
+2 -1
View File
@@ -188,7 +188,8 @@ are the same in every version, so serve them with `Cache-Control: no-cache` (not
## Measuring
Open `http://127.0.0.1:8080/?bench` to run a scripted measurement:
Open `http://127.0.0.1:8080/?bench` to run a scripted measurement. It always runs on the generated demo photos in an unsaved library
(`?bench` implies `?store=memory`), so it never edits the library kept in browser storage:
1. Wait for the grid thumbnails.
2. Open the first photo in Detail.