Merge pull request #614 from webadderallorg/fix/presets-crop-region

fix(presets): preserve crop region
This commit is contained in:
Phạm Thị Minh Hồng
2026-05-29 01:11:56 +07:00
committed by GitHub
3 changed files with 42 additions and 3 deletions
@@ -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);
@@ -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<string, string> = {}): 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 = () => {
@@ -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<PersistedEditorControls>;
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<EditorPresetSnapshot>)
: {};
const normalizedCropRegion = normalizeProjectEditor({
cropRegion: raw.cropRegion,
}).cropRegion;
return {
...normalizeEditorControls(normalizedPreferences, normalizedPreferences),
cropRegion: normalizedCropRegion,
autoCaptionSettings: normalizePresetAutoCaptionSettings(raw.autoCaptionSettings),
whisperExecutablePath:
normalizeNullablePath(raw.whisperExecutablePath) ??