feat(dashboard): show "Updating to a new version..." on loader during version-hash reload

When the dashboard reloads because the build version hash changed, surface that
on the loading screen instead of the generic "Initializing dashboard..." so the
user understands why they bounced.

Carry the signal across the hard reload via a sessionStorage flag set in
versionCheck just before reloadOnce(), and consume-and-clear it once on the
loader's first render.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-26 23:35:18 -07:00
parent 0c6186521b
commit 9d220717cb
3 changed files with 36 additions and 2 deletions

View File

@@ -43,6 +43,11 @@
color: var(--text-secondary);
}
.dashboard-loader__message--update {
color: var(--accent, var(--text));
font-weight: 500;
}
.dashboard-loader__steps {
display: flex;
flex-direction: column;

View File

@@ -1,4 +1,6 @@
import { Loader2 } from "lucide-react";
import { useState } from "react";
import { consumeVersionUpdateFlag } from "../versionCheck";
import "./DashboardLoader.css";
export type DashboardLoaderStage = "projects" | "project" | "tasks" | "ready";
@@ -38,17 +40,26 @@ function getStepState(stepId: LoaderStep["id"], stage: DashboardLoaderStage): "d
}
export function DashboardLoader({ stage }: DashboardLoaderProps) {
const [isVersionUpdate] = useState(() => consumeVersionUpdateFlag());
return (
<div
className="dashboard-loader"
role="status"
aria-live="polite"
aria-label="Loading Fusion dashboard"
aria-label={isVersionUpdate ? "Updating Fusion dashboard" : "Loading Fusion dashboard"}
data-stage={stage}
data-version-update={isVersionUpdate ? "true" : undefined}
>
<div className="dashboard-loader__content">
<h1 className="dashboard-loader__logo">Fusion</h1>
<p className="dashboard-loader__message">Initializing dashboard...</p>
{isVersionUpdate ? (
<p className="dashboard-loader__message dashboard-loader__message--update">
Updating to a new version...
</p>
) : (
<p className="dashboard-loader__message">Initializing dashboard...</p>
)}
<ol className="dashboard-loader__steps" aria-label="Dashboard loading progress">
{LOADER_STEPS.map((step) => {

View File

@@ -1,6 +1,19 @@
declare const __BUILD_VERSION__: string;
const RELOAD_FLAG = "fusion:version-reload";
const VERSION_UPDATE_FLAG = "fusion:version-update";
export function consumeVersionUpdateFlag(): boolean {
try {
if (sessionStorage.getItem(VERSION_UPDATE_FLAG)) {
sessionStorage.removeItem(VERSION_UPDATE_FLAG);
return true;
}
} catch {
// ignore (e.g. storage disabled)
}
return false;
}
function reloadOnce(reason: string): void {
if (sessionStorage.getItem(RELOAD_FLAG)) {
@@ -54,6 +67,11 @@ async function checkVersion(): Promise<void> {
try {
const remote = await fetchRemoteVersion();
if (remote && remote !== __BUILD_VERSION__) {
try {
sessionStorage.setItem(VERSION_UPDATE_FLAG, "1");
} catch {
// ignore
}
reloadOnce(`build version changed: ${__BUILD_VERSION__} -> ${remote}`);
}
} finally {