From 7bf0984698e43b9aa2dd879f65951318ed410390 Mon Sep 17 00:00:00 2001 From: Maze <167211895+mazeincoding@users.noreply.github.com> Date: Sat, 31 Jan 2026 00:20:04 +0100 Subject: codebase overhaul (#697) --- .../components/editor/media-panel/views/media.tsx | 545 --------------------- 1 file changed, 545 deletions(-) delete mode 100644 apps/web/src/components/editor/media-panel/views/media.tsx (limited to 'apps/web/src/components/editor/media-panel/views/media.tsx') diff --git a/apps/web/src/components/editor/media-panel/views/media.tsx b/apps/web/src/components/editor/media-panel/views/media.tsx deleted file mode 100644 index 07a44a7c..00000000 --- a/apps/web/src/components/editor/media-panel/views/media.tsx +++ /dev/null @@ -1,545 +0,0 @@ -"use client"; - -import { useDragDrop } from "@/hooks/use-drag-drop"; -import { processMediaFiles } from "@/lib/media-processing"; -import { useMediaStore } from "@/stores/media-store"; -import { MediaFile } from "@/types/media"; -import { - ArrowDown01, - CloudUpload, - Grid2X2, - Image, - List, - Loader2, - Music, - Video, -} from "lucide-react"; -import { useRef, useState, useMemo } from "react"; -import { useHighlightScroll } from "@/hooks/use-highlight-scroll"; -import { toast } from "sonner"; -import { Button } from "@/components/ui/button"; -import { MediaDragOverlay } from "@/components/editor/media-panel/drag-overlay"; -import { - ContextMenu, - ContextMenuContent, - ContextMenuItem, - ContextMenuTrigger, -} from "@/components/ui/context-menu"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; -import { DraggableMediaItem } from "@/components/ui/draggable-item"; -import { useProjectStore } from "@/stores/project-store"; -import { useTimelineStore } from "@/stores/timeline-store"; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "@/components/ui/tooltip"; -import { usePanelStore } from "@/stores/panel-store"; -import { useMediaPanelStore } from "../store"; - -function MediaItemWithContextMenu({ - item, - children, - onRemove, -}: { - item: MediaFile; - children: React.ReactNode; - onRemove: (e: React.MouseEvent, id: string) => Promise; -}) { - return ( - - {children} - - Export clips - onRemove(e, item.id)} - > - Delete - - - - ); -} - -export function MediaView() { - const { mediaFiles, addMediaFile, removeMediaFile } = useMediaStore(); - const { activeProject } = useProjectStore(); - const { mediaViewMode, setMediaViewMode } = usePanelStore(); - const fileInputRef = useRef(null); - const [isProcessing, setIsProcessing] = useState(false); - const [progress, setProgress] = useState(0); - const [sortBy, setSortBy] = useState<"name" | "type" | "duration" | "size">( - "name" - ); - const [sortOrder, setSortOrder] = useState<"asc" | "desc">("asc"); - const { highlightMediaId, clearHighlight } = useMediaPanelStore(); - const { highlightedId, registerElement } = useHighlightScroll( - highlightMediaId, - clearHighlight - ); - - const processFiles = async (files: FileList | File[]) => { - if (!files || files.length === 0) return; - if (!activeProject) { - toast.error("No active project"); - return; - } - - setIsProcessing(true); - setProgress(0); - try { - const processedItems = await processMediaFiles(files, (p) => - setProgress(p) - ); - for (const item of processedItems) { - await addMediaFile(activeProject.id, item); - } - } catch (error) { - console.error("Error processing files:", error); - toast.error("Failed to process files"); - } finally { - setIsProcessing(false); - setProgress(0); - } - }; - - const { isDragOver, dragProps } = useDragDrop({ - // When files are dropped, process them - onDrop: processFiles, - }); - - const handleFileSelect = () => fileInputRef.current?.click(); // Open file picker - - const handleFileChange = (e: React.ChangeEvent) => { - if (e.target.files) processFiles(e.target.files); - e.target.value = ""; // Reset input - }; - - const handleRemove = async (e: React.MouseEvent, id: string) => { - e.stopPropagation(); - - if (!activeProject) { - toast.error("No active project"); - return; - } - - await removeMediaFile(activeProject.id, id); - }; - - const formatDuration = (duration: number) => { - // Format seconds as mm:ss - const min = Math.floor(duration / 60); - const sec = Math.floor(duration % 60); - return `${min}:${sec.toString().padStart(2, "0")}`; - }; - - const filteredMediaItems = useMemo(() => { - let filtered = mediaFiles.filter((item) => { - if (item.ephemeral) return false; - return true; - }); - - filtered.sort((a, b) => { - let valueA: string | number; - let valueB: string | number; - - switch (sortBy) { - case "name": - valueA = a.name.toLowerCase(); - valueB = b.name.toLowerCase(); - break; - case "type": - valueA = a.type; - valueB = b.type; - break; - case "duration": - valueA = a.duration || 0; - valueB = b.duration || 0; - break; - case "size": - valueA = a.file.size; - valueB = b.file.size; - break; - default: - return 0; - } - - if (valueA < valueB) return sortOrder === "asc" ? -1 : 1; - if (valueA > valueB) return sortOrder === "asc" ? 1 : -1; - return 0; - }); - - return filtered; - }, [mediaFiles, sortBy, sortOrder]); - - const previewComponents = useMemo(() => { - const previews = new Map(); - - filteredMediaItems.forEach((item) => { - let preview: React.ReactNode; - - if (item.type === "image") { - preview = ( -
- {item.name} -
- ); - } else if (item.type === "video") { - if (item.thumbnailUrl) { - preview = ( -
- {item.name} -
-
- {item.duration && ( -
- {formatDuration(item.duration)} -
- )} -
- ); - } else { - preview = ( -
-
- ); - } - } else if (item.type === "audio") { - preview = ( -
- - Audio - {item.duration && ( - - {formatDuration(item.duration)} - - )} -
- ); - } else { - preview = ( -
- - Unknown -
- ); - } - - previews.set(item.id, preview); - }); - - return previews; - }, [filteredMediaItems]); - - const renderPreview = (item: MediaFile) => previewComponents.get(item.id); - - return ( - <> - {/* Hidden file input for uploading media */} - - -
-
- {/* Search and filter controls */} -
- -
- - - - - - -

- {mediaViewMode === "grid" - ? "Switch to list view" - : "Switch to grid view"} -

-
- - - - - - - - - { - if (sortBy === "name") { - setSortOrder( - sortOrder === "asc" ? "desc" : "asc" - ); - } else { - setSortBy("name"); - setSortOrder("asc"); - } - }} - > - Name{" "} - {sortBy === "name" && - (sortOrder === "asc" ? "↑" : "↓")} - - { - if (sortBy === "type") { - setSortOrder( - sortOrder === "asc" ? "desc" : "asc" - ); - } else { - setSortBy("type"); - setSortOrder("asc"); - } - }} - > - Type{" "} - {sortBy === "type" && - (sortOrder === "asc" ? "↑" : "↓")} - - { - if (sortBy === "duration") { - setSortOrder( - sortOrder === "asc" ? "desc" : "asc" - ); - } else { - setSortBy("duration"); - setSortOrder("asc"); - } - }} - > - Duration{" "} - {sortBy === "duration" && - (sortOrder === "asc" ? "↑" : "↓")} - - { - if (sortBy === "size") { - setSortOrder( - sortOrder === "asc" ? "desc" : "asc" - ); - } else { - setSortBy("size"); - setSortOrder("asc"); - } - }} - > - File Size{" "} - {sortBy === "size" && - (sortOrder === "asc" ? "↑" : "↓")} - - - - -

