web: the preset tester steps through every frame in its slot

This commit is contained in:
2026-09-18 21:02:30 +07:00
parent d3c5c47973
commit 2da045f232
2 changed files with 60 additions and 2 deletions
+37 -2
View File
@@ -162,6 +162,7 @@ export function Landing() {
const tools = useRef<HTMLSpanElement>(null);
const account = useRef<HTMLSpanElement>(null);
const [presetId, setPresetId] = useState(PRESETS[0].id);
const [testerIdx, setTesterIdx] = useState(0);
const [temp, setTemp] = useState(0);
const [sat, setSat] = useState(100);
const [con, setCon] = useState(100);
@@ -254,9 +255,17 @@ export function Landing() {
// The QR card's payload is the curated photo's own look, as the link the
// phone app downloads it from. The card's mock address stands in while the
// section holds nothing that has a look to hand out.
// The tester cycles every still the curator put in its slot, so a recipe
// can be checked against more than one frame. The built-in sample stands
// in on its own while the slot holds nothing.
const curated = photos.filter((p) => p.slots.includes('tester')).map((p) => api.photoUrl(p.id));
const testers = curated.length ? curated : [SAMPLE(1043)];
const qr = pick('qr');
return {
tester: src('tester', SAMPLE(1043)),
testers,
// A plain step count on top of one random start keeps the frame random
// per load without an effect that would reset it on every re-render.
testerStart: Math.floor(Math.random() * testers.length),
creator: src('creator', SAMPLE(1015)),
qr: qr ? api.photoUrl(qr.id) : SAMPLE(1069),
qrLink: qr?.hasPreset ? new URL(api.presetUrl(qr.id), window.location.origin).href : `${window.location.origin}/app`,
@@ -622,7 +631,33 @@ export function Landing() {
))}
</div>
<div className="lp-view">
<Shot src={slotPhoto.tester} alt={`${preset.name} preview`} filter={preset.filter} />
<Shot
src={slotPhoto.testers[(slotPhoto.testerStart + testerIdx) % slotPhoto.testers.length]}
alt={`${preset.name} preview`}
filter={preset.filter}
/>
{slotPhoto.testers.length > 1 && (
<>
<button
type="button"
className="lp-arrow lp-arrow-prev"
data-key="lp-tester-prev"
aria-label={c({ en: 'Previous frame', vi: 'Khung trước' })}
onClick={() => setTesterIdx((i) => (i - 1 + slotPhoto.testers.length) % slotPhoto.testers.length)}
>
{'\u2039'}
</button>
<button
type="button"
className="lp-arrow lp-arrow-next"
data-key="lp-tester-next"
aria-label={c({ en: 'Next frame', vi: 'Khung sau' })}
onClick={() => setTesterIdx((i) => (i + 1) % slotPhoto.testers.length)}
>
{'\u203a'}
</button>
</>
)}
<div className="lp-hud">
<span>f/<b>1.8</b></span>
<span>SS <b>1/500s</b></span>