restore mobile swipe navigation in modal

This commit is contained in:
2026-01-24 17:05:14 +00:00
parent 5d7d8db061
commit d77bee813d

View File

@ -1,6 +1,6 @@
import { Link } from '@tanstack/react-router';
import clsx from 'clsx';
import React, { type RefCallback, useCallback, useEffect, useMemo, useState } from 'react';
import React, { type RefCallback, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { fetchStatusWithContext } from 'pl-fe/actions/statuses';
@ -119,6 +119,40 @@ const MediaModal: React.FC<MediaModalProps & BaseModalProps> = (props) => {
}
}, [handleChangeIndex, index]);
// Touch swipe handling
const touchStartX = useRef<number | null>(null);
const touchStartY = useRef<number | null>(null);
const carouselRef = useRef<HTMLDivElement>(null);
const handleTouchStart = useCallback((e: React.TouchEvent) => {
if (zoomedIn) return;
touchStartX.current = e.touches[0].clientX;
touchStartY.current = e.touches[0].clientY;
}, [zoomedIn]);
const handleTouchEnd = useCallback((e: React.TouchEvent) => {
if (zoomedIn || touchStartX.current === null || touchStartY.current === null) return;
const touchEndX = e.changedTouches[0].clientX;
const touchEndY = e.changedTouches[0].clientY;
const deltaX = touchEndX - touchStartX.current;
const deltaY = touchEndY - touchStartY.current;
// Only trigger if horizontal swipe is greater than vertical (to avoid conflicts with scroll)
// and if the swipe distance is significant enough
const minSwipeDistance = 50;
if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > minSwipeDistance) {
if (deltaX > 0) {
handleChangeIndex(index - 1); // Swipe right = previous
} else {
handleChangeIndex(index + 1); // Swipe left = next
}
}
touchStartX.current = null;
touchStartY.current = null;
}, [zoomedIn, handleChangeIndex, index]);
const handleDownload = () => {
const mediaItem = hasMultipleImages ? media[index as number] : media[0];
window.open(mediaItem?.url);
@ -333,7 +367,12 @@ const MediaModal: React.FC<MediaModalProps & BaseModalProps> = (props) => {
</div>
)}
<div className='absolute inset-0 overflow-hidden'>
<div
ref={carouselRef}
className='absolute inset-0 overflow-hidden'
onTouchStart={handleTouchStart}
onTouchEnd={handleTouchEnd}
>
<div
style={{
width: `${media.length * 100}%`,