fix: preserve terminal buffer across tab switches and focus regain
Render all terminal sessions and hide inactive ones with display:none so xterm instances are no longer unmounted/remounted when switching tabs. Remove terminal.clear() on the connected status message: the server keeps the session buffer, and clearing was erasing visible content when the tab regained focus or reconnected. - Keep TerminalComponent instances alive in both Desktop and Mobile views. - Only refit/resize on reconnect instead of clearing. Closes terminal redraw on focus regain.
This commit is contained in:
@@ -172,21 +172,25 @@ export const DesktopTerminalView: React.FC<Props> = ({
|
||||
)}
|
||||
<div className="terminal-page-content">
|
||||
{error && <div className="terminal-error-banner">{error}</div>}
|
||||
{sessions
|
||||
.filter((session) => session.id === activeSessionId)
|
||||
.map((session) => (
|
||||
<div key={session.id} className="terminal-instance active">
|
||||
<TerminalComponent
|
||||
ref={terminalRefs.current[session.id]}
|
||||
instanceId={instanceId}
|
||||
sessionId={session.id}
|
||||
onClose={() => onClose(session.id)}
|
||||
isMobile={false}
|
||||
showControls={!isFullscreen}
|
||||
onTerminalReady={onTerminalReady}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
{sessions.map((session) => (
|
||||
<div
|
||||
key={session.id}
|
||||
className={`terminal-instance ${session.id === activeSessionId ? "active" : ""}`}
|
||||
style={{
|
||||
display: session.id === activeSessionId ? "flex" : "none",
|
||||
}}
|
||||
>
|
||||
<TerminalComponent
|
||||
ref={terminalRefs.current[session.id]}
|
||||
instanceId={instanceId}
|
||||
sessionId={session.id}
|
||||
onClose={() => onClose(session.id)}
|
||||
isMobile={false}
|
||||
showControls={!isFullscreen}
|
||||
onTerminalReady={onTerminalReady}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
{sessions.length === 0 && !loading && (
|
||||
<div className="terminal-empty-state">
|
||||
<p>No terminal sessions. Press Alt+Shift+N to create one.</p>
|
||||
|
||||
@@ -115,23 +115,27 @@ export const MobileTerminalView: React.FC<Props> = ({
|
||||
onClick={onToggleHeader}
|
||||
>
|
||||
{error && <div className="terminal-error-banner">{error}</div>}
|
||||
{sessions
|
||||
.filter((session) => session.id === activeSessionId)
|
||||
.map((session) => (
|
||||
<div key={session.id} className="terminal-instance active">
|
||||
<TerminalComponent
|
||||
ref={terminalRefs.current[session.id]}
|
||||
instanceId={instanceId}
|
||||
sessionId={session.id}
|
||||
onClose={() => onClose(session.id)}
|
||||
isMobile={true}
|
||||
showControls={false}
|
||||
activeModifier={activeModifier}
|
||||
onModifierChange={onModifierChange}
|
||||
onTerminalReady={onTerminalReady}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
{sessions.map((session) => (
|
||||
<div
|
||||
key={session.id}
|
||||
className={`terminal-instance ${session.id === activeSessionId ? "active" : ""}`}
|
||||
style={{
|
||||
display: session.id === activeSessionId ? "flex" : "none",
|
||||
}}
|
||||
>
|
||||
<TerminalComponent
|
||||
ref={terminalRefs.current[session.id]}
|
||||
instanceId={instanceId}
|
||||
sessionId={session.id}
|
||||
onClose={() => onClose(session.id)}
|
||||
isMobile={true}
|
||||
showControls={false}
|
||||
activeModifier={activeModifier}
|
||||
onModifierChange={onModifierChange}
|
||||
onTerminalReady={onTerminalReady}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
{sessions.length === 0 && !loading && (
|
||||
<div className="terminal-empty-state">
|
||||
<p>No terminal sessions. Press Alt+Shift+N to create one.</p>
|
||||
|
||||
@@ -174,9 +174,11 @@ export const TerminalComponent = React.forwardRef<TerminalRef, TerminalProps>(
|
||||
if (msg.status === "connected") {
|
||||
setStatus("connected");
|
||||
setError(null);
|
||||
// Clear terminal and refit after reset/reconnect
|
||||
// Refit after reset/reconnect but do NOT clear the
|
||||
// terminal: the server keeps the session buffer, and
|
||||
// clearing would erase it when the user switches back
|
||||
// to an already-connected session.
|
||||
if (termRef.current) {
|
||||
termRef.current.clear();
|
||||
requestAnimationFrame(() => {
|
||||
if (fitAddonRef.current && termRef.current) {
|
||||
fitAddonRef.current.fit();
|
||||
|
||||
Reference in New Issue
Block a user