summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor/timeline/timeline-action-handlers.tsx
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2025-07-17 19:46:23 +0200
committerMaze Winther <mazewinther@gmail.com>2025-07-17 19:46:23 +0200
commit648f0b8529b9f3bafb3bfd9a84a31bc9ac6623ae (patch)
tree00a438ce93f12b3b58f705189142a9385d497e4a /apps/web/src/components/editor/timeline/timeline-action-handlers.tsx
parent0b919d4df84ea523ac9e069bdad5c3b34b7c603d (diff)
downloadopencut-648f0b8529b9f3bafb3bfd9a84a31bc9ac6623ae.tar.gz
stable timeline
Diffstat (limited to 'apps/web/src/components/editor/timeline/timeline-action-handlers.tsx')
-rw-r--r--apps/web/src/components/editor/timeline/timeline-action-handlers.tsx178
1 files changed, 0 insertions, 178 deletions
diff --git a/apps/web/src/components/editor/timeline/timeline-action-handlers.tsx b/apps/web/src/components/editor/timeline/timeline-action-handlers.tsx
deleted file mode 100644
index 22c1efa5..00000000
--- a/apps/web/src/components/editor/timeline/timeline-action-handlers.tsx
+++ /dev/null
@@ -1,178 +0,0 @@
-import { useMemo } from "react";
-import { toast } from "sonner";
-import { useTimelineStore } from "@/stores/timeline-store";
-import { usePlaybackStore } from "@/stores/playback-store";
-
-export function useTimelineActionHandlers() {
- const {
- tracks,
- addElementToTrack,
- removeElementFromTrack,
- selectedElements,
- clearSelectedElements,
- splitElement,
- splitAndKeepLeft,
- splitAndKeepRight,
- separateAudio,
- } = useTimelineStore();
- const { currentTime } = usePlaybackStore();
-
- // Create optimized lookup maps for O(1) access instead of O(n) find operations
- const trackMap = useMemo(() => {
- const map = new Map();
- tracks.forEach((track) => {
- map.set(track.id, track);
- // Also create element lookup for this track
- const elementMap = new Map();
- track.elements.forEach((element) => {
- elementMap.set(element.id, element);
- });
- map.set(`${track.id}_elements`, elementMap);
- });
- return map;
- }, [tracks]);
-
- // Helper function for O(1) track/element lookup
- const findTrackAndElement = (trackId: string, elementId: string) => {
- const track = trackMap.get(trackId);
- const elementMap = trackMap.get(`${trackId}_elements`);
- const element = elementMap?.get(elementId);
- return { track, element };
- };
-
- // Action handlers for toolbar
- const handleSplitSelected = () => {
- if (selectedElements.length === 0) {
- toast.error("No elements selected");
- return;
- }
- let splitCount = 0;
- selectedElements.forEach(({ trackId, elementId }) => {
- const { track, element } = findTrackAndElement(trackId, elementId);
- if (element && track) {
- const effectiveStart = element.startTime;
- const effectiveEnd =
- element.startTime +
- (element.duration - element.trimStart - element.trimEnd);
-
- if (currentTime > effectiveStart && currentTime < effectiveEnd) {
- const newElementId = splitElement(trackId, elementId, currentTime);
- if (newElementId) splitCount++;
- }
- }
- });
- if (splitCount === 0) {
- toast.error("Playhead must be within selected elements to split");
- }
- };
-
- const handleDuplicateSelected = () => {
- if (selectedElements.length === 0) {
- toast.error("No elements selected");
- return;
- }
- const canDuplicate = selectedElements.length === 1;
- if (!canDuplicate) return;
-
- selectedElements.forEach(({ trackId, elementId }) => {
- const { element } = findTrackAndElement(trackId, elementId);
-
- if (element) {
- const newStartTime =
- element.startTime +
- (element.duration - element.trimStart - element.trimEnd) +
- 0.1;
-
- // Create element without id (will be generated by store)
- const { id, ...elementWithoutId } = element;
-
- addElementToTrack(trackId, {
- ...elementWithoutId,
- startTime: newStartTime,
- });
-
- // We can't predict the new id, so just clear selection for now
- // TODO: addElementToTrack could return the new element id
- }
- });
-
- clearSelectedElements();
- };
-
- const handleFreezeSelected = () => {
- toast.info("Freeze frame functionality coming soon!");
- };
-
- const handleSplitAndKeepLeft = () => {
- if (selectedElements.length !== 1) {
- toast.error("Select exactly one element");
- return;
- }
- const { trackId, elementId } = selectedElements[0];
- const { element } = findTrackAndElement(trackId, elementId);
- if (!element) return;
- const effectiveStart = element.startTime;
- const effectiveEnd =
- element.startTime +
- (element.duration - element.trimStart - element.trimEnd);
- if (currentTime <= effectiveStart || currentTime >= effectiveEnd) {
- toast.error("Playhead must be within selected element");
- return;
- }
- splitAndKeepLeft(trackId, elementId, currentTime);
- };
-
- const handleSplitAndKeepRight = () => {
- if (selectedElements.length !== 1) {
- toast.error("Select exactly one element");
- return;
- }
- const { trackId, elementId } = selectedElements[0];
- const { element } = findTrackAndElement(trackId, elementId);
- if (!element) return;
- const effectiveStart = element.startTime;
- const effectiveEnd =
- element.startTime +
- (element.duration - element.trimStart - element.trimEnd);
- if (currentTime <= effectiveStart || currentTime >= effectiveEnd) {
- toast.error("Playhead must be within selected element");
- return;
- }
- splitAndKeepRight(trackId, elementId, currentTime);
- };
-
- const handleSeparateAudio = () => {
- if (selectedElements.length !== 1) {
- toast.error("Select exactly one media element to separate audio");
- return;
- }
- const { trackId, elementId } = selectedElements[0];
- const { track } = findTrackAndElement(trackId, elementId);
- if (!track || track.type !== "media") {
- toast.error("Select a media element to separate audio");
- return;
- }
- separateAudio(trackId, elementId);
- };
-
- const handleDeleteSelected = () => {
- if (selectedElements.length === 0) {
- toast.error("No elements selected");
- return;
- }
- selectedElements.forEach(({ trackId, elementId }) => {
- removeElementFromTrack(trackId, elementId);
- });
- clearSelectedElements();
- };
-
- return {
- handleSplitSelected,
- handleDuplicateSelected,
- handleFreezeSelected,
- handleSplitAndKeepLeft,
- handleSplitAndKeepRight,
- handleSeparateAudio,
- handleDeleteSelected,
- };
-}