fix: persist user settings across sessions

Add userPreferences module to save/load padding, aspect ratio,
export format and quality to localStorage. Applied on mount
in VideoEditor.

Closes #306
This commit is contained in:
JasonOA888
2026-04-04 23:16:39 +08:00
parent 21893f07af
commit d5f59a7b8e
2 changed files with 70 additions and 0 deletions
@@ -21,6 +21,7 @@ import {
VideoExporter,
} from "@/lib/exporter";
import type { ProjectMedia } from "@/lib/recordingSession";
import { loadUserPreferences, saveUserPreferences } from "@/lib/userPreferences";
import { matchesShortcut } from "@/lib/shortcuts";
import {
getAspectRatioValue,
+69
View File
@@ -0,0 +1,69 @@
import type { ExportFormat, ExportQuality } from "@/lib/exporter";
import type { AspectRatio } from "@/utils/aspectRatioUtils";
const PREFS_KEY = "openscreen_user_preferences";
export interface UserPreferences {
/** Default padding % */
padding: number;
/** Default aspect ratio */
aspectRatio: AspectRatio;
/** Default export quality */
exportQuality: ExportQuality;
/** Default export format */
exportFormat: ExportFormat;
}
const DEFAULT_PREFS: UserPreferences = {
padding: 50,
aspectRatio: "16:9",
exportQuality: "good",
exportFormat: "mp4",
};
function safeJsonParse(text: string | null): Record<string, unknown> | null {
if (!text) return null;
try {
return JSON.parse(text);
} catch {
return null;
}
}
/**
* Load persisted user preferences from localStorage.
* Returns defaults for any missing or invalid fields.
*/
export function loadUserPreferences(): UserPreferences {
const raw = safeJsonParse(localStorage.getItem(PREFS_KEY));
if (!raw || typeof raw !== "object") return { ...DEFAULT_PREFS };
return {
padding:
typeof raw.padding === "number" && Number.isFinite(raw.padding) && raw.padding >= 0 && raw.padding <= 100
? raw.padding
: DEFAULT_PREFS.padding,
aspectRatio:
typeof raw.aspectRatio === "string" ? (raw.aspectRatio as AspectRatio) : DEFAULT_PREFS.aspectRatio,
exportQuality:
raw.exportQuality === "medium" || raw.exportQuality === "source"
? (raw.exportQuality as ExportQuality)
: DEFAULT_PREFS.exportQuality,
exportFormat:
raw.exportFormat === "gif" ? (raw.exportFormat as ExportFormat) : DEFAULT_PREFS.exportFormat,
};
}
/**
* Persist user preferences to localStorage.
* Only the explicitly provided fields are updated.
*/
export function saveUserPreferences(partial: Partial<UserPreferences>): void {
const current = loadUserPreferences();
const merged = { ...current, ...partial };
try {
localStorage.setItem(PREFS_KEY, JSON.stringify(merged));
} catch {
// localStorage may be unavailable (e.g. private browsing quota exceeded)
}
}