diff --git a/web/src/components/Shell.jsx b/web/src/components/Shell.jsx index efa9521..2ae3c00 100644 --- a/web/src/components/Shell.jsx +++ b/web/src/components/Shell.jsx @@ -425,15 +425,36 @@ export default function Shell({ api }) { } }, []) + const initPendingTabs = useCallback(() => { + for (const tab of tabsRef.current._tabList || []) { + if (!tabsRef.current[tab.id]) { + const container = document.getElementById(`terminal-${tab.id}`) + if (container && container.offsetHeight > 0) { + initTerminal(tab.id, tab) + } + } + } + requestAnimationFrame(() => { + for (const tab of tabsRef.current._tabList || []) { + const entry = tabsRef.current[tab.id] + if (entry) entry.fitAddon.fit() + } + }) + }, [initTerminal]) + + useEffect(() => { + tabsRef.current._tabList = tabs + }, [tabs]) + useEffect(() => { let cancelled = false const pending = [] const tryInitTab = (tab, attempt) => { - if (cancelled || attempt > 30) return + if (cancelled) return const shellCol = document.querySelector('.shell-terminal-col') if (!shellCol || shellCol.offsetParent === null) { - pending.push(setTimeout(() => tryInitTab(tab, attempt + 1), 150)) + pending.push(setTimeout(() => tryInitTab(tab, attempt + 1), 200)) return } const container = document.getElementById(`terminal-${tab.id}`) @@ -461,11 +482,23 @@ export default function Shell({ api }) { } } + const wrapper = document.querySelector('.shell-layout')?.parentElement + let observer + if (wrapper) { + observer = new MutationObserver(() => { + if (!wrapper.classList.contains('tab-hidden') && wrapper.offsetParent !== null) { + initPendingTabs() + } + }) + observer.observe(wrapper, { attributes: true, attributeFilter: ['class'] }) + } + return () => { cancelled = true pending.forEach(clearTimeout) + observer?.disconnect() } - }, [tabs, initTerminal]) + }, [tabs, initTerminal, initPendingTabs]) useEffect(() => { const entry = tabsRef.current[activeTab] @@ -480,6 +513,8 @@ export default function Shell({ api }) { useEffect(() => { const iv = setInterval(() => { + const wrapper = document.querySelector('.shell-layout')?.parentElement + if (wrapper && wrapper.classList.contains('tab-hidden')) return const entry = tabsRef.current[activeTabRef.current] if (entry) { entry.fitAddon.fit()