fix(desktop): stop the update overlay looking frozen while it works

Two ways the update overlay read as stuck even though the update was
streaming progress underneath:

- In-app (macOS/Linux) UpdatesOverlay: runStreamedUpdate forwards every
  stdout line as a progress event with percent: null, and ingestProgress
  wrote that straight through — clobbering the milestone percents (10/60)
  so the bar fell back to indeterminate on every log line. Keep the last
  percent when a line carries null.

- Staged install/update overlay: the bar is completedCount / totalCount,
  which counts only *finished* stages, so a long first stage pinned it at
  "0 of 2" / 0% until the stage ended. Count the running stage as half a
  unit so the bar advances during the stage (the per-stage spinner already
  shows which step is live).

Both are display-only; no stage/event semantics change. (The Windows
hermes-setup Tauri progress UI in apps/bootstrap-installer has the same
counter-only-on-completion logic — parity follow-up.)
This commit is contained in:
Brooklyn Nicholson 2026-06-24 19:20:38 -05:00
parent d335164833
commit 9a4600c5fb
2 changed files with 8 additions and 2 deletions

View file

@ -407,7 +407,11 @@ export function DesktopInstallOverlay({ enabled = true }: DesktopInstallOverlayP
const totalCount = stages.length
const failed = Boolean(state.error)
const progressPct = totalCount > 0 ? Math.round((completedCount / totalCount) * 100) : 0
// Count the running stage as half-done so the bar advances *during* a long
// stage instead of sitting frozen at the last completed step while its logs
// stream (e.g. "0 of 2" pinned at 0% for the whole first stage).
const progressUnits = completedCount + (!failed && currentStage ? 0.5 : 0)
const progressPct = totalCount > 0 ? Math.round((progressUnits / totalCount) * 100) : 0
const currentStartedAt = currentStage ? state.stages[currentStage]?.startedAt : null
const currentElapsed = typeof currentStartedAt === 'number' ? formatElapsed(now - currentStartedAt) : ''

View file

@ -531,7 +531,9 @@ function ingestProgress(payload: DesktopUpdateProgress): void {
applying: !terminal,
stage: payload.stage,
message: payload.message,
percent: payload.percent,
// Streamed log lines carry percent: null; keep the last milestone percent
// (10/60/…) instead of resetting the bar to indeterminate on every line.
percent: payload.percent ?? current.percent,
error: payload.error,
// 'manual' carries the command to run in its message field.
command: payload.stage === 'manual' ? payload.message : current.command,