Make React Spring respect animation preferences (#35018)
This commit is contained in:
parent
f53bb4cd7d
commit
3aed93711c
8 changed files with 14 additions and 30 deletions
|
@ -14,7 +14,6 @@ import { fetchPoll, vote } from 'mastodon/actions/polls';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import emojify from 'mastodon/features/emoji/emoji';
|
import emojify from 'mastodon/features/emoji/emoji';
|
||||||
import { useIdentity } from 'mastodon/identity_context';
|
import { useIdentity } from 'mastodon/identity_context';
|
||||||
import { reduceMotion } from 'mastodon/initial_state';
|
|
||||||
import { makeEmojiMap } from 'mastodon/models/custom_emoji';
|
import { makeEmojiMap } from 'mastodon/models/custom_emoji';
|
||||||
import type * as Model from 'mastodon/models/poll';
|
import type * as Model from 'mastodon/models/poll';
|
||||||
import type { Status } from 'mastodon/models/status';
|
import type { Status } from 'mastodon/models/status';
|
||||||
|
@ -265,7 +264,6 @@ const PollOption: React.FC<PollOptionProps> = (props) => {
|
||||||
to: {
|
to: {
|
||||||
width: `${percent}%`,
|
width: `${percent}%`,
|
||||||
},
|
},
|
||||||
immediate: reduceMotion,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { Audio } from 'mastodon/features/audio';
|
||||||
import { CharacterCounter } from 'mastodon/features/compose/components/character_counter';
|
import { CharacterCounter } from 'mastodon/features/compose/components/character_counter';
|
||||||
import { Tesseract as fetchTesseract } from 'mastodon/features/ui/util/async-components';
|
import { Tesseract as fetchTesseract } from 'mastodon/features/ui/util/async-components';
|
||||||
import { Video, getPointerPosition } from 'mastodon/features/video';
|
import { Video, getPointerPosition } from 'mastodon/features/video';
|
||||||
import { me, reduceMotion } from 'mastodon/initial_state';
|
import { me } from 'mastodon/initial_state';
|
||||||
import type { MediaAttachment } from 'mastodon/models/media_attachment';
|
import type { MediaAttachment } from 'mastodon/models/media_attachment';
|
||||||
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||||
import { assetHost } from 'mastodon/utils/config';
|
import { assetHost } from 'mastodon/utils/config';
|
||||||
|
@ -110,7 +110,7 @@ const Preview: React.FC<{
|
||||||
left: `${x * 100}%`,
|
left: `${x * 100}%`,
|
||||||
top: `${y * 100}%`,
|
top: `${y * 100}%`,
|
||||||
},
|
},
|
||||||
immediate: reduceMotion || draggingRef.current,
|
immediate: draggingRef.current,
|
||||||
});
|
});
|
||||||
const media = useAppSelector((state) =>
|
const media = useAppSelector((state) =>
|
||||||
(
|
(
|
||||||
|
|
|
@ -19,11 +19,7 @@ import { SpoilerButton } from 'mastodon/components/spoiler_button';
|
||||||
import { formatTime, getPointerPosition } from 'mastodon/features/video';
|
import { formatTime, getPointerPosition } from 'mastodon/features/video';
|
||||||
import { useAudioContext } from 'mastodon/hooks/useAudioContext';
|
import { useAudioContext } from 'mastodon/hooks/useAudioContext';
|
||||||
import { useAudioVisualizer } from 'mastodon/hooks/useAudioVisualizer';
|
import { useAudioVisualizer } from 'mastodon/hooks/useAudioVisualizer';
|
||||||
import {
|
import { displayMedia, useBlurhash } from 'mastodon/initial_state';
|
||||||
displayMedia,
|
|
||||||
useBlurhash,
|
|
||||||
reduceMotion,
|
|
||||||
} from 'mastodon/initial_state';
|
|
||||||
import { playerSettings } from 'mastodon/settings';
|
import { playerSettings } from 'mastodon/settings';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@ -163,7 +159,6 @@ export const Audio: React.FC<{
|
||||||
}
|
}
|
||||||
void spring.start({
|
void spring.start({
|
||||||
volume: `${audioRef.current.volume * 100}%`,
|
volume: `${audioRef.current.volume * 100}%`,
|
||||||
immediate: reduceMotion,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -217,7 +212,6 @@ export const Audio: React.FC<{
|
||||||
if (audioRef.current && audioRef.current.duration > 0) {
|
if (audioRef.current && audioRef.current.duration > 0) {
|
||||||
void spring.start({
|
void spring.start({
|
||||||
progress: `${(audioRef.current.currentTime / audioRef.current.duration) * 100}%`,
|
progress: `${(audioRef.current.currentTime / audioRef.current.duration) * 100}%`,
|
||||||
immediate: reduceMotion,
|
|
||||||
config: config.stiff,
|
config: config.stiff,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -263,7 +257,6 @@ export const Audio: React.FC<{
|
||||||
if (lastTimeRange > -1) {
|
if (lastTimeRange > -1) {
|
||||||
void spring.start({
|
void spring.start({
|
||||||
buffer: `${Math.ceil(audioRef.current.buffered.end(lastTimeRange) / audioRef.current.duration) * 100}%`,
|
buffer: `${Math.ceil(audioRef.current.buffered.end(lastTimeRange) / audioRef.current.duration) * 100}%`,
|
||||||
immediate: reduceMotion,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [spring]);
|
}, [spring]);
|
||||||
|
@ -278,7 +271,6 @@ export const Audio: React.FC<{
|
||||||
|
|
||||||
void spring.start({
|
void spring.start({
|
||||||
volume: `${audioRef.current.muted ? 0 : audioRef.current.volume * 100}%`,
|
volume: `${audioRef.current.muted ? 0 : audioRef.current.volume * 100}%`,
|
||||||
immediate: reduceMotion,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
persistVolume(audioRef.current.volume, audioRef.current.muted);
|
persistVolume(audioRef.current.volume, audioRef.current.muted);
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { animated, useSpring } from '@react-spring/web';
|
||||||
|
|
||||||
import UploadFileIcon from '@/material-icons/400-24px/upload_file.svg?react';
|
import UploadFileIcon from '@/material-icons/400-24px/upload_file.svg?react';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import { reduceMotion } from 'mastodon/initial_state';
|
|
||||||
|
|
||||||
interface UploadProgressProps {
|
interface UploadProgressProps {
|
||||||
active: boolean;
|
active: boolean;
|
||||||
|
@ -20,7 +19,7 @@ export const UploadProgress: React.FC<UploadProgressProps> = ({
|
||||||
const styles = useSpring({
|
const styles = useSpring({
|
||||||
from: { width: '0%' },
|
from: { width: '0%' },
|
||||||
to: { width: `${progress}%` },
|
to: { width: `${progress}%` },
|
||||||
immediate: reduceMotion || !active, // If this is not active, update the UI immediately.
|
immediate: !active, // If this is not active, update the UI immediately.
|
||||||
});
|
});
|
||||||
if (!active) {
|
if (!active) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -270,7 +270,6 @@ const ReactionsBar = ({
|
||||||
leave: {
|
leave: {
|
||||||
scale: 0,
|
scale: 0,
|
||||||
},
|
},
|
||||||
immediate: reduceMotion,
|
|
||||||
keys: visibleReactions.map(x => x.get('name')),
|
keys: visibleReactions.map(x => x.get('name')),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { animated, config, useSpring } from '@react-spring/web';
|
import { animated, config, useSpring } from '@react-spring/web';
|
||||||
|
|
||||||
import { reduceMotion } from 'mastodon/initial_state';
|
|
||||||
|
|
||||||
interface UploadAreaProps {
|
interface UploadAreaProps {
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
@ -39,7 +37,6 @@ export const UploadArea: React.FC<UploadAreaProps> = ({ active, onClose }) => {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
},
|
},
|
||||||
reverse: !active,
|
reverse: !active,
|
||||||
immediate: reduceMotion,
|
|
||||||
});
|
});
|
||||||
const backgroundAnimStyles = useSpring({
|
const backgroundAnimStyles = useSpring({
|
||||||
from: {
|
from: {
|
||||||
|
@ -50,7 +47,6 @@ export const UploadArea: React.FC<UploadAreaProps> = ({ active, onClose }) => {
|
||||||
},
|
},
|
||||||
reverse: !active,
|
reverse: !active,
|
||||||
config: config.wobbly,
|
config: config.wobbly,
|
||||||
immediate: reduceMotion,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -27,11 +27,7 @@ import {
|
||||||
attachFullscreenListener,
|
attachFullscreenListener,
|
||||||
detachFullscreenListener,
|
detachFullscreenListener,
|
||||||
} from 'mastodon/features/ui/util/fullscreen';
|
} from 'mastodon/features/ui/util/fullscreen';
|
||||||
import {
|
import { displayMedia, useBlurhash } from 'mastodon/initial_state';
|
||||||
displayMedia,
|
|
||||||
useBlurhash,
|
|
||||||
reduceMotion,
|
|
||||||
} from 'mastodon/initial_state';
|
|
||||||
import { playerSettings } from 'mastodon/settings';
|
import { playerSettings } from 'mastodon/settings';
|
||||||
|
|
||||||
import { HotkeyIndicator } from './components/hotkey_indicator';
|
import { HotkeyIndicator } from './components/hotkey_indicator';
|
||||||
|
@ -260,7 +256,6 @@ export const Video: React.FC<{
|
||||||
setMuted(videoRef.current.muted);
|
setMuted(videoRef.current.muted);
|
||||||
void api.start({
|
void api.start({
|
||||||
volume: `${videoRef.current.volume * 100}%`,
|
volume: `${videoRef.current.volume * 100}%`,
|
||||||
immediate: reduceMotion,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -350,7 +345,6 @@ export const Video: React.FC<{
|
||||||
videoRef.current.currentTime / videoRef.current.duration;
|
videoRef.current.currentTime / videoRef.current.duration;
|
||||||
void api.start({
|
void api.start({
|
||||||
progress: isNaN(progress) ? '0%' : `${progress * 100}%`,
|
progress: isNaN(progress) ? '0%' : `${progress * 100}%`,
|
||||||
immediate: reduceMotion,
|
|
||||||
config: config.stiff,
|
config: config.stiff,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -738,7 +732,6 @@ export const Video: React.FC<{
|
||||||
if (lastTimeRange > -1) {
|
if (lastTimeRange > -1) {
|
||||||
void api.start({
|
void api.start({
|
||||||
buffer: `${Math.ceil(videoRef.current.buffered.end(lastTimeRange) / videoRef.current.duration) * 100}%`,
|
buffer: `${Math.ceil(videoRef.current.buffered.end(lastTimeRange) / videoRef.current.duration) * 100}%`,
|
||||||
immediate: reduceMotion,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [api]);
|
}, [api]);
|
||||||
|
@ -753,7 +746,6 @@ export const Video: React.FC<{
|
||||||
|
|
||||||
void api.start({
|
void api.start({
|
||||||
volume: `${videoRef.current.muted ? 0 : videoRef.current.volume * 100}%`,
|
volume: `${videoRef.current.muted ? 0 : videoRef.current.volume * 100}%`,
|
||||||
immediate: reduceMotion,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
persistVolume(videoRef.current.volume, videoRef.current.muted);
|
persistVolume(videoRef.current.volume, videoRef.current.muted);
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
|
import { Globals } from '@react-spring/web';
|
||||||
|
|
||||||
import { setupBrowserNotifications } from 'mastodon/actions/notifications';
|
import { setupBrowserNotifications } from 'mastodon/actions/notifications';
|
||||||
import Mastodon from 'mastodon/containers/mastodon';
|
import Mastodon from 'mastodon/containers/mastodon';
|
||||||
import { me } from 'mastodon/initial_state';
|
import { me, reduceMotion } from 'mastodon/initial_state';
|
||||||
import * as perf from 'mastodon/performance';
|
import * as perf from 'mastodon/performance';
|
||||||
import ready from 'mastodon/ready';
|
import ready from 'mastodon/ready';
|
||||||
import { store } from 'mastodon/store';
|
import { store } from 'mastodon/store';
|
||||||
|
@ -21,6 +23,12 @@ function main() {
|
||||||
mountNode.getAttribute('data-props') ?? '{}',
|
mountNode.getAttribute('data-props') ?? '{}',
|
||||||
) as Record<string, unknown>;
|
) as Record<string, unknown>;
|
||||||
|
|
||||||
|
if (reduceMotion) {
|
||||||
|
Globals.assign({
|
||||||
|
skipAnimation: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const root = createRoot(mountNode);
|
const root = createRoot(mountNode);
|
||||||
root.render(<Mastodon {...props} />);
|
root.render(<Mastodon {...props} />);
|
||||||
store.dispatch(setupBrowserNotifications());
|
store.dispatch(setupBrowserNotifications());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue