This commit is contained in:
Maze Winther
2025-07-30 11:38:21 +02:00
parent deda0e366f
commit 004fa0c12b
4 changed files with 223 additions and 123 deletions
+177 -109
View File
@@ -26,136 +26,204 @@ export function useEditorActions() {
const { activeProject } = useProjectStore();
// Playback actions
useActionHandler("toggle-play", () => {
toggle();
}, undefined);
useActionHandler("stop-playback", () => {
if (isPlaying) {
useActionHandler(
"toggle-play",
() => {
toggle();
}
seek(0);
}, undefined);
},
undefined
);
useActionHandler("seek-forward", (args) => {
const seconds = args?.seconds ?? 1;
seek(Math.min(duration, currentTime + seconds));
}, undefined);
useActionHandler(
"stop-playback",
() => {
if (isPlaying) {
toggle();
}
seek(0);
},
undefined
);
useActionHandler("seek-backward", (args) => {
const seconds = args?.seconds ?? 1;
seek(Math.max(0, currentTime - seconds));
}, undefined);
useActionHandler(
"seek-forward",
(args) => {
const seconds = args?.seconds ?? 1;
seek(Math.min(duration, currentTime + seconds));
},
undefined
);
useActionHandler("frame-step-forward", () => {
const projectFps = activeProject?.fps || 30;
seek(Math.min(duration, currentTime + 1 / projectFps));
}, undefined);
useActionHandler(
"seek-backward",
(args) => {
const seconds = args?.seconds ?? 1;
seek(Math.max(0, currentTime - seconds));
},
undefined
);
useActionHandler("frame-step-backward", () => {
const projectFps = activeProject?.fps || 30;
seek(Math.max(0, currentTime - 1 / projectFps));
}, undefined);
useActionHandler(
"frame-step-forward",
() => {
const projectFps = activeProject?.fps || 30;
seek(Math.min(duration, currentTime + 1 / projectFps));
},
undefined
);
useActionHandler("jump-forward", (args) => {
const seconds = args?.seconds ?? 5;
seek(Math.min(duration, currentTime + seconds));
}, undefined);
useActionHandler(
"frame-step-backward",
() => {
const projectFps = activeProject?.fps || 30;
seek(Math.max(0, currentTime - 1 / projectFps));
},
undefined
);
useActionHandler("jump-backward", (args) => {
const seconds = args?.seconds ?? 5;
seek(Math.max(0, currentTime - seconds));
}, undefined);
useActionHandler(
"jump-forward",
(args) => {
const seconds = args?.seconds ?? 5;
seek(Math.min(duration, currentTime + seconds));
},
undefined
);
useActionHandler("goto-start", () => {
seek(0);
}, undefined);
useActionHandler(
"jump-backward",
(args) => {
const seconds = args?.seconds ?? 5;
seek(Math.max(0, currentTime - seconds));
},
undefined
);
useActionHandler("goto-end", () => {
seek(duration);
}, undefined);
useActionHandler(
"goto-start",
() => {
seek(0);
},
undefined
);
useActionHandler(
"goto-end",
() => {
seek(duration);
},
undefined
);
// Timeline editing actions
useActionHandler("split-element", () => {
if (selectedElements.length !== 1) {
toast.error("Select exactly one element to split");
return;
}
const { trackId, elementId } = selectedElements[0];
const track = tracks.find((t: any) => t.id === trackId);
const element = track?.elements.find((el: any) => el.id === elementId);
if (element) {
const effectiveStart = element.startTime;
const effectiveEnd =
element.startTime +
(element.duration - element.trimStart - element.trimEnd);
if (currentTime > effectiveStart && currentTime < effectiveEnd) {
splitElement(trackId, elementId, currentTime);
} else {
toast.error("Playhead must be within selected element");
useActionHandler(
"split-element",
() => {
if (selectedElements.length !== 1) {
toast.error("Select exactly one element to split");
return;
}
}
}, undefined);
useActionHandler("delete-selected", () => {
if (selectedElements.length === 0) {
return;
}
selectedElements.forEach(
({ trackId, elementId }: { trackId: string; elementId: string }) => {
removeElementFromTrack(trackId, elementId);
const { trackId, elementId } = selectedElements[0];
const track = tracks.find((t: any) => t.id === trackId);
const element = track?.elements.find((el: any) => el.id === elementId);
if (element) {
const effectiveStart = element.startTime;
const effectiveEnd =
element.startTime +
(element.duration - element.trimStart - element.trimEnd);
if (currentTime > effectiveStart && currentTime < effectiveEnd) {
splitElement(trackId, elementId, currentTime);
} else {
toast.error("Playhead must be within selected element");
}
}
);
clearSelectedElements();
}, undefined);
},
undefined
);
useActionHandler("select-all", () => {
const allElements = tracks.flatMap((track: any) =>
track.elements.map((element: any) => ({
trackId: track.id,
elementId: element.id,
}))
);
setSelectedElements(allElements);
}, undefined);
useActionHandler(
"delete-selected",
() => {
if (selectedElements.length === 0) {
return;
}
selectedElements.forEach(
({ trackId, elementId }: { trackId: string; elementId: string }) => {
removeElementFromTrack(trackId, elementId);
}
);
clearSelectedElements();
},
undefined
);
useActionHandler("duplicate-selected", () => {
if (selectedElements.length !== 1) {
toast.error("Select exactly one element to duplicate");
return;
}
useActionHandler(
"select-all",
() => {
const allElements = tracks.flatMap((track: any) =>
track.elements.map((element: any) => ({
trackId: track.id,
elementId: element.id,
}))
);
setSelectedElements(allElements);
},
undefined
);
const { trackId, elementId } = selectedElements[0];
const track = tracks.find((t: any) => t.id === trackId);
const element = track?.elements.find((el: any) => el.id === elementId);
useActionHandler(
"duplicate-selected",
() => {
if (selectedElements.length !== 1) {
toast.error("Select exactly one element to duplicate");
return;
}
if (element) {
const newStartTime =
element.startTime +
(element.duration - element.trimStart - element.trimEnd) +
0.1;
const { id, ...elementWithoutId } = element;
const { trackId, elementId } = selectedElements[0];
const track = tracks.find((t: any) => t.id === trackId);
const element = track?.elements.find((el: any) => el.id === elementId);
addElementToTrack(trackId, {
...elementWithoutId,
startTime: newStartTime,
});
}
}, undefined);
if (element) {
const newStartTime =
element.startTime +
(element.duration - element.trimStart - element.trimEnd) +
0.1;
const { id, ...elementWithoutId } = element;
useActionHandler("toggle-snapping", () => {
toggleSnapping();
}, undefined);
addElementToTrack(trackId, {
...elementWithoutId,
startTime: newStartTime,
});
}
},
undefined
);
useActionHandler(
"toggle-snapping",
() => {
toggleSnapping();
},
undefined
);
// History actions
useActionHandler("undo", () => {
undo();
}, undefined);
useActionHandler(
"undo",
() => {
undo();
},
undefined
);
useActionHandler("redo", () => {
redo();
}, undefined);
useActionHandler(
"redo",
() => {
redo();
},
undefined
);
}