mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
refactor: type-safety & separate concerns
This commit is contained in:
@@ -82,13 +82,11 @@ export function Timeline() {
|
||||
toggleTrackMute,
|
||||
dragState,
|
||||
} = useTimelineStore();
|
||||
const { mediaItems, addMediaItem } = useMediaStore();
|
||||
const { mediaFiles, addMediaFile } = useMediaStore();
|
||||
const { activeProject } = useProjectStore();
|
||||
const { currentTime, duration, seek, setDuration, isPlaying, toggle } =
|
||||
usePlaybackStore();
|
||||
const { currentTime, duration, seek, setDuration } = usePlaybackStore();
|
||||
const [isDragOver, setIsDragOver] = useState(false);
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
const [progress, setProgress] = useState(0);
|
||||
const { addElementToNewTrack } = useTimelineStore();
|
||||
const dragCounterRef = useRef(0);
|
||||
const timelineRef = useRef<HTMLDivElement>(null);
|
||||
const rulerRef = useRef<HTMLDivElement>(null);
|
||||
@@ -456,10 +454,10 @@ export function Timeline() {
|
||||
|
||||
if (dragData.type === "text") {
|
||||
// Always create new text track to avoid overlaps
|
||||
useTimelineStore.getState().addTextToNewTrack(dragData);
|
||||
addElementToNewTrack(dragData);
|
||||
} else {
|
||||
// Handle media items
|
||||
const mediaItem = mediaItems.find(
|
||||
const mediaItem = mediaFiles.find(
|
||||
(item: any) => item.id === dragData.id
|
||||
);
|
||||
if (!mediaItem) {
|
||||
@@ -467,7 +465,7 @@ export function Timeline() {
|
||||
return;
|
||||
}
|
||||
|
||||
useTimelineStore.getState().addMediaToNewTrack(mediaItem);
|
||||
addElementToNewTrack(mediaItem);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error parsing dropped item data:", error);
|
||||
@@ -480,17 +478,12 @@ export function Timeline() {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsProcessing(true);
|
||||
setProgress(0);
|
||||
try {
|
||||
const processedItems = await processMediaFiles(
|
||||
e.dataTransfer.files,
|
||||
(p) => setProgress(p)
|
||||
);
|
||||
const processedItems = await processMediaFiles(e.dataTransfer.files);
|
||||
for (const processedItem of processedItems) {
|
||||
await addMediaItem(activeProject.id, processedItem);
|
||||
const currentMediaItems = useMediaStore.getState().mediaItems;
|
||||
const addedItem = currentMediaItems.find(
|
||||
await addMediaFile(activeProject.id, processedItem);
|
||||
const currentMediaFiles = mediaFiles;
|
||||
const addedItem = currentMediaFiles.find(
|
||||
(item) =>
|
||||
item.name === processedItem.name && item.url === processedItem.url
|
||||
);
|
||||
@@ -516,9 +509,6 @@ export function Timeline() {
|
||||
// Show error if file processing fails
|
||||
console.error("Error processing external files:", error);
|
||||
toast.error("Failed to process dropped files");
|
||||
} finally {
|
||||
setIsProcessing(false);
|
||||
setProgress(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -40,10 +40,8 @@ export function TimelineElement({
|
||||
onElementMouseDown,
|
||||
onElementClick,
|
||||
}: TimelineElementProps) {
|
||||
const { mediaItems } = useMediaStore();
|
||||
const { mediaFiles } = useMediaStore();
|
||||
const {
|
||||
updateElementTrim,
|
||||
updateElementDuration,
|
||||
removeElementFromTrack,
|
||||
removeElementFromTrackWithRipple,
|
||||
dragState,
|
||||
@@ -58,7 +56,7 @@ export function TimelineElement({
|
||||
|
||||
const mediaItem =
|
||||
element.type === "media"
|
||||
? mediaItems.find((item) => item.id === element.mediaId)
|
||||
? mediaFiles.find((file) => file.id === element.mediaId)
|
||||
: null;
|
||||
const hasAudio = mediaItem?.type === "audio" || mediaItem?.type === "video";
|
||||
|
||||
@@ -67,8 +65,6 @@ export function TimelineElement({
|
||||
element,
|
||||
track,
|
||||
zoomLevel,
|
||||
onUpdateTrim: updateElementTrim,
|
||||
onUpdateDuration: updateElementDuration,
|
||||
});
|
||||
|
||||
const { requestRevealMedia } = useMediaPanelStore.getState();
|
||||
@@ -190,7 +186,7 @@ export function TimelineElement({
|
||||
}
|
||||
|
||||
// Render media element ->
|
||||
const mediaItem = mediaItems.find((item) => item.id === element.mediaId);
|
||||
const mediaItem = mediaFiles.find((file) => file.id === element.mediaId);
|
||||
if (!mediaItem) {
|
||||
return (
|
||||
<span className="text-xs text-foreground/80 truncate">
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
canElementGoOnTrack,
|
||||
} from "@/types/timeline";
|
||||
import { usePlaybackStore } from "@/stores/playback-store";
|
||||
import { DEFAULT_TEXT_ELEMENT } from "@/constants/text-constants";
|
||||
import type {
|
||||
TimelineElement as TimelineElementType,
|
||||
DragData,
|
||||
@@ -33,7 +34,7 @@ export function TimelineTrackContent({
|
||||
zoomLevel: number;
|
||||
onSnapPointChange?: (snapPoint: SnapPoint | null) => void;
|
||||
}) {
|
||||
const { mediaItems } = useMediaStore();
|
||||
const { mediaFiles } = useMediaStore();
|
||||
const {
|
||||
tracks,
|
||||
addTrack,
|
||||
@@ -537,7 +538,7 @@ export function TimelineTrackContent({
|
||||
});
|
||||
} else {
|
||||
// Media elements
|
||||
const mediaItem = mediaItems.find(
|
||||
const mediaItem = mediaFiles.find(
|
||||
(item) => item.id === dragData.id
|
||||
);
|
||||
if (mediaItem) {
|
||||
@@ -890,29 +891,14 @@ export function TimelineTrackContent({
|
||||
}
|
||||
|
||||
addElementToTrack(targetTrackId, {
|
||||
type: "text",
|
||||
name: dragData.name || "Text",
|
||||
content: dragData.content || "Default Text",
|
||||
duration: TIMELINE_CONSTANTS.DEFAULT_TEXT_DURATION,
|
||||
...DEFAULT_TEXT_ELEMENT,
|
||||
name: dragData.name || DEFAULT_TEXT_ELEMENT.name,
|
||||
content: dragData.content || DEFAULT_TEXT_ELEMENT.content,
|
||||
startTime: textSnappedTime,
|
||||
trimStart: 0,
|
||||
trimEnd: 0,
|
||||
fontSize: 48,
|
||||
fontFamily: "Arial",
|
||||
color: "#ffffff",
|
||||
backgroundColor: "transparent",
|
||||
textAlign: "center",
|
||||
fontWeight: "normal",
|
||||
fontStyle: "normal",
|
||||
textDecoration: "none",
|
||||
x: 0,
|
||||
y: 0,
|
||||
rotation: 0,
|
||||
opacity: 1,
|
||||
});
|
||||
} else {
|
||||
// Handle media items
|
||||
const mediaItem = mediaItems.find((item) => item.id === dragData.id);
|
||||
const mediaItem = mediaFiles.find((item) => item.id === dragData.id);
|
||||
|
||||
if (!mediaItem) {
|
||||
toast.error("Media item not found");
|
||||
@@ -1054,7 +1040,7 @@ export function TimelineTrackContent({
|
||||
} else if (hasFiles) {
|
||||
// External file drops
|
||||
const { activeProject } = useProjectStore.getState();
|
||||
const { addMediaItem } = useMediaStore.getState();
|
||||
const { addMediaFile } = useMediaStore.getState();
|
||||
const { addElementToTrack } = useTimelineStore.getState();
|
||||
|
||||
if (!activeProject) {
|
||||
@@ -1066,9 +1052,9 @@ export function TimelineTrackContent({
|
||||
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(
|
||||
await addMediaFile(activeProject.id, processedItem);
|
||||
const currentMediaFiles = mediaFiles;
|
||||
const addedItem = currentMediaFiles.find(
|
||||
(item) =>
|
||||
item.name === processedItem.name &&
|
||||
item.url === processedItem.url
|
||||
|
||||
Reference in New Issue
Block a user