| 23 | const log = createLogger('AppManager'); |
| 24 | |
| 25 | export class AppManager implements IAppManager { |
| 26 | private state: AppState; |
| 27 | private listeners = new Set<(event: AppEvent) => void>(); |
| 28 | /** Coalesce rapid layout/state updates into one event per animation frame (reduces main-thread churn). */ |
| 29 | private pendingStateNotifyRaf: number | null = null; |
| 30 | |
| 31 | constructor() { |
| 32 | // Clear legacy panel state data (run once) |
| 33 | this.clearPersistedPanelState(); |
| 34 | |
| 35 | // Initialize state |
| 36 | this.state = { |
| 37 | layout: { |
| 38 | ...DEFAULT_LAYOUT_STATE, |
| 39 | leftPanelWidth: typeof window !== 'undefined' && window.innerWidth > 0 |
| 40 | ? Math.min(300, Math.floor(window.innerWidth * 0.15)) // Left 15%, max 300px |
| 41 | : 280, |
| 42 | rightPanelWidth: loadPanelWidth(STORAGE_KEYS.RIGHT_PANEL_LAST_WIDTH, DEFAULT_LAYOUT_STATE.rightPanelWidth), |
| 43 | bottomTerminalPanelHeight: loadPanelWidth( |
| 44 | STORAGE_KEYS.BOTTOM_TERMINAL_PANEL_LAST_HEIGHT, |
| 45 | DEFAULT_LAYOUT_STATE.bottomTerminalPanelHeight |
| 46 | ), |
| 47 | }, |
| 48 | currentAgent: DEFAULT_AGENTS[0], |
| 49 | availableAgents: [...DEFAULT_AGENTS], |
| 50 | chatSessions: [], |
| 51 | activeChatSession: null, |
| 52 | extensions: [], |
| 53 | isLoading: false, |
| 54 | error: null |
| 55 | }; |
| 56 | |
| 57 | // Set up event listeners |
| 58 | this.setupEventListeners(); |
| 59 | } |
| 60 | |
| 61 | // State management |
| 62 | getState(): AppState { |
| 63 | return { ...this.state }; |
| 64 | } |
| 65 | |
| 66 | private updateState(updates: Partial<AppState>): void { |
| 67 | this.state = { ...this.state, ...updates }; |
| 68 | this.notifyStateChange(); |
| 69 | } |
| 70 | |
| 71 | updateLayout(layout: Partial<LayoutState>): void { |
| 72 | const hasLayoutChange = Object.entries(layout).some(([key, value]) => ( |
| 73 | this.state.layout[key as keyof LayoutState] !== value |
| 74 | )); |
| 75 | if (!hasLayoutChange) { |
| 76 | return; |
| 77 | } |
| 78 | |
| 79 | if (typeof layout.rightPanelWidth === 'number') { |
| 80 | savePanelWidth(STORAGE_KEYS.RIGHT_PANEL_LAST_WIDTH, layout.rightPanelWidth); |
| 81 | } |
| 82 | if (typeof layout.bottomTerminalPanelHeight === 'number') { |
nothing calls this directly
no outgoing calls
no test coverage detected