Skip to content

feat(editor): persist full editor preferences#1

Closed
kbdevs wants to merge 3 commits intofix/hud-reviewfrom
feat/cursor-sway
Closed

feat(editor): persist full editor preferences#1
kbdevs wants to merge 3 commits intofix/hud-reviewfrom
feat/cursor-sway

Conversation

@kbdevs
Copy link
Copy Markdown
Owner

@kbdevs kbdevs commented Mar 16, 2026

Summary

  • move the broader editor preference persistence work into its own follow-up PR
  • keep the existing aspect ratio preference behavior while also saving the expanded editor settings introduced on this branch
  • leave the HUD review fixes isolated in fix(hud): persist capture hiding review fixes webadderallorg/Recordly#40 so this preference work can be reviewed separately

Summary by cubic

Persist all editor preferences between sessions so the editor and timeline reopen with your last background, effects, crop, cursor, export, and aspect ratio (including custom X:Y). Adds a new editorPreferences module with safe normalization and unit tests.

  • New Features

    • Save/load preferences in localStorage with defaults and validation.
    • VideoEditor auto-saves preference changes; SettingsPanel remembers custom wallpapers and selected background tab; TimelineEditor restores and saves custom aspect width/height.
    • Tests cover normalization, invalid inputs, and merge behavior.
  • Bug Fixes

    • HUD overlay “hide from capture” now persists across app restarts and applies only on supported platforms (hidden on Linux). Defaults to hidden from capture.

Written for commit acf796b. Summary will update on new commits.

kbdevs added 2 commits March 15, 2026 18:27
Keep the last selected aspect ratio and custom X:Y values between editing sessions so the timeline opens with the user's preferred crop setup.
Keep the editor's background, effects, crop, cursor, and export controls between sessions so the workspace reopens with the user's last setup.
Copilot AI review requested due to automatic review settings March 16, 2026 03:31
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 5 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/components/video-editor/editorPreferences.ts">

<violation number="1" location="src/components/video-editor/editorPreferences.ts:226">
P2: Persisting uploaded wallpaper data URLs in this localStorage blob can exhaust storage quota and make all editor preferences stop saving.</violation>
</file>

<file name="src/components/video-editor/timeline/TimelineEditor.tsx">

<violation number="1" location="src/components/video-editor/timeline/TimelineEditor.tsx:682">
P2: This saves preset aspect ratios as the user's custom ratio. Because `aspectRatio` is copied into `customAspectWidth/customAspectHeight` for every non-`native` selection, choosing a preset like `1:1` will overwrite the persisted custom inputs for the next session.</violation>
</file>

<file name="src/components/video-editor/VideoEditor.tsx">

<violation number="1" location="src/components/video-editor/VideoEditor.tsx:894">
P1: The unconditional wallpaper init effect overwrites the persisted wallpaper preference on every mount. Since this effect runs with `[]` deps and `getAssetPath` is async, it will also race with `applyLoadedProject` and overwrite project-loaded wallpapers. This effect should be conditional — only resolve the default path when no custom wallpaper has been set (e.g., when the current value still matches the unresolved default).</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

const resolvedPath = await getAssetPath(
DEFAULT_WALLPAPER_RELATIVE_PATH,
);
const resolvedPath = await getAssetPath(DEFAULT_WALLPAPER_RELATIVE_PATH);
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The unconditional wallpaper init effect overwrites the persisted wallpaper preference on every mount. Since this effect runs with [] deps and getAssetPath is async, it will also race with applyLoadedProject and overwrite project-loaded wallpapers. This effect should be conditional — only resolve the default path when no custom wallpaper has been set (e.g., when the current value still matches the unresolved default).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/video-editor/VideoEditor.tsx, line 894:

<comment>The unconditional wallpaper init effect overwrites the persisted wallpaper preference on every mount. Since this effect runs with `[]` deps and `getAssetPath` is async, it will also race with `applyLoadedProject` and overwrite project-loaded wallpapers. This effect should be conditional — only resolve the default path when no custom wallpaper has been set (e.g., when the current value still matches the unresolved default).</comment>

