diff --git a/.gitignore b/.gitignore index 190e0ea0..1204503d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ public/codemirror-bundle.js .env .cache/ dev-app-update.yml + +# Scratch space (Skaleet workspace convention) +.work-files/ + diff --git a/eslint.config.js b/eslint.config.js index 3ea234f3..7e02cc7d 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -178,6 +178,7 @@ const rendererCrossFileGlobals = { renderMemories: 'readonly', loadWorkFiles: 'readonly', renderWorkFiles: 'readonly', + removeWorkFileFromCache: 'readonly', openWorkFile: 'readonly', clearNotifications: 'readonly', setSessionMcpActive: 'readonly', diff --git a/public/app.js b/public/app.js index 449379c2..ac5dc703 100644 --- a/public/app.js +++ b/public/app.js @@ -45,9 +45,11 @@ const workFilesPanel = new ViewerPanel(workFilesViewer, { onDelete: async (filePath) => { const result = await window.api.deleteWorkFile(filePath); if (result && result.ok) { - // Hide the panel and reload the list + // Hide the panel and surgically remove the entry from the cached list. + // We avoid loadWorkFiles() because the full disk re-scan can freeze the + // UI on projects with large .work-files/ trees (e.g. tagpay = 39k files). workFilesViewer.style.display = 'none'; - if (typeof loadWorkFiles === 'function') loadWorkFiles(); + if (typeof removeWorkFileFromCache === 'function') removeWorkFileFromCache(filePath); } return result; }, diff --git a/public/plans-memory-view.js b/public/plans-memory-view.js index 1d2b3da3..81c2fadb 100644 --- a/public/plans-memory-view.js +++ b/public/plans-memory-view.js @@ -297,6 +297,22 @@ async function loadWorkFiles() { renderWorkFiles(); } +// Remove a single deleted file from the in-memory model and re-render. +// Avoids re-running the (sometimes slow) full disk scan in get-work-files. +function removeWorkFileFromCache(filePath) { + for (const proj of cachedWorkFilesData) { + const idx = proj.files.findIndex(f => f.filePath === filePath); + if (idx !== -1) { + proj.files.splice(idx, 1); + if (typeof proj.totalCount === 'number') proj.totalCount = Math.max(0, proj.totalCount - 1); + break; + } + } + // Drop projects that no longer have files + cachedWorkFilesData = cachedWorkFilesData.filter(p => p.files.length > 0); + renderWorkFiles(); +} + function renderWorkFiles(filterIds) { workFilesContent.innerHTML = ''; if (cachedWorkFilesData.length === 0) {