mirror of
https://github.com/mastodon/mastodon.git
synced 2025-11-27 18:10:58 +00:00
Improve media modal swipe animation (#36916)
Some checks failed
Check i18n / check-i18n (push) Waiting to run
Chromatic / Run Chromatic (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (ruby) (push) Waiting to run
Check formatting / lint (push) Waiting to run
CSS Linting / lint (push) Waiting to run
JavaScript Linting / lint (push) Waiting to run
Ruby Linting / lint (push) Waiting to run
JavaScript Testing / test (push) Waiting to run
Historical data migration test / test (14-alpine) (push) Waiting to run
Historical data migration test / test (15-alpine) (push) Waiting to run
Historical data migration test / test (16-alpine) (push) Waiting to run
Historical data migration test / test (17-alpine) (push) Waiting to run
Ruby Testing / build (production) (push) Waiting to run
Ruby Testing / build (test) (push) Waiting to run
Ruby Testing / test (.ruby-version) (push) Blocked by required conditions
Ruby Testing / test (3.2) (push) Blocked by required conditions
Ruby Testing / test (3.3) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (.ruby-version) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (3.2) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (3.3) (push) Blocked by required conditions
Ruby Testing / End to End testing (.ruby-version) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.2) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.3) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:8.10.2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, opensearchproject/opensearch:2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.2, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.3, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Bundler Audit / security (push) Has been cancelled
Haml Linting / lint (push) Has been cancelled
Some checks failed
Check i18n / check-i18n (push) Waiting to run
Chromatic / Run Chromatic (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (ruby) (push) Waiting to run
Check formatting / lint (push) Waiting to run
CSS Linting / lint (push) Waiting to run
JavaScript Linting / lint (push) Waiting to run
Ruby Linting / lint (push) Waiting to run
JavaScript Testing / test (push) Waiting to run
Historical data migration test / test (14-alpine) (push) Waiting to run
Historical data migration test / test (15-alpine) (push) Waiting to run
Historical data migration test / test (16-alpine) (push) Waiting to run
Historical data migration test / test (17-alpine) (push) Waiting to run
Ruby Testing / build (production) (push) Waiting to run
Ruby Testing / build (test) (push) Waiting to run
Ruby Testing / test (.ruby-version) (push) Blocked by required conditions
Ruby Testing / test (3.2) (push) Blocked by required conditions
Ruby Testing / test (3.3) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (.ruby-version) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (3.2) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (3.3) (push) Blocked by required conditions
Ruby Testing / End to End testing (.ruby-version) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.2) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.3) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:8.10.2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, opensearchproject/opensearch:2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.2, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.3, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Bundler Audit / security (push) Has been cancelled
Haml Linting / lint (push) Has been cancelled
This commit is contained in:
parent
01b11c328c
commit
ea616ac4a4
|
|
@ -46,6 +46,8 @@ interface MediaModalProps {
|
||||||
volume?: number;
|
volume?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MIN_SWIPE_DISTANCE = 400;
|
||||||
|
|
||||||
export const MediaModal: FC<MediaModalProps> = forwardRef<
|
export const MediaModal: FC<MediaModalProps> = forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
MediaModalProps
|
MediaModalProps
|
||||||
|
|
@ -69,21 +71,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 * 100}%`,
|
||||||
|
}));
|
||||||
|
|
||||||
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: `-${newIndex * 100}%` });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[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 +112,25 @@ export const MediaModal: FC<MediaModalProps> = forwardRef<
|
||||||
[handleNextClick, handlePrevClick],
|
[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(() => {
|
useEffect(() => {
|
||||||
window.addEventListener('keydown', handleKeyDown, false);
|
window.addEventListener('keydown', handleKeyDown, false);
|
||||||
|
|
||||||
|
|
@ -145,17 +175,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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user