visuddhinanda 1 месяц назад
Родитель
Сommit
ae915f1368

+ 69 - 0
dashboard-v6/src/components/general/Video.tsx

@@ -0,0 +1,69 @@
+import { useEffect, useRef, useState } from "react";
+import players from "video.js";
+import VideoPlayer from "./VideoPlayer";
+import type { IAttachmentResponse } from "../../api/Attachments";
+import { get } from "../../request";
+
+interface IWidget {
+  fileName?: string;
+  fileId?: string;
+  src?: string;
+  type?: string;
+}
+const VideoWidget = ({ fileId, src, type }: IWidget) => {
+  const playerRef = useRef<players.Player | null>(null);
+  const [url, setUrl] = useState<string>();
+
+  useEffect(() => {
+    if (fileId) {
+      const url = `/v2/attachment/${fileId}`;
+      console.info("VideoWidget api request", url);
+      get<IAttachmentResponse>(url).then((json) => {
+        console.debug("VideoWidget api response", json);
+        if (json.ok) {
+          setUrl(json.data.url);
+        }
+      });
+    }
+  }, [fileId]);
+
+  useEffect(() => {
+    if (src) {
+      setUrl(src);
+    }
+  }, [src]);
+
+  const handlePlayerReady = (player: players.Player) => {
+    if (playerRef.current) {
+      playerRef.current = player;
+      player.on("waiting", () => {
+        console.log("player is waiting");
+      });
+
+      player.on("dispose", () => {
+        console.log("player will dispose");
+      });
+    }
+  };
+
+  return (
+    <VideoPlayer
+      options={{
+        autoplay: false,
+        controls: true,
+        responsive: true,
+        fluid: true,
+        poster: "",
+        sources: [
+          {
+            src: url ? url : "",
+            type: type ? type : "video/mp4",
+          },
+        ],
+      }}
+      onReady={handlePlayerReady}
+    />
+  );
+};
+
+export default VideoWidget;

+ 62 - 0
dashboard-v6/src/components/general/VideoModal.tsx

@@ -0,0 +1,62 @@
+import { useEffect, useState, type JSX } from "react";
+import { Modal } from "antd";
+import Video from "./Video";
+
+interface IWidget {
+  src?: string;
+  type?: string;
+  open?: boolean;
+  trigger?: JSX.Element;
+  onOpenChange?: (open: boolean) => void;
+}
+export const VideoModalWidget = ({
+  src,
+  type,
+  open = false,
+  trigger,
+  onOpenChange,
+}: IWidget) => {
+  //TODO 跟video ctl 合并
+  const [isModalOpen, setIsModalOpen] = useState(open);
+
+  useEffect(() => {
+    setIsModalOpen(open);
+  }, [open]);
+
+  const showModal = () => {
+    setIsModalOpen(true);
+    if (typeof onOpenChange !== "undefined") {
+      onOpenChange(true);
+    }
+  };
+
+  const handleClose = () => {
+    setIsModalOpen(false);
+    if (typeof onOpenChange !== "undefined") {
+      onOpenChange(false);
+    }
+  };
+
+  return (
+    <>
+      <span onClick={showModal}>{trigger}</span>
+      <Modal
+        style={{ top: 20 }}
+        title="Basic Modal"
+        footer={false}
+        open={isModalOpen}
+        onOk={handleClose}
+        onCancel={handleClose}
+        width={800}
+        destroyOnHidden={false}
+        mask={{ closable: false }}
+      >
+        <div>
+          <Video src={src} type={type} />
+        </div>
+      </Modal>
+    </>
+  );
+};
+
+export default VideoModalWidget;

+ 52 - 0
dashboard-v6/src/components/general/VideoPlayer.tsx

@@ -0,0 +1,52 @@
+import { useRef, useEffect } from "react";
+import videojs from "video.js";
+
+interface IProps {
+  options: videojs.PlayerOptions;
+  onReady: (player: videojs.Player) => void;
+}
+
+const VideoPlayerWidget = ({ options, onReady }: IProps) => {
+  const videoRef = useRef<HTMLDivElement>(null);
+  const playerRef = useRef<VideoJsPlayer | null>(null);
+
+  useEffect(() => {
+    if (!playerRef.current) {
+      const videoElement = document.createElement("video-js");
+      videoElement.classList.add("vjs-big-play-centered");
+
+      videoRef.current?.appendChild(videoElement);
+
+      const player = (playerRef.current = videojs(videoElement, options, () =>
+        onReady?.(player)
+      ));
+    } else {
+      const player = playerRef.current;
+
+      if (options.autoplay !== undefined) {
+        player.autoplay(options.autoplay);
+      }
+      if (options.sources !== undefined) {
+        player.src(options.sources);
+      }
+    }
+  }, [options, onReady]);
+
+  useEffect(() => {
+    return () => {
+      const player = playerRef.current;
+      if (player && !player.isDisposed()) {
+        player.dispose();
+        playerRef.current = null;
+      }
+    };
+  }, []);
+
+  return (
+    <div data-vjs-player>
+      <div ref={videoRef} className="video-js" />
+    </div>
+  );
+};
+
+export default VideoPlayerWidget;