diff --git a/src/app/page.tsx b/src/app/page.tsx
index 637feae3..ce473c3f 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,5 +1,6 @@
import VideoEditor from "@/components/VideoEditor";
-import Footer from "@/components/Footer";
+import Footer from "@/components/Footer";
+import PrivacyBanner from "@/components/PrivacyBanner";
export default function Home() {
return (
@@ -14,6 +15,7 @@ export default function Home() {
+
@@ -21,4 +23,4 @@ export default function Home() {
>
);
}
-
+
diff --git a/src/components/PrivacyBanner.tsx b/src/components/PrivacyBanner.tsx
new file mode 100644
index 00000000..e7dd86c9
--- /dev/null
+++ b/src/components/PrivacyBanner.tsx
@@ -0,0 +1,59 @@
+"use client";
+
+import { useEffect, useState } from "react";
+
+const STORAGE_KEY = "reframe-privacy-banner-dismissed";
+
+export default function PrivacyBanner() {
+ const [visible, setVisible] = useState(false);
+
+ useEffect(() => {
+ const dismissedAt = localStorage.getItem(STORAGE_KEY);
+
+ if (!dismissedAt) {
+ setVisible(true);
+ return;
+ }
+
+ const sevenDays = 7 * 24 * 60 * 60 * 1000;
+ const expired = Date.now() - Number(dismissedAt) > sevenDays;
+
+ if (expired) {
+ localStorage.removeItem(STORAGE_KEY);
+ setVisible(true);
+ }
+ }, []);
+
+ const handleClose = () => {
+ localStorage.setItem(STORAGE_KEY, Date.now().toString());
+ setVisible(false);
+ };
+
+ if (!visible) return null;
+
+ return (
+
+
+
+
+ Your videos never leave your device.
+
+
+
+ Processing is done entirely in your browser using FFmpeg.wasm.
+ No server, no upload, no account required.
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/VideoPreview.tsx b/src/components/VideoPreview.tsx
index 71095330..bd8cf48a 100644
--- a/src/components/VideoPreview.tsx
+++ b/src/components/VideoPreview.tsx
@@ -4,9 +4,11 @@
import { useEffect, useRef, useState, useCallback, RefObject } from "react";
import { EditRecipe } from "@/lib/types";
import { getPresetById } from "@/lib/presets";
+
import { cn } from "@/lib/utils";
import { Camera } from "lucide-react";
+
interface Props {
file: File | null;
recipe?: EditRecipe;
@@ -113,6 +115,40 @@ export default function VideoPreview({ file, recipe, videoRef }: Props) {
videoRef.current.playbackRate = recipe.speed;
}, [recipe, videoRef]);
+ const preset =
+ recipe.preset !== "custom"
+ ? getPresetById(recipe.preset)
+ : null;
+
+ const previewWidth =
+ recipe.preset === "custom"
+ ? recipe.customWidth || 1920
+ : preset?.width || 1920;
+
+ const previewHeight =
+ recipe.preset === "custom"
+ ? recipe.customHeight || 1080
+ : preset?.height || 1080;
+
+ const aspectRatio = `${previewWidth}/${previewHeight}`;
+ return (
+
+
+
);
-}
\ No newline at end of file
+}