summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor/preview-panel.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/components/editor/preview-panel.tsx')
-rw-r--r--apps/web/src/components/editor/preview-panel.tsx100
1 files changed, 98 insertions, 2 deletions
diff --git a/apps/web/src/components/editor/preview-panel.tsx b/apps/web/src/components/editor/preview-panel.tsx
index 1cc9d976..2f76af5a 100644
--- a/apps/web/src/components/editor/preview-panel.tsx
+++ b/apps/web/src/components/editor/preview-panel.tsx
@@ -21,6 +21,8 @@ import { useState, useRef, useEffect } from "react";
import { cn } from "@/lib/utils";
import { formatTimeCode } from "@/lib/time";
import { FONT_CLASS_MAP } from "@/lib/font-config";
+import { BackgroundSettings } from "../background-settings";
+import { useProjectStore } from "@/stores/project-store";
interface ActiveElement {
element: TimelineElement;
@@ -39,6 +41,7 @@ export function PreviewPanel() {
width: 0,
height: 0,
});
+ const { activeProject } = useProjectStore();
// Calculate optimal preview size that fits in container while maintaining aspect ratio
useEffect(() => {
@@ -136,6 +139,85 @@ export function PreviewPanel() {
// Check if there are any elements in the timeline at all
const hasAnyElements = tracks.some((track) => track.elements.length > 0);
+ // Get media elements for blur background (video/image only)
+ const getBlurBackgroundElements = (): ActiveElement[] => {
+ return activeElements.filter(
+ ({ element, mediaItem }) =>
+ element.type === "media" &&
+ mediaItem &&
+ (mediaItem.type === "video" || mediaItem.type === "image") &&
+ element.mediaId !== "test" // Exclude test elements
+ );
+ };
+
+ const blurBackgroundElements = getBlurBackgroundElements();
+
+ // Render blur background layer
+ const renderBlurBackground = () => {
+ if (
+ !activeProject?.backgroundType ||
+ activeProject.backgroundType !== "blur" ||
+ blurBackgroundElements.length === 0
+ ) {
+ return null;
+ }
+
+ // Use the first media element for background (could be enhanced to use primary/focused element)
+ const backgroundElement = blurBackgroundElements[0];
+ const { element, mediaItem } = backgroundElement;
+
+ if (!mediaItem) return null;
+
+ const blurIntensity = activeProject.blurIntensity || 8;
+
+ if (mediaItem.type === "video") {
+ return (
+ <div
+ key={`blur-${element.id}`}
+ className="absolute inset-0 overflow-hidden"
+ style={{
+ filter: `blur(${blurIntensity}px)`,
+ transform: "scale(1.1)", // Slightly zoom to avoid blur edge artifacts
+ transformOrigin: "center",
+ }}
+ >
+ <VideoPlayer
+ src={mediaItem.url!}
+ poster={mediaItem.thumbnailUrl}
+ clipStartTime={element.startTime}
+ trimStart={element.trimStart}
+ trimEnd={element.trimEnd}
+ clipDuration={element.duration}
+ className="w-full h-full object-cover"
+ />
+ </div>
+ );
+ }
+
+ if (mediaItem.type === "image") {
+ return (
+ <div
+ key={`blur-${element.id}`}
+ className="absolute inset-0 overflow-hidden"
+ style={{
+ filter: `blur(${blurIntensity}px)`,
+ transform: "scale(1.1)", // Slightly zoom to avoid blur edge artifacts
+ transformOrigin: "center",
+ }}
+ >
+ <img
+ src={mediaItem.url!}
+ alt={mediaItem.name}
+ className="w-full h-full object-cover"
+ draggable={false}
+ />
+ </div>
+ );
+ }
+
+ return null;
+ };
+
// Render an element
const renderElement = (elementData: ActiveElement, index: number) => {
const { element, mediaItem } = elementData;
@@ -265,12 +347,17 @@ export function PreviewPanel() {
{hasAnyElements ? (
<div
ref={previewRef}
- className="relative overflow-hidden rounded-sm bg-black border"
+ className="relative overflow-hidden rounded-sm border"
style={{
width: previewDimensions.width,
height: previewDimensions.height,
+ backgroundColor:
+ activeProject?.backgroundType === "blur"
+ ? "transparent"
+ : activeProject?.backgroundColor || "#000000",
}}
>
+ {renderBlurBackground()}
{activeElements.length === 0 ? (
<div className="absolute inset-0 flex items-center justify-center text-muted-foreground">
No elements at current time
@@ -280,6 +367,14 @@ export function PreviewPanel() {
renderElement(elementData, index)
)
)}
+ {/* Show message when blur is selected but no media available */}
+ {activeProject?.backgroundType === "blur" &&
+ blurBackgroundElements.length === 0 &&
+ activeElements.length > 0 && (
+ <div className="absolute bottom-2 left-2 right-2 bg-black/70 text-white text-xs p-2 rounded">
+ Add a video or image to use blur background
+ </div>
+ )}
</div>
) : null}
@@ -346,7 +441,8 @@ function PreviewToolbar({ hasAnyElements }: { hasAnyElements: boolean }) {
<Play className="h-3 w-3" />
)}
</Button>
- <div>
+ <div className="flex items-center gap-3">
+ <BackgroundSettings />
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button