diff options
| author | Maze Winther <mazewinther@gmail.com> | 2025-08-26 15:04:25 +0200 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2025-08-26 15:04:25 +0200 |
| commit | b459b46802a760a4a81ce91fdf24390e07375fb0 (patch) | |
| tree | e0070578d2b57acfba5f119cbf1abc6c9db5e741 /apps/web/src/components/editor/timeline | |
| parent | 2f7cd11ca123884969f90a94e59593d355518839 (diff) | |
| download | opencut-b459b46802a760a4a81ce91fdf24390e07375fb0.tar.gz | |
refactor: type-safety & separate concerns
Diffstat (limited to 'apps/web/src/components/editor/timeline')
3 files changed, 24 insertions, 52 deletions
diff --git a/apps/web/src/components/editor/timeline/index.tsx b/apps/web/src/components/editor/timeline/index.tsx index 284384eb..49769989 100644 --- a/apps/web/src/components/editor/timeline/index.tsx +++ b/apps/web/src/components/editor/timeline/index.tsx @@ -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); } } }; diff --git a/apps/web/src/components/editor/timeline/timeline-element.tsx b/apps/web/src/components/editor/timeline/timeline-element.tsx index a1a33837..300c4c7b 100644 --- a/apps/web/src/components/editor/timeline/timeline-element.tsx +++ b/apps/web/src/components/editor/timeline/timeline-element.tsx @@ -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"> diff --git a/apps/web/src/components/editor/timeline/timeline-track.tsx b/apps/web/src/components/editor/timeline/timeline-track.tsx index 5a037710..ad3ca9b7 100644 --- a/apps/web/src/components/editor/timeline/timeline-track.tsx +++ b/apps/web/src/components/editor/timeline/timeline-track.tsx @@ -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 |
