feat(DirectorySlideshow): enhance slideshow controls with persistent pause state and improved index handling

This commit is contained in:
Jaime Idolpx 2026-06-11 12:52:32 -04:00
parent 096f13d926
commit b8d3041035

View File

@ -10,7 +10,7 @@ interface Props {
export default function DirectorySlideshow({ path }: Props) {
const [images, setImages] = useState<EntryInfo[]>([]);
const [idx, setIdx] = useState(0);
const [paused, setPaused] = useState(false);
const [paused, setPaused] = useState(() => localStorage.getItem('slideshow.paused') === '1');
const [touched, setTouched] = useState(false);
const touchTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
@ -24,7 +24,8 @@ export default function DirectorySlideshow({ path }: Props) {
return IMAGE_EXTS.has(ext);
});
setImages(imgs);
setIdx(0);
const saved = parseInt(localStorage.getItem(`slideshow.idx:${path}`) ?? '0', 10);
setIdx(imgs.length > 0 ? Math.min(saved, imgs.length - 1) : 0);
})
.catch(() => setImages([]));
}, [path]);
@ -35,6 +36,11 @@ export default function DirectorySlideshow({ path }: Props) {
return () => clearInterval(t);
}, [images.length, paused]);
useEffect(() => {
if (images.length === 0) return;
localStorage.setItem(`slideshow.idx:${path}`, String(idx));
}, [idx, path, images.length]);
useEffect(() => () => clearTimeout(touchTimer.current), []);
if (images.length === 0) return null;
@ -73,15 +79,18 @@ export default function DirectorySlideshow({ path }: Props) {
</button>
</div>
{/* Dots + pause */}
<div className={`absolute bottom-0 left-0 right-0 flex items-center justify-center gap-2 py-1.5 transition-opacity duration-200 ${controlsVisible}`}>
{/* Pause / play — centered */}
<div className={`absolute inset-0 flex items-center justify-center pointer-events-none transition-opacity duration-200 ${controlsVisible}`}>
<button
onClick={() => setPaused(p => !p)}
className="p-0.5 rounded-full bg-black/50 text-white hover:bg-black/70"
onClick={() => setPaused(p => { const next = !p; localStorage.setItem('slideshow.paused', next ? '1' : '0'); return next; })}
className="pointer-events-auto p-3 rounded-full bg-black/50 text-white hover:bg-black/70"
>
{paused ? <Play className="w-3 h-3" /> : <Pause className="w-3 h-3" />}
{paused ? <Play className="w-7 h-7" /> : <Pause className="w-7 h-7" />}
</button>
<div className="flex gap-1.5">
</div>
{/* Dots */}
<div className={`absolute bottom-0 left-0 right-0 flex justify-center gap-1.5 py-1.5 transition-opacity duration-200 ${controlsVisible}`}>
{images.map((_, i) => (
<button
key={i}
@ -90,7 +99,6 @@ export default function DirectorySlideshow({ path }: Props) {
/>
))}
</div>
</div>
</>
)}
</div>