From 4590164b134668fa2f33a59bd963dbc1ee8e8108 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Fri, 15 Jan 2021 15:41:19 +0100
Subject: [PATCH] Cleaned up some code

---
 src/routes/player/Player.tsx                  | 145 +++---------------
 src/routes/player/SeekBar.tsx                 |  13 +-
 src/routes/player/video/AudioSelection.tsx    |  30 ++++
 src/routes/player/video/EpisodeSelection.tsx  |  24 +++
 src/routes/player/video/PlayerControls.tsx    |  77 ++++++++++
 src/routes/player/video/SubtitleSelection.tsx |  30 ++++
 6 files changed, 191 insertions(+), 128 deletions(-)
 create mode 100644 src/routes/player/video/AudioSelection.tsx
 create mode 100644 src/routes/player/video/EpisodeSelection.tsx
 create mode 100644 src/routes/player/video/PlayerControls.tsx
 create mode 100644 src/routes/player/video/SubtitleSelection.tsx

diff --git a/src/routes/player/Player.tsx b/src/routes/player/Player.tsx
index b6936f0..211dc2c 100644
--- a/src/routes/player/Player.tsx
+++ b/src/routes/player/Player.tsx
@@ -1,25 +1,23 @@
-import {ChangeEvent, Fragment, useCallback, useState} from "react";
+import {Fragment, useState} from "react";
 import {createUseStyles} from "react-jss";
 import {Link} from "react-router-dom";
 import {ContentMeta} from "../../api/models/dto/ContentMeta";
 import {Media} from "../../api/models/Media";
 import {getLocalizedDescription, getLocalizedName, getLocalizedRating} from "../../api/models/Content";
-import {formatDuration} from "../../util/formatDuration";
 import {useLocale} from "../../util/locale/LocalizedContext";
 import {SeekBar} from "./SeekBar";
 import {VideoElement} from "./video/VideoElement";
 import {PlayerApi} from "./video/PlayerApi";
-import {useAudioTracks} from "../../util/media/useAudioTracks";
-import {useDebugInfo} from "../../util/media/useDebugInfo";
 import {Subtitle} from "../../api/models/Subtitle";
 import {MousePosition} from "../../util/mouse/MousePosition";
 import {VideoProvider} from "./video/VideoContext";
 import {SubtitleRenderer} from "./subtitles/SubtitleRenderer";
 import {useShowEpisodes} from "../../api/ApiHooks";
-import {MediaEpisode} from "../main/MediaEpisode";
-import {usePaused} from "../../util/media/usePaused";
-import {useCurrentTime} from "../../util/media/useCurrentTime";
 import {useDuration} from "../../util/media/useDuration";
+import {AudioSelection} from "./video/AudioSelection";
+import {SubtitleSelection} from "./video/SubtitleSelection";
+import {EpisodeSelection} from "./video/EpisodeSelection";
+import {PlayerControls} from "./video/PlayerControls";
 
 interface Props {
     meta: ContentMeta,
@@ -47,42 +45,7 @@ export function Player(
     const [playerApi, setPlayerApi] = useState<PlayerApi | null>(null);
     const [mousePosition, setMousePosition] = useState<MousePosition | null>(null);
 
-    const [volume, setVolume] = useState<number>(1);
-    const paused = usePaused(playerApi);
-    const currentTime = useCurrentTime(playerApi)
     const duration = useDuration(playerApi);
-    const [audioTracks, currentTrack, setCurrentTrack] = useAudioTracks(playerApi);
-
-    useDebugInfo("player", playerApi);
-    useDebugInfo("content", content);
-    useDebugInfo("subtitle", subtitle);
-    useDebugInfo("currentTime", currentTime);
-    useDebugInfo("duration", duration);
-    useDebugInfo("audioTracks", audioTracks);
-
-    const onPause = useCallback(() => {
-        if (playerApi) {
-            playerApi.pause()
-        }
-    }, [playerApi]);
-
-    const onPlay = useCallback(() => {
-        if (playerApi) {
-            playerApi.play()
-        }
-    }, [playerApi]);
-
-    const onFastForward = useCallback(() => {
-        if (playerApi) {
-            playerApi.setCurrentTime(playerApi.getCurrentTime() + 10)
-        }
-    }, [playerApi]);
-
-    const onRewind = useCallback(() => {
-        if (playerApi) {
-            playerApi.setCurrentTime(playerApi.getCurrentTime() - 10)
-        }
-    }, [playerApi]);
 
     return (
         <VideoProvider value={playerApi?.getVideoElement() || null}>
@@ -98,20 +61,15 @@ export function Player(
                         {relatedEpisodesError ? (
                             <p>{"" + relatedEpisodesError}</p>
                         ) : (
-                            <ul>
-                                {relatedEpisodes.map(episode =>
-                                    <MediaEpisode
-                                        key={episode.content.ids.uuid}
-                                        item={episode}
-                                        disabled={episode.content.ids.uuid === content.ids.uuid}
-                                    />
-                                )}
-                            </ul>
+                            <EpisodeSelection
+                                content={content}
+                                episodes={relatedEpisodes}
+                            />
                         )}
                     </Fragment>
                 )}
-                <div className={classes.player}>
-                    <div className={classes.playerCanvas}>
+                <div className={classes.videoContainer}>
+                    <div className={classes.videoCanvas}>
                         <VideoElement
                             className={classes.video}
                             media={media}
@@ -126,83 +84,20 @@ export function Player(
                         />
                     </div>
                 </div>
-                <p style={{fontVariant: "tabular-nums"}}>
-                    {formatDuration(mousePosition ? (mousePosition.relative * duration) : currentTime)} / {formatDuration(duration)}
-                </p>
-                <button
-                    onClick={onPlay}
-                    disabled={!paused}
-                >
-                    Play
-                </button>
-                <button
-                    onClick={onPause}
-                    disabled={paused}
-                >
-                    Pause
-                </button>
-                <button
-                    onClick={onRewind}
-                >
-                    Rewind
-                </button>
-                <button
-                    onClick={onFastForward}
-                >
-                    Fast Forward
-                </button>
-                <p>
-                    <input
-                        type="range"
-                        min="0"
-                        max="100"
-                        value={volume * 100}
-                        onChange={(event: ChangeEvent<HTMLInputElement>) => {
-                            setVolume(event.target.valueAsNumber / 100);
-                            playerApi?.setVolume(event.target.valueAsNumber / 100)
-                        }}
-                    />
-                </p>
+                <PlayerControls playerApi={playerApi} />
                 <h3>Audio</h3>
-                <ul>
-                    {audioTracks.map(track => (
-                        <li key={track.index}>
-                            <strong>{track.lang}</strong>
-                            &nbsp;{track.labels}
-                            &nbsp;
-                            <button
-                                disabled={currentTrack === track}
-                                onClick={() => setCurrentTrack(track)}
-                            >
-                                Choose
-                            </button>
-                        </li>
-                    ))}
-                </ul>
+                <AudioSelection playerApi={playerApi} />
                 <h3>Subtitles</h3>
-                <ul>
-                    {[null, ...content.subtitles].map(track => (
-                        <li key={track?.src || "none"}>
-                            <strong>{track?.language || "none"}</strong>
-                            &nbsp;{track?.specifier}
-                            &nbsp;{track?.format}
-                            &nbsp;
-                            <button
-                                disabled={subtitle === track}
-                                onClick={() => setSubtitle(track)}
-                            >
-                                Choose
-                            </button>
-                        </li>
-                    ))}
-                </ul>
+                <SubtitleSelection
+                    subtitles={[null, ...content.subtitles]}
+                    subtitle={subtitle}
+                    setSubtitle={setSubtitle}
+                />
                 <SeekBar
                     videoApi={playerApi}
                     previewSrc={content.preview}
                     mousePosition={mousePosition}
                     setMousePosition={setMousePosition}
-                    duration={duration}
-                    position={currentTime}
                 />
             </div>
         </VideoProvider>
@@ -210,7 +105,7 @@ export function Player(
 }
 
 const useStyles = createUseStyles({
-    player: {
+    videoContainer: {
         width: "40rem",
         height: "30rem",
         background: "#dc5",
@@ -219,7 +114,7 @@ const useStyles = createUseStyles({
         justifyContent: "center",
         alignItems: "center",
     },
-    playerCanvas: {
+    videoCanvas: {
         position: "relative",
         display: "flex",
     },
diff --git a/src/routes/player/SeekBar.tsx b/src/routes/player/SeekBar.tsx
index 315d531..8454069 100644
--- a/src/routes/player/SeekBar.tsx
+++ b/src/routes/player/SeekBar.tsx
@@ -6,17 +6,18 @@ import {useOffsetAbsolute} from "../../util/offset/useOffsetAbsolute";
 import {useOffsetRelative} from "../../util/offset/useOffsetRelative";
 import {PreviewBar} from "./PreviewBar";
 import {PlayerApi} from "./video/PlayerApi";
+import {formatDuration} from "../../util/formatDuration";
+import {useCurrentTime} from "../../util/media/useCurrentTime";
+import {useDuration} from "../../util/media/useDuration";
 
 interface Props {
     videoApi: PlayerApi | null,
     previewSrc: string | null,
     mousePosition: MousePosition | null,
     setMousePosition: (position: MousePosition | null) => void,
-    duration: number,
-    position: number,
 }
 
-export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition, duration, position}: Props) {
+export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition}: Props) {
     const classes = useStyles();
 
     const isVisible = mousePosition !== null;
@@ -25,6 +26,9 @@ export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition,
     const [seekHeadRef, setSeekHeadRef] = useState<HTMLDivElement | null>(null);
     const [playHeadRef, setPlayHeadRef] = useState<HTMLDivElement | null>(null);
 
+    const position = useCurrentTime(videoApi)
+    const duration = useDuration(videoApi);
+
     const seekHeadOffset = useOffsetAbsolute(seekBarRef, seekHeadRef, mousePosition?.absolute || 0);
     const playHeadOffset = useOffsetRelative(seekBarRef, playHeadRef, position / duration);
 
@@ -84,6 +88,9 @@ export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition,
 
     return (
         <Fragment>
+            <p style={{fontVariant: "tabular-nums"}}>
+                {formatDuration(mousePosition ? (mousePosition.relative * duration) : position)} / {formatDuration(duration)}
+            </p>
             <PreviewBar
                 previewSrc={previewSrc}
                 duration={duration}
diff --git a/src/routes/player/video/AudioSelection.tsx b/src/routes/player/video/AudioSelection.tsx
new file mode 100644
index 0000000..d70f245
--- /dev/null
+++ b/src/routes/player/video/AudioSelection.tsx
@@ -0,0 +1,30 @@
+import {PlayerApi} from "./PlayerApi";
+import {useAudioTracks} from "../../../util/media/useAudioTracks";
+
+interface Props {
+    playerApi: PlayerApi | null
+}
+
+export function AudioSelection(
+    {playerApi}: Props
+) {
+    const [audioTracks, currentTrack, setCurrentTrack] = useAudioTracks(playerApi);
+
+    return (
+        <ul>
+            {audioTracks.map(track => (
+                <li key={track.index}>
+                    <strong>{track.lang}</strong>
+                    &nbsp;{track.labels}
+                    &nbsp;
+                    <button
+                        disabled={currentTrack === track}
+                        onClick={() => setCurrentTrack(track)}
+                    >
+                        Choose
+                    </button>
+                </li>
+            ))}
+        </ul>
+    );
+}
diff --git a/src/routes/player/video/EpisodeSelection.tsx b/src/routes/player/video/EpisodeSelection.tsx
new file mode 100644
index 0000000..13bb585
--- /dev/null
+++ b/src/routes/player/video/EpisodeSelection.tsx
@@ -0,0 +1,24 @@
+import {MediaEpisode} from "../../main/MediaEpisode";
+import {Instalment} from "../../../api/models/Instalment";
+import {Content} from "../../../api/models/Content";
+
+interface Props {
+    content: Content,
+    episodes: Instalment[],
+}
+
+export function EpisodeSelection(
+    {episodes, content}: Props
+) {
+    return (
+        <ul>
+            {episodes.map(episode =>
+                <MediaEpisode
+                    key={episode.content.ids.uuid}
+                    item={episode}
+                    disabled={episode.content.ids.uuid === content.ids.uuid}
+                />
+            )}
+        </ul>
+    );
+}
diff --git a/src/routes/player/video/PlayerControls.tsx b/src/routes/player/video/PlayerControls.tsx
new file mode 100644
index 0000000..8548d3b
--- /dev/null
+++ b/src/routes/player/video/PlayerControls.tsx
@@ -0,0 +1,77 @@
+import {ChangeEvent, Fragment, useCallback, useState} from "react";
+import {PlayerApi} from "./PlayerApi";
+import {usePaused} from "../../../util/media/usePaused";
+
+interface Props {
+    playerApi: PlayerApi | null,
+}
+
+export function PlayerControls(
+    {playerApi}: Props
+) {
+    const [volume, setVolume] = useState<number>(1);
+    const paused = usePaused(playerApi);
+
+    const onPause = useCallback(() => {
+        if (playerApi) {
+            playerApi.pause()
+        }
+    }, [playerApi]);
+
+    const onPlay = useCallback(() => {
+        if (playerApi) {
+            playerApi.play()
+        }
+    }, [playerApi]);
+
+    const onFastForward = useCallback(() => {
+        if (playerApi) {
+            playerApi.setCurrentTime(playerApi.getCurrentTime() + 10)
+        }
+    }, [playerApi]);
+
+    const onRewind = useCallback(() => {
+        if (playerApi) {
+            playerApi.setCurrentTime(playerApi.getCurrentTime() - 10)
+        }
+    }, [playerApi]);
+
+    return (
+        <Fragment>
+            <button
+                onClick={onPlay}
+                disabled={!paused}
+            >
+                Play
+            </button>
+            <button
+                onClick={onPause}
+                disabled={paused}
+            >
+                Pause
+            </button>
+            <button
+                onClick={onRewind}
+            >
+                Rewind
+            </button>
+            <button
+                onClick={onFastForward}
+            >
+                Fast Forward
+            </button>
+            <p>
+                <input
+                    type="range"
+                    min="0"
+                    max="100"
+                    value={volume * 100}
+                    onChange={(event: ChangeEvent<HTMLInputElement>) => {
+                        setVolume(event.target.valueAsNumber / 100);
+                        playerApi?.setVolume(event.target.valueAsNumber / 100)
+                    }}
+                />
+            </p>
+        </Fragment>
+    );
+}
diff --git a/src/routes/player/video/SubtitleSelection.tsx b/src/routes/player/video/SubtitleSelection.tsx
new file mode 100644
index 0000000..86f96a8
--- /dev/null
+++ b/src/routes/player/video/SubtitleSelection.tsx
@@ -0,0 +1,30 @@
+import {Subtitle} from "../../../api/models/Subtitle";
+
+interface Props {
+    subtitles: (Subtitle | null)[],
+    subtitle: Subtitle | null,
+    setSubtitle: (subtitle: Subtitle | null) => void,
+}
+
+export function SubtitleSelection(
+    {subtitles, subtitle, setSubtitle}: Props
+) {
+    return (
+        <ul>
+            {subtitles.map(track => (
+                <li key={track?.src || "none"}>
+                    <strong>{track?.language || "none"}</strong>
+                    &nbsp;{track?.specifier}
+                    &nbsp;{track?.format}
+                    &nbsp;
+                    <button
+                        disabled={subtitle === track}
+                        onClick={() => setSubtitle(track)}
+                    >
+                        Choose
+                    </button>
+                </li>
+            ))}
+        </ul>
+    );
+}
-- 
GitLab