summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor/timeline/timeline-action-handlers.tsx
diff options
context:
space:
mode:
authorSimon Orzel <simonorzel@gmail.com>2025-07-17 03:00:38 +0200
committerSimon Orzel <simonorzel@gmail.com>2025-07-17 03:00:38 +0200
commit167f366c6d791dfc054d64f50e83828960668e55 (patch)
tree28d6b037a2d0597990d290520a8265cca1ef66d7 /apps/web/src/components/editor/timeline/timeline-action-handlers.tsx
parent1505c1b12f516c65b6a3d076f0e9623a294031d6 (diff)
downloadopencut-167f366c6d791dfc054d64f50e83828960668e55.tar.gz
feat: bunx biome format --write .
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.tsx308
1 files changed, 154 insertions, 154 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
index c9560507..0e7323d3 100644
--- a/apps/web/src/components/editor/timeline/timeline-action-handlers.tsx
+++ b/apps/web/src/components/editor/timeline/timeline-action-handlers.tsx
@@ -4,175 +4,175 @@ 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();
+ 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]);
+ // 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 };
- };
+ // 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);
+ // 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");
- }
- };
+ 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;
+ 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);
+ selectedElements.forEach(({ trackId, elementId }) => {
+ const { element } = findTrackAndElement(trackId, elementId);
- if (element) {
- const newStartTime =
- element.startTime +
- (element.duration - element.trimStart - element.trimEnd) +
- 0.1;
+ 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;
+ // Create element without id (will be generated by store)
+ const { id, ...elementWithoutId } = element;
- addElementToTrack(trackId, {
- ...elementWithoutId,
- startTime: newStartTime,
- });
+ 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
- }
- });
+ // We can't predict the new id, so just clear selection for now
+ // TODO: addElementToTrack could return the new element id
+ }
+ });
- clearSelectedElements();
- };
+ clearSelectedElements();
+ };
- const handleFreezeSelected = () => {
- toast.info("Freeze frame functionality coming soon!");
- };
+ 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 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 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 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();
- };
+ 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,
- };
+ return {
+ handleSplitSelected,
+ handleDuplicateSelected,
+ handleFreezeSelected,
+ handleSplitAndKeepLeft,
+ handleSplitAndKeepRight,
+ handleSeparateAudio,
+ handleDeleteSelected,
+ };
}