summaryrefslogtreecommitdiff
path: root/apps/web/src/hooks/actions/use-editor-actions.ts
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-03-25 16:47:22 +0100
committerMaze Winther <mazewinther@gmail.com>2026-03-29 15:48:22 +0200
commit8db3bead13441a5882d8689dfc6a9f09c82375d9 (patch)
treee9d0cafa93904ffcbec3188c37961bcc16c6422d /apps/web/src/hooks/actions/use-editor-actions.ts
parent39ea298a9ccba3104c549c0ca079c231981811f5 (diff)
downloadopencut-8db3bead13441a5882d8689dfc6a9f09c82375d9.tar.gz
feat: masks, properties refactor, shaders, storage migrations, and more
Diffstat (limited to 'apps/web/src/hooks/actions/use-editor-actions.ts')
-rw-r--r--apps/web/src/hooks/actions/use-editor-actions.ts89
1 files changed, 81 insertions, 8 deletions
diff --git a/apps/web/src/hooks/actions/use-editor-actions.ts b/apps/web/src/hooks/actions/use-editor-actions.ts
index e4f378d6..bfac931b 100644
--- a/apps/web/src/hooks/actions/use-editor-actions.ts
+++ b/apps/web/src/hooks/actions/use-editor-actions.ts
@@ -1,15 +1,22 @@
"use client";
+import { useEffect, useRef } from "react";
import { useTimelineStore } from "@/stores/timeline-store";
import { useActionHandler } from "@/hooks/actions/use-action-handler";
import { useEditor } from "../use-editor";
import { useElementSelection } from "../timeline/element/use-element-selection";
import { useKeyframeSelection } from "../timeline/element/use-keyframe-selection";
import { getElementsAtTime } from "@/lib/timeline";
+import { cancelInteraction } from "@/lib/cancel-interaction";
+import { invokeAction } from "@/lib/actions";
+import {
+ activateScope,
+ clearActiveScope,
+ type ScopeEntry,
+} from "@/lib/selection/scope";
export function useEditorActions() {
const editor = useEditor();
- const activeProject = editor.project.getActive();
const { selectedElements, setElementSelection } = useElementSelection();
const { selectedKeyframes, clearKeyframeSelection } = useKeyframeSelection();
const clipboard = useTimelineStore((s) => s.clipboard);
@@ -17,6 +24,39 @@ export function useEditorActions() {
const toggleSnapping = useTimelineStore((s) => s.toggleSnapping);
const rippleEditingEnabled = useTimelineStore((s) => s.rippleEditingEnabled);
const toggleRippleEditing = useTimelineStore((s) => s.toggleRippleEditing);
+ const hasTimelineSelectionRef = useRef(false);
+ const clearTimelineSelectionRef = useRef(() => {});
+ const timelineScopeRef = useRef<ScopeEntry | null>(null);
+ const hasTimelineSelection =
+ selectedElements.length > 0 || selectedKeyframes.length > 0;
+
+ hasTimelineSelectionRef.current = hasTimelineSelection;
+ clearTimelineSelectionRef.current = () => {
+ setElementSelection({ elements: [] });
+ clearKeyframeSelection();
+ };
+
+ if (!timelineScopeRef.current) {
+ timelineScopeRef.current = {
+ hasSelection: () => hasTimelineSelectionRef.current,
+ clear: () => {
+ clearTimelineSelectionRef.current();
+ },
+ };
+ }
+
+ useEffect(() => {
+ if (!hasTimelineSelection) {
+ return;
+ }
+
+ const timelineScope = timelineScopeRef.current;
+ if (!timelineScope) {
+ return;
+ }
+
+ return activateScope({ entry: timelineScope });
+ }, [hasTimelineSelection]);
useActionHandler(
"toggle-play",
@@ -65,7 +105,7 @@ export function useEditorActions() {
useActionHandler(
"frame-step-forward",
() => {
- const fps = activeProject.settings.fps;
+ const fps = editor.project.getActive().settings.fps;
editor.playback.seek({
time: Math.min(
editor.timeline.getTotalDuration(),
@@ -79,7 +119,7 @@ export function useEditorActions() {
useActionHandler(
"frame-step-backward",
() => {
- const fps = activeProject.settings.fps;
+ const fps = editor.project.getActive().settings.fps;
editor.playback.seek({
time: Math.max(0, editor.playback.getCurrentTime() - 1 / fps),
});
@@ -241,13 +281,21 @@ export function useEditorActions() {
);
useActionHandler(
+ "cancel-interaction",
+ () => {
+ if (!cancelInteraction()) {
+ invokeAction("deselect-all");
+ }
+ },
+ undefined,
+ );
+
+ useActionHandler(
"deselect-all",
() => {
- setElementSelection({ elements: [] });
- clearKeyframeSelection();
- const activeElement = document.activeElement;
- if (activeElement instanceof HTMLButtonElement) {
- activeElement.blur();
+ if (!clearActiveScope()) {
+ setElementSelection({ elements: [] });
+ clearKeyframeSelection();
}
},
undefined,
@@ -353,4 +401,29 @@ export function useEditorActions() {
},
undefined,
);
+
+ // todo: potnetially unify these two actions:
+ useActionHandler(
+ "remove-media-asset",
+ (args) => {
+ if (!args) return;
+ editor.media.removeMediaAsset({
+ projectId: args.projectId,
+ id: args.assetId,
+ });
+ },
+ undefined,
+ );
+
+ useActionHandler(
+ "remove-media-assets",
+ (args) => {
+ if (!args) return;
+ editor.media.removeMediaAssets({
+ projectId: args.projectId,
+ ids: args.assetIds,
+ });
+ },
+ undefined,
+ );
}