fix: Prevent terminal disconnects when browser tab loses focus (#7538)
This commit is contained in:
commit
b3289aff71
2 changed files with 42 additions and 14 deletions
|
|
@ -11,20 +11,6 @@ class Terminal extends Component
|
|||
{
|
||||
public bool $hasShell = true;
|
||||
|
||||
public function getListeners()
|
||||
{
|
||||
$teamId = auth()->user()->currentTeam()->id;
|
||||
|
||||
return [
|
||||
"echo-private:team.{$teamId},ApplicationStatusChanged" => 'closeTerminal',
|
||||
];
|
||||
}
|
||||
|
||||
public function closeTerminal()
|
||||
{
|
||||
$this->dispatch('reloadWindow');
|
||||
}
|
||||
|
||||
private function checkShellAvailability(Server $server, string $container): bool
|
||||
{
|
||||
$escapedContainer = escapeshellarg($container);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ export function initializeTerminalComponent() {
|
|||
// Resize handling
|
||||
resizeObserver: null,
|
||||
resizeTimeout: null,
|
||||
// Visibility handling - prevent disconnects when tab loses focus
|
||||
isDocumentVisible: true,
|
||||
wasConnectedBeforeHidden: false,
|
||||
|
||||
init() {
|
||||
this.setupTerminal();
|
||||
|
|
@ -92,6 +95,11 @@ export function initializeTerminalComponent() {
|
|||
}, { once: true });
|
||||
});
|
||||
|
||||
// Handle visibility changes to prevent disconnects when tab loses focus
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
this.handleVisibilityChange();
|
||||
});
|
||||
|
||||
window.onresize = () => {
|
||||
this.resizeTerminal()
|
||||
};
|
||||
|
|
@ -451,6 +459,11 @@ export function initializeTerminalComponent() {
|
|||
},
|
||||
|
||||
keepAlive() {
|
||||
// Skip keepalive when document is hidden to prevent unnecessary disconnects
|
||||
if (!this.isDocumentVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
||||
this.sendMessage({ ping: true });
|
||||
} else if (this.connectionState === 'disconnected') {
|
||||
|
|
@ -459,6 +472,35 @@ export function initializeTerminalComponent() {
|
|||
}
|
||||
},
|
||||
|
||||
handleVisibilityChange() {
|
||||
const wasVisible = this.isDocumentVisible;
|
||||
this.isDocumentVisible = !document.hidden;
|
||||
|
||||
if (!this.isDocumentVisible) {
|
||||
// Tab is now hidden - pause heartbeat monitoring to prevent false disconnects
|
||||
this.wasConnectedBeforeHidden = this.connectionState === 'connected';
|
||||
if (this.pingTimeoutId) {
|
||||
clearTimeout(this.pingTimeoutId);
|
||||
this.pingTimeoutId = null;
|
||||
}
|
||||
console.log('[Terminal] Tab hidden, pausing heartbeat monitoring');
|
||||
} else if (wasVisible === false) {
|
||||
// Tab is now visible again
|
||||
console.log('[Terminal] Tab visible, resuming connection management');
|
||||
|
||||
if (this.wasConnectedBeforeHidden && this.socket && this.socket.readyState === WebSocket.OPEN) {
|
||||
// Send immediate ping to verify connection is still alive
|
||||
this.heartbeatMissed = 0;
|
||||
this.sendMessage({ ping: true });
|
||||
this.resetPingTimeout();
|
||||
} else if (this.wasConnectedBeforeHidden && this.connectionState !== 'connected') {
|
||||
// Was connected before but now disconnected - attempt reconnection
|
||||
this.reconnectAttempts = 0;
|
||||
this.initializeWebSocket();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
resetPingTimeout() {
|
||||
if (this.pingTimeoutId) {
|
||||
clearTimeout(this.pingTimeoutId);
|
||||
|
|
|
|||
Loading…
Reference in a new issue