@@ -102,7 +102,7 @@ interface DatabaseStatusState {
102102
103103const MainApp : React . FC = ( ) => {
104104 const { settings, saveSettings, loaded : settingsLoaded } = useSettings ( ) ;
105- const { items, addDocument, addFolder, updateItem, commitVersion, deleteItems, moveItems, getDescendantIds, duplicateItems, addDocumentsFromFiles, importNodesFromTransfer } = useDocuments ( ) ;
105+ const { items, addDocument, addFolder, updateItem, commitVersion, deleteItems, moveItems, getDescendantIds, duplicateItems, addDocumentsFromFiles, importNodesFromTransfer, isLoading : areDocumentsLoading } = useDocuments ( ) ;
106106 const { templates, addTemplate, updateTemplate, deleteTemplate, deleteTemplates } = useTemplates ( ) ;
107107 const { theme } = useTheme ( ) ;
108108
@@ -111,6 +111,7 @@ const MainApp: React.FC = () => {
111111 const [ lastClickedId , setLastClickedId ] = useState < string | null > ( null ) ;
112112 const [ activeTemplateId , setActiveTemplateId ] = useState < string | null > ( null ) ;
113113 const [ expandedFolderIds , setExpandedFolderIds ] = useState ( new Set < string > ( ) ) ;
114+ const [ hasLoadedExpandedFolders , setHasLoadedExpandedFolders ] = useState ( false ) ;
114115 const [ pendingRevealId , setPendingRevealId ] = useState < string | null > ( null ) ;
115116 const [ renamingNodeId , setRenamingNodeId ] = useState < string | null > ( null ) ;
116117
@@ -141,9 +142,12 @@ const MainApp: React.FC = () => {
141142 const [ databasePath , setDatabasePath ] = useState < string | null > ( null ) ;
142143 const [ databaseStatus , setDatabaseStatus ] = useState < DatabaseStatusState | null > ( null ) ;
143144 const [ isDatabaseBusy , setIsDatabaseBusy ] = useState ( false ) ;
145+ const [ isRestoringActiveDocument , setIsRestoringActiveDocument ] = useState ( true ) ;
146+ const [ hasRestoredActiveDocument , setHasRestoredActiveDocument ] = useState ( false ) ;
144147
145148 const activeNodeId = tabState . activeId ;
146149 const openDocumentIds = tabState . order ;
150+ const storedActiveDocumentIdRef = useRef < string | null > ( null ) ;
147151
148152 const activateDocumentTab = useCallback ( ( documentId : string ) => {
149153 setTabState ( prev => {
@@ -224,6 +228,27 @@ const MainApp: React.FC = () => {
224228 const dragCounter = useRef ( 0 ) ;
225229 const ensureNodeVisibleRef = useRef < ( node : Pick < DocumentOrFolder , 'id' | 'type' | 'parentId' > ) => void > ( ) ;
226230
231+ const ensureNodeVisible = useCallback ( ( node : Pick < DocumentOrFolder , 'id' | 'type' | 'parentId' > ) => {
232+ const ancestry = new Map ( items . map ( item => [ item . id , item . parentId ?? null ] ) ) ;
233+ setExpandedFolderIds ( prev => {
234+ const next = new Set ( prev ) ;
235+ let current = node . parentId ;
236+ while ( current ) {
237+ next . add ( current ) ;
238+ current = ancestry . get ( current ) ?? null ;
239+ }
240+ if ( node . type === 'folder' ) {
241+ next . add ( node . id ) ;
242+ }
243+ return next ;
244+ } ) ;
245+ setPendingRevealId ( node . id ) ;
246+ } , [ items , setPendingRevealId ] ) ;
247+
248+ useEffect ( ( ) => {
249+ ensureNodeVisibleRef . current = ensureNodeVisible ;
250+ } , [ ensureNodeVisible ] ) ;
251+
227252 const llmStatus = useLLMStatus ( settings . llmProviderUrl ) ;
228253 const { logs, addLog } = useLogger ( ) ;
229254 const lastLogRef = useRef < LogMessage | null > ( null ) ;
@@ -331,6 +356,68 @@ const MainApp: React.FC = () => {
331356 const documentItems = useMemo ( ( ) => items . filter ( item => item . type === 'document' ) , [ items ] ) ;
332357 const activeDocumentId = activeDocument ?. id ?? null ;
333358
359+ useEffect ( ( ) => {
360+ let isCancelled = false ;
361+ storageService . load < string | null > ( LOCAL_STORAGE_KEYS . ACTIVE_DOCUMENT_ID , null ) . then ( savedId => {
362+ if ( isCancelled ) {
363+ return ;
364+ }
365+ storedActiveDocumentIdRef . current = savedId ;
366+ setIsRestoringActiveDocument ( false ) ;
367+ } ) ;
368+
369+ return ( ) => {
370+ isCancelled = true ;
371+ } ;
372+ } , [ ] ) ;
373+
374+ useEffect ( ( ) => {
375+ if ( isRestoringActiveDocument || hasRestoredActiveDocument || ! hasLoadedExpandedFolders ) {
376+ return ;
377+ }
378+
379+ const savedId = storedActiveDocumentIdRef . current ;
380+ if ( ! savedId ) {
381+ storedActiveDocumentIdRef . current = null ;
382+ setHasRestoredActiveDocument ( true ) ;
383+ return ;
384+ }
385+
386+ if ( items . length === 0 ) {
387+ if ( areDocumentsLoading ) {
388+ return ;
389+ }
390+ storedActiveDocumentIdRef . current = null ;
391+ setHasRestoredActiveDocument ( true ) ;
392+ return ;
393+ }
394+
395+ const target = items . find ( item => item . id === savedId && item . type === 'document' ) ;
396+ if ( ! target ) {
397+ storedActiveDocumentIdRef . current = null ;
398+ setHasRestoredActiveDocument ( true ) ;
399+ return ;
400+ }
401+
402+ ensureNodeVisibleRef . current ?.( target ) ;
403+ setActiveTemplateId ( null ) ;
404+ setView ( 'editor' ) ;
405+ setDocumentView ( 'editor' ) ;
406+ activateDocumentTab ( savedId ) ;
407+ setSelectedIds ( new Set ( [ savedId ] ) ) ;
408+ setLastClickedId ( savedId ) ;
409+ storedActiveDocumentIdRef . current = null ;
410+ setHasRestoredActiveDocument ( true ) ;
411+ } , [ isRestoringActiveDocument , hasRestoredActiveDocument , items , activateDocumentTab , areDocumentsLoading , hasLoadedExpandedFolders , ensureNodeVisibleRef ] ) ;
412+
413+ useEffect ( ( ) => {
414+ if ( ! hasRestoredActiveDocument ) {
415+ return ;
416+ }
417+
418+ storageService . save ( LOCAL_STORAGE_KEYS . ACTIVE_DOCUMENT_ID , activeDocumentId ) ;
419+ } , [ activeDocumentId , hasRestoredActiveDocument ] ) ;
420+
334421
335422 useEffect ( ( ) => {
336423 const term = searchTerm . trim ( ) ;
@@ -841,18 +928,42 @@ const MainApp: React.FC = () => {
841928 storageService . load ( LOCAL_STORAGE_KEYS . LOGGER_PANEL_HEIGHT , DEFAULT_LOGGER_HEIGHT ) . then ( height => {
842929 if ( typeof height === 'number' ) setLoggerPanelHeight ( height ) ;
843930 } ) ;
844- storageService . load < string [ ] > ( LOCAL_STORAGE_KEYS . EXPANDED_FOLDERS , [ ] ) . then ( ids => {
845- setExpandedFolderIds ( new Set ( ids ) ) ;
846- } ) ;
931+
932+ let isCancelled = false ;
933+
934+ storageService
935+ . load < string [ ] > ( LOCAL_STORAGE_KEYS . EXPANDED_FOLDERS , [ ] )
936+ . then ( ids => {
937+ if ( isCancelled ) {
938+ return ;
939+ }
940+ setExpandedFolderIds ( new Set ( ids ) ) ;
941+ } )
942+ . catch ( ( ) => {
943+ // Loading failed; we'll fall back to the default empty set.
944+ } )
945+ . finally ( ( ) => {
946+ if ( ! isCancelled ) {
947+ setHasLoadedExpandedFolders ( true ) ;
948+ }
949+ } ) ;
950+
951+ return ( ) => {
952+ isCancelled = true ;
953+ } ;
847954 } , [ ] ) ;
848955
849956 useEffect ( ( ) => {
850- if ( settingsLoaded ) {
957+ if ( settingsLoaded && hasLoadedExpandedFolders ) {
851958 storageService . save ( LOCAL_STORAGE_KEYS . EXPANDED_FOLDERS , Array . from ( expandedFolderIds ) ) ;
852959 }
853- } , [ expandedFolderIds , settingsLoaded ] ) ;
960+ } , [ expandedFolderIds , settingsLoaded , hasLoadedExpandedFolders ] ) ;
854961
855962 useEffect ( ( ) => {
963+ if ( isRestoringActiveDocument || ! hasRestoredActiveDocument ) {
964+ return ;
965+ }
966+
856967 if ( items . length === 0 ) {
857968 if ( openDocumentIds . length > 0 || activeNodeId !== null ) {
858969 setTabState ( { activeId : null , order : [ ] } ) ;
@@ -876,7 +987,7 @@ const MainApp: React.FC = () => {
876987 setSelectedIds ( new Set ( [ firstItem . id ] ) ) ;
877988 setLastClickedId ( firstItem . id ) ;
878989 }
879- } , [ items , activeNodeId , activeTemplateId , openDocumentIds . length , activateDocumentTab , setActiveItem ] ) ;
990+ } , [ items , activeNodeId , activeTemplateId , openDocumentIds . length , activateDocumentTab , setActiveItem , isRestoringActiveDocument , hasRestoredActiveDocument ] ) ;
880991
881992 useEffect ( ( ) => {
882993 const documentIds = new Set ( items . filter ( item => item . type === 'document' ) . map ( item => item . id ) ) ;
@@ -1121,27 +1232,6 @@ const MainApp: React.FC = () => {
11211232 return activeNode . type === 'folder' ? activeNode . id : activeNode . parentId ;
11221233 } , [ activeNode ] ) ;
11231234
1124- const ensureNodeVisible = useCallback ( ( node : Pick < DocumentOrFolder , 'id' | 'type' | 'parentId' > ) => {
1125- const ancestry = new Map ( items . map ( item => [ item . id , item . parentId ?? null ] ) ) ;
1126- setExpandedFolderIds ( prev => {
1127- const next = new Set ( prev ) ;
1128- let current = node . parentId ;
1129- while ( current ) {
1130- next . add ( current ) ;
1131- current = ancestry . get ( current ) ?? null ;
1132- }
1133- if ( node . type === 'folder' ) {
1134- next . add ( node . id ) ;
1135- }
1136- return next ;
1137- } ) ;
1138- setPendingRevealId ( node . id ) ;
1139- } , [ items , setPendingRevealId ] ) ;
1140-
1141- useEffect ( ( ) => {
1142- ensureNodeVisibleRef . current = ensureNodeVisible ;
1143- } , [ ensureNodeVisible ] ) ;
1144-
11451235 const handleNavigateToNode = useCallback ( ( nodeId : string ) => {
11461236 const target = items . find ( item => item . id === nodeId ) ;
11471237 if ( ! target ) {
0 commit comments