From 8e662c8594cb1e85591dfd1cc144c7b4cd2f4db1 Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Fri, 27 Nov 2020 11:58:43 +0100 Subject: [PATCH] Update JSX and fix bugs --- src/App.test.tsx | 1 - src/App.tsx | 1 - src/index.tsx | 6 +-- src/routes/ContentRoute.tsx | 2 +- src/routes/main/MainPage.tsx | 2 +- src/routes/player/Player.tsx | 53 ++++++++++---------- src/routes/player/PlayerError.tsx | 2 - src/routes/player/PlayerLoading.tsx | 2 - src/routes/player/PlayerPage.tsx | 1 - src/routes/player/PreviewBar.tsx | 2 +- src/routes/player/PreviewViewer.tsx | 6 +-- src/routes/player/SeekBar.tsx | 8 +-- src/routes/player/subtitles/TtmlRenderer.tsx | 2 +- src/routes/player/video/DashVideoElement.tsx | 47 ++++++++++++++--- src/routes/player/video/RawVideoElement.tsx | 4 +- src/routes/player/video/VideoElement.tsx | 4 +- src/util/head/HeadPortal.tsx | 2 +- src/util/media/useTextTrackCues.ts | 6 +-- tsconfig.json | 3 +- 19 files changed, 91 insertions(+), 63 deletions(-) diff --git a/src/App.test.tsx b/src/App.test.tsx index 4db7ebc..9a9be2e 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { render } from '@testing-library/react'; import App from './App'; diff --git a/src/App.tsx b/src/App.tsx index 46aa883..be09b03 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import {BrowserRouter, Route} from 'react-router-dom'; import {MainPage} from "./routes/main/MainPage"; import {PlayerPage} from "./routes/player/PlayerPage"; diff --git a/src/index.tsx b/src/index.tsx index e245541..33c5e0b 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,5 +1,5 @@ import {produce} from 'immer' -import React from 'react'; +import { StrictMode } from 'react'; import ReactDOM from 'react-dom'; import {defaults} from 'react-sweet-state'; @@ -15,9 +15,9 @@ defaults.devtools = process.env.NODE_ENV !== "production"; defaults.mutator = (currentState, producer) => produce(currentState, producer) ReactDOM.render( - <React.StrictMode> + <StrictMode> <App/> - </React.StrictMode>, + </StrictMode>, document.getElementById('root') ); diff --git a/src/routes/ContentRoute.tsx b/src/routes/ContentRoute.tsx index be5f46f..5d5b36a 100644 --- a/src/routes/ContentRoute.tsx +++ b/src/routes/ContentRoute.tsx @@ -1,4 +1,4 @@ -import React, {PropsWithChildren, useEffect, useState} from "react"; +import { PropsWithChildren, useEffect, useState } from "react"; import {useParams} from "react-router"; import {useApiClient} from "../api/ApiClientContext"; import {ContentMeta} from "../api/models/dto/ContentMeta"; diff --git a/src/routes/main/MainPage.tsx b/src/routes/main/MainPage.tsx index 3501ace..03d69bc 100644 --- a/src/routes/main/MainPage.tsx +++ b/src/routes/main/MainPage.tsx @@ -1,4 +1,4 @@ -import React, {useEffect, useState} from "react"; +import { useEffect, useState } from "react"; import {createUseStyles} from "react-jss"; import {Link} from "react-router-dom"; import {useApiClient} from "../../api/ApiClientContext"; diff --git a/src/routes/player/Player.tsx b/src/routes/player/Player.tsx index 25d15d1..c812b3e 100644 --- a/src/routes/player/Player.tsx +++ b/src/routes/player/Player.tsx @@ -1,4 +1,4 @@ -import React, {useState} from "react"; +import {useState} from "react"; import {createUseStyles} from "react-jss"; import {Link} from "react-router-dom"; import {ContentMeta} from "../../api/models/dto/ContentMeta"; @@ -54,7 +54,10 @@ export function Player( return ( <div> <Link to="/">Back</Link> - <p>{name?.name}</p> + <h2>{name?.name}</h2> + <p>{rating?.certification}</p> + <strong>{description?.tagline}</strong> + <p>{description?.overview}</p> <p>{instalment?.content && getLocalizedName(instalment?.content, locale)?.name}</p> <div className={classes.player}> <div className={classes.playerCanvas}> @@ -91,30 +94,28 @@ export function Player( <p style={{fontVariant: "tabular-nums"}}>{formatDuration(position)} / {formatDuration(duration)}</p> <button onClick={videoElement?.play}>Play</button> <button onClick={videoElement?.pause}>Pause</button> - <p> - Audio - <ul> - {audioTracks.map(track => ( - <li key={track.index}> - <strong>{track.lang}</strong> - {track.labels} - <button onClick={() => videoElement?.setAudioTrack(track)}>Choose</button> - </li> - ))} - </ul> - </p> - <p> - Subtitles - <ul> - {content.subtitles.map(track => ( - <li key={track.src}> - <strong>{track.language}</strong> - {track.specifier} - <button onClick={() => setSubtitle(track)}>Choose</button> - </li> - ))} - </ul> - </p> + <h3>Audio</h3> + <ul> + {audioTracks.map(track => ( + <li key={track.index}> + <strong>{track.lang}</strong> + {track.labels} + + <button onClick={() => videoElement?.setAudioTrack(track)}>Choose</button> + </li> + ))} + </ul> + <h3>Subtitles</h3> + <ul> + {content.subtitles.map(track => ( + <li key={track.src}> + <strong>{track.language}</strong> + {track.specifier} + + <button onClick={() => setSubtitle(track)}>Choose</button> + </li> + ))} + </ul> <SeekBar video={videoElement} previewTrack={previewTrack} diff --git a/src/routes/player/PlayerError.tsx b/src/routes/player/PlayerError.tsx index 6cec388..d6669c2 100644 --- a/src/routes/player/PlayerError.tsx +++ b/src/routes/player/PlayerError.tsx @@ -1,5 +1,3 @@ -import React from "react"; - export function PlayerError() { return ( <div>Error</div> diff --git a/src/routes/player/PlayerLoading.tsx b/src/routes/player/PlayerLoading.tsx index ae71f1f..b11833e 100644 --- a/src/routes/player/PlayerLoading.tsx +++ b/src/routes/player/PlayerLoading.tsx @@ -1,5 +1,3 @@ -import React from "react"; - export function PlayerLoading() { return ( <div>Loading</div> diff --git a/src/routes/player/PlayerPage.tsx b/src/routes/player/PlayerPage.tsx index eb96af0..d65c9eb 100644 --- a/src/routes/player/PlayerPage.tsx +++ b/src/routes/player/PlayerPage.tsx @@ -1,4 +1,3 @@ -import React from "react"; import {getPlayableMedia} from "../../api/models/Content"; import {usePlayabilityRating} from "../../util/mime/usePlayabilityRating"; import {useCurrentContent} from "../../util/CurrentContentContext"; diff --git a/src/routes/player/PreviewBar.tsx b/src/routes/player/PreviewBar.tsx index 27a6b62..9c5a7fe 100644 --- a/src/routes/player/PreviewBar.tsx +++ b/src/routes/player/PreviewBar.tsx @@ -1,4 +1,4 @@ -import React, {useMemo} from "react"; +import { useMemo } from "react"; import {createUseStyles} from "react-jss"; import {MousePosition} from "../../util/mouse/MousePosition"; import {useOffsetAbsoluteRef} from "../../util/offset/useOffsetAbsoluteRef"; diff --git a/src/routes/player/PreviewViewer.tsx b/src/routes/player/PreviewViewer.tsx index 9928f52..4649bb4 100644 --- a/src/routes/player/PreviewViewer.tsx +++ b/src/routes/player/PreviewViewer.tsx @@ -1,4 +1,4 @@ -import React, {useMemo} from "react"; +import { Fragment, useMemo } from "react"; import {createUseStyles} from "react-jss"; import {HeadPortal} from "../../util/head/HeadPortal"; import {useImage} from "../../util/media/useImage"; @@ -26,14 +26,14 @@ export function PreviewViewer({previewTrack, position}: Props) { return url.toString(); }))), [cues, previewTrack]); return useMemo(() => ( - <React.Fragment> + <Fragment> <HeadPortal> {sources?.map(it => ( <link key={it} rel="preload" href={it} as="image" crossOrigin="anonymous"/> ))} </HeadPortal> <img alt="" className={classes.preview} src={sprite || undefined}/> - </React.Fragment> + </Fragment> ), [classes.preview, sources, sprite]); } diff --git a/src/routes/player/SeekBar.tsx b/src/routes/player/SeekBar.tsx index 90bcbda..b77d4de 100644 --- a/src/routes/player/SeekBar.tsx +++ b/src/routes/player/SeekBar.tsx @@ -1,4 +1,4 @@ -import React, {MouseEvent, useCallback, useMemo, useState} from "react"; +import { Fragment, MouseEvent, useCallback, useMemo, useState } from "react"; import {createUseStyles} from "react-jss"; import {getMousePosition} from "../../util/mouse/getMousePosition"; import {MousePosition} from "../../util/mouse/MousePosition"; @@ -79,7 +79,7 @@ export function SeekBar({video, previewTrack, duration, position}: Props) { ), [classes.seekBar, onClick, onMouseLeave, onMouseMove, playHead, seekHead]); return ( - <React.Fragment> + <Fragment> <PreviewBar previewTrack={previewTrack} duration={duration} @@ -87,8 +87,8 @@ export function SeekBar({video, previewTrack, duration, position}: Props) { hidden={mousePosition === null} /> {seekBar} - </React.Fragment> - ) + </Fragment> + ); } const useStyles = createUseStyles({ diff --git a/src/routes/player/subtitles/TtmlRenderer.tsx b/src/routes/player/subtitles/TtmlRenderer.tsx index 5f5b151..bd599e6 100644 --- a/src/routes/player/subtitles/TtmlRenderer.tsx +++ b/src/routes/player/subtitles/TtmlRenderer.tsx @@ -1,4 +1,4 @@ -import React, {useEffect, useState} from "react"; +import { useEffect, useState } from "react"; import TtmlHelper from "./TtmlHelper"; interface Props { diff --git a/src/routes/player/video/DashVideoElement.tsx b/src/routes/player/video/DashVideoElement.tsx index 84a0b3b..c6698ea 100644 --- a/src/routes/player/video/DashVideoElement.tsx +++ b/src/routes/player/video/DashVideoElement.tsx @@ -1,4 +1,4 @@ -import React, {PropsWithChildren, useEffect, useImperativeHandle, useMemo, useState} from "react"; +import {forwardRef, PropsWithChildren, useEffect, useImperativeHandle, useMemo, useState,} from "react"; import {Media} from "../../../api/models/Media"; import dashjs, {MediaInfo} from "dashjs"; import {VideoApi} from "./VideoApi"; @@ -9,7 +9,7 @@ interface Props { className?: string, } -export const DashVideoElement = React.forwardRef<VideoApi, PropsWithChildren<Props>>(function ( +export const DashVideoElement = forwardRef<VideoApi, PropsWithChildren<Props>>(function ( {media, autoPlay, className, children}, ref ) { @@ -19,34 +19,64 @@ export const DashVideoElement = React.forwardRef<VideoApi, PropsWithChildren<Pro useImperativeHandle(ref, () => ({ METADATA_EVENT: dashjs.MediaPlayer.events.PLAYBACK_METADATA_LOADED, TIMECHANGE_EVENT: dashjs.MediaPlayer.events.PLAYBACK_TIME_UPDATED, - play: () => { + play() { + if (!player.isReady()) { + return; + } player.play(); }, - pause: () => { + pause() { + if (!player.isReady()) { + return; + } player.pause(); }, - isPaused: () => { + isPaused() { + if (!player.isReady()) { + return true; + } return player.isPaused(); }, - setPlaybackRate: (value: number) => { + setPlaybackRate(value: number) { + if (!player.isReady()) { + return; + } player.setPlaybackRate(value); }, - getPlaybackRate: () => { + getPlaybackRate(): number { + if (!player.isReady()) { + return 1; + } return player.getPlaybackRate(); }, setCurrentTime(value: number) { + if (!player.isReady()) { + return; + } player.seek(value); }, getCurrentTime(): number { + if (!player.isReady()) { + return 0; + } return player.time(); }, getDuration(): number { + if (!player.isReady()) { + return 0; + } return player.duration(); }, canPlay(): boolean { + if (!player.isReady()) { + return false; + } return !Number.isNaN(player.duration()); }, setAudioTrack(track: MediaInfo) { + if (!player.isReady()) { + return; + } player.setQualityFor("audio", 0); player.setCurrentTrack(track); }, @@ -57,6 +87,9 @@ export const DashVideoElement = React.forwardRef<VideoApi, PropsWithChildren<Pro player.off(event, listener); }, getAudioTracks(): MediaInfo[] { + if (!player.isReady()) { + return []; + } return player.getTracksFor("audio").map((info: MediaInfo) => { return info; }) diff --git a/src/routes/player/video/RawVideoElement.tsx b/src/routes/player/video/RawVideoElement.tsx index 4dba70e..b957682 100644 --- a/src/routes/player/video/RawVideoElement.tsx +++ b/src/routes/player/video/RawVideoElement.tsx @@ -1,4 +1,4 @@ -import React, {PropsWithChildren, useImperativeHandle, useState} from "react"; +import { forwardRef, PropsWithChildren, useImperativeHandle, useState } from "react"; import {Media} from "../../../api/models/Media"; import {VideoApi} from "./VideoApi"; import {MediaInfo} from "dashjs"; @@ -9,7 +9,7 @@ interface Props { className?: string, } -export const RawVideoElement = React.forwardRef<VideoApi, PropsWithChildren<Props>>(function ( +export const RawVideoElement = forwardRef<VideoApi, PropsWithChildren<Props>>(function ( {media, autoPlay, className, children}, ref ) { diff --git a/src/routes/player/video/VideoElement.tsx b/src/routes/player/video/VideoElement.tsx index 99c9c48..526b40a 100644 --- a/src/routes/player/video/VideoElement.tsx +++ b/src/routes/player/video/VideoElement.tsx @@ -1,4 +1,4 @@ -import React, {PropsWithChildren} from "react"; +import { forwardRef, PropsWithChildren } from "react"; import {Media} from "../../../api/models/Media"; import {DashVideoElement} from "./DashVideoElement"; import {RawVideoElement} from "./RawVideoElement"; @@ -10,7 +10,7 @@ interface Props { className?: string, } -export const VideoElement = React.forwardRef<VideoApi, PropsWithChildren<Props>>(function ( +export const VideoElement = forwardRef<VideoApi, PropsWithChildren<Props>>(function ( props: Props, ref ) { switch (props.media.mime) { diff --git a/src/util/head/HeadPortal.tsx b/src/util/head/HeadPortal.tsx index 8b70c22..f35b2ef 100644 --- a/src/util/head/HeadPortal.tsx +++ b/src/util/head/HeadPortal.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import * as React from "react"; import ReactDOM from "react-dom"; export function HeadPortal({children}: React.PropsWithChildren<{}>) { diff --git a/src/util/media/useTextTrackCues.ts b/src/util/media/useTextTrackCues.ts index 557a774..b4e1d6d 100644 --- a/src/util/media/useTextTrackCues.ts +++ b/src/util/media/useTextTrackCues.ts @@ -1,17 +1,17 @@ import {useEffect, useState} from "react"; export const useTextTrackCues = (track: HTMLTrackElement | null) => { - const [cues, setCues] = useState<TextTrackCue[]>([]); + const [cues, setCues] = useState<VTTCue[]>([]); useEffect(() => { if (track !== null) { track.track.mode = "hidden"; if (track.readyState >= 1) { - setCues(Array.from(track.track.cues || [])) + setCues(Array.from(track.track.cues || []) as VTTCue[]) } else { let animationFrame: number | null = null; const listener = () => { animationFrame = window.requestAnimationFrame(() => { - setCues(Array.from(track.track.cues || [])) + setCues(Array.from(track.track.cues || []) as VTTCue[]) }) }; track.addEventListener("load", listener) diff --git a/tsconfig.json b/tsconfig.json index f2850b7..e18c413 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,8 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react" + "jsx": "react-jsx", + "noFallthroughCasesInSwitch": true }, "include": [ "src" -- GitLab