summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor/panels/assets/assets-panel-store.tsx
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-08-09 02:37:37 +0200
committercashmere <cashmere@autistici.org>2026-08-09 02:37:37 +0200
commitc555f1eaebff90749bdc543592cfa80a060b29e2 (patch)
treee6a04adb212871063653b66c17eb1b8c17c7d22f /apps/web/src/components/editor/panels/assets/assets-panel-store.tsx
parentdf82306a86d14bca0149e6d756ba82b75659af43 (diff)
downloadopencut-c555f1eaebff90749bdc543592cfa80a060b29e2.tar.gz
feat: lens effects tab, standalone motion effects, clip/asset rename, preview popout
- New Lens category in the assets panel: Blur, Motion Blur, Zoom In/Out, Pan x4, Shake, Pulse, Spin, Custom Zoom. EffectDefinition gains a category field; tabs with an empty category are hidden, and the properties-panel 'Open effects' button opens the first non-empty one. - Motion effects work standalone: dropping them on the timeline creates an effect-track element that animates (scale/translate/rotate) every track below it, computed purely in the TS frame descriptor - no wasm changes, identical in preview and export. supportsStandalone removed. - Motion Blur: directional gaussian smear (amount + angle) reusing the existing WGSL shader with arbitrary u_direction. - Custom Zoom: start/end scale params (keyframable clip-level). - MotionOffset gains optional rotate, accumulated clip-level and applied to standalone layer quads via rotationDegrees. - Rename clips (timeline context menu) and media assets (media panel context menu) via a shared RenameDialog; asset rename persists through storageService with rollback on error. - Preview pops out into a Document Picture-in-Picture window and docks back; button hidden where the API is unsupported. - Export keeps running when the export popover is closed; only the explicit Cancel button aborts. - Captions and Adjustment tabs removed from the assets panel.
Diffstat (limited to 'apps/web/src/components/editor/panels/assets/assets-panel-store.tsx')
-rw-r--r--apps/web/src/components/editor/panels/assets/assets-panel-store.tsx27
1 files changed, 14 insertions, 13 deletions
diff --git a/apps/web/src/components/editor/panels/assets/assets-panel-store.tsx b/apps/web/src/components/editor/panels/assets/assets-panel-store.tsx
index b412de7b..9e9f77c6 100644
--- a/apps/web/src/components/editor/panels/assets/assets-panel-store.tsx
+++ b/apps/web/src/components/editor/panels/assets/assets-panel-store.tsx
@@ -3,17 +3,16 @@ import { create } from "zustand";
import { persist } from "zustand/middleware";
import {
ArrowRightDoubleIcon,
- ClosedCaptionIcon,
+ CameraLensIcon,
Folder03Icon,
Happy01Icon,
HeadphonesIcon,
MagicWand05Icon,
TextIcon,
Settings01Icon,
- SlidersHorizontalIcon,
- ColorsIcon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon, type IconSvgElement } from "@hugeicons/react";
+import { effectsRegistry } from "@/effects";
export const TAB_KEYS = [
"media",
@@ -21,9 +20,8 @@ export const TAB_KEYS = [
"text",
"stickers",
"effects",
+ "lens",
"transitions",
- "captions",
- "adjustment",
"settings",
] as const;
@@ -56,18 +54,14 @@ export const tabs = {
icon: createHugeiconsIcon({ icon: MagicWand05Icon }),
label: "Effects",
},
+ lens: {
+ icon: createHugeiconsIcon({ icon: CameraLensIcon }),
+ label: "Lens",
+ },
transitions: {
icon: createHugeiconsIcon({ icon: ArrowRightDoubleIcon }),
label: "Transitions",
},
- captions: {
- icon: createHugeiconsIcon({ icon: ClosedCaptionIcon }),
- label: "Captions",
- },
- adjustment: {
- icon: createHugeiconsIcon({ icon: SlidersHorizontalIcon }),
- label: "Adjustment",
- },
settings: {
icon: createHugeiconsIcon({ icon: Settings01Icon }),
label: "Settings",
@@ -81,6 +75,13 @@ export type MediaViewMode = "grid" | "list";
export type MediaSortKey = "name" | "type" | "duration" | "size";
export type MediaSortOrder = "asc" | "desc";
+export function getDefaultEffectsTab(): Tab {
+ const hasLensEffects = effectsRegistry
+ .getAll()
+ .some((definition) => definition.category === "lens");
+ return hasLensEffects ? "lens" : "effects";
+}
+
interface AssetsPanelStore {
activeTab: Tab;
setActiveTab: (tab: Tab) => void;