summaryrefslogtreecommitdiff
path: root/apps/web/src/hooks/timeline/use-timeline-drag-drop.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/hooks/timeline/use-timeline-drag-drop.ts')
-rw-r--r--apps/web/src/hooks/timeline/use-timeline-drag-drop.ts168
1 files changed, 69 insertions, 99 deletions
diff --git a/apps/web/src/hooks/timeline/use-timeline-drag-drop.ts b/apps/web/src/hooks/timeline/use-timeline-drag-drop.ts
index 01af9362..632d2c78 100644
--- a/apps/web/src/hooks/timeline/use-timeline-drag-drop.ts
+++ b/apps/web/src/hooks/timeline/use-timeline-drag-drop.ts
@@ -7,10 +7,12 @@ import { snapTimeToFrame } from "@/lib/time";
import {
buildTextElement,
buildStickerElement,
- buildUploadAudioElement,
- buildVideoElement,
- buildImageElement,
+ buildElementFromMedia,
} from "@/lib/timeline/element-utils";
+import type { Command } from "@/lib/commands/base-command";
+import { AddMediaAssetCommand } from "@/lib/commands/media";
+import { AddTrackCommand, InsertElementCommand } from "@/lib/commands/timeline";
+import { BatchCommand } from "@/lib/commands";
import { computeDropTarget } from "@/lib/timeline/drop-utils";
import { getDragData, hasDragData } from "@/lib/drag-data";
import type { TrackType, DropTarget, ElementType } from "@/types/timeline";
@@ -231,7 +233,8 @@ export function useTimelineDragDrop({
}
const element = buildStickerElement({
- iconName: dragData.iconName,
+ stickerId: dragData.stickerId,
+ name: dragData.name,
startTime: target.xPosition,
});
@@ -265,38 +268,18 @@ export function useTimelineDragDrop({
const duration =
mediaAsset.duration ?? TIMELINE_CONSTANTS.DEFAULT_ELEMENT_DURATION;
+ const element = buildElementFromMedia({
+ mediaId: mediaAsset.id,
+ mediaType: mediaAsset.type,
+ name: mediaAsset.name,
+ duration,
+ startTime: target.xPosition,
+ });
- if (dragData.mediaType === "audio") {
- editor.timeline.insertElement({
- placement: { mode: "explicit", trackId },
- element: buildUploadAudioElement({
- mediaId: mediaAsset.id,
- name: mediaAsset.name,
- duration,
- startTime: target.xPosition,
- }),
- });
- } else if (dragData.mediaType === "video") {
- editor.timeline.insertElement({
- placement: { mode: "explicit", trackId },
- element: buildVideoElement({
- mediaId: mediaAsset.id,
- name: mediaAsset.name,
- duration,
- startTime: target.xPosition,
- }),
- });
- } else {
- editor.timeline.insertElement({
- placement: { mode: "explicit", trackId },
- element: buildImageElement({
- mediaId: mediaAsset.id,
- name: mediaAsset.name,
- duration,
- startTime: target.xPosition,
- }),
- });
- }
+ editor.timeline.insertElement({
+ placement: { mode: "explicit", trackId },
+ element,
+ });
},
[editor.timeline, mediaAssets, tracks],
);
@@ -314,80 +297,67 @@ export function useTimelineDragDrop({
if (!activeProject) return;
const processedAssets = await processMediaAssets({ files });
+ const projectId = activeProject.metadata.id;
for (const asset of processedAssets) {
- await editor.media.addMediaAsset({
- projectId: activeProject.metadata.id,
- asset,
+ const duration =
+ asset.duration ?? TIMELINE_CONSTANTS.DEFAULT_ELEMENT_DURATION;
+ const currentTracks = editor.timeline.getTracks();
+ const dropTarget = computeDropTarget({
+ elementType: asset.type,
+ mouseX,
+ mouseY,
+ tracks: currentTracks,
+ playheadTime: currentTime,
+ isExternalDrop: true,
+ elementDuration: duration,
+ pixelsPerSecond: TIMELINE_CONSTANTS.PIXELS_PER_SECOND,
+ zoomLevel,
});
- const added = editor.media
- .getAssets()
- .find((m) => m.name === asset.name && m.url === asset.url);
+ const trackType: TrackType = asset.type === "audio" ? "audio" : "video";
+ const addMediaCmd = new AddMediaAssetCommand(projectId, asset);
+ const assetId = addMediaCmd.getAssetId();
- if (added) {
- const duration =
- added.duration ?? TIMELINE_CONSTANTS.DEFAULT_ELEMENT_DURATION;
- const currentTracks = editor.timeline.getTracks();
- const dropTarget = computeDropTarget({
- elementType: added.type,
- mouseX,
- mouseY,
- tracks: currentTracks,
- playheadTime: currentTime,
- isExternalDrop: true,
- elementDuration: duration,
- pixelsPerSecond: TIMELINE_CONSTANTS.PIXELS_PER_SECOND,
- zoomLevel,
- });
+ const commands: Command[] = [addMediaCmd];
- const trackType: TrackType =
- added.type === "audio" ? "audio" : "video";
- const trackId = dropTarget.isNewTrack
- ? editor.timeline.addTrack({
- type: trackType,
- index: dropTarget.trackIndex,
- })
- : currentTracks[dropTarget.trackIndex]?.id;
+ let trackId: string | undefined;
+ if (dropTarget.isNewTrack) {
+ const addTrackCmd = new AddTrackCommand(
+ trackType,
+ dropTarget.trackIndex,
+ );
+ trackId = addTrackCmd.getTrackId();
+ commands.unshift(addTrackCmd);
+ } else {
+ trackId = currentTracks[dropTarget.trackIndex]?.id;
+ }
- if (!trackId) return;
+ if (!trackId) return;
- if (added.type === "audio") {
- editor.timeline.insertElement({
- placement: { mode: "explicit", trackId },
- element: buildUploadAudioElement({
- mediaId: added.id,
- name: added.name,
- duration,
- startTime: dropTarget.xPosition,
- buffer: new AudioBuffer({ length: 1, sampleRate: 44100 }),
- }),
- });
- } else if (added.type === "video") {
- editor.timeline.insertElement({
- placement: { mode: "explicit", trackId },
- element: buildVideoElement({
- mediaId: added.id,
- name: added.name,
- duration,
- startTime: dropTarget.xPosition,
- }),
- });
- } else {
- editor.timeline.insertElement({
- placement: { mode: "explicit", trackId },
- element: buildImageElement({
- mediaId: added.id,
- name: added.name,
- duration,
- startTime: dropTarget.xPosition,
- }),
- });
- }
- }
+ const element = buildElementFromMedia({
+ mediaId: assetId,
+ mediaType: asset.type,
+ name: asset.name,
+ duration,
+ startTime: dropTarget.xPosition,
+ buffer:
+ asset.type === "audio"
+ ? new AudioBuffer({ length: 1, sampleRate: 44100 })
+ : undefined,
+ });
+
+ const insertCmd = new InsertElementCommand({
+ element,
+ placement: { mode: "explicit", trackId },
+ });
+ commands.push(insertCmd);
+
+ const batchCmd = new BatchCommand(commands);
+ editor.command.execute({ command: batchCmd });
}
},
- [activeProject, editor.media, editor.timeline, currentTime, zoomLevel],
+ [activeProject, editor.command, editor.timeline, currentTime, zoomLevel],
);
const handleDrop = useCallback(