Automerge backed Markdown editor for the Atmosphere
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121// src/layout/LayoutContext.tsximport { 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<LayoutContextValue | null>(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<LayoutState>(() => { 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 ( <LayoutContext.Provider value={value}> {children} </LayoutContext.Provider> )}
export function useLayout(): LayoutContextValue { const context = useContext(LayoutContext) if (!context) { throw new Error('useLayout must be used within a LayoutProvider') } return context}