- Sort by {sortBy} ( - {sortOrder === "asc" ? "ascending" : "descending"}) -

-
-
-
-
-
-
-
- -
-
- {isDragOver || filteredMediaItems.length === 0 ? ( - - ) : mediaViewMode === "grid" ? ( - - ) : ( - - )} -
-
-
- - ); -} - -function GridView({ - filteredMediaItems, - renderPreview, - handleRemove, - highlightedId, - registerElement, -}: { - filteredMediaItems: MediaFile[]; - renderPreview: (item: MediaFile) => React.ReactNode; - handleRemove: (e: React.MouseEvent, id: string) => Promise; - highlightedId: string | null; - registerElement: (id: string, element: HTMLElement | null) => void; -}) { - const { addElementAtTime } = useTimelineStore(); - - return ( -
- {filteredMediaItems.map((item) => ( -
registerElement(item.id, el)}> - - - addElementAtTime(item, currentTime) - } - rounded={false} - variant="card" - isHighlighted={highlightedId === item.id} - /> - -
- ))} -
- ); -} - -function ListView({ - filteredMediaItems, - renderPreview, - handleRemove, - highlightedId, - registerElement, -}: { - filteredMediaItems: MediaFile[]; - renderPreview: (item: MediaFile) => React.ReactNode; - handleRemove: (e: React.MouseEvent, id: string) => Promise; - highlightedId: string | null; - registerElement: (id: string, element: HTMLElement | null) => void; -}) { - const { addElementAtTime } = useTimelineStore(); - - return ( -
- {filteredMediaItems.map((item) => ( -
registerElement(item.id, el)}> - - - addElementAtTime(item, currentTime) - } - variant="compact" - isHighlighted={highlightedId === item.id} - /> - -
- ))} -
- ); -} -- cgit v1.3.1