feat: lift docs state to App for persistence across view changes
Move externalDocs, fileTree, selectedPath, and currentContent state from ApiDocViewer to App component so that docs state persists when switching between docs and blueprint views. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
24
src/App.tsx
24
src/App.tsx
@@ -3,6 +3,14 @@ import { FileText, Box, Plus } from 'lucide-react';
|
||||
import { ApiDocViewer } from './components/ApiDocViewer';
|
||||
import BlueprintPage from './components/blueprint/BlueprintPage';
|
||||
import { config } from './config';
|
||||
import type { DocFile } from '@/lib/types';
|
||||
|
||||
interface ExternalDoc {
|
||||
name: string
|
||||
path: string
|
||||
relativePath: string
|
||||
content: string
|
||||
}
|
||||
|
||||
const _origLog = console.log;
|
||||
const _origError = console.error;
|
||||
@@ -27,6 +35,12 @@ function App() {
|
||||
const [currentPage, setCurrentPage] = useState<Page>('docs');
|
||||
const [docsPath, setDocsPath] = useState<string>('');
|
||||
const [showAddModal, setShowAddModal] = useState(false);
|
||||
|
||||
// Docs state lifted from ApiDocViewer to persist across view changes
|
||||
const [externalDocs, setExternalDocs] = useState<ExternalDoc[]>([]);
|
||||
const [fileTree, setFileTree] = useState<DocFile[]>([]);
|
||||
const [selectedPath, setSelectedPath] = useState<string | undefined>(undefined);
|
||||
const [currentContent, setCurrentContent] = useState<string>('');
|
||||
|
||||
useEffect(() => {
|
||||
document.title = config.projectName;
|
||||
@@ -74,10 +88,18 @@ function App() {
|
||||
</header>
|
||||
<main className="flex-1 overflow-hidden">
|
||||
{currentPage === 'docs' ? (
|
||||
<ApiDocViewer
|
||||
<ApiDocViewer
|
||||
onDocsPathChange={setDocsPath}
|
||||
showAddModal={showAddModal}
|
||||
onCloseAddModal={() => setShowAddModal(false)}
|
||||
externalDocs={externalDocs}
|
||||
setExternalDocs={setExternalDocs}
|
||||
fileTree={fileTree}
|
||||
setFileTree={setFileTree}
|
||||
selectedPath={selectedPath}
|
||||
setSelectedPath={setSelectedPath}
|
||||
currentContent={currentContent}
|
||||
setCurrentContent={setCurrentContent}
|
||||
/>
|
||||
) : (
|
||||
<BlueprintPage docsPath={docsPath} />
|
||||
|
||||
@@ -16,6 +16,14 @@ interface ApiDocViewerProps {
|
||||
onDocsPathChange?: (path: string) => void;
|
||||
showAddModal?: boolean;
|
||||
onCloseAddModal?: () => void;
|
||||
externalDocs: ExternalDoc[];
|
||||
setExternalDocs: React.Dispatch<React.SetStateAction<ExternalDoc[]>>;
|
||||
fileTree: DocFile[];
|
||||
setFileTree: React.Dispatch<React.SetStateAction<DocFile[]>>;
|
||||
selectedPath: string | undefined;
|
||||
setSelectedPath: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||
currentContent: string;
|
||||
setCurrentContent: React.Dispatch<React.SetStateAction<string>>;
|
||||
}
|
||||
|
||||
const STORAGE_KEY = 'xc-docs-config';
|
||||
@@ -36,14 +44,22 @@ function saveStoredConfig(docsPath: string, externalDocs: ExternalDoc[], selecte
|
||||
} catch {}
|
||||
}
|
||||
|
||||
export const ApiDocViewer = ({ onDocsPathChange, showAddModal, onCloseAddModal }: ApiDocViewerProps) => {
|
||||
export const ApiDocViewer = ({
|
||||
onDocsPathChange,
|
||||
showAddModal,
|
||||
onCloseAddModal,
|
||||
externalDocs,
|
||||
setExternalDocs,
|
||||
fileTree,
|
||||
setFileTree,
|
||||
selectedPath,
|
||||
setSelectedPath,
|
||||
currentContent,
|
||||
setCurrentContent
|
||||
}: ApiDocViewerProps) => {
|
||||
const stored = loadStoredConfig();
|
||||
const [fileTree, setFileTree] = useState<DocFile[]>([])
|
||||
const [selectedPath, setSelectedPath] = useState<string | undefined>(stored.selectedPath)
|
||||
const [currentContent, setCurrentContent] = useState<string>('')
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const [docsPath, setDocsPath] = useState(stored.docsPath)
|
||||
const [externalDocs, setExternalDocs] = useState<ExternalDoc[]>(stored.externalDocs)
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [errorMsg, setErrorMsg] = useState<string | null>(null)
|
||||
|
||||
@@ -54,6 +70,7 @@ export const ApiDocViewer = ({ onDocsPathChange, showAddModal, onCloseAddModal }
|
||||
}
|
||||
}, [showAddModal])
|
||||
|
||||
// Auto-select first document when externalDocs and fileTree are loaded
|
||||
useEffect(() => {
|
||||
if (externalDocs.length > 0 && fileTree.length > 0 && !selectedPath) {
|
||||
const fileList = externalDocs
|
||||
@@ -65,17 +82,17 @@ export const ApiDocViewer = ({ onDocsPathChange, showAddModal, onCloseAddModal }
|
||||
return filename !== parentFolder
|
||||
})
|
||||
.map(d => d.relativePath)
|
||||
|
||||
|
||||
const targetPath = stored.selectedPath && externalDocs.find(d => d.relativePath === stored.selectedPath)
|
||||
? stored.selectedPath
|
||||
: fileList[0]
|
||||
|
||||
|
||||
if (targetPath) {
|
||||
setSelectedPath(targetPath)
|
||||
setCurrentContent(externalDocs.find(d => d.relativePath === targetPath)?.content || '')
|
||||
}
|
||||
}
|
||||
}, [externalDocs, fileTree, selectedPath])
|
||||
}, [externalDocs, fileTree, selectedPath, stored.selectedPath, setSelectedPath, setCurrentContent])
|
||||
|
||||
useEffect(() => {
|
||||
if (docsPath && externalDocs.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user