<file context>
@@ -912,9 +891,7 @@ export default function VideoEditor() {
-        const resolvedPath = await getAssetPath(
-          DEFAULT_WALLPAPER_RELATIVE_PATH,
-        );
+        const resolvedPath = await getAssetPath(DEFAULT_WALLPAPER_RELATIVE_PATH);
         if (mounted) {
           setWallpaper(resolvedPath);
</file context>
Fix with Cubic

try {
const current = loadEditorPreferences();
const merged = normalizeEditorPreferences({ ...current, ...preferences }, current);
globalThis.localStorage.setItem(EDITOR_PREFERENCES_STORAGE_KEY, JSON.stringify(merged));
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Persisting uploaded wallpaper data URLs in this localStorage blob can exhaust storage quota and make all editor preferences stop saving.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/video-editor/editorPreferences.ts, line 226:

<comment>Persisting uploaded wallpaper data URLs in this localStorage blob can exhaust storage quota and make all editor preferences stop saving.</comment>

<file context>
@@ -0,0 +1,230 @@
+	try {
+		const current = loadEditorPreferences();
+		const merged = normalizeEditorPreferences({ ...current, ...preferences }, current);
+		globalThis.localStorage.setItem(EDITOR_PREFERENCES_STORAGE_KEY, JSON.stringify(merged));
+	} catch {
+		// Ignore storage failures so editor controls still work.
</file context>
Fix with Cubic

Comment on lines +682 to +686
saveEditorPreferences({
customAspectWidth,
customAspectHeight,
});
}, [customAspectHeight, customAspectWidth]);
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This saves preset aspect ratios as the user's custom ratio. Because aspectRatio is copied into customAspectWidth/customAspectHeight for every non-native selection, choosing a preset like 1:1 will overwrite the persisted custom inputs for the next session.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/video-editor/timeline/TimelineEditor.tsx, line 682:

<comment>This saves preset aspect ratios as the user's custom ratio. Because `aspectRatio` is copied into `customAspectWidth/customAspectHeight` for every non-`native` selection, choosing a preset like `1:1` will overwrite the persisted custom inputs for the next session.</comment>

<file context>
@@ -676,6 +678,13 @@ export default function TimelineEditor({
   }, [aspectRatio]);
 
+  useEffect(() => {
+    saveEditorPreferences({
+      customAspectWidth,
+      customAspectHeight,
</file context>
Suggested change
saveEditorPreferences({
customAspectWidth,
customAspectHeight,
});
}, [customAspectHeight, customAspectWidth]);
if (isCustomAspectRatio(aspectRatio)) {
saveEditorPreferences({
customAspectWidth,
customAspectHeight,
});
}
}, [aspectRatio, customAspectHeight, customAspectWidth]);
Fix with Cubic

@kbdevs
Copy link
Copy Markdown
Owner Author

kbdevs commented Mar 16, 2026

Closing this stacked fork PR; the changes are being kept on webadderallorg#38 instead.

@kbdevs kbdevs closed this Mar 16, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a dedicated editor-preferences persistence layer (localStorage-backed) so the video editor can restore the last-used settings across sessions, including expanded editor controls and custom aspect inputs.

Changes:

  • Introduces editorPreferences module with normalization, load/save helpers, and Vitest coverage.
  • Initializes editor/timeline/settings UI state from persisted preferences.
  • Persists editor control changes (and custom wallpapers/custom aspect inputs) back to storage.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/components/video-editor/timeline/TimelineEditor.tsx Loads/saves custom aspect ratio input preferences.
src/components/video-editor/editorPreferences.ts New preferences schema, normalization, and localStorage load/save helpers.
src/components/video-editor/editorPreferences.test.ts Adds unit tests for normalization and persistence behavior.
src/components/video-editor/VideoEditor.tsx Initializes many editor controls from preferences and persists changes.
src/components/video-editor/SettingsPanel.tsx Persists custom wallpapers list and keeps background tabs in sync with selected wallpaper type.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +122 to +123
const [wallpaper, setWallpaper] = useState<string>(initialEditorPreferences.wallpaper);
const [shadowIntensity, setShadowIntensity] = useState(initialEditorPreferences.shadowIntensity);
Comment on lines +682 to +685
saveEditorPreferences({
customAspectWidth,
customAspectHeight,
});
Comment on lines +493 to +499
useEffect(() => {
saveEditorPreferences({
wallpaper,
shadowIntensity,
backgroundBlur,
zoomMotionBlur,
connectZooms,
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/components/launch/LaunchWindow.tsx">

<violation number="1" location="src/components/launch/LaunchWindow.tsx:229">
P2: Treat the unknown platform as unsupported until `getPlatform()` resolves; otherwise the HUD capture toggle renders briefly on Linux and can call an unsupported action.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

? recordingsDirectory.split(/[\\/]/).filter(Boolean).pop() || recordingsDirectory
: "recordings";
const dividerClass = "mx-1 h-5 w-px shrink-0 bg-white/35";
const supportsHudCaptureProtection = platform !== "linux";
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Treat the unknown platform as unsupported until getPlatform() resolves; otherwise the HUD capture toggle renders briefly on Linux and can call an unsupported action.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/launch/LaunchWindow.tsx, line 229:

<comment>Treat the unknown platform as unsupported until `getPlatform()` resolves; otherwise the HUD capture toggle renders briefly on Linux and can call an unsupported action.</comment>

<file context>
@@ -204,6 +226,7 @@ export function LaunchWindow() {
 		? recordingsDirectory.split(/[\\/]/).filter(Boolean).pop() || recordingsDirectory
 		: "recordings";
 	const dividerClass = "mx-1 h-5 w-px shrink-0 bg-white/35";
+	const supportsHudCaptureProtection = platform !== "linux";
 
 	const toggleMicrophone = () => {
</file context>
Suggested change
const supportsHudCaptureProtection = platform !== "linux";
const supportsHudCaptureProtection = platform !== null && platform !== "linux";
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants