From eff3c66821395fe0d78bd75b2614ea2fdce5cde4 Mon Sep 17 00:00:00 2001 From: wil Date: Wed, 11 Sep 2024 14:40:30 -0400 Subject: [PATCH] smooth and optimized the play cursor, play cursor done less files --- .../UploadVideo/QuickTrimVideoPlayer.tsx | 11 ++- .../TrimmerPlaybar/ProgressCursor.tsx | 95 +++++++++++++++++++ .../TrimmerPlaybarCore.tsx} | 86 ++--------------- .../TrimmerPlaybar/TrimmerPlaybarLoading.tsx | 13 +++ .../UploadVideo/TrimmerPlaybar/constants.ts | 5 + .../UploadVideo/TrimmerPlaybar/index.tsx | 15 +++ .../UploadVideo/TrimmerPlaybar/utilities.ts | 20 ++++ .../VideoControls/ButtonPlayPause.tsx | 1 - 8 files changed, 164 insertions(+), 82 deletions(-) create mode 100644 src/components/features/UploadVideo/TrimmerPlaybar/ProgressCursor.tsx rename src/components/features/UploadVideo/{TrimmerPlaybar.tsx => TrimmerPlaybar/TrimmerPlaybarCore.tsx} (58%) create mode 100644 src/components/features/UploadVideo/TrimmerPlaybar/TrimmerPlaybarLoading.tsx create mode 100644 src/components/features/UploadVideo/TrimmerPlaybar/constants.ts create mode 100644 src/components/features/UploadVideo/TrimmerPlaybar/index.tsx create mode 100644 src/components/features/UploadVideo/TrimmerPlaybar/utilities.ts diff --git a/src/components/features/UploadVideo/QuickTrimVideoPlayer.tsx b/src/components/features/UploadVideo/QuickTrimVideoPlayer.tsx index bb667820d6..1aec86099b 100644 --- a/src/components/features/UploadVideo/QuickTrimVideoPlayer.tsx +++ b/src/components/features/UploadVideo/QuickTrimVideoPlayer.tsx @@ -1,4 +1,4 @@ -import { useCallback, useRef } from "react"; +import { useCallback, useState } from "react"; import { VideoControls } from "./VideoControls"; import { TrimmerPlaybar } from "./TrimmerPlaybar"; @@ -13,14 +13,15 @@ export const QuickTrimVideoPlayer = ({ file }: { file: File }) => { // trimStartMs: undefined, // trimEndMs: undefined, // }); + const [vidEl, setVidEl] = useState(undefined); - const videoRef = useRef(undefined); + // const videoRef = useRef(undefined); const videoRefCallback = useCallback( (node: HTMLVideoElement) => { if (node !== null) { // DOM node referenced by ref has changed and exists - videoRef.current = node; + setVidEl(node); } }, [ @@ -41,8 +42,8 @@ export const QuickTrimVideoPlayer = ({ file }: { file: File }) => { />
- - + +
); diff --git a/src/components/features/UploadVideo/TrimmerPlaybar/ProgressCursor.tsx b/src/components/features/UploadVideo/TrimmerPlaybar/ProgressCursor.tsx new file mode 100644 index 0000000000..10cc53cddc --- /dev/null +++ b/src/components/features/UploadVideo/TrimmerPlaybar/ProgressCursor.tsx @@ -0,0 +1,95 @@ +import { useCallback, useState } from "react"; +import { twMerge } from "tailwind-merge"; + +import { + makePositionCalculator, + buttonStyles, + verticalPositionStyles, +} from "./utilities"; + +export const ProgressCursor = ({ + progress, + vidEl, +}: { + progress: number; + vidEl: HTMLVideoElement; +}) => { + const [state, setState] = useState<{ + isScrubbing: boolean; + scrubbingPosition: number; + }>({ + isScrubbing: false, + scrubbingPosition: 0, + }); + + const { isScrubbing, scrubbingPosition } = state; + + const handleScrubbingCurrentTime = useCallback( + (e: React.MouseEvent) => { + e.stopPropagation(); + e.preventDefault(); + + const calcPosition = makePositionCalculator(e); + const wasPlaying = !vidEl.paused; + if (wasPlaying) { + vidEl.pause(); + } + + setState({ + isScrubbing: true, + scrubbingPosition: calcPosition(e), + }); + + const handleMouseMove = (e: MouseEvent) => { + e.stopPropagation(); + e.preventDefault(); + const newPosition = calcPosition(e); + vidEl.currentTime = (newPosition / 100) * vidEl.duration; + setState({ + isScrubbing: true, + scrubbingPosition: newPosition, + }); + }; + const handleMouseUp = () => { + setState((prev) => { + if (wasPlaying) { + vidEl.play(); + } + return { + ...prev, + isScrubbing: false, + }; + }); + + window.removeEventListener("mousemove", handleMouseMove); + window.removeEventListener("mouseup", handleMouseUp); + }; + window.addEventListener("mousemove", handleMouseMove); + window.addEventListener("mouseup", handleMouseUp); + }, + [vidEl], + ); + + return ( + <> +
+
+ + ); +}; diff --git a/src/components/features/UploadVideo/TrimmerPlaybar.tsx b/src/components/features/UploadVideo/TrimmerPlaybar/TrimmerPlaybarCore.tsx similarity index 58% rename from src/components/features/UploadVideo/TrimmerPlaybar.tsx rename to src/components/features/UploadVideo/TrimmerPlaybar/TrimmerPlaybarCore.tsx index 7fc9ca37cc..975bb83d33 100644 --- a/src/components/features/UploadVideo/TrimmerPlaybar.tsx +++ b/src/components/features/UploadVideo/TrimmerPlaybar/TrimmerPlaybarCore.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import { twMerge } from "tailwind-merge"; import { faBracketCurly, @@ -6,32 +6,12 @@ import { } from "@fortawesome/pro-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -const MAX_TRIM_DURATION = 6000; +import { TrimmingPlaybarLoading } from "./TrimmerPlaybarLoading"; +import { MAX_TRIM_DURATION } from "./constants"; +import { buttonStyles, verticalPositionStyles } from "./utilities"; +import { ProgressCursor } from "./ProgressCursor"; -export const TrimmerPlaybar = ({ - vidEl, - className, -}: { - vidEl: HTMLVideoElement | undefined; - className?: string; -}) => { - if (!vidEl) { - return ; - } - return ; -}; -const TrimmingPlaybarLoading = ({ className }: { className?: string }) => { - return ( -
-
-
- ); -}; - -const TrimmerPlaybarCore = ({ +export const TrimmerPlaybarCore = ({ vidEl, className, }: { @@ -49,6 +29,7 @@ const TrimmerPlaybarCore = ({ trimStartMs: undefined, trimEndMs: undefined, }); + const { duration, currentTime, trimStartMs, trimEndMs } = states; const setTrimStartMs = useCallback((value: number) => { @@ -109,42 +90,6 @@ const TrimmerPlaybarCore = ({ }; }, [vidEl]); - const handleScrubbingCurrentTime = useCallback( - (e: React.MouseEvent) => { - e.stopPropagation(); - e.preventDefault(); - const wasPlaying = !vidEl.paused; - if (wasPlaying) { - vidEl.pause(); - } - - const startX = e.clientX; - const handleMouseMove = (e: MouseEvent) => { - e.stopPropagation(); - e.preventDefault(); - // const width = (e.target as HTMLDivElement).getBoundingClientRect() - // .width; - // const deltaX = e.clientX - startX; - // const newCurrentTime = - // (currentTime ?? 0) + (deltaX / width) * (duration ?? 1); - // vidEl.currentTime = newCurrentTime; - }; - const handleMouseUp = () => { - if (wasPlaying) { - vidEl.play(); - } - window.removeEventListener("mousemove", handleMouseMove); - window.removeEventListener("mouseup", handleMouseUp); - }; - window.addEventListener("mousemove", handleMouseMove); - window.addEventListener("mouseup", handleMouseUp); - }, - [vidEl], - ); - - const buttonStyles = "border border-ui-border bg-ui-panel cursor-grab"; - const verticalPositionStyles = "absolute top-1/2 -translate-y-1/2"; - if (!duration) { return ; } @@ -152,20 +97,9 @@ const TrimmerPlaybarCore = ({
-
-
{ + return ( +
+
+
+ ); +}; diff --git a/src/components/features/UploadVideo/TrimmerPlaybar/constants.ts b/src/components/features/UploadVideo/TrimmerPlaybar/constants.ts new file mode 100644 index 0000000000..a0fa534e7d --- /dev/null +++ b/src/components/features/UploadVideo/TrimmerPlaybar/constants.ts @@ -0,0 +1,5 @@ +export const MAX_TRIM_DURATION = 6000; +export enum MouseState { + IDLE = "idle", + DRAGGING = "dragging", +} diff --git a/src/components/features/UploadVideo/TrimmerPlaybar/index.tsx b/src/components/features/UploadVideo/TrimmerPlaybar/index.tsx new file mode 100644 index 0000000000..1c88868b88 --- /dev/null +++ b/src/components/features/UploadVideo/TrimmerPlaybar/index.tsx @@ -0,0 +1,15 @@ +import { TrimmerPlaybarCore } from "./TrimmerPlaybarCore"; +import { TrimmingPlaybarLoading } from "./TrimmerPlaybarLoading"; + +export const TrimmerPlaybar = ({ + vidEl, + className, +}: { + vidEl: HTMLVideoElement | undefined; + className?: string; +}) => { + if (!vidEl) { + return ; + } + return ; +}; diff --git a/src/components/features/UploadVideo/TrimmerPlaybar/utilities.ts b/src/components/features/UploadVideo/TrimmerPlaybar/utilities.ts new file mode 100644 index 0000000000..63aa5ab75e --- /dev/null +++ b/src/components/features/UploadVideo/TrimmerPlaybar/utilities.ts @@ -0,0 +1,20 @@ +export const buttonStyles = "border border-ui-border bg-ui-panel cursor-grab"; +export const verticalPositionStyles = "absolute top-1/2 -translate-y-1/2"; + +export const makePositionCalculator = ( + e: MouseEvent | React.MouseEvent, +) => { + const thisEl = e.target as HTMLDivElement; + const parentEl = thisEl.parentElement as HTMLDivElement; + const parentWidth = parentEl.getBoundingClientRect().width; + return (currE: MouseEvent | React.MouseEvent) => { + const result = ((currE.clientX - parentEl.offsetLeft) / parentWidth) * 100; + if (result < 0) { + return 0; + } + if (result > 100) { + return 100; + } + return result; + }; +}; diff --git a/src/components/features/UploadVideo/VideoControls/ButtonPlayPause.tsx b/src/components/features/UploadVideo/VideoControls/ButtonPlayPause.tsx index 5586e8c614..d9315c989e 100644 --- a/src/components/features/UploadVideo/VideoControls/ButtonPlayPause.tsx +++ b/src/components/features/UploadVideo/VideoControls/ButtonPlayPause.tsx @@ -13,7 +13,6 @@ export function ButtonPlaypause({ vidEl }: { vidEl: HTMLVideoElement }) { PlayPauseStatus.PAUSED, ); const togglePlaypause = () => { - console.log("togglePlaypause", playpause); if (playpause === PlayPauseStatus.PLAYING) { vidEl.pause(); } else {