web: the preset tester steps through every frame in its slot
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -343,6 +343,29 @@ html { scroll-behavior: smooth; scroll-padding-top: 116px; }
|
||||
.lp-tab[aria-pressed="true"] { border-color: var(--lp-amber); color: var(--lp-ink-amber); background: var(--accent-soft); }
|
||||
.lp-view { position: relative; border-radius: 16px; overflow: hidden; border: 1px solid var(--lp-line); background: #000; }
|
||||
.lp-view img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; transition: filter 380ms ease; }
|
||||
.lp-arrow {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
z-index: 2;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 0;
|
||||
border-radius: 50%;
|
||||
border: 1px solid var(--lp-line);
|
||||
background: rgba(0, 0, 0, 0.55);
|
||||
color: var(--lp-text);
|
||||
font: inherit;
|
||||
font-size: 22px;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition: background 160ms ease, border-color 160ms ease, color 160ms ease;
|
||||
}
|
||||
.lp-arrow:hover, .lp-arrow:focus-visible { background: rgba(0, 0, 0, 0.85); border-color: var(--lp-amber); color: var(--lp-amber); }
|
||||
.lp-arrow-prev { left: 10px; }
|
||||
.lp-arrow-next { right: 10px; }
|
||||
.lp-hud {
|
||||
position: absolute;
|
||||
inset: auto 0 0 0;
|
||||
|
||||
Reference in New Issue
Block a user