import { useEffect, useRef, useState } from 'react' import { ACCEPT_GLYPH, REJECT_GLYPH } from './components/Thumbs' // Shared culling interaction for a lightbox over a (possibly filtered) photo // list: the keyboard table (P/X/U, stars, select), swipe gestures, the // action toast, and the modal fade-out after voting the last photo. export default function useCulling({ visible, lightbox, setVerdict, setRating, toggle, canSelect = true, }) { const [flash, setFlash] = useState(null) const flashSeq = useRef(0) const flashTimer = useRef() const showFlash = (text) => { flashSeq.current += 1 setFlash({ text, key: flashSeq.current }) clearTimeout(flashTimer.current) flashTimer.current = setTimeout(() => setFlash(null), 1400) } useEffect(() => () => clearTimeout(flashTimer.current), []) const [fading, setFading] = useState(false) useEffect(() => { if (lightbox.index < 0) setFading(false) }, [lightbox.index]) // Keyboard votes stay on the photo (the footer controls show the result); // only touch gestures advance, where the fly-off animation carries the // context. const vote = (photo, verdict) => { setVerdict(photo, verdict) showFlash( verdict === 'accept' ? `${ACCEPT_GLYPH} ${photo.filename}` : `${REJECT_GLYPH} ${photo.filename}`, ) } const voteAndAdvance = (photo, verdict) => { const next = visible[lightbox.index + 1] setVerdict(photo, verdict) showFlash( verdict === 'accept' ? `${ACCEPT_GLYPH} ${photo.filename}` : verdict === 'reject' ? `${REJECT_GLYPH} ${photo.filename}` : `↺ ${photo.filename} cleared`, ) if (next) lightbox.show(next.id) else setFading(true) } const keyActions = [ { keys: ['p'], help: ['P', 'accept'], run: (p) => vote(p, 'accept') }, { keys: ['x'], help: ['X', 'reject'], run: (p) => vote(p, 'reject') }, { keys: ['u'], help: ['U', 'clear accept / reject'], run: (p) => setVerdict(p, null) }, { keys: ['1', '2', '3', '4', '5'], help: ['1–5', 'star rating'], run: (p, key) => setRating(p, Number(key)), }, { keys: ['0'], help: ['0', 'clear star rating'], run: (p) => setRating(p, 0) }, ...(canSelect ? [{ keys: ['s'], help: ['S', 'select for download'], run: (p) => toggle(p.id) }] : []), ] return { flash, keyActions, lightboxProps: { actions: keyActions, gestures: { up: (p) => voteAndAdvance(p, 'accept'), down: (p) => voteAndAdvance(p, 'reject'), }, closing: fading, onClosed: () => { setFading(false) lightbox.close() }, }, } }