// src/layout/LayoutContext.tsx import { createContext, useContext, useState, useCallback, useEffect, type ReactNode } from 'react' import { toggleSidebar as toggleSidebarState, setSidebarMode as setSidebarModeState, toggleRightPanel as toggleRightPanelState, setRightPanelCollapsed as setRightPanelCollapsedState, setSidebarWidth as setSidebarWidthState, setRightPanelWidth as setRightPanelWidthState, setEditorMode as setEditorModeState, type LayoutState, type EditorMode, type SidebarMode, } from './layout-state' import { loadLayoutState, saveLayoutState } from './layout-persistence' import type { VaultPreferences } from '../services/vault-preferences' const EDITOR_MODE_PREFERENCE = 'reams:editor-mode' function readEditorMode(preferences: VaultPreferences): EditorMode | null { const mode = preferences.get(EDITOR_MODE_PREFERENCE) return mode === 'source' || mode === 'live-preview' ? mode : null } interface LayoutContextValue { state: LayoutState toggleSidebar: () => void setSidebarMode: (mode: SidebarMode) => void toggleRightPanel: () => void setRightPanelCollapsed: (collapsed: boolean) => void setSidebarWidth: (width: number) => void setRightPanelWidth: (width: number) => void setEditorMode: (mode: EditorMode) => void } const LayoutContext = createContext(null) interface LayoutProviderProps { children: ReactNode /** Opened by the host before mounting the workspace. */ preferences?: VaultPreferences } export function LayoutProvider({ children, preferences }: LayoutProviderProps) { // Restore device chrome. When a vault is open, its mode (or the current // default) is authoritative; legacy device mode is not imported. const [state, setState] = useState(() => { const local = loadLayoutState() return { ...local, editorMode: preferences ? readEditorMode(preferences) ?? 'live-preview' : local.editorMode } }) useEffect(() => { if (!preferences) return const refresh = () => { const mode = readEditorMode(preferences) ?? 'live-preview' setState(s => s.editorMode === mode ? s : setEditorModeState(s, mode)) } refresh() return preferences.subscribe(key => { if (key === EDITOR_MODE_PREFERENCE) refresh() }) }, [preferences]) // Persist device chrome without writing a second editor-mode authority. useEffect(() => { saveLayoutState(state, { persistEditorMode: !preferences }) }, [state, preferences]) const toggleSidebar = useCallback(() => { setState(s => toggleSidebarState(s)) }, []) const setSidebarMode = useCallback((mode: SidebarMode) => { setState(s => setSidebarModeState(s, mode)) }, []) const toggleRightPanel = useCallback(() => { setState(s => toggleRightPanelState(s)) }, []) const setRightPanelCollapsed = useCallback((collapsed: boolean) => { setState(s => setRightPanelCollapsedState(s, collapsed)) }, []) const setSidebarWidth = useCallback((width: number) => { setState(s => setSidebarWidthState(s, width)) }, []) const setRightPanelWidth = useCallback((width: number) => { setState(s => setRightPanelWidthState(s, width)) }, []) const setEditorMode = useCallback((mode: EditorMode) => { preferences?.set(EDITOR_MODE_PREFERENCE, mode) setState(s => setEditorModeState(s, mode)) }, [preferences]) const value: LayoutContextValue = { state, toggleSidebar, setSidebarMode, toggleRightPanel, setRightPanelCollapsed, setSidebarWidth, setRightPanelWidth, setEditorMode, } return ( {children} ) } export function useLayout(): LayoutContextValue { const context = useContext(LayoutContext) if (!context) { throw new Error('useLayout must be used within a LayoutProvider') } return context }