diff --git a/frontend/src/app/AppLayout.jsx b/frontend/src/app/AppLayout.jsx index b445161..a54a655 100644 --- a/frontend/src/app/AppLayout.jsx +++ b/frontend/src/app/AppLayout.jsx @@ -192,10 +192,17 @@ const AppLayout = () => { return new Map([[rootNode.id, rootNode]]); }); const [folderContents, setFolderContents] = useState(() => new Map()); + const folderContentsRef = useRef(folderContents); const [selectedFolder, setSelectedFolder] = useState(routeFolderId || 'root'); const [currentFolder, setCurrentFolder] = useState(null); const [currentSubfolders, setCurrentSubfolders] = useState([]); - const [documents, setDocuments] = useState([]); + const [documents, setDocumentsState] = useState([]); + const setDocuments = useCallback((updater) => { + const stack = new Error('[trace] setDocuments invoked').stack?.split('\n').slice(1, 10); + console.log('[desk][trace] setDocuments invoked', { type: typeof updater }); + console.log('[desk][trace] setDocuments stack', stack); + setDocumentsState(updater); + }, []); const [documentsViewMode, setDocumentsViewMode] = useState(() => { if (typeof window === 'undefined') { return 'list'; @@ -344,6 +351,37 @@ const AppLayout = () => { } }, [appDispatch]); const [searchResults, setSearchResults] = useState(null); + const documentsTraceRef = useRef(documents); + const searchResultsTraceRef = useRef(searchResults); + useEffect(() => { + if (documentsTraceRef.current !== documents) { + const prev = documentsTraceRef.current || []; + const next = documents || []; + const stack = new Error('[trace] documents updated').stack?.split('\n').slice(1, 8); + console.log('[desk][trace] documents state updated', { + prevCount: prev.length, + nextCount: next.length, + sameRef: prev === next, + }); + console.log('[desk][trace] documents stack', stack); + documentsTraceRef.current = documents; + } + }, [documents]); + + useEffect(() => { + if (searchResultsTraceRef.current !== searchResults) { + const prev = searchResultsTraceRef.current || []; + const next = searchResults || []; + const stack = new Error('[trace] searchResults updated').stack?.split('\n').slice(1, 8); + console.log('[desk][trace] searchResults state updated', { + prevCount: Array.isArray(prev) ? prev.length : null, + nextCount: Array.isArray(next) ? next.length : null, + sameRef: prev === next, + }); + console.log('[desk][trace] searchResults stack', stack); + searchResultsTraceRef.current = searchResults; + } + }, [searchResults]); const [previewEntries, setPreviewEntries] = useState(() => new Map()); const previewInflightRef = useRef(new Map()); const previewReturnPathRef = useRef(null); @@ -563,6 +601,10 @@ const AppLayout = () => { } }, [appStatus, resetWorkspaceState]); + useEffect(() => { + folderContentsRef.current = folderContents; + }, [folderContents]); + useEffect(() => { tokenRef.current = token; }, [token]); @@ -1090,7 +1132,7 @@ const AppLayout = () => { } = {}, ) => { const requestTenantId = tenantIdRef.current; - const cached = folderContents.get(folderId); + const cached = folderContentsRef.current.get(folderId); const cachedSortField = cached?.__sortField ?? DEFAULT_SORT_FIELD; const cachedSortDirection = cached?.__sortDirection ?? DEFAULT_SORT_DIRECTION; const sortField = includeDocuments @@ -1253,7 +1295,7 @@ const AppLayout = () => { return enriched; }, - [assetManager, documentsSortDirectionRef, documentsSortFieldRef, folderContents], + [assetManager, documentsSortDirectionRef, documentsSortFieldRef], ); const isInvalidFolderDrop = useCallback( diff --git a/frontend/src/desktop/DesktopWorkspace.jsx b/frontend/src/desktop/DesktopWorkspace.jsx index 1811a92..6dea893 100644 --- a/frontend/src/desktop/DesktopWorkspace.jsx +++ b/frontend/src/desktop/DesktopWorkspace.jsx @@ -140,6 +140,23 @@ const DesktopWorkspace = ({ const allowLayoutPersistence = Boolean(tenantId && viewId && viewId.startsWith('folder:')); + const itemsTraceRef = useRef(items); + useEffect(() => { + if (itemsTraceRef.current !== items) { + const prev = itemsTraceRef.current || []; + const next = items || []; + const stack = new Error('[trace] items updated').stack?.split('\n').slice(1, 8); + console.log('[desk][trace] items value changed', { + prevCount: prev.length, + nextCount: next.length, + sameRef: prev === next, + fromSearch: Boolean(searchResults), + }); + console.log('[desk][trace] items stack', stack); + itemsTraceRef.current = items; + } + }, [items, searchResults]); + const containerRef = useRef(null); const itemRefs = useRef(new Map()); const dragTransformsRef = useRef(new Map()); @@ -149,7 +166,6 @@ const DesktopWorkspace = ({ const [previewSnapshots, setPreviewSnapshots] = useState(() => new Map()); const [docSizeVersion, setDocSizeVersion] = useState(0); const docSizeMapRef = useRef(new Map()); - const documentLookupRef = useRef(new Map()); const ensureDocumentSize = useCallback((doc) => { if (!doc?.id) { return null; @@ -168,10 +184,6 @@ const DesktopWorkspace = ({ return map; }, [items]); - useEffect(() => { - documentLookupRef.current = documentLookup; - }, [documentLookup]); - const engineRef = useRef(null); if (!engineRef.current) { engineRef.current = new WorkspaceEngine({ @@ -187,12 +199,20 @@ const DesktopWorkspace = ({ }, [engine, allowLayoutPersistence, tenantId, viewId]); useEffect(() => { - engine.setItems(items); - }, [engine, items]); + const nextItems = searchResults ? searchResults : documents; + engine.setItems(nextItems || []); + }, [engine, documents, searchResults]); useEffect(() => { - engine.setDocumentLookup(documentLookup); - }, [engine, documentLookup]); + const map = new Map(); + items.forEach((doc) => { + const key = doc?.id != null ? String(doc.id) : null; + if (key) { + map.set(key, doc); + } + }); + engine.setDocumentLookup(map); + }, [engine, items]); useEffect(() => { engine.setEnsureDocumentSize(ensureDocumentSize);