From 6ee16f9df8aeabfef0ca533f9f5b13daab3a3758 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Sun, 22 Jun 2025 19:28:03 +0200 Subject: feat: so much stuff --- apps/web/src/components/editor/media-panel.tsx | 282 ++++++++++++++++++++----- 1 file changed, 229 insertions(+), 53 deletions(-) (limited to 'apps/web/src/components/editor/media-panel.tsx') diff --git a/apps/web/src/components/editor/media-panel.tsx b/apps/web/src/components/editor/media-panel.tsx index 565a4e7d..17fe0417 100644 --- a/apps/web/src/components/editor/media-panel.tsx +++ b/apps/web/src/components/editor/media-panel.tsx @@ -4,25 +4,76 @@ import { Button } from "../ui/button"; import { AspectRatio } from "../ui/aspect-ratio"; import { DragOverlay } from "../ui/drag-overlay"; import { useMediaStore } from "@/stores/media-store"; -import { Plus, Image, Video, Music } from "lucide-react"; +import { processMediaFiles } from "@/lib/media-processing"; +import { Plus, Image, Video, Music, Trash2, Upload } from "lucide-react"; import { useDragDrop } from "@/hooks/use-drag-drop"; +import { useRef, useState } from "react"; +import { toast } from "sonner"; export function MediaPanel() { - const { mediaItems, addMediaItem } = useMediaStore(); + const { mediaItems, addMediaItem, removeMediaItem } = useMediaStore(); + const fileInputRef = useRef(null); + const [isProcessing, setIsProcessing] = useState(false); + + const processFiles = async (files: FileList | File[]) => { + setIsProcessing(true); + + try { + const processedItems = await processMediaFiles(files); + + for (const processedItem of processedItems) { + addMediaItem(processedItem); + toast.success(`Added ${processedItem.name} to project`); + } + } catch (error) { + console.error("Error processing files:", error); + toast.error("Failed to process files"); + } finally { + setIsProcessing(false); + } + }; const { isDragOver, dragProps } = useDragDrop({ onDrop: (files) => { - // TODO: Handle file drop functionality - console.log("Files dropped on media panel:", files); + processFiles(files); }, }); - const handleAddSampleMedia = () => { - // Just for testing - add a sample media item - addMediaItem({ - name: `Sample ${mediaItems.length + 1}`, - type: "image", - }); + const handleFileSelect = () => { + fileInputRef.current?.click(); + }; + + const handleFileInputChange = (e: React.ChangeEvent) => { + if (e.target.files && e.target.files.length > 0) { + processFiles(e.target.files); + // Reset the input so the same file can be selected again + e.target.value = ""; + } + }; + + const handleRemoveItem = (e: React.MouseEvent, itemId: string) => { + e.stopPropagation(); + removeMediaItem(itemId); + toast.success("Media removed from project"); + }; + + const handleDragStart = (e: React.DragEvent, item: any) => { + // Mark this as an internal app drag + e.dataTransfer.setData( + "application/x-media-item", + JSON.stringify({ + id: item.id, + type: item.type, + name: item.name, + }) + ); + e.dataTransfer.effectAllowed = "copy"; + }; + + const formatDuration = (duration: number) => { + const minutes = Math.floor(duration / 60); + const seconds = Math.floor(duration % 60); + return `${minutes}:${seconds.toString().padStart(2, "0")}`; }; const getMediaIcon = (type: string) => { @@ -36,63 +87,188 @@ export function MediaPanel() { } }; - return ( -
- - -
- {/* Media Grid */} - {mediaItems.length === 0 ? ( - + const renderMediaPreview = (item: any) => { + switch (item.type) { + case "image": + return ( + {item.name} handleDragStart(e, item)} + /> + ); + case "video": + return item.thumbnailUrl ? ( +
+ {item.name} handleDragStart(e, item)} + /> +
+
+ {item.duration && ( +
+ {formatDuration(item.duration)} +
+ )} +
) : ( -
- {mediaItems.map((item) => ( - + + {/* Remove button - positioned outside the button container */} +
e.preventDefault()} + onDrag={(e) => e.preventDefault()} + > +
- - - ))} -
- )} +
+ ))} +
+ )} + - + ); } -function EmptyMedia({ onAddSample }: { onAddSample: () => void }) { +function EmptyMedia({ + onFileSelect, + isProcessing, +}: { + onFileSelect: () => void; + isProcessing: boolean; +}) { return (
- + {isProcessing ? ( +
+ +
+ ) : ( + + )}
-

No media in project

+

+ {isProcessing ? "Processing files..." : "No media in project"} +

- Drag files or click to add media + {isProcessing + ? "Please wait while files are being processed" + : "Drag files or click to add media"}

- + {!isProcessing && ( + + )}
); } -- cgit v1.3.1