parent
7fa69b356f
commit
bf4a8c7de9
@ -13,7 +13,6 @@
|
|||||||
"@snort/system-wasm": "^1.0.4",
|
"@snort/system-wasm": "^1.0.4",
|
||||||
"@snort/wallet": "^0.1.7",
|
"@snort/wallet": "^0.1.7",
|
||||||
"@snort/worker-relay": "^1.1.0",
|
"@snort/worker-relay": "^1.1.0",
|
||||||
"@sqlite.org/sqlite-wasm": "^3.45.1-build1",
|
|
||||||
"@szhsin/react-menu": "^4.1.0",
|
"@szhsin/react-menu": "^4.1.0",
|
||||||
"@types/webscopeio__react-textarea-autocomplete": "^4.7.5",
|
"@types/webscopeio__react-textarea-autocomplete": "^4.7.5",
|
||||||
"@webscopeio/react-textarea-autocomplete": "^4.9.2",
|
"@webscopeio/react-textarea-autocomplete": "^4.9.2",
|
||||||
@ -22,9 +21,9 @@
|
|||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
"emoji-mart": "^5.6.0",
|
"emoji-mart": "^5.6.0",
|
||||||
"flag-icons": "^7.2.1",
|
"flag-icons": "^7.2.1",
|
||||||
"hls.js": "^1.5.8",
|
"hls-video-element": "^1.2.7",
|
||||||
"marked": "^12.0.2",
|
"marked": "^12.0.2",
|
||||||
"media-chrome": "^3.2.2",
|
"media-chrome": "^3.2.4",
|
||||||
"qr-code-styling": "^1.6.0-rc.1",
|
"qr-code-styling": "^1.6.0-rc.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-confetti": "^6.1.0",
|
"react-confetti": "^6.1.0",
|
||||||
@ -36,8 +35,6 @@
|
|||||||
"react-intl": "^6.6.8",
|
"react-intl": "^6.6.8",
|
||||||
"react-router-dom": "^6.23.1",
|
"react-router-dom": "^6.23.1",
|
||||||
"react-tag-input-component": "^2.0.2",
|
"react-tag-input-component": "^2.0.2",
|
||||||
"react-use-gesture": "^9.1.3",
|
|
||||||
"react-use-pip": "^1.5.0",
|
|
||||||
"recharts": "^2.12.7",
|
"recharts": "^2.12.7",
|
||||||
"usehooks-ts": "^3.1.0",
|
"usehooks-ts": "^3.1.0",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
|
@ -1,287 +1,64 @@
|
|||||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||||
import Hls from "hls.js";
|
import { CSSProperties, HTMLProps } from "react";
|
||||||
import { HTMLProps, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
||||||
import { FormattedMessage } from "react-intl";
|
|
||||||
import { Icon } from "../icon";
|
|
||||||
import { ProgressBar } from "../progress-bar";
|
|
||||||
import { Menu, MenuItem } from "@szhsin/react-menu";
|
|
||||||
import { StreamState } from "@/const";
|
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import usePictureInPicture, { VideoRefType } from "react-use-pip";
|
import {
|
||||||
|
MediaControlBar,
|
||||||
export enum VideoStatus {
|
MediaController,
|
||||||
Online = "online",
|
MediaFullscreenButton,
|
||||||
Offline = "offline",
|
MediaMuteButton,
|
||||||
}
|
MediaPipButton,
|
||||||
|
MediaPlayButton,
|
||||||
|
MediaTimeRange,
|
||||||
|
MediaVolumeRange,
|
||||||
|
MediaCastButton,
|
||||||
|
MediaLiveButton,
|
||||||
|
MediaRenditionMenu,
|
||||||
|
MediaRenditionMenuButton,
|
||||||
|
MediaPosterImage,
|
||||||
|
MediaTimeDisplay,
|
||||||
|
MediaPlaybackRateButton,
|
||||||
|
} from "media-chrome/react";
|
||||||
|
import "hls-video-element";
|
||||||
|
import { StreamState } from "@/const";
|
||||||
|
|
||||||
type VideoPlayerProps = {
|
type VideoPlayerProps = {
|
||||||
title?: string;
|
title?: string;
|
||||||
stream?: string;
|
|
||||||
status?: StreamState;
|
status?: StreamState;
|
||||||
|
stream?: string;
|
||||||
poster?: string;
|
poster?: string;
|
||||||
muted?: boolean;
|
muted?: boolean;
|
||||||
} & HTMLProps<HTMLVideoElement>;
|
} & HTMLProps<HTMLVideoElement>;
|
||||||
|
|
||||||
export default function LiveVideoPlayer({
|
export default function LiveVideoPlayer({ title, stream, status, poster, ...props }: VideoPlayerProps) {
|
||||||
title,
|
|
||||||
stream,
|
|
||||||
status: pStatus,
|
|
||||||
poster,
|
|
||||||
muted: pMuted,
|
|
||||||
...props
|
|
||||||
}: VideoPlayerProps) {
|
|
||||||
const video = useRef<HTMLVideoElement>(null);
|
|
||||||
const hlsObj = useRef<Hls>(null);
|
|
||||||
const streamCached = useMemo(() => stream, [stream]);
|
|
||||||
const [status, setStatus] = useState<VideoStatus>();
|
|
||||||
const [src, setSrc] = useState<string>();
|
|
||||||
const [levels, setLevels] = useState<Array<{ level: number; height: number }>>();
|
|
||||||
const [level, setLevel] = useState<number>(-1);
|
|
||||||
const [playState, iSetPlayState] = useState<"loading" | "playing" | "paused">("paused");
|
|
||||||
const [volume, setVolume] = useState(1);
|
|
||||||
const [muted, setMuted] = useState(pMuted ?? false);
|
|
||||||
const [position, setPosition] = useState<number>();
|
|
||||||
const [maxPosition, setMaxPosition] = useState<number>();
|
|
||||||
|
|
||||||
function setPlayState(s: typeof playState) {
|
|
||||||
console.debug("PLAY STATE", s);
|
|
||||||
iSetPlayState(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (streamCached && video.current) {
|
|
||||||
if (Hls.isSupported() && streamCached.endsWith(".m3u8")) {
|
|
||||||
try {
|
|
||||||
const hls = new Hls({
|
|
||||||
enableWorker: true,
|
|
||||||
lowLatencyMode: true,
|
|
||||||
backBufferLength: 90,
|
|
||||||
});
|
|
||||||
hls.loadSource(streamCached);
|
|
||||||
hls.attachMedia(video.current);
|
|
||||||
hls.on(Hls.Events.ERROR, (event, data) => {
|
|
||||||
console.debug(event, data);
|
|
||||||
const errorType = data.type;
|
|
||||||
if (errorType === Hls.ErrorTypes.NETWORK_ERROR && data.fatal) {
|
|
||||||
hls.stopLoad();
|
|
||||||
hls.detachMedia();
|
|
||||||
setStatus(VideoStatus.Offline);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
|
||||||
setStatus(VideoStatus.Online);
|
|
||||||
setLevels([
|
|
||||||
{
|
|
||||||
level: -1,
|
|
||||||
height: 0,
|
|
||||||
},
|
|
||||||
...hls.levels.map((a, i) => ({
|
|
||||||
level: i,
|
|
||||||
height: a.height,
|
|
||||||
})),
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
hls.on(Hls.Events.LEVEL_SWITCHING, (_, l) => {
|
|
||||||
console.debug("HLS Level Switch", l);
|
|
||||||
setMaxPosition(l.details?.totalduration);
|
|
||||||
});
|
|
||||||
// @ts-ignore Can write anyway
|
|
||||||
hlsObj.current = hls;
|
|
||||||
return () => {
|
|
||||||
// @ts-ignore Can write anyway
|
|
||||||
hlsObj.current = null;
|
|
||||||
hls.destroy();
|
|
||||||
};
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
setStatus(VideoStatus.Offline);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setSrc(streamCached);
|
|
||||||
setStatus(VideoStatus.Online);
|
|
||||||
video.current.muted = true;
|
|
||||||
video.current.load();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [video, streamCached, pStatus]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (hlsObj.current) {
|
|
||||||
hlsObj.current.nextLevel = level;
|
|
||||||
}
|
|
||||||
}, [hlsObj, level]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (video.current) {
|
|
||||||
video.current.onplaying = () => setPlayState("playing");
|
|
||||||
video.current.onpause = () => setPlayState("paused");
|
|
||||||
video.current.onseeking = () => {
|
|
||||||
if (video.current?.paused) {
|
|
||||||
setPlayState("paused");
|
|
||||||
} else {
|
|
||||||
setPlayState("loading");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
video.current.onplay = () => setPlayState("loading");
|
|
||||||
video.current.onvolumechange = () => setVolume(video.current?.volume ?? 1);
|
|
||||||
video.current.ontimeupdate = () => setPosition(video.current?.currentTime);
|
|
||||||
}
|
|
||||||
}, [video.current]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (video.current) {
|
|
||||||
if (video.current.volume !== volume) {
|
|
||||||
video.current.volume = volume;
|
|
||||||
}
|
|
||||||
if (video.current.muted !== muted) {
|
|
||||||
video.current.muted = muted;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [video, volume, muted]);
|
|
||||||
|
|
||||||
const { isPictureInPictureActive, isPictureInPictureAvailable, togglePictureInPicture } = usePictureInPicture(
|
|
||||||
video as VideoRefType,
|
|
||||||
);
|
|
||||||
|
|
||||||
const handlePIPClick = useCallback(async () => {
|
|
||||||
togglePictureInPicture(!isPictureInPictureActive);
|
|
||||||
}, [isPictureInPictureActive, togglePictureInPicture]);
|
|
||||||
|
|
||||||
function playStateToIcon() {
|
|
||||||
switch (playState) {
|
|
||||||
case "playing":
|
|
||||||
return "pause";
|
|
||||||
case "paused":
|
|
||||||
return "play";
|
|
||||||
case "loading":
|
|
||||||
return "loading";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function togglePlay() {
|
|
||||||
if (video.current) {
|
|
||||||
if (playState === "playing") {
|
|
||||||
video.current.pause();
|
|
||||||
} else if (playState === "paused") {
|
|
||||||
video.current.play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleMute() {
|
|
||||||
setMuted(s => !s);
|
|
||||||
}
|
|
||||||
|
|
||||||
function levelName(l: number) {
|
|
||||||
if (l === -1) {
|
|
||||||
return <FormattedMessage defaultMessage="AUTO" id="o8pHw3" />;
|
|
||||||
} else {
|
|
||||||
const h = levels?.find(a => a.level === l)?.height;
|
|
||||||
return <FormattedMessage defaultMessage="{n}p" id="YagVIe" values={{ n: h }} />;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function playerOverlay() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{status === VideoStatus.Online && (
|
|
||||||
<div
|
|
||||||
className="absolute opacity-0 hover:opacity-90 transition-opacity w-full h-full z-20 bg-[#00000055] select-none"
|
|
||||||
onClick={() => togglePlay()}>
|
|
||||||
{/* TITLE */}
|
|
||||||
<div className="absolute top-2 w-full text-center">
|
|
||||||
<h2>{title}</h2>
|
|
||||||
</div>
|
|
||||||
{/* CENTER PLAY ICON */}
|
|
||||||
<div className="absolute w-full h-full flex items-center justify-center cursor-pointer">
|
|
||||||
{!isPictureInPictureActive && (
|
|
||||||
<Icon name={playStateToIcon()} size={80} className={playState === "loading" ? "animate-spin" : ""} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{/* PLAYER CONTROLS OVERLAY */}
|
|
||||||
<div
|
|
||||||
className="absolute flex items-center gap-1 bottom-0 w-full bg-primary h-[40px]"
|
|
||||||
onClick={e => e.stopPropagation()}>
|
|
||||||
<div className="flex grow gap-1 items-center">
|
|
||||||
<div className="px-5 py-2 cursor-pointer" onClick={() => togglePlay()}>
|
|
||||||
<Icon name={playStateToIcon()} className={playState === "loading" ? "animate-spin" : ""} />
|
|
||||||
</div>
|
|
||||||
<div className="px-3 py-2 uppercase font-bold tracking-wide hover:bg-primary-hover">{pStatus}</div>
|
|
||||||
{pStatus === StreamState.Ended && maxPosition !== undefined && position !== undefined && (
|
|
||||||
<ProgressBar
|
|
||||||
value={position / maxPosition}
|
|
||||||
setValue={v => {
|
|
||||||
const ct = maxPosition * v;
|
|
||||||
if (video.current) {
|
|
||||||
video.current.currentTime = ct;
|
|
||||||
}
|
|
||||||
setPosition(ct);
|
|
||||||
}}
|
|
||||||
marker={<div className="w-[16px] h-[16px] mt-[-8px] rounded-full bg-white"></div>}
|
|
||||||
style={{ width: "100%", height: "4px" }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-1 items-center h-full py-2 max-sm:hidden">
|
|
||||||
<Icon name={muted ? "volume-muted" : "volume"} onClick={toggleMute} />
|
|
||||||
<ProgressBar value={volume} setValue={v => setVolume(v)} style={{ width: "100px", height: "100%" }} />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Menu
|
|
||||||
direction="top"
|
|
||||||
align="center"
|
|
||||||
menuButton={<div className="px-3 py-2 tracking-wide cursor-pointer">{levelName(level)}</div>}
|
|
||||||
menuClassName="bg-primary w-fit">
|
|
||||||
{levels?.map(v => (
|
|
||||||
<MenuItem
|
|
||||||
value={v.level}
|
|
||||||
key={v.level}
|
|
||||||
onClick={() => setLevel(v.level)}
|
|
||||||
className="bg-primary px-3 py-2 text-white">
|
|
||||||
{levelName(v.level)}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Menu>
|
|
||||||
</div>
|
|
||||||
{isPictureInPictureAvailable && (
|
|
||||||
<div
|
|
||||||
className="pl-3 py-2 cursor-pointer tracking-wide font-bold text-sm max-xl:hidden"
|
|
||||||
onClick={handlePIPClick}>
|
|
||||||
PIP
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div
|
|
||||||
className="px-2 py-2 cursor-pointer"
|
|
||||||
onClick={() => {
|
|
||||||
if (video.current) {
|
|
||||||
video.current.requestFullscreen();
|
|
||||||
}
|
|
||||||
}}>
|
|
||||||
<Icon name="fullscreen" size={24} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{status === VideoStatus.Offline && (
|
|
||||||
<div className="absolute w-full h-full z-20 bg-[#000000aa] flex items-center justify-center text-3xl font-bold uppercase">
|
|
||||||
<FormattedMessage defaultMessage="Offline" id="7UOvbT" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<div className="relative h-inherit">
|
<MediaController
|
||||||
{playerOverlay()}
|
className={classNames(props.className, "h-inherit aspect-video")}
|
||||||
<video
|
style={
|
||||||
{...props}
|
{
|
||||||
className={classNames(props.className, "aspect-video")}
|
"--media-secondary-color": "var(--primary)",
|
||||||
ref={video}
|
"--media-control-hover-background": "color-mix(in srgb, var(--primary) 80%, transparent)",
|
||||||
autoPlay={true}
|
} as CSSProperties
|
||||||
poster={poster}
|
}>
|
||||||
src={src}
|
<div slot="top-chrome" className="py-1 text-center w-full text-2xl bg-primary">
|
||||||
playsInline={true}
|
{title}
|
||||||
/>
|
</div>
|
||||||
</div>
|
{/* @ts-ignore Web Componenet */}
|
||||||
|
<hls-video {...props} slot="media" src={stream} playsInline={true} />
|
||||||
|
<MediaRenditionMenu hidden anchor="auto" />
|
||||||
|
{poster && <MediaPosterImage slot="poster" src={poster} />}
|
||||||
|
<MediaControlBar>
|
||||||
|
<MediaPlayButton />
|
||||||
|
{status === StreamState.Live && <MediaLiveButton />}
|
||||||
|
{status === StreamState.Ended && <MediaPlaybackRateButton />}
|
||||||
|
<MediaTimeRange />
|
||||||
|
{status === StreamState.Ended && <MediaTimeDisplay showduration={true} />}
|
||||||
|
<MediaMuteButton />
|
||||||
|
<MediaVolumeRange />
|
||||||
|
{status === StreamState.Live && <MediaRenditionMenuButton />}
|
||||||
|
<MediaPipButton />
|
||||||
|
<MediaCastButton />
|
||||||
|
<MediaFullscreenButton />
|
||||||
|
</MediaControlBar>
|
||||||
|
</MediaController>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -593,9 +593,6 @@
|
|||||||
"defaultMessage": "@ {rate}",
|
"defaultMessage": "@ {rate}",
|
||||||
"description": "Showing zap amount in USD @ rate"
|
"description": "Showing zap amount in USD @ rate"
|
||||||
},
|
},
|
||||||
"YagVIe": {
|
|
||||||
"defaultMessage": "{n}p"
|
|
||||||
},
|
|
||||||
"YjhNaf": {
|
"YjhNaf": {
|
||||||
"defaultMessage": "Create Stream"
|
"defaultMessage": "Create Stream"
|
||||||
},
|
},
|
||||||
@ -820,9 +817,6 @@
|
|||||||
"nwA8Os": {
|
"nwA8Os": {
|
||||||
"defaultMessage": "Add card"
|
"defaultMessage": "Add card"
|
||||||
},
|
},
|
||||||
"o8pHw3": {
|
|
||||||
"defaultMessage": "AUTO"
|
|
||||||
},
|
|
||||||
"oHPB8Q": {
|
"oHPB8Q": {
|
||||||
"defaultMessage": "Zap {name}"
|
"defaultMessage": "Zap {name}"
|
||||||
},
|
},
|
||||||
|
@ -195,7 +195,6 @@
|
|||||||
"Xq2sb0": "To go live, copy and paste your Server URL and Stream Key below into your streaming software settings and press 'Start Streaming'. We recommend <a>OBS</a>.",
|
"Xq2sb0": "To go live, copy and paste your Server URL and Stream Key below into your streaming software settings and press 'Start Streaming'. We recommend <a>OBS</a>.",
|
||||||
"Y0DXJb": "Recording URL",
|
"Y0DXJb": "Recording URL",
|
||||||
"YPh5Nq": "@ {rate}",
|
"YPh5Nq": "@ {rate}",
|
||||||
"YagVIe": "{n}p",
|
|
||||||
"YjhNaf": "Create Stream",
|
"YjhNaf": "Create Stream",
|
||||||
"YwzT/0": "Clip title",
|
"YwzT/0": "Clip title",
|
||||||
"YyXVHf": "Clear Draft",
|
"YyXVHf": "Clear Draft",
|
||||||
@ -270,7 +269,6 @@
|
|||||||
"nBCvvJ": "Topup",
|
"nBCvvJ": "Topup",
|
||||||
"nOaArs": "Setup Profile",
|
"nOaArs": "Setup Profile",
|
||||||
"nwA8Os": "Add card",
|
"nwA8Os": "Add card",
|
||||||
"o8pHw3": "AUTO",
|
|
||||||
"oHPB8Q": "Zap {name}",
|
"oHPB8Q": "Zap {name}",
|
||||||
"oZrFyI": "Stream type should be HLS",
|
"oZrFyI": "Stream type should be HLS",
|
||||||
"p4N05H": "Upload",
|
"p4N05H": "Upload",
|
||||||
|
75
yarn.lock
75
yarn.lock
@ -2730,15 +2730,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@sqlite.org/sqlite-wasm@npm:^3.45.1-build1":
|
|
||||||
version: 3.45.1-build1
|
|
||||||
resolution: "@sqlite.org/sqlite-wasm@npm:3.45.1-build1"
|
|
||||||
bin:
|
|
||||||
sqlite-wasm: bin/index.js
|
|
||||||
checksum: 10c0/bb774ea390a18087837408b43ab5355dda0867c92092e15591d2bdcdfbfeab90bd6d11413ff98b2d82db48bd565a8a212fe375b53fa1116e45c8dbe912cc374a
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@sqlite.org/sqlite-wasm@npm:^3.45.3-build3":
|
"@sqlite.org/sqlite-wasm@npm:^3.45.3-build3":
|
||||||
version: 3.45.3-build3
|
version: 3.45.3-build3
|
||||||
resolution: "@sqlite.org/sqlite-wasm@npm:3.45.3-build3"
|
resolution: "@sqlite.org/sqlite-wasm@npm:3.45.3-build3"
|
||||||
@ -3975,6 +3966,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"custom-media-element@npm:^1.3.2":
|
||||||
|
version: 1.3.2
|
||||||
|
resolution: "custom-media-element@npm:1.3.2"
|
||||||
|
checksum: 10c0/49b1efa65ecb3dbf2c49f66132496c50bc44fd73dcdb5529bdc601e9642eba1d02400ad18c28d640c1fe0d671cee3613ae26f50575a1c7702a14f656a69e9d10
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:^3.1.6":
|
"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:^3.1.6":
|
||||||
version: 3.2.4
|
version: 3.2.4
|
||||||
resolution: "d3-array@npm:3.2.4"
|
resolution: "d3-array@npm:3.2.4"
|
||||||
@ -5217,10 +5215,21 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"hls.js@npm:^1.5.8":
|
"hls-video-element@npm:^1.2.7":
|
||||||
version: 1.5.8
|
version: 1.2.7
|
||||||
resolution: "hls.js@npm:1.5.8"
|
resolution: "hls-video-element@npm:1.2.7"
|
||||||
checksum: 10c0/feb36dd1c7c6759d78c3b1597e681ded497eba71e883c4bc8b49232f1169cbcf7d6c3214e0a40ef824da47a4262b6ea30d181cb543d0f8912f6588ea08be68e8
|
dependencies:
|
||||||
|
custom-media-element: "npm:^1.3.2"
|
||||||
|
hls.js: "npm:^1.5.11"
|
||||||
|
media-tracks: "npm:^0.3.3"
|
||||||
|
checksum: 10c0/ed1a9839c2119d084fdd89eeb313b7733649e153638735ced985a40ecf79cd5505363982b7583277d98604d5c824e75f7b2f8f161924375905c0cce12087f8de
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"hls.js@npm:^1.5.11":
|
||||||
|
version: 1.5.13
|
||||||
|
resolution: "hls.js@npm:1.5.13"
|
||||||
|
checksum: 10c0/58f5b9dda5c0faca72059be51f88180a8cff49bf1011f50c9d6f30cdb21b44ab9f9493f18443bf6861ee68f262adb0e43bbba8dea668108816adff738e2a3f7e
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -6042,10 +6051,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"media-chrome@npm:^3.2.2":
|
"media-chrome@npm:^3.2.4":
|
||||||
version: 3.2.2
|
version: 3.2.4
|
||||||
resolution: "media-chrome@npm:3.2.2"
|
resolution: "media-chrome@npm:3.2.4"
|
||||||
checksum: 10c0/d3e36629aaf67eae12837be06a874ba1d56c5b6094c26baa8b76b4e420618564447491fd05b28e593306d2025ffd171db6598bab308255dcd69024e9b70c33b6
|
checksum: 10c0/60596bfc8661c5b99c62107774b3227966aab976dbe5ab4cc960512a7cac3dc002ad3f6e8bffa8fc6d7e44603d3dc1df91cbae080516ad781138740b13b97d51
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"media-tracks@npm:^0.3.3":
|
||||||
|
version: 0.3.3
|
||||||
|
resolution: "media-tracks@npm:0.3.3"
|
||||||
|
checksum: 10c0/ecd57e628222b6e0611f21813a291a47b30c96aa1c9d7e13546932b59e8bb206651961a36360cc5584bf76bf890ce01be3bb0c045facf76ab8b1cfacecf9808b
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -6981,24 +6997,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"react-use-gesture@npm:^9.1.3":
|
|
||||||
version: 9.1.3
|
|
||||||
resolution: "react-use-gesture@npm:9.1.3"
|
|
||||||
peerDependencies:
|
|
||||||
react: ">= 16.8.0"
|
|
||||||
checksum: 10c0/36e8991811c9bf97018cda24b84d9010143fbb8c43eec1089580ef69450f4004a60969b662b489f5416a5c45c516a5d718f20ae46b3fbf0c49f7e34320021246
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"react-use-pip@npm:^1.5.0":
|
|
||||||
version: 1.5.0
|
|
||||||
resolution: "react-use-pip@npm:1.5.0"
|
|
||||||
peerDependencies:
|
|
||||||
react: ^16.9.0 || ^17 || ^18
|
|
||||||
checksum: 10c0/448a6d176eada90cafdcc2465dd9c974ba46e80c033168b3ecef87a064dd5f2976a8758f039e8b5c3f4abf15f844ad4096a2db6b1b0465f8a76988bee28aefdc
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"react@npm:^18.2.0":
|
"react@npm:^18.2.0":
|
||||||
version: 18.2.0
|
version: 18.2.0
|
||||||
resolution: "react@npm:18.2.0"
|
resolution: "react@npm:18.2.0"
|
||||||
@ -7624,7 +7622,6 @@ __metadata:
|
|||||||
"@snort/system-wasm": "npm:^1.0.4"
|
"@snort/system-wasm": "npm:^1.0.4"
|
||||||
"@snort/wallet": "npm:^0.1.7"
|
"@snort/wallet": "npm:^0.1.7"
|
||||||
"@snort/worker-relay": "npm:^1.1.0"
|
"@snort/worker-relay": "npm:^1.1.0"
|
||||||
"@sqlite.org/sqlite-wasm": "npm:^3.45.1-build1"
|
|
||||||
"@szhsin/react-menu": "npm:^4.1.0"
|
"@szhsin/react-menu": "npm:^4.1.0"
|
||||||
"@testing-library/dom": "npm:^9.3.1"
|
"@testing-library/dom": "npm:^9.3.1"
|
||||||
"@types/node": "npm:^20.12.12"
|
"@types/node": "npm:^20.12.12"
|
||||||
@ -7646,9 +7643,9 @@ __metadata:
|
|||||||
emoji-mart: "npm:^5.6.0"
|
emoji-mart: "npm:^5.6.0"
|
||||||
eslint: "npm:^8.56.0"
|
eslint: "npm:^8.56.0"
|
||||||
flag-icons: "npm:^7.2.1"
|
flag-icons: "npm:^7.2.1"
|
||||||
hls.js: "npm:^1.5.8"
|
hls-video-element: "npm:^1.2.7"
|
||||||
marked: "npm:^12.0.2"
|
marked: "npm:^12.0.2"
|
||||||
media-chrome: "npm:^3.2.2"
|
media-chrome: "npm:^3.2.4"
|
||||||
postcss: "npm:^8.4.38"
|
postcss: "npm:^8.4.38"
|
||||||
prettier: "npm:^3.2.5"
|
prettier: "npm:^3.2.5"
|
||||||
prop-types: "npm:^15.8.1"
|
prop-types: "npm:^15.8.1"
|
||||||
@ -7663,8 +7660,6 @@ __metadata:
|
|||||||
react-intl: "npm:^6.6.8"
|
react-intl: "npm:^6.6.8"
|
||||||
react-router-dom: "npm:^6.23.1"
|
react-router-dom: "npm:^6.23.1"
|
||||||
react-tag-input-component: "npm:^2.0.2"
|
react-tag-input-component: "npm:^2.0.2"
|
||||||
react-use-gesture: "npm:^9.1.3"
|
|
||||||
react-use-pip: "npm:^1.5.0"
|
|
||||||
recharts: "npm:^2.12.7"
|
recharts: "npm:^2.12.7"
|
||||||
rollup-plugin-visualizer: "npm:^5.12.0"
|
rollup-plugin-visualizer: "npm:^5.12.0"
|
||||||
tailwindcss: "npm:^3.4.3"
|
tailwindcss: "npm:^3.4.3"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user