mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-13 07:49:29 +00:00
[Glitch] Improve media modal swipe animation
Port ea616ac4a4 to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
@@ -46,6 +46,8 @@ interface MediaModalProps {
|
||||
volume?: number;
|
||||
}
|
||||
|
||||
const MIN_SWIPE_DISTANCE = 400;
|
||||
|
||||
export const MediaModal: FC<MediaModalProps> = forwardRef<
|
||||
HTMLDivElement,
|
||||
MediaModalProps
|
||||
@@ -69,21 +71,30 @@ export const MediaModal: FC<MediaModalProps> = forwardRef<
|
||||
const [zoomedIn, setZoomedIn] = useState(false);
|
||||
const currentMedia = media.get(index);
|
||||
|
||||
const [wrapperStyles, api] = useSpring(() => ({
|
||||
x: `-${index * 100}%`,
|
||||
}));
|
||||
|
||||
const handleChangeIndex = useCallback(
|
||||
(newIndex: number) => {
|
||||
(newIndex: number, animate = false) => {
|
||||
if (newIndex < 0) {
|
||||
newIndex = media.size + newIndex;
|
||||
} else if (newIndex >= media.size) {
|
||||
newIndex = newIndex % media.size;
|
||||
}
|
||||
setIndex(newIndex % media.size);
|
||||
setIndex(newIndex);
|
||||
setZoomedIn(false);
|
||||
if (animate) {
|
||||
void api.start({ x: `-${newIndex * 100}%` });
|
||||
}
|
||||
},
|
||||
[media.size],
|
||||
[api, media.size],
|
||||
);
|
||||
const handlePrevClick = useCallback(() => {
|
||||
handleChangeIndex(index - 1);
|
||||
handleChangeIndex(index - 1, true);
|
||||
}, [handleChangeIndex, index]);
|
||||
const handleNextClick = useCallback(() => {
|
||||
handleChangeIndex(index + 1);
|
||||
handleChangeIndex(index + 1, true);
|
||||
}, [handleChangeIndex, index]);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
@@ -101,6 +112,25 @@ export const MediaModal: FC<MediaModalProps> = forwardRef<
|
||||
[handleNextClick, handlePrevClick],
|
||||
);
|
||||
|
||||
const bind = useDrag(
|
||||
({ active, movement: [mx], direction: [xDir], cancel }) => {
|
||||
// If dragging and swipe distance is enough, change the index.
|
||||
if (
|
||||
active &&
|
||||
Math.abs(mx) > Math.min(window.innerWidth / 4, MIN_SWIPE_DISTANCE)
|
||||
) {
|
||||
handleChangeIndex(index - xDir);
|
||||
cancel();
|
||||
}
|
||||
// Set the x position via calc to ensure proper centering regardless of screen size.
|
||||
const x = active ? mx : 0;
|
||||
void api.start({
|
||||
x: `calc(-${index * 100}% + ${x}px)`,
|
||||
});
|
||||
},
|
||||
{ pointer: { capture: false } },
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('keydown', handleKeyDown, false);
|
||||
|
||||
@@ -145,17 +175,6 @@ export const MediaModal: FC<MediaModalProps> = forwardRef<
|
||||
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 handleToggleNavigation = useCallback(() => {
|
||||
setNavigationHidden((prev) => !prev);
|
||||
|
||||
Reference in New Issue
Block a user