diff --git a/src/features/editor/components/editor.test.tsx b/src/features/editor/components/editor.test.tsx index e43244e0..601f6831 100644 --- a/src/features/editor/components/editor.test.tsx +++ b/src/features/editor/components/editor.test.tsx @@ -168,8 +168,8 @@ vi.mock('@/shared/state/editor-panel-layout-store', () => ({ tools: 25, preview: 50, properties: 25, - mainContent: 50, - timeline: 50, + mainContent: 72, + timeline: 28, }, setPanel: vi.fn(), }), @@ -259,12 +259,6 @@ vi.mock('@/shared/ui/editor-layout', async (importOriginal) => { const actual = await importOriginal(); return { ...actual, - getEditorLayout: () => ({ - ...actual.getEditorLayout(), - timelineDefaultSize: 35, - timelineMinSize: 20, - timelineMaxSize: 60, - }), getEditorLayoutCssVars: () => ({}), }; }); diff --git a/src/shared/state/editor-panel-layout-store.test.ts b/src/shared/state/editor-panel-layout-store.test.ts new file mode 100644 index 00000000..9afdd8bc --- /dev/null +++ b/src/shared/state/editor-panel-layout-store.test.ts @@ -0,0 +1,48 @@ +import { describe, expect, it } from 'vitest'; +import { migrateEditorPanelLayout } from './editor-panel-layout-store'; +import { EDITOR_LAYOUT } from '@/shared/ui/editor-layout'; + +const v1DefaultState = { + panels: { + tools: 25, + preview: 50, + properties: 25, + mainContent: 50, + timeline: 50, + }, +}; + +describe('migrateEditorPanelLayout', () => { + it('moves an untouched v1 default split to the EDITOR_LAYOUT default', () => { + const migrated = migrateEditorPanelLayout(v1DefaultState, 1); + + expect(migrated.panels?.timeline).toBe(EDITOR_LAYOUT.timelineDefaultSize); + expect(migrated.panels?.mainContent).toBe(100 - EDITOR_LAYOUT.timelineDefaultSize); + }); + + it('keeps main/timeline summing to 100 after migration', () => { + const migrated = migrateEditorPanelLayout(v1DefaultState, 1); + + expect((migrated.panels?.mainContent ?? 0) + (migrated.panels?.timeline ?? 0)).toBe(100); + }); + + it('preserves the untouched sidebar panel sizes', () => { + const migrated = migrateEditorPanelLayout(v1DefaultState, 1); + + expect(migrated.panels?.tools).toBe(25); + expect(migrated.panels?.preview).toBe(50); + expect(migrated.panels?.properties).toBe(25); + }); + + it('leaves a user-resized v1 layout alone', () => { + const resized = { + panels: { ...v1DefaultState.panels, mainContent: 40, timeline: 60 }, + }; + + expect(migrateEditorPanelLayout(resized, 1)).toEqual(resized); + }); + + it('passes current-version state through untouched', () => { + expect(migrateEditorPanelLayout(v1DefaultState, 2)).toEqual(v1DefaultState); + }); +}); diff --git a/src/shared/state/editor-panel-layout-store.ts b/src/shared/state/editor-panel-layout-store.ts index 2bf4187d..6cf96e65 100644 --- a/src/shared/state/editor-panel-layout-store.ts +++ b/src/shared/state/editor-panel-layout-store.ts @@ -4,6 +4,7 @@ */ import { create } from 'zustand'; import { persist } from 'zustand/middleware'; +import { EDITOR_LAYOUT } from '@/shared/ui/editor-layout'; export interface EditorPanelSizes { tools: number; @@ -19,10 +20,45 @@ const DEFAULT_PANELS: EditorPanelSizes = { tools: 25, preview: 50, properties: 25, - mainContent: 50, - timeline: 50, + mainContent: 100 - EDITOR_LAYOUT.timelineDefaultSize, + timeline: EDITOR_LAYOUT.timelineDefaultSize, }; +/** The main/timeline split that version 1 of this store shipped with. */ +const V1_DEFAULT_SPLIT = { mainContent: 50, timeline: 50 }; + +interface PersistedPanelLayout { + panels?: EditorPanelSizes; +} + +/** + * Version 1 shipped a 50/50 main/timeline split. Layouts still sitting on + * that untouched default follow the new default from EDITOR_LAYOUT; anything + * the user resized themselves is left alone. + */ +export function migrateEditorPanelLayout( + persistedState: unknown, + version: number +): PersistedPanelLayout { + const state = persistedState as PersistedPanelLayout; + if (version >= 2) return state; + if ( + state?.panels && + state.panels.mainContent === V1_DEFAULT_SPLIT.mainContent && + state.panels.timeline === V1_DEFAULT_SPLIT.timeline + ) { + return { + ...state, + panels: { + ...state.panels, + mainContent: DEFAULT_PANELS.mainContent, + timeline: DEFAULT_PANELS.timeline, + }, + }; + } + return state; +} + interface EditorPanelLayoutState { panels: EditorPanelSizes; setPanel: (panel: EditorPanelId, size: number) => void; @@ -44,8 +80,9 @@ export const useEditorPanelLayoutStore = create()( }), { name: 'kubeez-editor-panel-sizes', - version: 1, + version: 2, partialize: (state) => ({ panels: state.panels }), + migrate: migrateEditorPanelLayout, } ) );