From 79a9f93ae2fcd019d4ce404eaf35732b88337c14 Mon Sep 17 00:00:00 2001 From: jwcrystal <121911854+jwcrystal@users.noreply.github.com> Date: Fri, 17 Apr 2026 04:31:57 +0800 Subject: [PATCH] feat(files): auto-refresh file tree on external changes (#919) --- .../ui/src/components/views/FilesView.tsx | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/packages/ui/src/components/views/FilesView.tsx b/packages/ui/src/components/views/FilesView.tsx index 83cc9641..894d3d00 100644 --- a/packages/ui/src/components/views/FilesView.tsx +++ b/packages/ui/src/components/views/FilesView.tsx @@ -907,6 +907,37 @@ export const FilesView: React.FC = ({ mode = 'full' }) => { } }, [loadDirectory, root, showGitignored, showHidden]); + // Auto-refresh expanded directories when user returns to the tab + React.useEffect(() => { + if (!files.listDirectory) return; + + const handleVisibilityChange = () => { + if (!document.hidden && expandedPaths.length > 0) { + for (const dir of expandedPaths) { + void refreshDirectory(dir); + } + } + }; + + document.addEventListener('visibilitychange', handleVisibilityChange); + return () => document.removeEventListener('visibilitychange', handleVisibilityChange); + }, [expandedPaths, files.listDirectory, refreshDirectory]); + + // Poll expanded directories for external changes + React.useEffect(() => { + if (!files.listDirectory) return; + if (expandedPaths.length === 0) return; + + const interval = setInterval(() => { + if (document.hidden) return; + for (const dir of expandedPaths) { + void refreshDirectory(dir); + } + }, 8000); + + return () => clearInterval(interval); + }, [expandedPaths, files.listDirectory, refreshDirectory]); + const handleDialogSubmit = React.useCallback(async (e?: React.FormEvent) => { e?.preventDefault(); if (!dialogData || !activeDialog) return;