refac
This commit is contained in:
+78
-21
@@ -118,9 +118,48 @@
|
||||
let heartbeatInterval = null;
|
||||
let disconnectToastTimer = null;
|
||||
let disconnectWarningShown = false;
|
||||
let pageIsVisible = true;
|
||||
let pageWasHidden = false;
|
||||
let lastVisibleAt = Date.now();
|
||||
let disconnectReason = null;
|
||||
|
||||
const BREAKPOINT = 768;
|
||||
const DISCONNECT_TOAST_DELAY_MS = 2000;
|
||||
const RECENT_RESUME_GRACE_MS = 8000;
|
||||
const RESUME_DISCONNECT_REASONS = new Set(['ping timeout', 'transport close', 'transport error']);
|
||||
|
||||
const clearDisconnectToastTimer = () => {
|
||||
if (disconnectToastTimer) {
|
||||
clearTimeout(disconnectToastTimer);
|
||||
disconnectToastTimer = null;
|
||||
}
|
||||
};
|
||||
|
||||
const recentlyResumed = () =>
|
||||
pageWasHidden && Date.now() - lastVisibleAt < RECENT_RESUME_GRACE_MS;
|
||||
|
||||
const isLikelyResumeDisconnect = (reason) => {
|
||||
return (!pageIsVisible || recentlyResumed()) && RESUME_DISCONNECT_REASONS.has(reason);
|
||||
};
|
||||
|
||||
const scheduleDisconnectToast = () => {
|
||||
clearDisconnectToastTimer();
|
||||
|
||||
const resumeDelay = isLikelyResumeDisconnect(disconnectReason)
|
||||
? Math.max(RECENT_RESUME_GRACE_MS - (Date.now() - lastVisibleAt), 0)
|
||||
: 0;
|
||||
|
||||
disconnectToastTimer = setTimeout(() => {
|
||||
disconnectToastTimer = null;
|
||||
|
||||
if ($socket?.connected || !pageIsVisible || isLikelyResumeDisconnect(disconnectReason)) {
|
||||
return;
|
||||
}
|
||||
|
||||
disconnectWarningShown = true;
|
||||
toast.warning($i18n.t('Connection lost. Reconnecting...'));
|
||||
}, resumeDelay + DISCONNECT_TOAST_DELAY_MS);
|
||||
};
|
||||
|
||||
const setupSocket = async (enableWebsocket) => {
|
||||
const _socket = io(`${WEBUI_BASE_URL}` || undefined, {
|
||||
@@ -144,19 +183,17 @@
|
||||
console.log('connected', _socket.id);
|
||||
|
||||
// Cancel any pending disconnect toast if we reconnected quickly
|
||||
if (disconnectToastTimer) {
|
||||
clearTimeout(disconnectToastTimer);
|
||||
disconnectToastTimer = null;
|
||||
}
|
||||
clearDisconnectToastTimer();
|
||||
|
||||
if (hasConnectedOnce) {
|
||||
socketConnected.set(true);
|
||||
// Only show "Reconnected" if the user actually saw the disconnect warning
|
||||
if (disconnectWarningShown) {
|
||||
toast.success($i18n.t('Reconnected'));
|
||||
disconnectWarningShown = false;
|
||||
}
|
||||
}
|
||||
disconnectWarningShown = false;
|
||||
disconnectReason = null;
|
||||
hasConnectedOnce = true;
|
||||
|
||||
const res = await getVersion(localStorage.token);
|
||||
@@ -213,18 +250,15 @@
|
||||
_socket.on('disconnect', (reason, details) => {
|
||||
console.log(`Socket ${_socket.id} disconnected due to ${reason}`);
|
||||
socketConnected.set(false);
|
||||
|
||||
// Delay showing the disconnect toast so brief interruptions
|
||||
// (e.g. mobile tab backgrounding) don't flash a nuisance warning
|
||||
if (disconnectToastTimer) {
|
||||
clearTimeout(disconnectToastTimer);
|
||||
}
|
||||
disconnectReason = reason;
|
||||
disconnectWarningShown = false;
|
||||
disconnectToastTimer = setTimeout(() => {
|
||||
disconnectToastTimer = null;
|
||||
disconnectWarningShown = true;
|
||||
toast.warning($i18n.t('Connection lost. Reconnecting...'));
|
||||
}, DISCONNECT_TOAST_DELAY_MS);
|
||||
|
||||
// Delay visible warnings while mobile browsers resume suspended tabs.
|
||||
if (isLikelyResumeDisconnect(reason)) {
|
||||
clearDisconnectToastTimer();
|
||||
} else {
|
||||
scheduleDisconnectToast();
|
||||
}
|
||||
|
||||
if (heartbeatInterval) {
|
||||
clearInterval(heartbeatInterval);
|
||||
@@ -1044,18 +1078,39 @@
|
||||
};
|
||||
|
||||
// Set yourself as the last active tab when this tab is focused
|
||||
const handlePageHidden = () => {
|
||||
pageIsVisible = false;
|
||||
pageWasHidden = true;
|
||||
clearDisconnectToastTimer();
|
||||
};
|
||||
|
||||
const handlePageVisible = () => {
|
||||
pageIsVisible = true;
|
||||
lastVisibleAt = Date.now();
|
||||
|
||||
isLastActiveTab.set(true); // This tab is now the active tab
|
||||
bc.postMessage('active'); // Notify other tabs that this tab is active
|
||||
|
||||
// Check token expiry when the tab becomes active
|
||||
checkTokenExpiry();
|
||||
|
||||
if ($socket && !$socket.connected) {
|
||||
scheduleDisconnectToast();
|
||||
}
|
||||
};
|
||||
|
||||
const handleVisibilityChange = () => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
isLastActiveTab.set(true); // This tab is now the active tab
|
||||
bc.postMessage('active'); // Notify other tabs that this tab is active
|
||||
|
||||
// Check token expiry when the tab becomes active
|
||||
checkTokenExpiry();
|
||||
handlePageVisible();
|
||||
} else {
|
||||
handlePageHidden();
|
||||
}
|
||||
};
|
||||
|
||||
// Add event listener for visibility state changes
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
window.addEventListener('pagehide', handlePageHidden);
|
||||
window.addEventListener('pageshow', handlePageVisible);
|
||||
|
||||
// Call visibility change handler initially to set state on load
|
||||
handleVisibilityChange();
|
||||
@@ -1228,6 +1283,8 @@
|
||||
document.removeEventListener('touchmove', touchmoveHandler);
|
||||
document.removeEventListener('touchend', touchendHandler);
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
window.removeEventListener('pagehide', handlePageHidden);
|
||||
window.removeEventListener('pageshow', handlePageVisible);
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user