mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
feat: allow external file drops to individual timeline tracks
This commit is contained in:
@@ -4,11 +4,10 @@ import { useRef, useState, useEffect } from "react";
|
|||||||
import { useTimelineStore } from "@/stores/timeline-store";
|
import { useTimelineStore } from "@/stores/timeline-store";
|
||||||
import { useMediaStore } from "@/stores/media-store";
|
import { useMediaStore } from "@/stores/media-store";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
import { processMediaFiles } from "@/lib/media-processing";
|
||||||
import { TimelineElement } from "./timeline-element";
|
import { TimelineElement } from "./timeline-element";
|
||||||
import {
|
import {
|
||||||
TimelineTrack,
|
TimelineTrack,
|
||||||
sortTracksByOrder,
|
|
||||||
ensureMainTrack,
|
|
||||||
getMainTrack,
|
getMainTrack,
|
||||||
canElementGoOnTrack,
|
canElementGoOnTrack,
|
||||||
} from "@/types/timeline";
|
} from "@/types/timeline";
|
||||||
@@ -689,8 +688,9 @@ export function TimelineTrackContent({
|
|||||||
const hasMediaItem = e.dataTransfer.types.includes(
|
const hasMediaItem = e.dataTransfer.types.includes(
|
||||||
"application/x-media-item"
|
"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(
|
const trackContainer = e.currentTarget.querySelector(
|
||||||
".track-elements-container"
|
".track-elements-container"
|
||||||
@@ -1050,6 +1050,47 @@ export function TimelineTrackContent({
|
|||||||
trimEnd: 0,
|
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 timeline at the drop 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) {
|
||||||
|
// Add to current track at the drop position
|
||||||
|
addElementToTrack(track.id, {
|
||||||
|
type: "media",
|
||||||
|
mediaId: addedItem.id,
|
||||||
|
name: addedItem.name,
|
||||||
|
duration: addedItem.duration || 5,
|
||||||
|
startTime: snappedTime,
|
||||||
|
trimStart: 0,
|
||||||
|
trimEnd: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error processing external files:", error);
|
||||||
|
toast.error("Failed to process dropped files");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error handling drop:", error);
|
console.error("Error handling drop:", error);
|
||||||
|
|||||||
Reference in New Issue
Block a user