mirror of
https://github.com/tiennm99/coolify.git
synced 2026-04-17 17:21:04 +00:00
fix: Prevent terminal disconnects when browser tab loses focus (#7538)
This commit is contained in:
@@ -11,20 +11,6 @@ class Terminal extends Component
|
|||||||
{
|
{
|
||||||
public bool $hasShell = true;
|
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
|
private function checkShellAvailability(Server $server, string $container): bool
|
||||||
{
|
{
|
||||||
$escapedContainer = escapeshellarg($container);
|
$escapedContainer = escapeshellarg($container);
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ export function initializeTerminalComponent() {
|
|||||||
// Resize handling
|
// Resize handling
|
||||||
resizeObserver: null,
|
resizeObserver: null,
|
||||||
resizeTimeout: null,
|
resizeTimeout: null,
|
||||||
|
// Visibility handling - prevent disconnects when tab loses focus
|
||||||
|
isDocumentVisible: true,
|
||||||
|
wasConnectedBeforeHidden: false,
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.setupTerminal();
|
this.setupTerminal();
|
||||||
@@ -92,6 +95,11 @@ export function initializeTerminalComponent() {
|
|||||||
}, { once: true });
|
}, { once: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle visibility changes to prevent disconnects when tab loses focus
|
||||||
|
document.addEventListener('visibilitychange', () => {
|
||||||
|
this.handleVisibilityChange();
|
||||||
|
});
|
||||||
|
|
||||||
window.onresize = () => {
|
window.onresize = () => {
|
||||||
this.resizeTerminal()
|
this.resizeTerminal()
|
||||||
};
|
};
|
||||||
@@ -451,6 +459,11 @@ export function initializeTerminalComponent() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
keepAlive() {
|
keepAlive() {
|
||||||
|
// Skip keepalive when document is hidden to prevent unnecessary disconnects
|
||||||
|
if (!this.isDocumentVisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
||||||
this.sendMessage({ ping: true });
|
this.sendMessage({ ping: true });
|
||||||
} else if (this.connectionState === 'disconnected') {
|
} 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() {
|
resetPingTimeout() {
|
||||||
if (this.pingTimeoutId) {
|
if (this.pingTimeoutId) {
|
||||||
clearTimeout(this.pingTimeoutId);
|
clearTimeout(this.pingTimeoutId);
|
||||||
|
|||||||
Reference in New Issue
Block a user