feat: add None option to remove premade backgrounds

Co-authored-by: lawrence-mil <221152068+lawrence-mil@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-16 22:00:52 +00:00
co-authored by lawrence-mil
parent a678bd2e96
commit d908448a3e
7 changed files with 51 additions and 15 deletions
+27 -9
View File
@@ -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"
/>
<Button
onClick={() => fileInputRef.current?.click()}
variant="outline"
className="w-full gap-2 bg-white/5 text-slate-200 border-white/10 hover:bg-[#2563EB] hover:text-white hover:border-[#2563EB] transition-all h-7 text-[10px]"
>
<Upload className="w-3 h-3" />
{tSettings('background.uploadCustom')}
</Button>
<div className="flex gap-1.5">
<div
className={cn(
"aspect-square w-9 h-9 rounded-md border-2 overflow-hidden cursor-pointer transition-all duration-200 shadow-sm flex items-center justify-center",
selected === NO_BACKGROUND
? "border-[#2563EB] ring-1 ring-[#2563EB]/30"
: "border-white/10 hover:border-[#2563EB]/40 opacity-80 hover:opacity-100"
)}
style={{
backgroundImage: 'repeating-conic-gradient(#555 0% 25%, #333 0% 50%)',
backgroundSize: '8px 8px',
}}
aria-label={tSettings('background.none')}
title={tSettings('background.none')}
onClick={() => onWallpaperChange(NO_BACKGROUND)}
role="button"
/>
<Button
onClick={() => fileInputRef.current?.click()}
variant="outline"
className="flex-1 gap-2 bg-white/5 text-slate-200 border-white/10 hover:bg-[#2563EB] hover:text-white hover:border-[#2563EB] transition-all h-7 text-[10px]"
>
<Upload className="w-3 h-3" />
{tSettings('background.uploadCustom')}
</Button>
</div>
<div className="grid grid-cols-7 gap-1.5">
{customImages.map((imageUrl, idx) => {
+11 -5
View File
@@ -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<VideoPlaybackRef, VideoPlaybackProps>(({
};
}, [])
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<VideoPlaybackRef, VideoPlaybackProps>(({
{/* Background layer */}
<div
className="absolute inset-0 bg-cover bg-center"
style={{
style={isNoBackground ? {
backgroundImage: 'repeating-conic-gradient(#3a3a3a 0% 25%, #222 0% 50%)',
backgroundSize: '16px 16px',
} : {
...backgroundStyle,
filter: backgroundBlur > 0 ? `blur(${backgroundBlur}px)` : 'none',
}}
+1
View File
@@ -34,6 +34,7 @@
},
"background": {
"title": "Background",
"none": "None",
"image": "Image",
"color": "Color",
"gradient": "Gradient",
+1
View File
@@ -34,6 +34,7 @@
},
"background": {
"title": "Fondo",
"none": "Ninguno",
"image": "Imagen",
"color": "Color",
"gradient": "Degradado",
+1
View File
@@ -34,6 +34,7 @@
},
"background": {
"title": "背景",
"none": "无",
"image": "图片",
"color": "颜色",
"gradient": "渐变",
+7 -1
View File
@@ -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<void> {
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!');
}
+3
View File
@@ -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';