From 4a8220652e5c27c1f9decd6f5207e7f6fd8f10cb Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Thu, 19 Mar 2026 22:06:53 +0800 Subject: [PATCH] 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 --- src/App.tsx | 24 +++++++++++++++++++++++- src/components/ApiDocViewer.tsx | 33 +++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 9c235a3..3b2a8e9 100644 --- a/src/App.tsx +++ b/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('docs'); const [docsPath, setDocsPath] = useState(''); const [showAddModal, setShowAddModal] = useState(false); + + // Docs state lifted from ApiDocViewer to persist across view changes + const [externalDocs, setExternalDocs] = useState([]); + const [fileTree, setFileTree] = useState([]); + const [selectedPath, setSelectedPath] = useState(undefined); + const [currentContent, setCurrentContent] = useState(''); useEffect(() => { document.title = config.projectName; @@ -74,10 +88,18 @@ function App() {
{currentPage === 'docs' ? ( - setShowAddModal(false)} + externalDocs={externalDocs} + setExternalDocs={setExternalDocs} + fileTree={fileTree} + setFileTree={setFileTree} + selectedPath={selectedPath} + setSelectedPath={setSelectedPath} + currentContent={currentContent} + setCurrentContent={setCurrentContent} /> ) : ( diff --git a/src/components/ApiDocViewer.tsx b/src/components/ApiDocViewer.tsx index efc1c5f..63ebc77 100644 --- a/src/components/ApiDocViewer.tsx +++ b/src/components/ApiDocViewer.tsx @@ -16,6 +16,14 @@ interface ApiDocViewerProps { onDocsPathChange?: (path: string) => void; showAddModal?: boolean; onCloseAddModal?: () => void; + externalDocs: ExternalDoc[]; + setExternalDocs: React.Dispatch>; + fileTree: DocFile[]; + setFileTree: React.Dispatch>; + selectedPath: string | undefined; + setSelectedPath: React.Dispatch>; + currentContent: string; + setCurrentContent: React.Dispatch>; } 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([]) - const [selectedPath, setSelectedPath] = useState(stored.selectedPath) - const [currentContent, setCurrentContent] = useState('') const [showModal, setShowModal] = useState(false) const [docsPath, setDocsPath] = useState(stored.docsPath) - const [externalDocs, setExternalDocs] = useState(stored.externalDocs) const [isLoading, setIsLoading] = useState(false) const [errorMsg, setErrorMsg] = useState(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) {