Compare commits
4 Commits
v0.3.5-bet
...
v0.3.5-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08dc1fd53b | ||
|
|
13e937a11b | ||
|
|
3cf701b002 | ||
|
|
3a09e0e0c2 |
@@ -399,10 +399,7 @@ export default function Shell({ api }) {
|
||||
})
|
||||
|
||||
const onResize = () => {
|
||||
const el = document.getElementById(`terminal-${tabId}`)
|
||||
if (el && el.style.display !== 'none') {
|
||||
fitAddon.fit()
|
||||
}
|
||||
fitAddon.fit()
|
||||
}
|
||||
|
||||
const resizeObserver = new ResizeObserver(onResize)
|
||||
@@ -428,23 +425,45 @@ export default function Shell({ api }) {
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const tab = tabs.find(t => t.id === activeTab)
|
||||
if (!tab) return
|
||||
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 tryInit = (attempt) => {
|
||||
if (cancelled || attempt > 20) return
|
||||
const tryInitTab = (tab, attempt) => {
|
||||
if (cancelled) return
|
||||
const shellCol = document.querySelector('.shell-terminal-col')
|
||||
if (!shellCol || shellCol.offsetParent === null) {
|
||||
pending.push(setTimeout(() => tryInit(attempt + 1), 150))
|
||||
pending.push(setTimeout(() => tryInitTab(tab, attempt + 1), 200))
|
||||
return
|
||||
}
|
||||
const container = document.getElementById(`terminal-${tab.id}`)
|
||||
if (!container || container.offsetHeight === 0) {
|
||||
pending.push(setTimeout(() => tryInit(attempt + 1), 100))
|
||||
if (!container) {
|
||||
pending.push(setTimeout(() => tryInitTab(tab, attempt + 1), 100))
|
||||
return
|
||||
}
|
||||
if (container.offsetHeight === 0) {
|
||||
pending.push(setTimeout(() => tryInitTab(tab, attempt + 1), 100))
|
||||
return
|
||||
}
|
||||
if (!tabsRef.current[tab.id]) {
|
||||
@@ -457,23 +476,48 @@ export default function Shell({ api }) {
|
||||
})
|
||||
}
|
||||
|
||||
tryInit(0)
|
||||
for (const tab of tabs) {
|
||||
if (!tabsRef.current[tab.id]) {
|
||||
tryInitTab(tab, 0)
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}, [activeTab, tabs, initTerminal])
|
||||
}, [tabs, initTerminal, initPendingTabs])
|
||||
|
||||
useEffect(() => {
|
||||
const entry = tabsRef.current[activeTab]
|
||||
if (entry) {
|
||||
requestAnimationFrame(() => {
|
||||
if (activeTabRef.current === activeTab) {
|
||||
entry.fitAddon.fit()
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [activeTab])
|
||||
|
||||
useEffect(() => {
|
||||
const iv = setInterval(() => {
|
||||
for (const tab of tabs) {
|
||||
const entry = tabsRef.current[tab.id]
|
||||
if (entry) {
|
||||
const el = document.getElementById(`terminal-${tab.id}`)
|
||||
if (el && el.style.display !== 'none') {
|
||||
entry.fitAddon.fit()
|
||||
}
|
||||
}
|
||||
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()
|
||||
}
|
||||
}, 2000)
|
||||
return () => clearInterval(iv)
|
||||
@@ -838,8 +882,7 @@ export default function Shell({ api }) {
|
||||
<div
|
||||
key={tab.id}
|
||||
id={`terminal-${tab.id}`}
|
||||
className="shell-xterm-instance"
|
||||
style={{ display: activeTab === tab.id ? 'block' : 'none' }}
|
||||
className={`shell-xterm-instance${activeTab === tab.id ? ' active' : ''}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -382,11 +382,18 @@ input::placeholder { color: var(--text-disabled); }
|
||||
}
|
||||
.shell-menu-divider { height: 1px; background: var(--border); margin: 4px 6px; }
|
||||
|
||||
.shell-xterm-wrapper { flex: 1; background: var(--bg); overflow: hidden; position: relative; }
|
||||
.shell-xterm-wrapper { flex: 1; height: 100%; background: var(--bg); overflow: hidden; position: relative; }
|
||||
.shell-xterm-instance {
|
||||
position: absolute; inset: 0; padding: 4px;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
.shell-xterm-instance .xterm { height: 100%; padding: 4px; }
|
||||
.shell-xterm-instance.active {
|
||||
visibility: visible;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.shell-xterm-instance .xterm { height: 100%; }
|
||||
|
||||
.connection-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
|
||||
.connection-dot.on { background: var(--success); box-shadow: 0 0 6px var(--success); }
|
||||
|
||||
Reference in New Issue
Block a user