()
| 18 | const log = createLogger('useApp'); |
| 19 | |
| 20 | export const useApp = (): UseAppReturn => { |
| 21 | const [state, setState] = useState<AppState>(appManager.getState()); |
| 22 | |
| 23 | // Listen for app state changes |
| 24 | useEffect(() => { |
| 25 | const unsubscribe = appManager.addEventListener(() => { |
| 26 | // Update state on each event |
| 27 | setState(appManager.getState()); |
| 28 | }); |
| 29 | |
| 30 | // Sync state on initialization |
| 31 | setState(appManager.getState()); |
| 32 | |
| 33 | return unsubscribe; |
| 34 | }, []); |
| 35 | |
| 36 | // Layout actions |
| 37 | const toggleLeftPanel = useCallback(() => { |
| 38 | appManager.updateLayout({ |
| 39 | leftPanelCollapsed: !state.layout.leftPanelCollapsed |
| 40 | }); |
| 41 | }, [state.layout.leftPanelCollapsed]); |
| 42 | |
| 43 | const toggleRightPanel = useCallback(() => { |
| 44 | appManager.updateLayout({ |
| 45 | rightPanelCollapsed: !state.layout.rightPanelCollapsed |
| 46 | }); |
| 47 | }, [state.layout.rightPanelCollapsed]); |
| 48 | |
| 49 | const toggleBottomTerminalPanel = useCallback(() => { |
| 50 | appManager.updateLayout({ |
| 51 | bottomTerminalPanelCollapsed: !state.layout.bottomTerminalPanelCollapsed |
| 52 | }); |
| 53 | }, [state.layout.bottomTerminalPanelCollapsed]); |
| 54 | |
| 55 | const toggleChatPanel = useCallback(() => { |
| 56 | const nextChatCollapsed = !state.layout.chatCollapsed; |
| 57 | appManager.updateLayout({ |
| 58 | chatCollapsed: nextChatCollapsed, |
| 59 | // Keep behavior aligned with editor-mode layout: |
| 60 | // when chat is hidden, ensure the right panel is visible to occupy center space. |
| 61 | rightPanelCollapsed: nextChatCollapsed ? false : state.layout.rightPanelCollapsed |
| 62 | }); |
| 63 | }, [state.layout.chatCollapsed, state.layout.rightPanelCollapsed]); |
| 64 | |
| 65 | const switchLeftPanelTab = useCallback((tab: PanelType) => { |
| 66 | appManager.updateLayout({ |
| 67 | leftPanelActiveTab: tab, |
| 68 | leftPanelCollapsed: false // Auto-expand panel when switching tabs |
| 69 | }); |
| 70 | }, []); |
| 71 | |
| 72 | const updateLeftPanelWidth = useCallback((width: number) => { |
| 73 | // Clamp width: minimum 50px, no upper bound |
| 74 | const MIN_WIDTH = 50; |
| 75 | const clampedWidth = Math.max(MIN_WIDTH, width); |
| 76 | |
| 77 | appManager.updateLayout({ |
no test coverage detected