From 238e489f555d19b3327703942fbbe5af104518a1 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Sun, 13 Oct 2024 11:43:34 -0500 Subject: [PATCH] custom hook and generic video player component --- .../components/player/GenericVideoPlayer.tsx | 52 +++++++++++++++++++ web/src/hooks/use-video-dimensions.ts | 45 ++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 web/src/components/player/GenericVideoPlayer.tsx create mode 100644 web/src/hooks/use-video-dimensions.ts diff --git a/web/src/components/player/GenericVideoPlayer.tsx b/web/src/components/player/GenericVideoPlayer.tsx new file mode 100644 index 000000000..75f56e96f --- /dev/null +++ b/web/src/components/player/GenericVideoPlayer.tsx @@ -0,0 +1,52 @@ +import React, { useState, useRef } from "react"; +import { useVideoDimensions } from "@/hooks/use-video-dimensions"; +import HlsVideoPlayer from "./HlsVideoPlayer"; +import ActivityIndicator from "../indicators/activity-indicator"; + +type GenericVideoPlayerProps = { + source: string; + onPlaying?: () => void; + children?: React.ReactNode; +}; + +export function GenericVideoPlayer({ + source, + onPlaying, + children, +}: GenericVideoPlayerProps) { + const [isLoading, setIsLoading] = useState(true); + const videoRef = useRef(null); + const containerRef = useRef(null); + const { videoDimensions, setVideoResolution } = + useVideoDimensions(containerRef); + + return ( +
+
+ {isLoading && ( + + )} +
+ { + setIsLoading(false); + onPlaying?.(); + }} + setFullResolution={setVideoResolution} + /> + {!isLoading && children} +
+
+
+ ); +} diff --git a/web/src/hooks/use-video-dimensions.ts b/web/src/hooks/use-video-dimensions.ts new file mode 100644 index 000000000..448dd5078 --- /dev/null +++ b/web/src/hooks/use-video-dimensions.ts @@ -0,0 +1,45 @@ +import { useState, useMemo } from "react"; +import { useResizeObserver } from "./resize-observer"; + +export type VideoResolutionType = { + width: number; + height: number; +}; + +export function useVideoDimensions( + containerRef: React.RefObject, +) { + const [{ width: containerWidth, height: containerHeight }] = + useResizeObserver(containerRef); + const [videoResolution, setVideoResolution] = useState({ + width: 0, + height: 0, + }); + + const videoAspectRatio = useMemo(() => { + return videoResolution.width / videoResolution.height || 16 / 9; + }, [videoResolution]); + + const containerAspectRatio = useMemo(() => { + return containerWidth / containerHeight || 16 / 9; + }, [containerWidth, containerHeight]); + + const videoDimensions = useMemo(() => { + if (!containerWidth || !containerHeight) + return { width: "100%", height: "100%" }; + if (containerAspectRatio > videoAspectRatio) { + const height = containerHeight; + const width = height * videoAspectRatio; + return { width: `${width}px`, height: `${height}px` }; + } else { + const width = containerWidth; + const height = width / videoAspectRatio; + return { width: `${width}px`, height: `${height}px` }; + } + }, [containerWidth, containerHeight, videoAspectRatio, containerAspectRatio]); + + return { + videoDimensions, + setVideoResolution, + }; +}