UNPKG

@react95/core

Version:
208 lines (207 loc) 7.13 kB
import React, { forwardRef, useState, useRef, useImperativeHandle, useEffect } from "react"; import { Mplayer113, User4 } from "@react95/icons"; import { videoTag, divider, countDownContainer, videoFont, currentTime, elapsedTime, controls, controlBtn, range } from "./Video.css.mjs"; import { Frame } from "../Frame/Frame.mjs"; import { Button } from "../Button/Button.mjs"; import { Range } from "../Range/Range.mjs"; import { TitleBar } from "../TitleBar/TitleBar.mjs"; import Play from "./buttons/Play.mjs"; import Pause from "./buttons/Pause.mjs"; import Stop from "./buttons/Stop.mjs"; import Fullscreen from "./buttons/Fullscreen.mjs"; import cn from "classnames"; const Source = ({ src }) => /* @__PURE__ */ React.createElement("source", { src, type: `video/${src.substring(src.length - 3)}` }); const PlayOrPause = ({ playing }) => playing ? /* @__PURE__ */ React.createElement(Pause, null) : /* @__PURE__ */ React.createElement(Play, null); const arrayFy = (str) => [].concat(str); function updateProgressBar(player, updateProgress) { const percentage = Math.floor(100 / player.duration * player.currentTime); updateProgress(percentage); } function parseCurrentTime(secs) { if (!secs) { return "00:00"; } const sec = parseInt(secs.toString(), 10); const hours = Math.floor(sec / 3600); const minutes = Math.floor(sec / 60) % 60; const seconds = sec % 60; return [hours, minutes, seconds].map((v) => v < 10 ? `0${v}` : v).filter((v, i) => v !== "00" || i > 0).join(":"); } const VideoRenderer = ({ name, src, videoProps, ...props }, ref) => { const [playing, setPlaying] = useState(false); const [loadeddata, setLoadeddata] = useState(false); const [progress, setProgress] = useState(0); const player = useRef(null); const progressRef = useRef(null); const wrapperRef = useRef(null); const playPauseRef = useRef(null); const stopRef = useRef(null); const fullScreenRef = useRef(null); const paths = arrayFy(src); const [pathname] = paths; const normalizedName = name || pathname.replace(/^.*[\\/]/, ""); const title = `${normalizedName}${!loadeddata ? " (Opening)" : ""}`; useImperativeHandle(ref, () => ({ get video() { return player; }, get progress() { return progressRef; }, get wrapper() { return wrapperRef; }, get playpause() { return playPauseRef; }, get stop() { return stopRef; }, get fullScreen() { return fullScreenRef; } })); useEffect(() => { var _a, _b, _c, _d; (_a = player.current) == null ? void 0 : _a.addEventListener( "ended", () => { setPlaying(false); setProgress(0); }, false ); (_b = player.current) == null ? void 0 : _b.addEventListener( "timeupdate", () => { if (player.current) { updateProgressBar(player.current, setProgress); } }, false ); (_c = player.current) == null ? void 0 : _c.addEventListener( "loadeddata", () => { setLoadeddata(true); }, false ); (_d = player.current) == null ? void 0 : _d.addEventListener( "playing", () => { setPlaying(true); }, false ); }, [player.current]); return /* @__PURE__ */ React.createElement( Frame, { ...props, padding: "$2", boxShadow: "$out", backgroundColor: "$material", ref: wrapperRef }, /* @__PURE__ */ React.createElement(TitleBar, { icon: /* @__PURE__ */ React.createElement(Mplayer113, { variant: "16x16_4" }), title }), /* @__PURE__ */ React.createElement( "video", { className: videoTag({ visible: loadeddata }), ...videoProps, ref: player }, paths.map((s) => /* @__PURE__ */ React.createElement(Source, { key: s, src: s })) ), loadeddata && /* @__PURE__ */ React.createElement("span", { className: divider }), /* @__PURE__ */ React.createElement(Frame, { maxWidth: "250px", mx: "auto", mb: "$4" }, /* @__PURE__ */ React.createElement("div", { className: countDownContainer }, /* @__PURE__ */ React.createElement(Frame, { display: "flex", flexDirection: "column", w: "40%" }, /* @__PURE__ */ React.createElement( "div", { className: videoFont, style: { marginTop: "auto" } }, player.current && parseCurrentTime(player.current.duration) ), /* @__PURE__ */ React.createElement("div", { className: videoFont, style: { height: 12 } }, !loadeddata && "Openning")), /* @__PURE__ */ React.createElement(Frame, { display: "flex", flexDirection: "column", w: "40%" }, /* @__PURE__ */ React.createElement("div", { className: cn(videoFont, currentTime) }, player.current && parseCurrentTime(player.current.currentTime)), /* @__PURE__ */ React.createElement("div", { className: cn(videoFont, elapsedTime) }, "time"))), /* @__PURE__ */ React.createElement("div", { className: controls }, /* @__PURE__ */ React.createElement( Button, { as: "button", className: controlBtn, disabled: !loadeddata, onClick: () => { var _a, _b; if (!playing) { (_a = player.current) == null ? void 0 : _a.play(); } else { (_b = player.current) == null ? void 0 : _b.pause(); } setPlaying(!playing); }, ref: playPauseRef }, loadeddata ? /* @__PURE__ */ React.createElement(PlayOrPause, { playing }) : /* @__PURE__ */ React.createElement( User4, { style: { borderRight: "none", borderBottom: "none" }, variant: "32x32_4" } ) ), /* @__PURE__ */ React.createElement( Button, { className: controlBtn, disabled: !loadeddata, onClick: () => { if (player.current) { player.current.pause(); player.current.currentTime = 0; } setPlaying(false); }, ref: stopRef }, /* @__PURE__ */ React.createElement(Stop, null) ), /* @__PURE__ */ React.createElement( Button, { className: controlBtn, disabled: !loadeddata, onClick: () => { var _a; (_a = player == null ? void 0 : player.current) == null ? void 0 : _a.requestFullscreen(); }, ref: fullScreenRef }, /* @__PURE__ */ React.createElement(Fullscreen, null) ), /* @__PURE__ */ React.createElement( Range, { className: range, ref: progressRef, min: "0", max: "100", step: "1", value: progress, style: { width: "70%", marginLeft: 20 }, onChange: ({ target }) => { const { current: video } = player; if (video) { const value = parseInt(target.value); const percent = value / 100; video.currentTime = percent * video.duration; setProgress(value); } } } ))) ); }; const Video = forwardRef(VideoRenderer); export { Video };