import { useEffect, useRef, useState } from "react"; import { api, type MediaItem } from "../../api/client"; interface Props { items: MediaItem[]; onClose: () => void; onViewInLibrary: (item: MediaItem) => void; } export default function DoomScrollViewer({ items, onClose, onViewInLibrary }: Props) { const [index, setIndex] = useState(0); const [fading, setFading] = useState(false); const wheelLock = useRef(false); const touchStartY = useRef(null); const item = items[index]; function go(delta: 1 | -1) { if (wheelLock.current) return; const next = index + delta; if (next < 0 || next >= items.length) return; wheelLock.current = true; setFading(true); setTimeout(() => { setIndex(next); setFading(false); wheelLock.current = false; }, 200); } useEffect(() => { const onWheel = (e: WheelEvent) => { e.deltaY > 0 ? go(1) : go(-1); }; const onKey = (e: KeyboardEvent) => { if (e.key === "ArrowDown" || e.key === " ") { e.preventDefault(); go(1); } if (e.key === "ArrowUp") { e.preventDefault(); go(-1); } if (e.key === "Escape") onClose(); }; const onTouchStart = (e: TouchEvent) => { touchStartY.current = e.touches[0].clientY; }; const onTouchEnd = (e: TouchEvent) => { if (touchStartY.current === null) return; const delta = touchStartY.current - e.changedTouches[0].clientY; if (Math.abs(delta) > 50) delta > 0 ? go(1) : go(-1); touchStartY.current = null; }; window.addEventListener("wheel", onWheel, { passive: true }); window.addEventListener("keydown", onKey); window.addEventListener("touchstart", onTouchStart); window.addEventListener("touchend", onTouchEnd); return () => { window.removeEventListener("wheel", onWheel); window.removeEventListener("keydown", onKey); window.removeEventListener("touchstart", onTouchStart); window.removeEventListener("touchend", onTouchEnd); }; }, [index, fading]); return ( <> {/* Backdrop */}
{/* Media area */}
{item?.media_type === "image" && ( {item.filename} )} {item?.media_type === "video" && (
{/* Bottom bar */}
{index + 1} / {items.length}
); }