From 3f0fe9d20e85a10e8615fd868e9ff8222dba0c29 Mon Sep 17 00:00:00 2001 From: DevloperAmanSingh Date: Fri, 27 Jun 2025 00:07:41 +0530 Subject: [PATCH] refactor: improve playback controls by replacing inline functions with useCallback for clip manipulation and audio separation --- apps/web/src/hooks/use-playback-controls.ts | 224 ++++++++++---------- 1 file changed, 112 insertions(+), 112 deletions(-) diff --git a/apps/web/src/hooks/use-playback-controls.ts b/apps/web/src/hooks/use-playback-controls.ts index 23bffe1..2c68947 100644 --- a/apps/web/src/hooks/use-playback-controls.ts +++ b/apps/web/src/hooks/use-playback-controls.ts @@ -1,4 +1,4 @@ -import { useEffect } from "react"; +import { useEffect, useCallback } from "react"; import { usePlaybackStore } from "@/stores/playback-store"; import { useTimelineStore } from "@/stores/timeline-store"; import { toast } from "sonner"; @@ -15,8 +15,101 @@ export const usePlaybackControls = () => { separateAudio, } = useTimelineStore(); - useEffect(() => { - const handleKeyPress = (e: KeyboardEvent) => { + const handleSplitSelectedClip = useCallback(() => { + if (selectedClips.length !== 1) { + toast.error("Select exactly one clip to split"); + return; + } + + const { trackId, clipId } = selectedClips[0]; + const track = tracks.find((t) => t.id === trackId); + const clip = track?.clips.find((c) => c.id === clipId); + + if (!clip) return; + + const effectiveStart = clip.startTime; + const effectiveEnd = + clip.startTime + (clip.duration - clip.trimStart - clip.trimEnd); + + if (currentTime <= effectiveStart || currentTime >= effectiveEnd) { + toast.error("Playhead must be within selected clip"); + return; + } + + splitClip(trackId, clipId, currentTime); + toast.success("Clip split at playhead"); + }, [selectedClips, tracks, currentTime, splitClip]); + + const handleSplitAndKeepLeftCallback = useCallback(() => { + if (selectedClips.length !== 1) { + toast.error("Select exactly one clip"); + return; + } + + const { trackId, clipId } = selectedClips[0]; + const track = tracks.find((t) => t.id === trackId); + const clip = track?.clips.find((c) => c.id === clipId); + + if (!clip) return; + + const effectiveStart = clip.startTime; + const effectiveEnd = + clip.startTime + (clip.duration - clip.trimStart - clip.trimEnd); + + if (currentTime <= effectiveStart || currentTime >= effectiveEnd) { + toast.error("Playhead must be within selected clip"); + return; + } + + splitAndKeepLeft(trackId, clipId, currentTime); + toast.success("Split and kept left portion"); + }, [selectedClips, tracks, currentTime, splitAndKeepLeft]); + + const handleSplitAndKeepRightCallback = useCallback(() => { + if (selectedClips.length !== 1) { + toast.error("Select exactly one clip"); + return; + } + + const { trackId, clipId } = selectedClips[0]; + const track = tracks.find((t) => t.id === trackId); + const clip = track?.clips.find((c) => c.id === clipId); + + if (!clip) return; + + const effectiveStart = clip.startTime; + const effectiveEnd = + clip.startTime + (clip.duration - clip.trimStart - clip.trimEnd); + + if (currentTime <= effectiveStart || currentTime >= effectiveEnd) { + toast.error("Playhead must be within selected clip"); + return; + } + + splitAndKeepRight(trackId, clipId, currentTime); + toast.success("Split and kept right portion"); + }, [selectedClips, tracks, currentTime, splitAndKeepRight]); + + const handleSeparateAudioCallback = useCallback(() => { + if (selectedClips.length !== 1) { + toast.error("Select exactly one video clip to separate audio"); + return; + } + + const { trackId, clipId } = selectedClips[0]; + const track = tracks.find((t) => t.id === trackId); + + if (!track || track.type !== "video") { + toast.error("Select a video clip to separate audio"); + return; + } + + separateAudio(trackId, clipId); + toast.success("Audio separated to audio track"); + }, [selectedClips, tracks, separateAudio]); + + const handleKeyPress = useCallback( + (e: KeyboardEvent) => { if ( e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement @@ -44,131 +137,38 @@ export const usePlaybackControls = () => { case "q": if (e.ctrlKey || e.metaKey) { e.preventDefault(); - handleSplitAndKeepLeft(); + handleSplitAndKeepLeftCallback(); } break; case "w": if (e.ctrlKey || e.metaKey) { e.preventDefault(); - handleSplitAndKeepRight(); + handleSplitAndKeepRightCallback(); } break; case "d": if (e.ctrlKey || e.metaKey) { e.preventDefault(); - handleSeparateAudio(); + handleSeparateAudioCallback(); } break; } - }; - - const handleSplitSelectedClip = () => { - if (selectedClips.length !== 1) { - toast.error("Select exactly one clip to split"); - return; - } - - const { trackId, clipId } = selectedClips[0]; - const track = tracks.find((t) => t.id === trackId); - const clip = track?.clips.find((c) => c.id === clipId); - - if (!clip) return; - - const effectiveStart = clip.startTime; - const effectiveEnd = - clip.startTime + (clip.duration - clip.trimStart - clip.trimEnd); - - if (currentTime <= effectiveStart || currentTime >= effectiveEnd) { - toast.error("Playhead must be within selected clip"); - return; - } - - splitClip(trackId, clipId, currentTime); - toast.success("Clip split at playhead"); - }; - - const handleSplitAndKeepLeft = () => { - if (selectedClips.length !== 1) { - toast.error("Select exactly one clip"); - return; - } - - const { trackId, clipId } = selectedClips[0]; - const track = tracks.find((t) => t.id === trackId); - const clip = track?.clips.find((c) => c.id === clipId); - - if (!clip) return; - - const effectiveStart = clip.startTime; - const effectiveEnd = - clip.startTime + (clip.duration - clip.trimStart - clip.trimEnd); - - if (currentTime <= effectiveStart || currentTime >= effectiveEnd) { - toast.error("Playhead must be within selected clip"); - return; - } - - splitAndKeepLeft(trackId, clipId, currentTime); - toast.success("Split and kept left portion"); - }; - - const handleSplitAndKeepRight = () => { - if (selectedClips.length !== 1) { - toast.error("Select exactly one clip"); - return; - } - - const { trackId, clipId } = selectedClips[0]; - const track = tracks.find((t) => t.id === trackId); - const clip = track?.clips.find((c) => c.id === clipId); - - if (!clip) return; - - const effectiveStart = clip.startTime; - const effectiveEnd = - clip.startTime + (clip.duration - clip.trimStart - clip.trimEnd); - - if (currentTime <= effectiveStart || currentTime >= effectiveEnd) { - toast.error("Playhead must be within selected clip"); - return; - } - - splitAndKeepRight(trackId, clipId, currentTime); - toast.success("Split and kept right portion"); - }; - - const handleSeparateAudio = () => { - if (selectedClips.length !== 1) { - toast.error("Select exactly one video clip to separate audio"); - return; - } - - const { trackId, clipId } = selectedClips[0]; - const track = tracks.find((t) => t.id === trackId); - - if (!track || track.type !== "video") { - toast.error("Select a video clip to separate audio"); - return; - } - - separateAudio(trackId, clipId); - toast.success("Audio separated to audio track"); - }; + }, + [ + isPlaying, + play, + pause, + handleSplitSelectedClip, + handleSplitAndKeepLeftCallback, + handleSplitAndKeepRightCallback, + handleSeparateAudioCallback, + ] + ); + useEffect(() => { document.addEventListener("keydown", handleKeyPress); return () => document.removeEventListener("keydown", handleKeyPress); - }, [ - isPlaying, - currentTime, - selectedClips, - tracks, - play, - pause, - splitClip, - splitAndKeepLeft, - splitAndKeepRight, - separateAudio, - ]); + }, [handleKeyPress]); };