From 970c473df75c9de1e55f4a60e6c4ec70829fc123 Mon Sep 17 00:00:00 2001 From: wiiiii123 Date: Fri, 29 May 2026 01:00:49 +0700 Subject: [PATCH] fix(presets): preserve crop region --- src/components/video-editor/VideoEditor.tsx | 3 ++ .../video-editor/editorPreferences.test.ts | 32 ++++++++++++++++++- .../video-editor/editorPreferences.ts | 10 ++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/components/video-editor/VideoEditor.tsx b/src/components/video-editor/VideoEditor.tsx index 4644abe07..574ecd4a0 100644 --- a/src/components/video-editor/VideoEditor.tsx +++ b/src/components/video-editor/VideoEditor.tsx @@ -705,6 +705,7 @@ export default function VideoEditor() { borderRadius, padding: { ...padding }, frame, + cropRegion: { ...cropRegion }, webcam: { ...webcam }, aspectRatio, exportEncodingMode, @@ -756,6 +757,7 @@ export default function VideoEditor() { borderRadius, padding, frame, + cropRegion, webcam, aspectRatio, exportEncodingMode, @@ -848,6 +850,7 @@ export default function VideoEditor() { setBorderRadius(snapshot.borderRadius); setPadding({ ...snapshot.padding }); setFrame(snapshot.frame); + setCropRegion({ ...snapshot.cropRegion }); setWebcam({ ...snapshot.webcam }); setAspectRatio(snapshot.aspectRatio); setExportEncodingMode(snapshot.exportEncodingMode); diff --git a/src/components/video-editor/editorPreferences.test.ts b/src/components/video-editor/editorPreferences.test.ts index 4f80b660d..b3124acb9 100644 --- a/src/components/video-editor/editorPreferences.test.ts +++ b/src/components/video-editor/editorPreferences.test.ts @@ -10,7 +10,7 @@ import { saveEditorPreferences, saveEditorPresets, } from "./editorPreferences"; -import { DEFAULT_AUTO_CAPTION_SETTINGS } from "./types"; +import { DEFAULT_AUTO_CAPTION_SETTINGS, DEFAULT_CROP_REGION } from "./types"; function createStorageMock(initialValues: Record = {}): Storage { const store = new Map(Object.entries(initialValues)); @@ -358,6 +358,7 @@ describe("editorPreferences", () => { updatedAt: "2026-05-01T00:00:00.000Z", snapshot: { ...DEFAULT_EDITOR_PREFERENCES, + cropRegion: DEFAULT_CROP_REGION, autoCaptionSettings: DEFAULT_AUTO_CAPTION_SETTINGS, }, }, @@ -385,6 +386,7 @@ describe("editorPreferences", () => { updatedAt: "2026-05-02T00:00:00.000Z", snapshot: { ...DEFAULT_EDITOR_PREFERENCES, + cropRegion: DEFAULT_CROP_REGION, autoCaptionSettings: DEFAULT_AUTO_CAPTION_SETTINGS, }, }, @@ -399,6 +401,34 @@ describe("editorPreferences", () => { ]); }); + it("preserves crop region in editor preset snapshots", () => { + const localStorage = createStorageMock(); + vi.stubGlobal("localStorage", localStorage); + + expect( + saveEditorPresets([ + { + id: "preset-1", + name: "Cropped Demo", + createdAt: "2026-05-01T00:00:00.000Z", + updatedAt: "2026-05-01T00:00:00.000Z", + snapshot: { + ...DEFAULT_EDITOR_PREFERENCES, + cropRegion: { x: 0.08, y: 0.12, width: 0.8, height: 0.7 }, + autoCaptionSettings: DEFAULT_AUTO_CAPTION_SETTINGS, + }, + }, + ]), + ).toBe(true); + + expect(loadEditorPresets()[0]?.snapshot.cropRegion).toEqual({ + x: 0.08, + y: 0.12, + width: 0.8, + height: 0.7, + }); + }); + it("returns false when preset persistence fails", () => { const localStorage = createStorageMock(); localStorage.setItem = () => { diff --git a/src/components/video-editor/editorPreferences.ts b/src/components/video-editor/editorPreferences.ts index cbd417561..ee3bdafd6 100644 --- a/src/components/video-editor/editorPreferences.ts +++ b/src/components/video-editor/editorPreferences.ts @@ -1,12 +1,12 @@ +import { loadAppSetting, saveAppSetting } from "../../lib/appSettings"; import { normalizeExportBackendPreference, normalizeExportMp4FrameRate, normalizeExportPipelineModel, normalizeProjectEditor, - stripPersistedDevMotionBlurSettings, type ProjectEditorState, + stripPersistedDevMotionBlurSettings, } from "./projectPersistence"; -import { loadAppSetting, saveAppSetting } from "../../lib/appSettings"; type PersistedEditorControls = Pick< ProjectEditorState, @@ -61,8 +61,10 @@ type PersistedEditorControls = Pick< type PartialEditorControls = Partial; type PresetAutoCaptionSettings = ProjectEditorState["autoCaptionSettings"]; +type PresetCropRegion = ProjectEditorState["cropRegion"]; export interface EditorPresetSnapshot extends PersistedEditorControls { + cropRegion: PresetCropRegion; autoCaptionSettings: PresetAutoCaptionSettings; whisperExecutablePath: string | null; whisperModelPath: string | null; @@ -196,9 +198,13 @@ function normalizeEditorPresetSnapshot(candidate: unknown): EditorPresetSnapshot candidate && typeof candidate === "object" ? (candidate as Partial) : {}; + const normalizedCropRegion = normalizeProjectEditor({ + cropRegion: raw.cropRegion, + }).cropRegion; return { ...normalizeEditorControls(normalizedPreferences, normalizedPreferences), + cropRegion: normalizedCropRegion, autoCaptionSettings: normalizePresetAutoCaptionSettings(raw.autoCaptionSettings), whisperExecutablePath: normalizeNullablePath(raw.whisperExecutablePath) ??