summaryrefslogtreecommitdiff
path: root/apps/web/src/hooks
diff options
context:
space:
mode:
authorDevloperAmanSingh <amansinghneh211205@gmail.com>2025-06-27 00:07:41 +0530
committerDevloperAmanSingh <amansinghneh211205@gmail.com>2025-06-27 00:07:41 +0530
commit3f0fe9d20e85a10e8615fd868e9ff8222dba0c29 (patch)
tree9a1cfecf6628397e1c5d9d7a63611561785e30a3 /apps/web/src/hooks
parent0383000adacc19d582799fd5935916dff7cbf83e (diff)
downloadopencut-3f0fe9d20e85a10e8615fd868e9ff8222dba0c29.tar.gz
refactor: improve playback controls by replacing inline functions with useCallback for clip manipulation and audio separation
Diffstat (limited to 'apps/web/src/hooks')
-rw-r--r--apps/web/src/hooks/use-playback-controls.ts224
1 files 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 23bffe13..2c689470 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]);
};