From 8b42ec1cfb5d741864bce27aaf6e5449e2fab895 Mon Sep 17 00:00:00 2001 From: Claire Date: Sun, 4 May 2025 22:25:08 +0200 Subject: [PATCH] [Glitch] Change design of audio player in web UI (#3059) Port b4394ec12954414b7d601473ecb21a49d9558082 to glitch-soc Signed-off-by: Claire Co-authored-by: Eugen Rochko --- app/javascript/flavours/glitch/blurhash.ts | 10 +- .../picture_in_picture_placeholder.jsx | 35 - .../picture_in_picture_placeholder.tsx | 46 + .../flavours/glitch/components/status.jsx | 5 +- .../glitch/containers/media_container.jsx | 2 +- .../glitch/features/alt_text_modal/index.tsx | 4 +- .../flavours/glitch/features/audio/index.jsx | 594 ------------- .../flavours/glitch/features/audio/index.tsx | 840 ++++++++++++++++++ .../glitch/features/audio/visualizer.js | 136 --- .../components/embedded_status.tsx | 5 +- .../components/notification_mention.tsx | 3 +- .../picture_in_picture/components/footer.jsx | 222 ----- .../picture_in_picture/components/footer.tsx | 268 ++++++ .../features/picture_in_picture/index.tsx | 14 +- .../status/components/detailed_status.tsx | 39 +- .../features/ui/components/audio_modal.jsx | 74 -- .../features/ui/components/audio_modal.tsx | 78 ++ .../features/ui/components/media_modal.jsx | 2 +- .../features/ui/components/video_modal.jsx | 2 +- .../flavours/glitch/features/video/index.tsx | 6 +- .../glitch/hooks/useAudioVisualizer.ts | 112 +++ .../flavours/glitch/reducers/statuses.js | 3 +- .../flavours/glitch/styles/components.scss | 125 ++- .../flavours/glitch/styles/css_variables.scss | 2 +- 24 files changed, 1507 insertions(+), 1120 deletions(-) delete mode 100644 app/javascript/flavours/glitch/components/picture_in_picture_placeholder.jsx create mode 100644 app/javascript/flavours/glitch/components/picture_in_picture_placeholder.tsx delete mode 100644 app/javascript/flavours/glitch/features/audio/index.jsx create mode 100644 app/javascript/flavours/glitch/features/audio/index.tsx delete mode 100644 app/javascript/flavours/glitch/features/audio/visualizer.js delete mode 100644 app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx create mode 100644 app/javascript/flavours/glitch/features/picture_in_picture/components/footer.tsx delete mode 100644 app/javascript/flavours/glitch/features/ui/components/audio_modal.jsx create mode 100644 app/javascript/flavours/glitch/features/ui/components/audio_modal.tsx create mode 100644 app/javascript/flavours/glitch/hooks/useAudioVisualizer.ts diff --git a/app/javascript/flavours/glitch/blurhash.ts b/app/javascript/flavours/glitch/blurhash.ts index cafe7b12dc..a1d1a0f4e1 100644 --- a/app/javascript/flavours/glitch/blurhash.ts +++ b/app/javascript/flavours/glitch/blurhash.ts @@ -96,13 +96,19 @@ export const decode83 = (str: string) => { return value; }; -export const intToRGB = (int: number) => ({ +export interface RGB { + r: number; + g: number; + b: number; +} + +export const intToRGB = (int: number): RGB => ({ r: Math.max(0, int >> 16), g: Math.max(0, (int >> 8) & 255), b: Math.max(0, int & 255), }); -export const getAverageFromBlurhash = (blurhash: string) => { +export const getAverageFromBlurhash = (blurhash: string | null) => { if (!blurhash) { return null; } diff --git a/app/javascript/flavours/glitch/components/picture_in_picture_placeholder.jsx b/app/javascript/flavours/glitch/components/picture_in_picture_placeholder.jsx deleted file mode 100644 index 10a0a7f5bb..0000000000 --- a/app/javascript/flavours/glitch/components/picture_in_picture_placeholder.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import PropTypes from 'prop-types'; -import { PureComponent } from 'react'; - -import { FormattedMessage } from 'react-intl'; - -import { connect } from 'react-redux'; - - -import CancelPresentationIcon from '@/material-icons/400-24px/cancel_presentation.svg?react'; -import { removePictureInPicture } from 'flavours/glitch/actions/picture_in_picture'; -import { Icon } from 'flavours/glitch/components/icon'; - -class PictureInPicturePlaceholder extends PureComponent { - - static propTypes = { - dispatch: PropTypes.func.isRequired, - }; - - handleClick = () => { - const { dispatch } = this.props; - dispatch(removePictureInPicture()); - }; - - render () { - return ( -
- - -
- ); - } - -} - -export default connect()(PictureInPicturePlaceholder); diff --git a/app/javascript/flavours/glitch/components/picture_in_picture_placeholder.tsx b/app/javascript/flavours/glitch/components/picture_in_picture_placeholder.tsx new file mode 100644 index 0000000000..952e8e44eb --- /dev/null +++ b/app/javascript/flavours/glitch/components/picture_in_picture_placeholder.tsx @@ -0,0 +1,46 @@ +import { useCallback } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import PipExitIcon from '@/material-icons/400-24px/pip_exit.svg?react'; +import { removePictureInPicture } from 'flavours/glitch/actions/picture_in_picture'; +import { Icon } from 'flavours/glitch/components/icon'; +import { useAppDispatch } from 'flavours/glitch/store'; + +export const PictureInPicturePlaceholder: React.FC<{ aspectRatio: string }> = ({ + aspectRatio, +}) => { + const dispatch = useAppDispatch(); + + const handleClick = useCallback(() => { + dispatch(removePictureInPicture()); + }, [dispatch]); + + const handleKeyDown = useCallback( + (e: React.KeyboardEvent) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + e.stopPropagation(); + handleClick(); + } + }, + [handleClick], + ); + + return ( +
+ + +
+ ); +}; diff --git a/app/javascript/flavours/glitch/components/status.jsx b/app/javascript/flavours/glitch/components/status.jsx index 30b67efbd8..18545b79f7 100644 --- a/app/javascript/flavours/glitch/components/status.jsx +++ b/app/javascript/flavours/glitch/components/status.jsx @@ -10,7 +10,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { HotKeys } from 'react-hotkeys'; import { ContentWarning } from 'flavours/glitch/components/content_warning'; -import PictureInPicturePlaceholder from 'flavours/glitch/components/picture_in_picture_placeholder'; +import { PictureInPicturePlaceholder } from 'flavours/glitch/components/picture_in_picture_placeholder'; import { autoUnfoldCW } from 'flavours/glitch/utils/content_warning'; import { withOptionalRouter, WithOptionalRouterPropTypes } from 'flavours/glitch/utils/react_router'; @@ -579,9 +579,6 @@ class Status extends ImmutablePureComponent { foregroundColor={attachment.getIn(['meta', 'colors', 'foreground'])} accentColor={attachment.getIn(['meta', 'colors', 'accent'])} duration={attachment.getIn(['meta', 'original', 'duration'], 0)} - width={this.props.cachedMediaWidth} - height={110} - cacheWidth={this.props.cacheMediaWidth} deployPictureInPicture={pictureInPicture.get('available') ? this.handleDeployPictureInPicture : undefined} sensitive={status.get('sensitive')} blurhash={attachment.get('blurhash')} diff --git a/app/javascript/flavours/glitch/containers/media_container.jsx b/app/javascript/flavours/glitch/containers/media_container.jsx index ec84b793c0..6fccd3c48e 100644 --- a/app/javascript/flavours/glitch/containers/media_container.jsx +++ b/app/javascript/flavours/glitch/containers/media_container.jsx @@ -8,7 +8,7 @@ import { ImmutableHashtag as Hashtag } from 'flavours/glitch/components/hashtag' import MediaGallery from 'flavours/glitch/components/media_gallery'; import ModalRoot from 'flavours/glitch/components/modal_root'; import { Poll } from 'flavours/glitch/components/poll'; -import Audio from 'flavours/glitch/features/audio'; +import { Audio } from 'flavours/glitch/features/audio'; import Card from 'flavours/glitch/features/status/components/card'; import MediaModal from 'flavours/glitch/features/ui/components/media_modal'; import { Video } from 'flavours/glitch/features/video'; diff --git a/app/javascript/flavours/glitch/features/alt_text_modal/index.tsx b/app/javascript/flavours/glitch/features/alt_text_modal/index.tsx index 48e8e72da5..c2aba44dc2 100644 --- a/app/javascript/flavours/glitch/features/alt_text_modal/index.tsx +++ b/app/javascript/flavours/glitch/features/alt_text_modal/index.tsx @@ -27,7 +27,7 @@ import { Button } from 'flavours/glitch/components/button'; import { GIFV } from 'flavours/glitch/components/gifv'; import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator'; import { Skeleton } from 'flavours/glitch/components/skeleton'; -import Audio from 'flavours/glitch/features/audio'; +import { Audio } from 'flavours/glitch/features/audio'; import { CharacterCounter } from 'flavours/glitch/features/compose/components/character_counter'; import { Tesseract as fetchTesseract } from 'flavours/glitch/features/ui/util/async-components'; import { Video, getPointerPosition } from 'flavours/glitch/features/video'; @@ -212,11 +212,11 @@ const Preview: React.FC<{ return (