style: introduce preview panel and move play button there

This commit is contained in:
Maze Winther
2025-06-25 23:43:10 +02:00
parent 2f3a148dd4
commit e23cf66373

View File

@ -9,7 +9,7 @@ import { useMediaStore, type MediaItem } from "@/stores/media-store";
import { usePlaybackStore } from "@/stores/playback-store"; import { usePlaybackStore } from "@/stores/playback-store";
import { VideoPlayer } from "@/components/ui/video-player"; import { VideoPlayer } from "@/components/ui/video-player";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Play, Pause, Volume2, VolumeX } from "lucide-react"; import { Play, Pause, Volume2, VolumeX, Plus } from "lucide-react";
import { useState, useRef, useEffect } from "react"; import { useState, useRef, useEffect } from "react";
interface ActiveClip { interface ActiveClip {
@ -21,8 +21,7 @@ interface ActiveClip {
export function PreviewPanel() { export function PreviewPanel() {
const { tracks } = useTimelineStore(); const { tracks } = useTimelineStore();
const { mediaItems } = useMediaStore(); const { mediaItems } = useMediaStore();
const { isPlaying, toggle, currentTime, muted, toggleMute, volume } = const { currentTime, muted, toggleMute, volume } = usePlaybackStore();
usePlaybackStore();
const [canvasSize, setCanvasSize] = useState({ width: 1920, height: 1080 }); const [canvasSize, setCanvasSize] = useState({ width: 1920, height: 1080 });
const previewRef = useRef<HTMLDivElement>(null); const previewRef = useRef<HTMLDivElement>(null);
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
@ -37,18 +36,44 @@ export function PreviewPanel() {
if (!containerRef.current) return; if (!containerRef.current) return;
const container = containerRef.current.getBoundingClientRect(); const container = containerRef.current.getBoundingClientRect();
const computedStyle = getComputedStyle(containerRef.current);
// Get padding values
const paddingTop = parseFloat(computedStyle.paddingTop);
const paddingBottom = parseFloat(computedStyle.paddingBottom);
const paddingLeft = parseFloat(computedStyle.paddingLeft);
const paddingRight = parseFloat(computedStyle.paddingRight);
// Get gap value (gap-4 = 1rem = 16px)
const gap = parseFloat(computedStyle.gap) || 16;
// Get toolbar height if it exists
const toolbar = containerRef.current.querySelector("[data-toolbar]");
const toolbarHeight = toolbar
? toolbar.getBoundingClientRect().height
: 0;
// Calculate available space after accounting for padding, gap, and toolbar
const availableWidth = container.width - paddingLeft - paddingRight;
const availableHeight =
container.height -
paddingTop -
paddingBottom -
toolbarHeight -
(toolbarHeight > 0 ? gap : 0);
const targetRatio = canvasSize.width / canvasSize.height; const targetRatio = canvasSize.width / canvasSize.height;
const containerRatio = container.width / container.height; const containerRatio = availableWidth / availableHeight;
let width, height; let width, height;
if (containerRatio > targetRatio) { if (containerRatio > targetRatio) {
// Container is wider - constrain by height // Container is wider - constrain by height
height = container.height; height = availableHeight;
width = height * targetRatio; width = height * targetRatio;
} else { } else {
// Container is taller - constrain by width // Container is taller - constrain by width
width = container.width; width = availableWidth;
height = width / targetRatio; height = width / targetRatio;
} }
@ -206,21 +231,12 @@ export function PreviewPanel() {
)} )}
{muted || volume === 0 ? "Unmute" : "Mute"} {muted || volume === 0 ? "Unmute" : "Mute"}
</Button> </Button>
<Button variant="outline" size="sm" onClick={toggle}>
{isPlaying ? (
<Pause className="h-3 w-3 mr-1" />
) : (
<Play className="h-3 w-3 mr-1" />
)}
{isPlaying ? "Pause" : "Play"}
</Button>
</div> </div>
{/* Preview Area */} {/* Preview Area */}
<div <div
ref={containerRef} ref={containerRef}
className="flex-1 flex items-center justify-center p-2 sm:p-4 min-h-0 min-w-0" className="flex-1 flex flex-col items-center justify-center p-3 min-h-0 min-w-0 gap-4"
> >
<div <div
ref={previewRef} ref={previewRef}
@ -240,7 +256,28 @@ export function PreviewPanel() {
activeClips.map((clipData, index) => renderClip(clipData, index)) activeClips.map((clipData, index) => renderClip(clipData, index))
)} )}
</div> </div>
<PreviewToolbar />
</div> </div>
</div> </div>
); );
} }
function PreviewToolbar() {
const { isPlaying, toggle } = usePlaybackStore();
return (
<div
data-toolbar
className="flex items-center justify-center gap-2 px-4 pt-2 bg-background-500 w-full"
>
<Button variant="text" size="icon" onClick={toggle}>
{isPlaying ? (
<Pause className="h-3 w-3" />
) : (
<Play className="h-3 w-3" />
)}
</Button>
</div>
);
}