import { useEffect, useState } from 'react' import { FileTree } from './components/FileTree/FileTree' import { MarkdownEditor } from './components/Editor/MarkdownEditor' import { DocumentOutline } from './components/Editor/DocumentOutline' import { ChatPanel } from './components/AIChat/ChatPanel' import { AnalysisToolbar } from './components/Toolbar/AnalysisToolbar' import { RevisionPanel } from './components/Revisions/RevisionPanel' import { useEditorStore } from './store/editorStore' import './styles/app.css' export default function App(): JSX.Element { const { setFileTree, activeFilePath, isDirty, markSaved, activeFileContent, theme, toggleTheme, loadSession, revisionPanelOpen, toggleRevisionPanel } = useEditorStore() const [sidebarOpen, setSidebarOpen] = useState( () => localStorage.getItem('sidebarOpen') !== 'false' ) const [chatOpen, setChatOpen] = useState( () => localStorage.getItem('chatOpen') !== 'false' ) // Load file tree, apply persisted theme, and restore last session useEffect(() => { window.api.listFiles().then(setFileTree) document.documentElement.classList.toggle('light', theme === 'light') loadSession() }, []) // Handle Cmd+S / Ctrl+S useEffect(() => { const handler = async (e: KeyboardEvent): Promise => { if ((e.metaKey || e.ctrlKey) && e.key === 's') { e.preventDefault() if (activeFilePath && isDirty) { await window.api.writeFile(activeFilePath, activeFileContent) await window.api.saveRevision(activeFilePath, activeFileContent) markSaved() } } } window.addEventListener('keydown', handler) return () => window.removeEventListener('keydown', handler) }, [activeFilePath, isDirty, activeFileContent]) return (
Hohoff Editor
{revisionPanelOpen && }
) }