summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor/timeline/timeline-track.tsx
diff options
context:
space:
mode:
authorryu <ryumacodes@gmail.com>2025-08-13 14:01:07 +0500
committerGitHub <noreply@github.com>2025-08-13 14:01:07 +0500
commit0ae09c9df5591e2d18991a9f98647826997fe740 (patch)
tree69738461bd269ad418bc82c47e64a2670cee7f19 /apps/web/src/components/editor/timeline/timeline-track.tsx
parente71788014d137a74f10420601451ddfbb84701bb (diff)
parentf7fddff1fc8359fc056a2a90488121980fb8ead2 (diff)
downloadopencut-0ae09c9df5591e2d18991a9f98647826997fe740.tar.gz
Merge branch 'staging' into feat/timeline-return-to-start
Diffstat (limited to 'apps/web/src/components/editor/timeline/timeline-track.tsx')
-rw-r--r--apps/web/src/components/editor/timeline/timeline-track.tsx51
1 files changed, 48 insertions, 3 deletions
diff --git a/apps/web/src/components/editor/timeline/timeline-track.tsx b/apps/web/src/components/editor/timeline/timeline-track.tsx
index 1982d03e..ff4797fb 100644
--- a/apps/web/src/components/editor/timeline/timeline-track.tsx
+++ b/apps/web/src/components/editor/timeline/timeline-track.tsx
@@ -4,11 +4,10 @@ import { useRef, useState, useEffect } from "react";
import { useTimelineStore } from "@/stores/timeline-store";
import { useMediaStore } from "@/stores/media-store";
import { toast } from "sonner";
+import { processMediaFiles } from "@/lib/media-processing";
import { TimelineElement } from "./timeline-element";
import {
TimelineTrack,
- sortTracksByOrder,
- ensureMainTrack,
getMainTrack,
canElementGoOnTrack,
} from "@/types/timeline";
@@ -16,6 +15,7 @@ import { usePlaybackStore } from "@/stores/playback-store";
import type {
TimelineElement as TimelineElementType,
DragData,
+ TrackType,
} from "@/types/timeline";
import {
snapTimeToFrame,
@@ -689,8 +689,9 @@ export function TimelineTrackContent({
const hasMediaItem = e.dataTransfer.types.includes(
"application/x-media-item"
);
+ const hasFiles = e.dataTransfer.files?.length > 0;
- if (!hasTimelineElement && !hasMediaItem) return;
+ if (!hasTimelineElement && !hasMediaItem && !hasFiles) return;
const trackContainer = e.currentTarget.querySelector(
".track-elements-container"
@@ -1050,6 +1051,50 @@ export function TimelineTrackContent({
trimEnd: 0,
});
}
+ } else if (hasFiles) {
+ // External file drops
+ const { activeProject } = useProjectStore.getState();
+ const { addMediaItem } = useMediaStore.getState();
+ const { addElementToTrack } = useTimelineStore.getState();
+
+ if (!activeProject) {
+ toast.error("No active project");
+ return;
+ }
+
+ // Process and add files to new timeline tracks at playhead position
+ processMediaFiles(e.dataTransfer.files)
+ .then(async (processedItems) => {
+ for (const processedItem of processedItems) {
+ await addMediaItem(activeProject.id, processedItem);
+ const currentMediaItems = useMediaStore.getState().mediaItems;
+ const addedItem = currentMediaItems.find(
+ (item) =>
+ item.name === processedItem.name &&
+ item.url === processedItem.url
+ );
+
+ if (addedItem) {
+ const trackType: TrackType =
+ addedItem.type === "audio" ? "audio" : "media";
+ const targetTrackId = insertTrackAt(trackType, 0);
+
+ addElementToTrack(targetTrackId, {
+ type: "media",
+ mediaId: addedItem.id,
+ name: addedItem.name,
+ duration: addedItem.duration || 5,
+ startTime: currentTime,
+ trimStart: 0,
+ trimEnd: 0,
+ });
+ }
+ }
+ })
+ .catch((error) => {
+ console.error("Error processing external files:", error);
+ toast.error("Failed to process dropped files");
+ });
}
} catch (error) {
console.error("Error handling drop:", error);