From d908448a3e4e5fc17febe765163c93779dc393bc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Mar 2026 22:00:52 +0000 Subject: [PATCH] feat: add None option to remove premade backgrounds Co-authored-by: lawrence-mil <221152068+lawrence-mil@users.noreply.github.com> --- src/components/video-editor/SettingsPanel.tsx | 36 ++++++++++++++----- src/components/video-editor/VideoPlayback.tsx | 16 ++++++--- src/i18n/locales/en/settings.json | 1 + src/i18n/locales/es/settings.json | 1 + src/i18n/locales/zh-CN/settings.json | 1 + src/lib/exporter/frameRenderer.ts | 8 ++++- src/lib/wallpapers.ts | 3 ++ 7 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/components/video-editor/SettingsPanel.tsx b/src/components/video-editor/SettingsPanel.tsx index 1cbf39b7..2c983e26 100644 --- a/src/components/video-editor/SettingsPanel.tsx +++ b/src/components/video-editor/SettingsPanel.tsx @@ -1,7 +1,7 @@ import { cn } from "@/lib/utils"; import { useEffect, useRef } from "react"; import { getAssetPath, getRenderableAssetUrl } from "@/lib/assetPath"; -import { BUILT_IN_WALLPAPERS, WALLPAPER_PATHS, WALLPAPER_RELATIVE_PATHS } from "@/lib/wallpapers"; +import { BUILT_IN_WALLPAPERS, NO_BACKGROUND, WALLPAPER_PATHS, WALLPAPER_RELATIVE_PATHS } from "@/lib/wallpapers"; import { SliderControl } from "./SliderControl"; import { Switch } from "@/components/ui/switch"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; @@ -631,14 +631,32 @@ export function SettingsPanel({ accept=".jpg,.jpeg,image/jpeg" className="hidden" /> - +
+
onWallpaperChange(NO_BACKGROUND)} + role="button" + /> + +
{customImages.map((imageUrl, idx) => { diff --git a/src/components/video-editor/VideoPlayback.tsx b/src/components/video-editor/VideoPlayback.tsx index 6c5b7f0d..36313d84 100644 --- a/src/components/video-editor/VideoPlayback.tsx +++ b/src/components/video-editor/VideoPlayback.tsx @@ -1,7 +1,7 @@ import type React from "react"; import { useEffect, useRef, useImperativeHandle, forwardRef, useState, useMemo, useCallback } from "react"; import { getAssetPath, getRenderableAssetUrl } from "@/lib/assetPath"; -import { DEFAULT_WALLPAPER_PATH, DEFAULT_WALLPAPER_RELATIVE_PATH } from "@/lib/wallpapers"; +import { DEFAULT_WALLPAPER_PATH, DEFAULT_WALLPAPER_RELATIVE_PATH, NO_BACKGROUND } from "@/lib/wallpapers"; import { Application, Container, Sprite, Graphics, BlurFilter, Texture, VideoSource } from 'pixi.js'; import { MotionBlurFilter } from 'pixi-filters/motion-blur'; import { ZOOM_DEPTH_SCALES, type ZoomRegion, type ZoomFocus, type ZoomDepth, type TrimRegion, type SpeedRegion, type AnnotationRegion, type CursorTelemetryPoint } from "./types"; @@ -1024,10 +1024,13 @@ const VideoPlayback = forwardRef(({ }; }, []) + const isNoBackground = wallpaper === NO_BACKGROUND; const isImageUrl = Boolean(resolvedWallpaper && (resolvedWallpaper.startsWith('file://') || resolvedWallpaper.startsWith('http') || resolvedWallpaper.startsWith('/') || resolvedWallpaper.startsWith('data:'))) - const backgroundStyle = isImageUrl - ? { backgroundImage: `url(${resolvedWallpaper || ''})` } - : { background: resolvedWallpaper || '' }; + const backgroundStyle = isNoBackground + ? {} + : isImageUrl + ? { backgroundImage: `url(${resolvedWallpaper || ''})` } + : { background: resolvedWallpaper || '' }; const nativeAspectRatio = (() => { const locked = lockedVideoDimensionsRef.current; @@ -1046,7 +1049,10 @@ const VideoPlayback = forwardRef(({ {/* Background layer */}
0 ? `blur(${backgroundBlur}px)` : 'none', }} diff --git a/src/i18n/locales/en/settings.json b/src/i18n/locales/en/settings.json index 2405ce5f..46a76248 100644 --- a/src/i18n/locales/en/settings.json +++ b/src/i18n/locales/en/settings.json @@ -34,6 +34,7 @@ }, "background": { "title": "Background", + "none": "None", "image": "Image", "color": "Color", "gradient": "Gradient", diff --git a/src/i18n/locales/es/settings.json b/src/i18n/locales/es/settings.json index 7b3a1379..1eb012fd 100644 --- a/src/i18n/locales/es/settings.json +++ b/src/i18n/locales/es/settings.json @@ -34,6 +34,7 @@ }, "background": { "title": "Fondo", + "none": "Ninguno", "image": "Imagen", "color": "Color", "gradient": "Degradado", diff --git a/src/i18n/locales/zh-CN/settings.json b/src/i18n/locales/zh-CN/settings.json index 46106e60..310a8cc3 100644 --- a/src/i18n/locales/zh-CN/settings.json +++ b/src/i18n/locales/zh-CN/settings.json @@ -34,6 +34,7 @@ }, "background": { "title": "背景", + "none": "无", "image": "图片", "color": "颜色", "gradient": "渐变", diff --git a/src/lib/exporter/frameRenderer.ts b/src/lib/exporter/frameRenderer.ts index 65dc925d..8805ef1a 100644 --- a/src/lib/exporter/frameRenderer.ts +++ b/src/lib/exporter/frameRenderer.ts @@ -8,6 +8,7 @@ import { applyZoomTransform, computeFocusFromTransform, computeZoomTransform, cr import { DEFAULT_FOCUS, ZOOM_SCALE_DEADZONE, ZOOM_TRANSLATION_DEADZONE_PX } from '@/components/video-editor/videoPlayback/constants'; import { renderAnnotations } from './annotationRenderer'; import { PixiCursorOverlay, DEFAULT_CURSOR_CONFIG, preloadCursorAssets } from '@/components/video-editor/videoPlayback/cursorRenderer'; +import { NO_BACKGROUND } from '@/lib/wallpapers'; interface FrameRenderConfig { width: number; @@ -187,6 +188,11 @@ export class FrameRenderer { private async setupBackground(): Promise { const wallpaper = await this.resolveWallpaperForExport(this.config.wallpaper); + // No background requested — leave the composite canvas transparent + if (this.config.wallpaper === NO_BACKGROUND) { + return; + } + // Create background canvas for separate rendering (not affected by zoom) const bgCanvas = document.createElement('canvas'); bgCanvas.width = this.config.width; @@ -615,7 +621,7 @@ export class FrameRenderer { } else { ctx.drawImage(bgCanvas, 0, 0, w, h); } - } else { + } else if (this.config.wallpaper !== NO_BACKGROUND) { console.warn('[FrameRenderer] No background sprite found during compositing!'); } diff --git a/src/lib/wallpapers.ts b/src/lib/wallpapers.ts index 4540fe6c..7b6be16f 100644 --- a/src/lib/wallpapers.ts +++ b/src/lib/wallpapers.ts @@ -35,3 +35,6 @@ export const WALLPAPER_PATHS = BUILT_IN_WALLPAPERS.map((wallpaper) => wallpaper. export const WALLPAPER_RELATIVE_PATHS = BUILT_IN_WALLPAPERS.map((wallpaper) => wallpaper.relativePath); export const DEFAULT_WALLPAPER_PATH = WALLPAPER_PATHS[0]; export const DEFAULT_WALLPAPER_RELATIVE_PATH = WALLPAPER_RELATIVE_PATHS[0]; + +/** Sentinel value indicating no background should be rendered. */ +export const NO_BACKGROUND = 'none';