From e7dcb586c0408255a0bf788e355fdb6d50d9b923 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 2 Mar 2026 13:13:07 +0100 Subject: feat: Clip effects, asset sorting, and timeline improvements Major features and improvements: * **Clip Effects**: * Added UI in Properties Panel to manage effects on video/image clips (add, remove, toggle, reorder). * Implemented dynamic parameter fields for effects. * Added support for keyframing effect parameters. * **Assets Panel**: * Added sorting options: Name, Type, Duration, and File Size. * Persisted view preferences (grid/list mode, sort order) to local storage. * Refactored media item rendering and drag interactions. * **Timeline & Interaction**: * **Keyframe Dragging**: Added ability to drag keyframes directly on the timeline element. * **Resizing**: Improved resize logic to respect neighboring clips (prevents overlaps). * **Visuals**: Implemented tiled background rendering for video/image clips on the timeline. * **Shortcuts**: Added "Deselect All" action bound to the `Escape` key. * **Fixes**: Corrected drag-and-drop coordinate calculations when the timeline track area is scrolled. * **Text Elements**: * Refactored text background storage to use an explicit `enabled` flag. * Added `V8toV9` storage migration to update existing projects. * **Architecture**: * Moved export state management to `ProjectManager` for better lifecycle handling. * Refactored `PropertiesPanel` sections to be more composable (custom headers, borders). --- apps/web/src/hooks/actions/use-editor-actions.ts | 34 ++++++++++++++++++------ 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'apps/web/src/hooks/actions') diff --git a/apps/web/src/hooks/actions/use-editor-actions.ts b/apps/web/src/hooks/actions/use-editor-actions.ts index 5f48fc8f..e4f378d6 100644 --- a/apps/web/src/hooks/actions/use-editor-actions.ts +++ b/apps/web/src/hooks/actions/use-editor-actions.ts @@ -4,19 +4,19 @@ 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"; export function useEditorActions() { const editor = useEditor(); const activeProject = editor.project.getActive(); const { selectedElements, setElementSelection } = useElementSelection(); - const { - clipboard, - setClipboard, - toggleSnapping, - rippleEditingEnabled, - toggleRippleEditing, - } = useTimelineStore(); + 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); useActionHandler( "toggle-play", @@ -209,6 +209,11 @@ export function useEditorActions() { useActionHandler( "delete-selected", () => { + if (selectedKeyframes.length > 0) { + editor.timeline.removeKeyframes({ keyframes: selectedKeyframes }); + clearKeyframeSelection(); + return; + } if (selectedElements.length === 0) { return; } @@ -235,6 +240,19 @@ export function useEditorActions() { undefined, ); + useActionHandler( + "deselect-all", + () => { + setElementSelection({ elements: [] }); + clearKeyframeSelection(); + const activeElement = document.activeElement; + if (activeElement instanceof HTMLButtonElement) { + activeElement.blur(); + } + }, + undefined, + ); + useActionHandler( "duplicate-selected", () => { @@ -278,7 +296,7 @@ export function useEditorActions() { elements: selectedElements, }); const items = results.map(({ track, element }) => { - const { ...elementWithoutId } = element; + const { id: _, ...elementWithoutId } = element; return { trackId: track.id, trackType: track.type, -- cgit v1.3.1