Fix updater auto-refresh for all open tabs (related to #671)
Problem: When an update was triggered, only the tab that clicked "Apply Update" would show the progress modal and auto-refresh after completion. Other open tabs would remain on the old version indefinitely. Root cause: The UpdateProgressModal was only shown when explicitly opened via the UpdateBanner component. WebSocket already broadcasts update:progress events, but no global listener existed to show the modal in all tabs. Solution: Added GlobalUpdateProgressWatcher component in App.tsx that: - Listens to WebSocket updateProgress events globally (in all tabs) - Filters to only real update-in-progress states (downloading, verifying, extracting, installing, restarting) to avoid false positives from routine update checks - Auto-opens the progress modal when an update starts - Allows manual dismissal after update completes - Works independently of UpdateBanner visibility (e.g., when banner is dismissed) The modal's existing health-check and auto-reload logic handles the page refresh once the backend is healthy again.
This commit is contained in:
parent
6bf32f98d6
commit
706822ed58
1 changed files with 57 additions and 0 deletions
|
|
@ -40,6 +40,8 @@ import BellIcon from 'lucide-solid/icons/bell';
|
|||
import SettingsIcon from 'lucide-solid/icons/settings';
|
||||
import { TokenRevealDialog } from './components/TokenRevealDialog';
|
||||
import { useAlertsActivation } from './stores/alertsActivation';
|
||||
import { UpdateProgressModal } from './components/UpdateProgressModal';
|
||||
import type { UpdateStatus } from './api/updates';
|
||||
|
||||
const Dashboard = lazy(() =>
|
||||
import('./components/Dashboard/Dashboard').then((module) => ({ default: module.Dashboard })),
|
||||
|
|
@ -106,6 +108,60 @@ function HostsRoute() {
|
|||
);
|
||||
}
|
||||
|
||||
// Helper to detect if an update is actively in progress (not just checking for updates)
|
||||
function isUpdateInProgress(status: string | undefined): boolean {
|
||||
if (!status) return false;
|
||||
const inProgressStates = ['downloading', 'verifying', 'extracting', 'installing', 'restarting'];
|
||||
return inProgressStates.includes(status);
|
||||
}
|
||||
|
||||
// Global update progress watcher - shows modal in ALL tabs when an update is running
|
||||
function GlobalUpdateProgressWatcher() {
|
||||
const wsContext = useContext(WebSocketContext);
|
||||
const navigate = useNavigate();
|
||||
const [showProgressModal, setShowProgressModal] = createSignal(false);
|
||||
const [hasAutoOpened, setHasAutoOpened] = createSignal(false);
|
||||
|
||||
// Watch for update progress events from WebSocket
|
||||
createEffect(() => {
|
||||
const progress = wsContext?.updateProgress?.() as UpdateStatus | null;
|
||||
|
||||
if (!progress) {
|
||||
// Reset when no progress data
|
||||
setHasAutoOpened(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const inProgress = isUpdateInProgress(progress.status);
|
||||
|
||||
if (inProgress && !showProgressModal() && !hasAutoOpened()) {
|
||||
// Update is starting - auto-open the modal in this tab
|
||||
logger.info('Update in progress detected via WebSocket, showing progress modal', {
|
||||
status: progress.status,
|
||||
message: progress.message,
|
||||
});
|
||||
setShowProgressModal(true);
|
||||
setHasAutoOpened(true);
|
||||
} else if (!inProgress && hasAutoOpened()) {
|
||||
// Update finished - allow the modal to be dismissed
|
||||
setHasAutoOpened(false);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<UpdateProgressModal
|
||||
isOpen={showProgressModal()}
|
||||
onClose={() => setShowProgressModal(false)}
|
||||
onViewHistory={() => {
|
||||
setShowProgressModal(false);
|
||||
navigate('/settings/updates');
|
||||
}}
|
||||
connected={wsContext?.connected}
|
||||
reconnecting={wsContext?.reconnecting}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function App() {
|
||||
const TooltipRoot = createTooltipSystem();
|
||||
const owner = getOwner();
|
||||
|
|
@ -644,6 +700,7 @@ function App() {
|
|||
<SecurityWarning />
|
||||
<DemoBanner />
|
||||
<UpdateBanner />
|
||||
<GlobalUpdateProgressWatcher />
|
||||
<div class="min-h-screen bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-200 font-sans py-4 sm:py-6">
|
||||
<AppLayout
|
||||
connected={connected}
|
||||
|
|
|
|||
Loading…
Reference in a new issue