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

Fix errors, improve seeking

parent 386a39a5
Branches
No related tags found
No related merge requests found
import React, {useMemo} from "react"; import React, {useMemo} from "react";
import {useImage} from "../../util/media/useImage";
import {useTextTrackCues} from "../../util/media/useTextTrackCues"; import {useTextTrackCues} from "../../util/media/useTextTrackCues";
import {parseImageSprite} from "../../util/sprite/parseImageSprite"; import {parseImageSprite} from "../../util/sprite/parseImageSprite";
import {useImage} from "../../util/media/useImage";
import {useImageSprite} from "../../util/sprite/useImageSprite"; import {useImageSprite} from "../../util/sprite/useImageSprite";
interface Props { interface Props {
...@@ -14,10 +14,9 @@ export function PreviewViewer({previewTrack, position}: Props) { ...@@ -14,10 +14,9 @@ export function PreviewViewer({previewTrack, position}: Props) {
const activeCue = cues.find(it => it.startTime <= position && it.endTime >= position) const activeCue = cues.find(it => it.startTime <= position && it.endTime >= position)
const activeUrl = activeCue ? new URL(activeCue.text, previewTrack.src).toString() : null; const activeUrl = activeCue ? new URL(activeCue.text, previewTrack.src).toString() : null;
const imageSprite = useMemo(() => parseImageSprite(activeUrl), [activeUrl]); const imageSprite = useMemo(() => parseImageSprite(activeUrl), [activeUrl]);
console.log("active", activeUrl, imageSprite);
const image = useImage(imageSprite?.src || null); const image = useImage(imageSprite?.src || null);
const sprite = useImageSprite(imageSprite, image); const sprite = useImageSprite(imageSprite, image);
return useMemo(() => ( return useMemo(() => (
<img src={sprite || undefined}/> <img alt="" src={sprite || undefined}/>
), [sprite]); ), [sprite]);
} }
...@@ -13,9 +13,10 @@ interface MousePosition { ...@@ -13,9 +13,10 @@ interface MousePosition {
relative: number relative: number
} }
function getMousePosition(event: React.MouseEvent<HTMLDivElement>): MousePosition { function getMousePosition(event: React.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;
return { return {
absolute: position, absolute: position,
relative: position / width relative: position / width
...@@ -35,12 +36,18 @@ export function SeekBar({video, previewTrack, duration}: Props) { ...@@ -35,12 +36,18 @@ export function SeekBar({video, previewTrack, duration}: Props) {
onMouseLeave={() => setSeekPosition(null)} onMouseLeave={() => setSeekPosition(null)}
onClick={(event) => { onClick={(event) => {
const position = getMousePosition(event); const position = getMousePosition(event);
if (position === null) {
return;
}
if (video) { if (video) {
video.currentTime = position.relative * duration; video.currentTime = position.relative * duration;
} }
}} }}
onMouseMove={(event) => { onMouseMove={(event) => {
const position = getMousePosition(event); const position = getMousePosition(event);
if (position === null) {
return;
}
if (seekHeadRef.current) { if (seekHeadRef.current) {
seekHeadRef.current.style.transform = `translate3d(${position.absolute}px, 0, 0)` seekHeadRef.current.style.transform = `translate3d(${position.absolute}px, 0, 0)`
} }
...@@ -57,7 +64,7 @@ export function SeekBar({video, previewTrack, duration}: Props) { ...@@ -57,7 +64,7 @@ export function SeekBar({video, previewTrack, duration}: Props) {
}} }}
/> />
</div> </div>
), [classes.seekBar, classes.seekHead, duration, isVisible]); ), [classes.seekBar, classes.seekHead, duration, isVisible, video]);
return ( return (
<div> <div>
...@@ -80,7 +87,7 @@ const useStyles = createUseStyles({ ...@@ -80,7 +87,7 @@ const useStyles = createUseStyles({
position: "absolute", position: "absolute",
top: 0, top: 0,
bottom: 0, bottom: 0,
left: 0, left: "-0.05rem",
width: "0.1rem", width: "0.1rem",
background: "#f00", background: "#f00",
} }
......
import {useEffect, useRef, useState} from "react"; import {useEffect, useMemo, useState} from "react";
export const useImage = (url: string | null): HTMLImageElement | null => { export const useImage = (url: string | null): HTMLImageElement | null => {
const image = useRef(new Image())
image.current.setAttribute("crossorigin", "anonymous");
const [imageData, setImageData] = useState<HTMLImageElement | null>(null); const [imageData, setImageData] = useState<HTMLImageElement | null>(null);
useEffect(() => { const image = useMemo(() => {
try { if (url === null) {
image.current.src = url || ""; return null;
image.current.decode().then(() => { } else {
setImageData(image.current); const image = new Image();
}) image.setAttribute("crossorigin", "anonymous");
} catch (_) { image.src = url;
return image;
} }
}, [url]); }, [url]);
useEffect(() => {
let isCancelled = false;
image?.decode().then(() => {
if (!isCancelled) {
setImageData(image);
}
}).catch(err => {
console.error("Error while decoding image " + url + ": ", err);
});
return () => {
isCancelled = true;
}
}, [image, url]);
return imageData; return imageData;
} }
...@@ -9,9 +9,9 @@ export const usePosition = (video: HTMLVideoElement | null) => { ...@@ -9,9 +9,9 @@ export const usePosition = (video: HTMLVideoElement | null) => {
setPosition(video.currentTime); setPosition(video.currentTime);
}) })
}; };
video.addEventListener("progress", listener) video.addEventListener("timeupdate", listener)
return () => { return () => {
video.removeEventListener("progress", listener) video.removeEventListener("timeupdate", listener)
} }
} }
}, [video]); }, [video]);
......
...@@ -7,14 +7,18 @@ export const useTextTrackCues = (track: HTMLTrackElement) => { ...@@ -7,14 +7,18 @@ export const useTextTrackCues = (track: HTMLTrackElement) => {
if (track.readyState >= 1) { if (track.readyState >= 1) {
setCues(Array.from(track.track.cues || [])) setCues(Array.from(track.track.cues || []))
} else { } else {
let animationFrame: number | null = null;
const listener = () => { const listener = () => {
window.requestAnimationFrame(() => { animationFrame = window.requestAnimationFrame(() => {
setCues(Array.from(track.track.cues || [])) setCues(Array.from(track.track.cues || []))
}) })
}; };
track.addEventListener("load", listener) track.addEventListener("load", listener)
return () => { return () => {
track.removeEventListener("load", listener) track.removeEventListener("load", listener);
if (animationFrame) {
window.cancelAnimationFrame(animationFrame);
}
} }
} }
}, [track]); }, [track]);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment