Skip to content
Snippets Groups Projects
Verified Commit b1decb21 authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Improve duration display and positioning

parent 16d9329f
No related branches found
No related tags found
No related merge requests found
...@@ -3,6 +3,7 @@ import {createUseStyles} from "react-jss"; ...@@ -3,6 +3,7 @@ import {createUseStyles} from "react-jss";
import {TitleMeta} from "../../api/models/dto/TitleMeta"; import {TitleMeta} from "../../api/models/dto/TitleMeta";
import {Media} from "../../api/models/Media"; import {Media} from "../../api/models/Media";
import {getLocalizedDescription, getLocalizedName, getLocalizedRating} from "../../api/models/Title"; import {getLocalizedDescription, getLocalizedName, getLocalizedRating} from "../../api/models/Title";
import {formatDuration} from "../../util/formatDuration";
import {useLocale} from "../../util/locale/LocalizedContext"; import {useLocale} from "../../util/locale/LocalizedContext";
import {useDuration} from "../../util/media/useDuration"; import {useDuration} from "../../util/media/useDuration";
import {usePosition} from "../../util/media/usePosition"; import {usePosition} from "../../util/media/usePosition";
...@@ -42,11 +43,12 @@ export function Player(props: Props) { ...@@ -42,11 +43,12 @@ export function Player(props: Props) {
<div> <div>
<p>{name?.name}</p> <p>{name?.name}</p>
{video} {video}
<p>{position}:{duration}</p> <p style={{fontVariant: "tabular-nums"}}>{formatDuration(position)} / {formatDuration(duration)}</p>
<SeekBar <SeekBar
video={videoElement} video={videoElement}
previewTrack={previewTrackElement} previewTrack={previewTrackElement}
duration={duration} duration={duration}
position={position}
/> />
</div> </div>
); );
......
import React, {useMemo, useRef, useState} from "react"; import React, {MouseEvent, useCallback, useMemo, useRef, useState} from "react";
import {createUseStyles} from "react-jss"; import {createUseStyles} from "react-jss";
import {PreviewViewer} from "./PreviewViewer"; import {PreviewViewer} from "./PreviewViewer";
...@@ -6,6 +6,7 @@ interface Props { ...@@ -6,6 +6,7 @@ interface Props {
previewTrack: HTMLTrackElement | null, previewTrack: HTMLTrackElement | null,
video: HTMLVideoElement | null, video: HTMLVideoElement | null,
duration: number, duration: number,
position: number,
} }
interface MousePosition { interface MousePosition {
...@@ -13,7 +14,7 @@ interface MousePosition { ...@@ -13,7 +14,7 @@ interface MousePosition {
relative: number relative: number
} }
function getMousePosition(event: React.MouseEvent<HTMLDivElement>): MousePosition | null { function getMousePosition(event: MouseEvent<HTMLDivElement>): MousePosition | null {
const position = event.clientX - event.currentTarget.offsetLeft; const position = event.clientX - event.currentTarget.offsetLeft;
const width = event.currentTarget.offsetWidth; const width = event.currentTarget.offsetWidth;
if (position > width) return null; if (position > width) return null;
...@@ -23,18 +24,18 @@ function getMousePosition(event: React.MouseEvent<HTMLDivElement>): MousePositio ...@@ -23,18 +24,18 @@ function getMousePosition(event: React.MouseEvent<HTMLDivElement>): MousePositio
}; };
} }
export function SeekBar({video, previewTrack, duration}: Props) { export function SeekBar({video, previewTrack, duration, position}: Props) {
const classes = useStyles(); const classes = useStyles();
const seekHeadRef = useRef<HTMLDivElement | null>(null); const seekHeadRef = useRef<HTMLDivElement | null>(null);
const [seekPosition, setSeekPosition] = useState<number | null>(null); const [seekPosition, setSeekPosition] = useState<number | null>(null);
const isVisible = seekPosition !== null; const isVisible = seekPosition !== null;
const seekBar = useMemo(() => ( const onMouseLeave = useCallback(() => {
<div setSeekPosition(null)
className={classes.seekBar} }, [setSeekPosition]);
onMouseLeave={() => setSeekPosition(null)}
onClick={(event) => { const onClick = useCallback((event: MouseEvent<HTMLDivElement>) => {
const position = getMousePosition(event); const position = getMousePosition(event);
if (position === null) { if (position === null) {
return; return;
...@@ -42,8 +43,9 @@ export function SeekBar({video, previewTrack, duration}: Props) { ...@@ -42,8 +43,9 @@ export function SeekBar({video, previewTrack, duration}: Props) {
if (video) { if (video) {
video.currentTime = position.relative * duration; video.currentTime = position.relative * duration;
} }
}} }, [duration, video]);
onMouseMove={(event) => {
const onMouseMove = useCallback((event: MouseEvent<HTMLDivElement>) => {
const position = getMousePosition(event); const position = getMousePosition(event);
if (position === null) { if (position === null) {
return; return;
...@@ -54,7 +56,14 @@ export function SeekBar({video, previewTrack, duration}: Props) { ...@@ -54,7 +56,14 @@ export function SeekBar({video, previewTrack, duration}: Props) {
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
setSeekPosition(position.relative * duration) setSeekPosition(position.relative * duration)
}) })
}} }, [duration]);
const seekBar = useMemo(() => (
<div
className={classes.seekBar}
onMouseLeave={onMouseLeave}
onClick={onClick}
onMouseMove={onMouseMove}
> >
<div <div
className={classes.seekHead} className={classes.seekHead}
...@@ -64,7 +73,7 @@ export function SeekBar({video, previewTrack, duration}: Props) { ...@@ -64,7 +73,7 @@ export function SeekBar({video, previewTrack, duration}: Props) {
}} }}
/> />
</div> </div>
), [classes.seekBar, classes.seekHead, duration, isVisible, video]); ), [classes.seekBar, classes.seekHead, isVisible, onClick, onMouseLeave, onMouseMove]);
return ( return (
<div> <div>
......
export function formatDuration(duration: number): string {
const seconds = Math.round(duration) % 60;
const minutes = Math.floor(duration / 60) % 60;
const hours = Math.floor(duration / 3600);
if (hours === 0) {
return `${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
} else {
return `${hours}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment