From 469a00b6d6d1b56c17a60914ae1fe8e5a6cf9e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Sun, 29 Sep 2024 10:40:12 +0200 Subject: [PATCH 1/4] Port PreviewMediaDialog to TypeScript --- .../Dialogs/PreviewMediaDialog/index.jsx | 63 ------------------- .../Dialogs/PreviewMediaDialog/index.tsx | 51 +++++++++++++++ src/components/Video/Player.tsx | 4 +- 3 files changed, 52 insertions(+), 66 deletions(-) delete mode 100644 src/components/Dialogs/PreviewMediaDialog/index.jsx create mode 100644 src/components/Dialogs/PreviewMediaDialog/index.tsx diff --git a/src/components/Dialogs/PreviewMediaDialog/index.jsx b/src/components/Dialogs/PreviewMediaDialog/index.jsx deleted file mode 100644 index 6ac1846db..000000000 --- a/src/components/Dialogs/PreviewMediaDialog/index.jsx +++ /dev/null @@ -1,63 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Dialog from '@mui/material/Dialog'; -import DialogContent from '@mui/material/DialogContent'; -import DialogCloseAnimation from '../../DialogCloseAnimation'; -import PreviewPlayer from '../../Video/Player'; - -function getTitle(media) { - return `${media.artist} – ${media.title}`; -} - -function PreviewDialogWrapper(props) { - return ( - - ); -} - -const PreviewMediaDialog = ({ - open, - media, - volume, - onCloseDialog, -}) => ( - - {open ? ( - - - {open && ( - - )} - - - ) : null} - -); - -PreviewMediaDialog.propTypes = { - open: PropTypes.bool, - media: PropTypes.object, - volume: PropTypes.number, - onCloseDialog: PropTypes.func.isRequired, -}; - -export default PreviewMediaDialog; diff --git a/src/components/Dialogs/PreviewMediaDialog/index.tsx b/src/components/Dialogs/PreviewMediaDialog/index.tsx new file mode 100644 index 000000000..379ce7b1f --- /dev/null +++ b/src/components/Dialogs/PreviewMediaDialog/index.tsx @@ -0,0 +1,51 @@ +import Dialog from '@mui/material/Dialog'; +import DialogContent from '@mui/material/DialogContent'; +import DialogCloseAnimation from '../../DialogCloseAnimation'; +import PreviewPlayer from '../../Video/Player'; +import type { Media } from '../../../reducers/booth'; + +function getTitle(media: Media) { + return `${media.artist} – ${media.title}`; +} + +type PreviewMediaDialogProps = { + open: boolean, + media?: Media | null, + volume: number, + onCloseDialog: () => void, +}; +function PreviewMediaDialog({ + open, + media, + volume, + onCloseDialog, +}: PreviewMediaDialogProps) { + const dialog = open && media != null ? ( + + + + + + ) : null; + + return ( + + {dialog} + + ); +} + +export default PreviewMediaDialog; diff --git a/src/components/Video/Player.tsx b/src/components/Video/Player.tsx index c8a0be542..f61b16046 100644 --- a/src/components/Video/Player.tsx +++ b/src/components/Video/Player.tsx @@ -5,13 +5,11 @@ type PreviewPlayerProps = { media: Media, seek?: number, volume: number, - isMuted: boolean, }; function PreviewPlayer({ media, seek = 0, volume, - isMuted, }: PreviewPlayerProps) { const { getMediaSource } = useMediaSources(); const source = getMediaSource(media.sourceType); @@ -27,7 +25,7 @@ function PreviewPlayer({ active seek={seek} media={media} - volume={isMuted ? 0 : volume} + volume={volume} mode="preview" /> ); From 970f890940a89af230846a3eae5084ffb76fbb1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Sun, 29 Sep 2024 11:18:54 +0200 Subject: [PATCH 2/4] Port mobile components to TypeScript --- src/components/Player/index.tsx | 2 +- .../App/{Overlays.jsx => Overlays.tsx} | 15 ++--- .../components/App/{index.jsx => index.tsx} | 18 +++--- ...edMessage.jsx => VideoDisabledMessage.tsx} | 11 ++-- .../MainView/{index.jsx => index.tsx} | 32 +++++------ src/mobile/components/MediaList/Row.css | 4 ++ src/mobile/components/MediaList/Row.jsx | 32 ----------- src/mobile/components/MediaList/Row.tsx | 33 +++++++++++ .../MediaList/{index.jsx => index.tsx} | 8 ++- .../{HistoryList.jsx => HistoryList.tsx} | 0 src/mobile/components/RoomHistory/Row.jsx | 34 ----------- src/mobile/components/RoomHistory/Row.tsx | 35 ++++++++++++ .../RoomHistory/{Votes.jsx => Votes.tsx} | 14 ++--- .../RoomHistory/{index.jsx => index.tsx} | 19 ++----- .../{UserList.jsx => UserList.tsx} | 30 +++++----- src/mobile/components/UsersDrawer/UserRow.jsx | 32 ----------- src/mobile/components/UsersDrawer/UserRow.tsx | 30 ++++++++++ .../UsersDrawer/WaitlistPosition.jsx | 14 ----- .../UsersDrawer/WaitlistPosition.tsx | 13 +++++ src/mobile/components/UsersDrawer/index.jsx | 54 ------------------ src/mobile/components/UsersDrawer/index.tsx | 51 +++++++++++++++++ .../{VoteButtons.jsx => VoteButtons.tsx} | 26 ++++----- .../components/Video/{index.jsx => index.tsx} | 43 +++++++------- .../containers/{About.jsx => About.tsx} | 21 +++---- src/mobile/containers/{Chat.jsx => Chat.tsx} | 0 .../{DrawerMenu.jsx => DrawerMenu.tsx} | 8 +-- .../{LoginButtons.jsx => LoginButtons.tsx} | 4 +- .../containers/{MainView.jsx => MainView.tsx} | 13 +---- src/mobile/containers/PlaylistManager.tsx | 14 ++--- src/mobile/containers/PlaylistPanel.js | 56 ------------------- src/mobile/containers/PlaylistPanel.tsx | 14 +++++ .../{RoomHistory.jsx => RoomHistory.tsx} | 10 +++- .../{ServerList.jsx => ServerList.tsx} | 11 ++-- src/mobile/containers/UsersDrawer.js | 33 ----------- src/mobile/containers/UsersDrawer.tsx | 47 ++++++++++++++++ .../containers/{Video.jsx => Video.tsx} | 26 ++++++--- 36 files changed, 370 insertions(+), 437 deletions(-) rename src/mobile/components/App/{Overlays.jsx => Overlays.tsx} (79%) rename src/mobile/components/App/{index.jsx => index.tsx} (86%) rename src/mobile/components/MainView/{VideoDisabledMessage.jsx => VideoDisabledMessage.tsx} (68%) rename src/mobile/components/MainView/{index.jsx => index.tsx} (81%) delete mode 100644 src/mobile/components/MediaList/Row.jsx create mode 100644 src/mobile/components/MediaList/Row.tsx rename src/mobile/components/MediaList/{index.jsx => index.tsx} (60%) rename src/mobile/components/RoomHistory/{HistoryList.jsx => HistoryList.tsx} (100%) delete mode 100644 src/mobile/components/RoomHistory/Row.jsx create mode 100644 src/mobile/components/RoomHistory/Row.tsx rename src/mobile/components/RoomHistory/{Votes.jsx => Votes.tsx} (84%) rename src/mobile/components/RoomHistory/{index.jsx => index.tsx} (70%) rename src/mobile/components/UsersDrawer/{UserList.jsx => UserList.tsx} (75%) delete mode 100644 src/mobile/components/UsersDrawer/UserRow.jsx create mode 100644 src/mobile/components/UsersDrawer/UserRow.tsx delete mode 100644 src/mobile/components/UsersDrawer/WaitlistPosition.jsx create mode 100644 src/mobile/components/UsersDrawer/WaitlistPosition.tsx delete mode 100644 src/mobile/components/UsersDrawer/index.jsx create mode 100644 src/mobile/components/UsersDrawer/index.tsx rename src/mobile/components/Video/{VoteButtons.jsx => VoteButtons.tsx} (60%) rename src/mobile/components/Video/{index.jsx => index.tsx} (76%) rename src/mobile/containers/{About.jsx => About.tsx} (64%) rename src/mobile/containers/{Chat.jsx => Chat.tsx} (100%) rename src/mobile/containers/{DrawerMenu.jsx => DrawerMenu.tsx} (92%) rename src/mobile/containers/{LoginButtons.jsx => LoginButtons.tsx} (92%) rename src/mobile/containers/{MainView.jsx => MainView.tsx} (80%) delete mode 100644 src/mobile/containers/PlaylistPanel.js create mode 100644 src/mobile/containers/PlaylistPanel.tsx rename src/mobile/containers/{RoomHistory.jsx => RoomHistory.tsx} (56%) rename src/mobile/containers/{ServerList.jsx => ServerList.tsx} (74%) delete mode 100644 src/mobile/containers/UsersDrawer.js create mode 100644 src/mobile/containers/UsersDrawer.tsx rename src/mobile/containers/{Video.jsx => Video.tsx} (66%) diff --git a/src/components/Player/index.tsx b/src/components/Player/index.tsx index 91f9a0d93..cd856a088 100644 --- a/src/components/Player/index.tsx +++ b/src/components/Player/index.tsx @@ -8,7 +8,7 @@ type PlayerProps = { mode?: 'preview' | undefined, volume: number, isMuted: boolean, - media: Media, + media: Media | null, seek: number, onPlay?: () => void, }; diff --git a/src/mobile/components/App/Overlays.jsx b/src/mobile/components/App/Overlays.tsx similarity index 79% rename from src/mobile/components/App/Overlays.jsx rename to src/mobile/components/App/Overlays.tsx index 48aaa16d3..4b8e9ed0b 100644 --- a/src/mobile/components/App/Overlays.jsx +++ b/src/mobile/components/App/Overlays.tsx @@ -1,8 +1,10 @@ -import React from 'react'; -import PropTypes from 'prop-types'; import { CSSTransition, TransitionGroup } from 'react-transition-group'; -const Overlays = ({ children, active }) => { +type OverlaysProps = { + children: React.ReactElement | React.ReactElement[], + active?: string | null, +}; +function Overlays({ children, active }: OverlaysProps) { let view; if (Array.isArray(children)) { view = children.find((child) => child.key === active); @@ -31,11 +33,6 @@ const Overlays = ({ children, active }) => { {view} ); -}; - -Overlays.propTypes = { - children: PropTypes.node, - active: PropTypes.string, -}; +} export default Overlays; diff --git a/src/mobile/components/App/index.jsx b/src/mobile/components/App/index.tsx similarity index 86% rename from src/mobile/components/App/index.jsx rename to src/mobile/components/App/index.tsx index 042e22b68..c577c3b0c 100644 --- a/src/mobile/components/App/index.jsx +++ b/src/mobile/components/App/index.tsx @@ -1,6 +1,5 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; +import { useState } from 'react'; import Snackbar from '@mui/material/Snackbar'; import { useSelector } from '../../../hooks/useRedux'; import ErrorArea from '../../../containers/ErrorArea'; @@ -15,12 +14,14 @@ import ServerList from '../../containers/ServerList'; import { videoEnabledSelector } from '../../../reducers/settings'; import Overlays from './Overlays'; -const { useState } = React; - +type MobileAppProps = { + activeOverlay?: string | null, + onCloseOverlay: () => void, +}; function MobileApp({ activeOverlay, onCloseOverlay, -}) { +}: MobileAppProps) { const [dismissedWarning, dismissWarning] = useState(false); const videoEnabled = useSelector(videoEnabledSelector); @@ -36,7 +37,7 @@ function MobileApp({ - + @@ -51,9 +52,4 @@ function MobileApp({ ); } -MobileApp.propTypes = { - activeOverlay: PropTypes.string, - onCloseOverlay: PropTypes.func.isRequired, -}; - export default MobileApp; diff --git a/src/mobile/components/MainView/VideoDisabledMessage.jsx b/src/mobile/components/MainView/VideoDisabledMessage.tsx similarity index 68% rename from src/mobile/components/MainView/VideoDisabledMessage.jsx rename to src/mobile/components/MainView/VideoDisabledMessage.tsx index 8e08ae714..4d41514de 100644 --- a/src/mobile/components/MainView/VideoDisabledMessage.jsx +++ b/src/mobile/components/MainView/VideoDisabledMessage.tsx @@ -1,9 +1,10 @@ -import React from 'react'; -import PropTypes from 'prop-types'; import { useTranslator } from '@u-wave/react-translate'; import Button from '@mui/material/Button'; -function VideoDisabledMessage({ onEnableVideo }) { +type VideoDisabledMessageProps = { + onEnableVideo: () => void, +}; +function VideoDisabledMessage({ onEnableVideo }: VideoDisabledMessageProps) { const { t } = useTranslator(); return ( @@ -16,8 +17,4 @@ function VideoDisabledMessage({ onEnableVideo }) { ); } -VideoDisabledMessage.propTypes = { - onEnableVideo: PropTypes.func.isRequired, -}; - export default VideoDisabledMessage; diff --git a/src/mobile/components/MainView/index.jsx b/src/mobile/components/MainView/index.tsx similarity index 81% rename from src/mobile/components/MainView/index.jsx rename to src/mobile/components/MainView/index.tsx index cd62e00d5..4cd1d7277 100644 --- a/src/mobile/components/MainView/index.jsx +++ b/src/mobile/components/MainView/index.tsx @@ -1,5 +1,3 @@ -import React from 'react'; -import PropTypes from 'prop-types'; import { useTranslator } from '@u-wave/react-translate'; import AppBar from '@mui/material/AppBar'; import Toolbar from '@mui/material/Toolbar'; @@ -13,13 +11,14 @@ import Chat from '../../containers/Chat'; import DrawerMenu from '../../containers/DrawerMenu'; import UsersDrawer from '../../containers/UsersDrawer'; import VideoDisabledMessage from './VideoDisabledMessage'; +import type { Media } from '../../../reducers/booth'; -const waitlistIconStyle = { +const waitlistIconStyle: React.CSSProperties = { fontSize: '125%', textAlign: 'center', }; -const getWaitlistLabel = (size, position) => { +function getWaitlistLabel(size: number, position: number) { if (size > 0) { const posText = position !== -1 ? `${position + 1}/${size}` @@ -28,8 +27,18 @@ const getWaitlistLabel = (size, position) => { return posText; } return '0'; -}; +} +type MainViewProps = { + media: Media | null, + videoEnabled: boolean, + waitlistPosition: number, + waitlistSize: number, + onOpenRoomHistory: () => void, + onOpenDrawer: () => void, + onOpenWaitlist: () => void, + onEnableVideo: () => void, +}; function MainView({ media, videoEnabled, @@ -39,7 +48,7 @@ function MainView({ onOpenDrawer, onOpenWaitlist, onEnableVideo, -}) { +}: MainViewProps) { const { t } = useTranslator(); let title = t('booth.empty'); @@ -87,15 +96,4 @@ function MainView({ ); } -MainView.propTypes = { - media: PropTypes.object, - videoEnabled: PropTypes.bool.isRequired, - waitlistPosition: PropTypes.number.isRequired, - waitlistSize: PropTypes.number.isRequired, - onOpenRoomHistory: PropTypes.func.isRequired, - onOpenWaitlist: PropTypes.func.isRequired, - onOpenDrawer: PropTypes.func.isRequired, - onEnableVideo: PropTypes.func.isRequired, -}; - export default MainView; diff --git a/src/mobile/components/MediaList/Row.css b/src/mobile/components/MediaList/Row.css index ceb12c77b..7ff905410 100644 --- a/src/mobile/components/MediaList/Row.css +++ b/src/mobile/components/MediaList/Row.css @@ -1,3 +1,7 @@ +.MobileMediaRow { + position: absolute; +} + .MobileMediaRow-artist, .MobileMediaRow-title { max-width: 100%; diff --git a/src/mobile/components/MediaList/Row.jsx b/src/mobile/components/MediaList/Row.jsx deleted file mode 100644 index bc46db167..000000000 --- a/src/mobile/components/MediaList/Row.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Avatar from '@mui/material/Avatar'; -import ListItem from '@mui/material/ListItem'; -import ListItemAvatar from '@mui/material/ListItemAvatar'; -import ListItemText from '@mui/material/ListItemText'; - -const noWrap = { noWrap: true }; - -const MediaRow = ({ media, style }) => ( - - - - - - -); - -MediaRow.propTypes = { - style: PropTypes.object, // from virtual list positioning - media: PropTypes.object, -}; - -export default MediaRow; diff --git a/src/mobile/components/MediaList/Row.tsx b/src/mobile/components/MediaList/Row.tsx new file mode 100644 index 000000000..57dd158e3 --- /dev/null +++ b/src/mobile/components/MediaList/Row.tsx @@ -0,0 +1,33 @@ +import Avatar from '@mui/material/Avatar'; +import ListItem from '@mui/material/ListItem'; +import ListItemAvatar from '@mui/material/ListItemAvatar'; +import ListItemText from '@mui/material/ListItemText'; +import type { Media } from '../../../reducers/booth'; + +const noWrap = { noWrap: true }; + +type MediaRowProps = { + media: Media, + /** For virtual list positioning. */ + style: React.CSSProperties, +}; +function MediaRow({ media, style }: MediaRowProps) { + return ( + + + + + + + ); +} + +export default MediaRow; diff --git a/src/mobile/components/MediaList/index.jsx b/src/mobile/components/MediaList/index.tsx similarity index 60% rename from src/mobile/components/MediaList/index.jsx rename to src/mobile/components/MediaList/index.tsx index fd2c96cd5..dfc28dfbb 100644 --- a/src/mobile/components/MediaList/index.jsx +++ b/src/mobile/components/MediaList/index.tsx @@ -1,9 +1,13 @@ -import React from 'react'; import List from '@mui/material/List'; import Base from '../../../components/MediaList/BaseMediaList'; import MediaRow from './Row'; +import type { Media } from '../../../reducers/booth'; -function MediaList(props) { +type MediaListProps = { + className?: string, + media: (Media | null)[], +}; +function MediaList(props: MediaListProps) { return ( ( - - - - - - - -); - -HistoryRow.propTypes = { - style: PropTypes.object, // from virtual list positioning - media: PropTypes.object, -}; - -export default HistoryRow; diff --git a/src/mobile/components/RoomHistory/Row.tsx b/src/mobile/components/RoomHistory/Row.tsx new file mode 100644 index 000000000..84a2bb455 --- /dev/null +++ b/src/mobile/components/RoomHistory/Row.tsx @@ -0,0 +1,35 @@ +import Avatar from '@mui/material/Avatar'; +import ListItem from '@mui/material/ListItem'; +import ListItemAvatar from '@mui/material/ListItemAvatar'; +import ListItemText from '@mui/material/ListItemText'; +import Votes from './Votes'; +import type { HistoryEntry } from '../../../hooks/useRoomHistory'; + +const noWrap = { noWrap: true }; + +type HistoryRowProps = { + media: HistoryEntry, + /** For virtual list positioning. */ + style: React.CSSProperties, +}; +function HistoryRow({ media, style }: HistoryRowProps) { + return ( + + + + + + + + ); +} + +export default HistoryRow; diff --git a/src/mobile/components/RoomHistory/Votes.jsx b/src/mobile/components/RoomHistory/Votes.tsx similarity index 84% rename from src/mobile/components/RoomHistory/Votes.jsx rename to src/mobile/components/RoomHistory/Votes.tsx index c15d3eed2..a68a4c457 100644 --- a/src/mobile/components/RoomHistory/Votes.jsx +++ b/src/mobile/components/RoomHistory/Votes.tsx @@ -1,12 +1,16 @@ import cx from 'clsx'; -import PropTypes from 'prop-types'; import { mdiHeart, mdiHeartOutline, mdiThumbDown, mdiThumbUp, } from '@mdi/js'; import SvgIcon from '../../../components/SvgIcon'; import useCurrentUser from '../../../hooks/useCurrentUser'; -function Votes({ upvotes, downvotes, favorites }) { +type VotesProps = { + upvotes: string[], + downvotes: string[], + favorites: string[], +}; +function Votes({ upvotes, downvotes, favorites }: VotesProps) { const user = useCurrentUser(); const isUpvote = user ? upvotes.includes(user._id) : false; const isDownvote = user ? downvotes.includes(user._id) : false; @@ -30,10 +34,4 @@ function Votes({ upvotes, downvotes, favorites }) { ); } -Votes.propTypes = { - upvotes: PropTypes.array.isRequired, - favorites: PropTypes.array.isRequired, - downvotes: PropTypes.array.isRequired, -}; - export default Votes; diff --git a/src/mobile/components/RoomHistory/index.jsx b/src/mobile/components/RoomHistory/index.tsx similarity index 70% rename from src/mobile/components/RoomHistory/index.jsx rename to src/mobile/components/RoomHistory/index.tsx index 4b94f65c6..437090350 100644 --- a/src/mobile/components/RoomHistory/index.jsx +++ b/src/mobile/components/RoomHistory/index.tsx @@ -1,16 +1,14 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; import { useTranslator } from '@u-wave/react-translate'; import OverlayHeader from '../../../components/Overlay/Header'; import OverlayContent from '../../../components/Overlay/Content'; import HistoryList from './HistoryList'; -function RoomHistory({ - className, - onCloseOverlay, - ...props -}) { +type RoomHistoryProps = { + className?: string, + onCloseOverlay: () => void, +}; +function RoomHistory({ className, onCloseOverlay }: RoomHistoryProps) { const { t } = useTranslator(); return ( @@ -22,15 +20,10 @@ function RoomHistory({ onCloseOverlay={onCloseOverlay} /> - + ); } -RoomHistory.propTypes = { - className: PropTypes.string, - onCloseOverlay: PropTypes.func.isRequired, -}; - export default RoomHistory; diff --git a/src/mobile/components/UsersDrawer/UserList.jsx b/src/mobile/components/UsersDrawer/UserList.tsx similarity index 75% rename from src/mobile/components/UsersDrawer/UserList.jsx rename to src/mobile/components/UsersDrawer/UserList.tsx index 88546ca45..3133d376c 100644 --- a/src/mobile/components/UsersDrawer/UserList.jsx +++ b/src/mobile/components/UsersDrawer/UserList.tsx @@ -1,16 +1,15 @@ -import React from 'react'; -import PropTypes from 'prop-types'; import { useTranslator } from '@u-wave/react-translate'; import List from '@mui/material/List'; import ListSubheader from '@mui/material/ListSubheader'; import Divider from '@mui/material/Divider'; -import Button from '@mui/material/Button'; +import Button, { type ButtonProps } from '@mui/material/Button'; import { mdiPlay } from '@mdi/js'; import SvgIcon from '../../../components/SvgIcon'; import UserRow from './UserRow'; import WaitlistPosition from './WaitlistPosition'; +import type { User } from '../../../reducers/users'; -function JoinWaitlistButton(props) { +function JoinWaitlistButton(props: ButtonProps) { return (