mirror of
https://github.com/coollabsio/coolify.git
synced 2025-12-27 21:25:48 +00:00
fix: Prevent terminal disconnects when browser tab loses focus
Add visibility API handling to pause heartbeat monitoring when the browser tab is hidden, preventing false disconnection timeouts. When the tab becomes visible again, verify the connection is still alive or attempt reconnection. Also remove the ApplicationStatusChanged event listener that was triggering terminal reloads whenever any application status changed across the team. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
e1d5da3622
commit
dca6d9f7aa
@ -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 New Issue
Block a user