Skip to content

Commit

Permalink
chore: add multi-engine react demo app
Browse files Browse the repository at this point in the history
  • Loading branch information
martinstark committed Sep 16, 2024
1 parent dd0dcc3 commit ec88eb0
Show file tree
Hide file tree
Showing 81 changed files with 1,419 additions and 225 deletions.
Binary file not shown.
17 changes: 17 additions & 0 deletions .swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"jsc": {
"target": "esnext",
"parser": {
"syntax": "typescript",
"jsx": true
},
"transform": {
"react": {
"runtime": "automatic"
}
},
"experimental": {
"plugins": [["@swc/plugin-emotion", {}]]
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
16 changes: 12 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,26 @@
"prepublishOnly": "yarn build"
},
"devDependencies": {
"@emotion/react": "11.13.3",
"@emotion/styled": "11.13.0",
"@semantic-release/changelog": "6.0.3",
"@semantic-release/git": "10.0.1",
"@snowpack/plugin-typescript": "1.2.1",
"@swc/core": "1.6.13",
"@types/node": "20.14.10",
"@swc/core": "1.7.26",
"@swc/plugin-emotion": "4.0.1",
"@types/react": "18.3.5",
"@types/react-dom": "18.3.0",
"@types/webpack": "5.28.5",
"hls.js": "1.5.15",
"prettier": "3.3.2",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-hook-form": "7.53.0",
"semantic-release": "24",
"shaka-player": "4.11.2",
"swc-loader": "0.2.6",
"terser-webpack-plugin": "5.3.10",
"ts-node": "10.9.2",
"typescript": "5.5.3",
"typescript": "5.6.2",
"webpack": "5.93.0",
"webpack-bundle-analyzer": "4.10.2",
"webpack-cli": "5.1.4",
Expand Down
134 changes: 5 additions & 129 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,140 +78,16 @@
</style>
</head>
<body>
<div class="wrapper">
<div class="box">
<video preload="metadata" playsinline controls id="videoEl"></video>
<div class="box-2">
<button id="switch">Update src</button>
<button id="clear">Clear src</button>
<button id="load">Load</button>
</div>
</div>
<p>Check console for additional logging.</p>
<div class="box">
<div id="events"></div>
</div>
</div>
<div id="reactRoot"></div>

<script type="module">
import {
getMediaEventFilter,
FilteredMediaEvent,
MediaEvent,
Demo,
} from "./main.mjs";
const rootEl = document.getElementById("reactRoot");

const videos = [
"https://testcontent.eyevinn.technology/mp4/VINN.mp4",
"https://testcontent.eyevinn.technology/mp4/stswe-tvplus-promo.mp4",
];

const mediaElement = document.getElementById("videoEl");
let i = 1;
let seekOrBufferTimestamp = 0;

mediaElement.src = videos[0];

Object.values(MediaEvent).forEach((evt) =>
mediaElement.addEventListener(evt, () => {
const mediaElementState = {
networkState: mediaElement.networkState,
readyState: mediaElement.readyState,
paused: mediaElement.paused,
ended: mediaElement.ended,
error: mediaElement.error,
currentTime: mediaElement.currentTime,
duration: mediaElement.duration,
seeking: mediaElement.seeking,
};

console[evt === MediaEvent.timeupdate ? "debug" : "log"](
"%cNativeEv: %s",
"color:#cf1313;font-weight:bold;",
evt,
);

console[evt === MediaEvent.timeupdate ? "debug" : "info"](
"Media Element State",
mediaElementState,
);
}),
);

getMediaEventFilter({
mediaElement,
callback: (evt) => {
if (evt === FilteredMediaEvent.TIME_UPDATE) {
console.debug(
"%cFiltered: %s",
"color:#267dff;font-weight:bold;",
evt,
);
return;
}

if (
[FilteredMediaEvent.BUFFERING, FilteredMediaEvent.SEEKING].includes(
evt,
)
) {
seekOrBufferTimestamp = Date.now();
}

if (
[FilteredMediaEvent.BUFFERED, FilteredMediaEvent.SEEKED].includes(evt)
) {
console.log(
"%cFiltered: %s",
"color:#267dff;font-weight:bold;",
`${evt} (${(Date.now() - seekOrBufferTimestamp) / 1000}s)`,
);
console.info("\n");
} else {
console.log("%cFiltered: %s", "color:#267dff;font-weight:bold;", evt);
console.info("\n");
}

const box = document.createElement("div");

box.classList.add("event");
box.innerText =
i +
": " +
`${evt} ${
seekOrBufferTimestamp &&
[FilteredMediaEvent.BUFFERED, FilteredMediaEvent.SEEKED].includes(
evt,
)
? `(${(Date.now() - seekOrBufferTimestamp) / 1000}s)`
: ""
}`;

i++;

const events = document.getElementById("events");

events.prepend(box);

if (events.childElementCount > 20) {
events.removeChild(events.lastChild);
}
},
Demo({
rootEl
});

const switchButton = document.getElementById("switch");
const clearButton = document.getElementById("clear");
const loadButton = document.getElementById("load");

switchButton.onclick = () => {
mediaElement.src = mediaElement.src !== videos[0] ? videos[0] : videos[1];
};

clearButton.onclick = () => {
mediaElement.src = "";
};

loadButton.onclick = () => {
mediaElement.load();
};
</script>
</body>
79 changes: 79 additions & 0 deletions src/demo/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import styled from "@emotion/styled";
import { Global } from "@emotion/react";
import { resetStyles, defaultStyles } from "./css-global";
import { useForm, useWatch } from "react-hook-form";
import {
DecorativeLabel,
FormContainer,
FormLabel,
FormSelect,
} from "./form-elements";
import { Player } from "./player";

const Select = styled.select``;
const Option = styled.option``;

type FormValues = {
engine: "shaka" | "hlsjs" | "native";
asset: string;
};

export const App = () => {
const { register, control } = useForm<FormValues>({
defaultValues: {
engine: "native",
asset: "",
},
resetOptions: {
keepDirtyValues: true, // user-interacted input will be retained
keepErrors: true, // input errors will be retained with value update
},
});

const { engine, asset } = useWatch<FormValues>({ control });

return (
<>
<Global
styles={`
${resetStyles}
${defaultStyles}
`}
/>
<FormContainer>
<FormLabel>
<DecorativeLabel>Engine</DecorativeLabel>
<FormSelect
// eslint-disable-next-line
{...register(`engine`)}
>
{["shaka", "hlsjs", "native"].map((engine) => (
<option key={engine} value={engine}>
{engine}
</option>
))}
</FormSelect>
</FormLabel>
<FormLabel>
<DecorativeLabel>Asset</DecorativeLabel>
<FormSelect
// eslint-disable-next-line
{...register(`asset`)}
>
{["1", "2", "3"].map((engine) => (
<option key={engine} value={engine}>
{engine}
</option>
))}
</FormSelect>
</FormLabel>
</FormContainer>

<div>
Selected engine: {engine} {asset}
</div>

<Player />
</>
);
};
28 changes: 28 additions & 0 deletions src/demo/controls.hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { RefObject, useCallback } from "react";

export const useControls = ({
playing,
videoRef,
}: {
playing: boolean;
videoRef: RefObject<HTMLVideoElement>;
}) => {
const playPause = useCallback(() => {
if (playing) videoRef.current?.pause();
if (!playing) videoRef.current?.play().catch(console.error);
}, [videoRef.current, playing]);

const skip = useCallback(
(num: number) => {
if (!videoRef.current) return;

videoRef.current.currentTime = videoRef.current.currentTime + num;
},
[videoRef.current, playing],
);

return {
playPause,
skip,
};
};
Loading

0 comments on commit ec88eb0

Please sign in to comment.