commit 95232622cc612c9f1d76d806c7f1e6008da4a6ec
parent 59dce84264011210c01ca422a659c95075cd1b79
Author: Michael Camilleri <[email protected]>
Date: Mon, 1 Jun 2026 09:48:48 +0900
Hold the replay scrubber's height while it loads
The Success Panel's scrubber row started as EmptyView while idle, grew
to a caption row once loading began, then collapsed back to nothing when
the load resolved to no reachable history — appearing and vanishing as
it went. That could read as a hitch: the scoreboard below shifting up
and down as the row changed size.
ReplayScrubber now reserves the same row height in every state. The
idle, empty-ready and unavailable states all render a blank box of that
height rather than EmptyView, so the load can resolve without the banner
changing size. The loading caption shows only while a load is genuinely
in flight, so the no-replay path no longer flashes a spinner before
settling.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Diffstat:
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/Crossmate/Views/SuccessPanel.swift b/Crossmate/Views/SuccessPanel.swift
@@ -246,10 +246,13 @@ private struct ReplayScrubber: View {
ProgressView().controlSize(.small)
Text("Loading replay…")
}
- case .ready, .idle, .unavailable:
- // Nothing to replay (empty log) or no reachable history:
- // leave the banner as just the scoreboard.
- EmptyView()
+ case .idle, .ready, .unavailable:
+ // Not started yet (`.idle`), nothing to replay (empty log), or
+ // no reachable history. Hold the row's height anyway so the
+ // banner doesn't change size as the load resolves — otherwise
+ // the scoreboard below hitches up and down as the scrubber
+ // appears then collapses.
+ Color.clear.frame(height: Self.rowHeight)
}
}
.padding(.horizontal, 18)