summaryrefslogtreecommitdiff
path: root/apps/web/src/hooks/actions
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-13 04:40:56 +0200
committerMaze Winther <mazewinther@gmail.com>2026-04-13 05:03:10 +0200
commit2272598d420cf078aaa3928246bfa3a414f6eddb (patch)
treeb52460a2e3576c9e517ef8a9dd86959a68f31b69 /apps/web/src/hooks/actions
parent5a2aaf3601b6b050603f51e487a31fb07862a21f (diff)
downloadopencut-2272598d420cf078aaa3928246bfa3a414f6eddb.tar.gz
feat: clipboard with keyframe paste
Made-with: Cursor
Diffstat (limited to 'apps/web/src/hooks/actions')
-rw-r--r--apps/web/src/hooks/actions/use-editor-actions.ts43
1 files changed, 12 insertions, 31 deletions
diff --git a/apps/web/src/hooks/actions/use-editor-actions.ts b/apps/web/src/hooks/actions/use-editor-actions.ts
index be04a7d3..1c4735bb 100644
--- a/apps/web/src/hooks/actions/use-editor-actions.ts
+++ b/apps/web/src/hooks/actions/use-editor-actions.ts
@@ -7,10 +7,7 @@ import { useEditor } from "../use-editor";
import { useElementSelection } from "../timeline/element/use-element-selection";
import { TICKS_PER_SECOND } from "@/lib/wasm";
import { useKeyframeSelection } from "../timeline/element/use-keyframe-selection";
-import {
- getElementsAtTime,
- hasMediaId,
-} from "@/lib/timeline";
+import { getElementsAtTime, hasMediaId } from "@/lib/timeline";
import { cancelInteraction } from "@/lib/cancel-interaction";
import { invokeAction } from "@/lib/actions";
import { canToggleSourceAudio } from "@/lib/timeline/audio-separation";
@@ -24,8 +21,6 @@ export function useEditorActions() {
const editor = useEditor();
const { selectedElements, setElementSelection } = useElementSelection();
const { selectedKeyframes, clearKeyframeSelection } = useKeyframeSelection();
- const clipboard = useTimelineStore((s) => s.clipboard);
- const setClipboard = useTimelineStore((s) => s.setClipboard);
const toggleSnapping = useTimelineStore((s) => s.toggleSnapping);
const rippleEditingEnabled = useTimelineStore((s) => s.rippleEditingEnabled);
const toggleRippleEditing = useTimelineStore((s) => s.toggleRippleEditing);
@@ -111,7 +106,9 @@ export function useEditorActions() {
"frame-step-forward",
() => {
const fps = editor.project.getActive().settings.fps;
- const ticksPerFrame = Math.round(TICKS_PER_SECOND * fps.denominator / fps.numerator);
+ const ticksPerFrame = Math.round(
+ (TICKS_PER_SECOND * fps.denominator) / fps.numerator,
+ );
editor.playback.seek({
time: Math.min(
editor.timeline.getTotalDuration(),
@@ -126,7 +123,9 @@ export function useEditorActions() {
"frame-step-backward",
() => {
const fps = editor.project.getActive().settings.fps;
- const ticksPerFrame = Math.round(TICKS_PER_SECOND * fps.denominator / fps.numerator);
+ const ticksPerFrame = Math.round(
+ (TICKS_PER_SECOND * fps.denominator) / fps.numerator,
+ );
editor.playback.seek({
time: Math.max(0, editor.playback.getCurrentTime() - ticksPerFrame),
});
@@ -294,8 +293,9 @@ export function useEditorActions() {
}
return (
- editor.media.getAssets().find((asset) => asset.id === element.mediaId) ??
- null
+ editor.media
+ .getAssets()
+ .find((asset) => asset.id === element.mediaId) ?? null
);
})();
if (!canToggleSourceAudio(selectedElement.element, mediaAsset)) {
@@ -387,21 +387,7 @@ export function useEditorActions() {
useActionHandler(
"copy-selected",
() => {
- if (selectedElements.length === 0) return;
-
- const results = editor.timeline.getElementsWithTracks({
- elements: selectedElements,
- });
- const items = results.map(({ track, element }) => {
- const { id: _, ...elementWithoutId } = element;
- return {
- trackId: track.id,
- trackType: track.type,
- element: elementWithoutId,
- };
- });
-
- setClipboard({ items });
+ editor.clipboard.copy();
},
undefined,
);
@@ -409,12 +395,7 @@ export function useEditorActions() {
useActionHandler(
"paste-copied",
() => {
- if (!clipboard?.items.length) return;
-
- editor.timeline.pasteAtTime({
- time: editor.playback.getCurrentTime(),
- clipboardItems: clipboard.items,
- });
+ editor.clipboard.paste();
},
undefined,
);