diff --git a/apps/web/src/app/globals.css b/apps/web/src/app/globals.css index 4f9bb10..eafdc86 100644 --- a/apps/web/src/app/globals.css +++ b/apps/web/src/app/globals.css @@ -40,7 +40,7 @@ } .dark { --background: 0 0% 8%; - --foreground: 0 0% 98%; + --foreground: 0 0% 89%; --card: 0 0% 3.9%; --card-foreground: 0 0% 98%; --popover: 0 0% 14.9%; diff --git a/apps/web/src/components/editor/preview-panel.tsx b/apps/web/src/components/editor/preview-panel.tsx index 0c26948..72d5898 100644 --- a/apps/web/src/components/editor/preview-panel.tsx +++ b/apps/web/src/components/editor/preview-panel.tsx @@ -10,8 +10,16 @@ import { usePlaybackStore } from "@/stores/playback-store"; import { useEditorStore } from "@/stores/editor-store"; import { VideoPlayer } from "@/components/ui/video-player"; import { Button } from "@/components/ui/button"; -import { Play, Pause, Volume2, VolumeX, Plus } from "lucide-react"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, + DropdownMenuSeparator, +} from "@/components/ui/dropdown-menu"; +import { Play, Pause, Volume2, VolumeX, Plus, Square } from "lucide-react"; import { useState, useRef, useEffect } from "react"; +import { cn } from "@/lib/utils"; interface ActiveClip { clip: TimelineClip; @@ -189,51 +197,11 @@ export function PreviewPanel() { return (
- {/* Controls */} -
- Canvas: - - - -
- - {/* Preview Area */}
- {hasAnyClips && ( + {hasAnyClips ? (
renderClip(clipData, index)) )}
+ ) : ( + <> + {/* Empty div so toolbar stays at the bottom */} +
+ )} - {hasAnyClips && } +
); } -function PreviewToolbar() { +function PreviewToolbar({ hasAnyClips }: { hasAnyClips: boolean }) { const { isPlaying, toggle } = usePlaybackStore(); + const { + canvasSize, + canvasPresets, + setCanvasSize, + setCanvasSizeFromAspectRatio, + } = useEditorStore(); + const { mediaItems } = useMediaStore(); + const { tracks } = useTimelineStore(); + + // Find the current preset based on canvas size + const currentPreset = canvasPresets.find( + (preset) => + preset.width === canvasSize.width && preset.height === canvasSize.height + ); + + const handlePresetSelect = (preset: { width: number; height: number }) => { + setCanvasSize({ width: preset.width, height: preset.height }); + }; + + // Get the first video/image media item to determine original aspect ratio + const getOriginalAspectRatio = () => { + // Find first video or image in timeline + for (const track of tracks) { + for (const clip of track.clips) { + const mediaItem = mediaItems.find((item) => item.id === clip.mediaId); + if ( + mediaItem && + (mediaItem.type === "video" || mediaItem.type === "image") + ) { + return mediaItem.aspectRatio || 16 / 9; // Default to 16:9 if aspectRatio not available + } + } + } + return 16 / 9; // Default aspect ratio + }; + + const handleOriginalSelect = () => { + const aspectRatio = getOriginalAspectRatio(); + setCanvasSizeFromAspectRatio(aspectRatio); + }; + + // Check if current size is "Original" (not matching any preset) + const isOriginal = !currentPreset; return (
- +
+ + + + + + + Original + + + {canvasPresets.map((preset) => ( + handlePresetSelect(preset)} + className={cn( + "text-xs", + currentPreset?.name === preset.name && "font-semibold" + )} + > + {preset.name} + + ))} + + +
); }