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

Cleanup and adding preload

parent 939f5dec
Branches
No related tags found
No related merge requests found
...@@ -11415,6 +11415,11 @@ ...@@ -11415,6 +11415,11 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
}, },
"resize-observer-polyfill": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
},
"resolve": { "resolve": {
"version": "1.15.0", "version": "1.15.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz",
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-scripts": "3.4.3", "react-scripts": "3.4.3",
"react-sweet-state": "^2.3.1", "react-sweet-state": "^2.3.1",
"resize-observer-polyfill": "^1.5.1",
"typescript": "^3.7.5" "typescript": "^3.7.5"
}, },
"scripts": { "scripts": {
......
...@@ -7,9 +7,10 @@ interface Props { ...@@ -7,9 +7,10 @@ interface Props {
previewTrack: HTMLTrackElement | null, previewTrack: HTMLTrackElement | null,
duration: number, duration: number,
position: number, position: number,
hidden: boolean,
} }
export function PreviewBar({previewTrack, duration, position}: Props) { export function PreviewBar({previewTrack, duration, position, hidden}: Props) {
const classes = useStyles(); const classes = useStyles();
const [previewBarRef, previewHeadRef, offset] = useOffsetRef(position); const [previewBarRef, previewHeadRef, offset] = useOffsetRef(position);
...@@ -23,7 +24,8 @@ export function PreviewBar({previewTrack, duration, position}: Props) { ...@@ -23,7 +24,8 @@ export function PreviewBar({previewTrack, duration, position}: Props) {
ref={previewHeadRef} ref={previewHeadRef}
className={classes.previewHead} className={classes.previewHead}
style={{ style={{
transform: `translate3d(${offset}px, 0, 0)` transform: `translate3d(${offset}px, 0, 0)`,
opacity: hidden ? 0 : 1,
}} }}
> >
<PreviewViewer <PreviewViewer
...@@ -32,22 +34,21 @@ export function PreviewBar({previewTrack, duration, position}: Props) { ...@@ -32,22 +34,21 @@ export function PreviewBar({previewTrack, duration, position}: Props) {
/> />
</div> </div>
</div> </div>
), [classes.previewHead, classes.previewBar, duration, offset, position, previewBarRef, previewHeadRef, previewTrack]); ), [previewBarRef, classes.previewBar, classes.previewHead, previewHeadRef, offset, hidden, previewTrack, position, duration]);
} }
const useStyles = createUseStyles({ const useStyles = createUseStyles({
previewBar: { previewBar: {
position: "relative", position: "relative",
width: "40rem", width: "40rem",
height: "6rem", display: "flex",
flexDirection: "row",
alignContent: "stretch",
background: "#7c7", background: "#7c7",
}, },
previewHead: { previewHead: {
position: "absolute", maxWidth: "136rem",
top: 0, maxHeight: "9rem",
bottom: 0,
left: "-5rem",
width: "10rem",
display: "flex", display: "flex",
flexDirection: "column-reverse", flexDirection: "column-reverse",
background: "#f00", background: "#f00",
......
import React, {useMemo} from "react"; import React, {useMemo} from "react";
import {createUseStyles} from "react-jss"; import {createUseStyles} from "react-jss";
import {HeadPortal} from "../../util/head/HeadPortal";
import {useImage} from "../../util/media/useImage"; 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";
...@@ -19,9 +20,21 @@ export function PreviewViewer({previewTrack, position}: Props) { ...@@ -19,9 +20,21 @@ export function PreviewViewer({previewTrack, position}: Props) {
const imageSprite = useMemo(() => parseImageSprite(activeUrl), [activeUrl]); const imageSprite = useMemo(() => parseImageSprite(activeUrl), [activeUrl]);
const image = useImage(imageSprite?.src || null); const image = useImage(imageSprite?.src || null);
const sprite = useImageSprite(imageSprite, image); const sprite = useImageSprite(imageSprite, image);
const sources = useMemo(() => previewTrack === null ? null : Array.from(new Set(cues.map(it => {
const url = new URL(it.text, previewTrack.src);
url.hash = "";
return url.toString();
}))), [cues, previewTrack]);
return useMemo(() => ( return useMemo(() => (
<React.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}/> <img alt="" className={classes.preview} src={sprite || undefined}/>
), [sprite]); </React.Fragment>
), [classes.preview, sources, sprite]);
} }
const useStyles = createUseStyles({ const useStyles = createUseStyles({
......
...@@ -60,11 +60,16 @@ export function SeekBar({video, previewTrack, duration, position}: Props) { ...@@ -60,11 +60,16 @@ export function SeekBar({video, previewTrack, duration, position}: Props) {
}} }}
/> />
</div> </div>
), [classes.seekBar, classes.seekHead, isVisible, offset, onClick, onMouseLeave, onMouseMove, seekBarRef, seekHeadRef]); ), [classes, isVisible, offset, onClick, onMouseLeave, onMouseMove, seekBarRef, seekHeadRef]);
return ( return (
<React.Fragment> <React.Fragment>
<PreviewBar previewTrack={previewTrack} duration={duration} position={seekPosition || 0}/> <PreviewBar
previewTrack={previewTrack}
duration={duration}
position={seekPosition || 0}
hidden={seekPosition === null}
/>
{seekBar} {seekBar}
</React.Fragment> </React.Fragment>
) )
...@@ -74,14 +79,13 @@ const useStyles = createUseStyles({ ...@@ -74,14 +79,13 @@ const useStyles = createUseStyles({
seekBar: { seekBar: {
position: "relative", position: "relative",
width: "40rem", width: "40rem",
display: "flex",
flexDirection: "row",
alignContent: "stretch",
height: "5rem", height: "5rem",
background: "#77c", background: "#77c",
}, },
seekHead: { seekHead: {
position: "absolute",
top: 0,
bottom: 0,
left: "-0.05rem",
width: "0.1rem", width: "0.1rem",
background: "#f00", background: "#f00",
} }
......
import React from "react";
import ReactDOM from "react-dom";
export function HeadPortal({children}: React.PropsWithChildren<{}>) {
return ReactDOM.createPortal(children, document.head);
}
...@@ -4,8 +4,6 @@ export const useOffset = <T extends HTMLElement, U extends HTMLElement>(parent: ...@@ -4,8 +4,6 @@ export const useOffset = <T extends HTMLElement, U extends HTMLElement>(parent:
const parentWidth = useWidth(parent); const parentWidth = useWidth(parent);
const childWidth = useWidth(child); const childWidth = useWidth(child);
const offset = parentWidth * position; const offset = parentWidth * position - childWidth / 2;
const minOffset = childWidth / 2; return Math.max(0, Math.min(offset, parentWidth - childWidth));
const maxOffset = parentWidth - minOffset;
return Math.max(minOffset, Math.min(offset, maxOffset));
} }
import {useEffect, useState} from "react"; import {useEffect, useState} from "react";
import ResizeObserver from 'resize-observer-polyfill';
export const useWidth = <T extends HTMLElement>(it: T | null) => { export const useWidth = <T extends HTMLElement>(it: T | null) => {
const [width, setWidth] = useState<number>(0); const [width, setWidth] = useState<number>(0);
useEffect(() => { useEffect(() => {
if (it !== null) {
let animationFrame: number | null = null; let animationFrame: number | null = null;
const listener = () => { const listener = () => {
};
listener();
const observer = new ResizeObserver(([element]) => {
animationFrame = window.requestAnimationFrame(() => { animationFrame = window.requestAnimationFrame(() => {
animationFrame = null; animationFrame = null;
setWidth(it?.offsetWidth || 0); setWidth(element.contentRect.width || 0);
}); });
}; })
listener(); observer.observe(it);
window.addEventListener("resize", listener);
return () => { return () => {
window.removeEventListener("resize", listener); observer.unobserve(it);
if (animationFrame !== null) { if (animationFrame !== null) {
window.cancelAnimationFrame(animationFrame); window.cancelAnimationFrame(animationFrame);
} }
} }
}
}, [it]); }, [it]);
return width; return width;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment