replace swipe animation with more fluid logic

This commit is contained in:
ChaosExAnima 2025-11-17 14:14:53 +01:00
parent 284b46fee7
commit 43cada2fc5
No known key found for this signature in database
GPG Key ID: 8F2B333100FB6117

View File

@ -69,21 +69,30 @@ export const MediaModal: FC<MediaModalProps> = forwardRef<
const [zoomedIn, setZoomedIn] = useState(false); const [zoomedIn, setZoomedIn] = useState(false);
const currentMedia = media.get(index); const currentMedia = media.get(index);
const [wrapperStyles, api] = useSpring(() => ({
x: index * -1 * window.innerWidth,
}));
const handleChangeIndex = useCallback( const handleChangeIndex = useCallback(
(newIndex: number) => { (newIndex: number, animate = false) => {
if (newIndex < 0) { if (newIndex < 0) {
newIndex = media.size + newIndex; newIndex = media.size + newIndex;
} else if (newIndex >= media.size) {
newIndex = newIndex % media.size;
} }
setIndex(newIndex % media.size); setIndex(newIndex);
setZoomedIn(false); setZoomedIn(false);
if (animate) {
void api.start({ x: -1 * newIndex * window.innerWidth });
}
}, },
[media.size], [api, media.size],
); );
const handlePrevClick = useCallback(() => { const handlePrevClick = useCallback(() => {
handleChangeIndex(index - 1); handleChangeIndex(index - 1, true);
}, [handleChangeIndex, index]); }, [handleChangeIndex, index]);
const handleNextClick = useCallback(() => { const handleNextClick = useCallback(() => {
handleChangeIndex(index + 1); handleChangeIndex(index + 1, true);
}, [handleChangeIndex, index]); }, [handleChangeIndex, index]);
const handleKeyDown = useCallback( const handleKeyDown = useCallback(
@ -101,6 +110,20 @@ export const MediaModal: FC<MediaModalProps> = forwardRef<
[handleNextClick, handlePrevClick], [handleNextClick, handlePrevClick],
); );
const bind = useDrag(
({ active, movement: [mx], direction: [xDir], cancel }) => {
if (active && Math.abs(mx) > window.innerWidth / 2) {
handleChangeIndex(index + (xDir > 0 ? -1 : 1));
cancel();
}
const x = -1 * index * window.innerWidth + (active ? mx : 0);
void api.start({
x,
});
},
{ pointer: { capture: false } },
);
useEffect(() => { useEffect(() => {
window.addEventListener('keydown', handleKeyDown, false); window.addEventListener('keydown', handleKeyDown, false);
@ -145,17 +168,6 @@ export const MediaModal: FC<MediaModalProps> = forwardRef<
setZoomedIn((prev) => !prev); setZoomedIn((prev) => !prev);
}, []); }, []);
const wrapperStyles = useSpring({
x: `-${index * 100}%`,
});
const bind = useDrag(
({ swipe: [swipeX] }) => {
if (swipeX === 0) return;
handleChangeIndex(index + swipeX * -1); // Invert swipe as swiping left loads the next slide.
},
{ pointer: { capture: false } },
);
const [navigationHidden, setNavigationHidden] = useState(false); const [navigationHidden, setNavigationHidden] = useState(false);
const handleToggleNavigation = useCallback(() => { const handleToggleNavigation = useCallback(() => {
setNavigationHidden((prev) => !prev); setNavigationHidden((prev) => !prev);