authorgravatar for 88523594+RakshithBhat03@users.noreply.github.comRakshith Bhat <88523594+RakshithBhat03@users.noreply.github.com> 2026-09-03 22:06:09+05:30
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-03 09:36:09-07:00
log2120fbc185737b71f09de020b95224f9e636d1e5
tree609354464b4b4efb80086457503af75e077d6d95
parentcfddb4201df8941bbfde008919da70fe5ec7552b
signature Signed by PGP key B5690EEEBB952194

fix(web): avoid duplicate Antigravity install status (#9419)


2 files changed, 51 insertions(+), 15 deletions(-)

apps/web/src/components/settings/ProviderSetupSection.test.tsx+35-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1import type { FunctionComponent, ReactElement } from "react";1import { isValidElement, type FunctionComponent, type ReactElement } from "react";
2import {2import {
3 EnvironmentId,3 EnvironmentId,
4 ProviderDriverKind,4 ProviderDriverKind,
...@@ -142,6 +142,23 @@ function button(view: unknown, label: string) {...@@ -142,6 +142,23 @@ function button(view: unknown, label: string) {
142 );142 );
143}143}
144144
145function countElements(
146 node: unknown,
147 predicate: (element: ReactElement<Record<string, unknown>>) => boolean,
148): number {
149 if (Array.isArray(node)) {
150 return node.reduce((total, child) => total + countElements(child, predicate), 0);
151 }
152 if (!isValidElement<Record<string, unknown>>(node)) return 0;
153 return (
154 Number(predicate(node)) +
155 Object.values(node.props).reduce<number>(
156 (total, value) => total + countElements(value, predicate),
157 0,
158 )
159 );
160}
161
145function click(view: unknown, label: string) {162function click(view: unknown, label: string) {
146 const target = button(view, label);163 const target = button(view, label);
147 if (!target) throw new Error(`Missing button: ${label}`);164 if (!target) throw new Error(`Missing button: ${label}`);
...@@ -285,6 +302,23 @@ describe("Antigravity setup", () => {...@@ -285,6 +302,23 @@ describe("Antigravity setup", () => {
285 await flushPromises();302 await flushPromises();
286 });303 });
287304
305 it("shows a repeated runtime status message only once", () => {
306 setup.installation = {
307 ...setup.installation!,
308 operationId: "install-1",
309 phase: "verifying",
310 message: "Checking the downloaded runtime.",
311 };
312
313 const view = renderSetup();
314 expect(
315 countElements(
316 view,
317 (element) => element.props.children === "Checking the downloaded runtime.",
318 ),
319 ).toBe(1);
320 });
321
288 it("removes an owned damaged runtime only after confirmation", async () => {322 it("removes an owned damaged runtime only after confirmation", async () => {
289 setup.auth = authState({ phase: "idle", flowId: null, authorizationUrl: null });323 setup.auth = authState({ phase: "idle", flowId: null, authorizationUrl: null });
290 setup.installation = {324 setup.installation = {
apps/web/src/components/settings/ProviderSetupSection.tsx+16-14
...@@ -169,6 +169,20 @@ function ProviderSetupActions({...@@ -169,6 +169,20 @@ function ProviderSetupActions({
169 const authorizationUrl = auth?.phase === "waiting" ? auth.authorizationUrl : null;169 const authorizationUrl = auth?.phase === "waiting" ? auth.authorizationUrl : null;
170 const queryError = authQuery.error ?? installQuery.error;170 const queryError = authQuery.error ?? installQuery.error;
171 const actionsDisabled = pendingLabel !== null || queryError !== null;171 const actionsDisabled = pendingLabel !== null || queryError !== null;
172 const installationStatusMessage =
173 installation?.phase === "downloading"
174 ? `Downloading ${(installation.downloadedBytes / 1_000_000).toFixed(1)} MB${installation.totalBytes === null ? "" : ` of ${(installation.totalBytes / 1_000_000).toFixed(1)} MB`}.`
175 : installation?.phase === "extracting"
176 ? "Extracting Antigravity."
177 : installation?.phase === "verifying"
178 ? "Checking the downloaded runtime."
179 : installed
180 ? "Antigravity is installed."
181 : usesCustomBinary
182 ? enabled
183 ? "The configured Antigravity runtime is unavailable."
184 : "The configured Antigravity runtime has not been checked."
185 : "Install the official Antigravity runtime before signing in.";
172186
173 async function runCommand<A, E>(187 async function runCommand<A, E>(
174 label: string,188 label: string,
...@@ -252,19 +266,7 @@ function ProviderSetupActions({...@@ -252,19 +266,7 @@ function ProviderSetupActions({
252 <div className="grid gap-2">266 <div className="grid gap-2">
253 <p className="font-medium">Runtime</p>267 <p className="font-medium">Runtime</p>
254 <p role="status" className="text-muted-foreground">268 <p role="status" className="text-muted-foreground">
255 {installation?.phase === "downloading"269 {installationStatusMessage}
256 ? `Downloading ${(installation.downloadedBytes / 1_000_000).toFixed(1)} MB${installation.totalBytes === null ? "" : ` of ${(installation.totalBytes / 1_000_000).toFixed(1)} MB`}.`
257 : installation?.phase === "extracting"
258 ? "Extracting Antigravity."
259 : installation?.phase === "verifying"
260 ? "Checking the downloaded runtime."
261 : installed
262 ? "Antigravity is installed."
263 : usesCustomBinary
264 ? enabled
265 ? "The configured Antigravity runtime is unavailable."
266 : "The configured Antigravity runtime has not been checked."
267 : "Install the official Antigravity runtime before signing in."}
268 </p>270 </p>
269 {installation?.phase === "downloading" &&271 {installation?.phase === "downloading" &&
270 installation.totalBytes !== null &&272 installation.totalBytes !== null &&
...@@ -276,7 +278,7 @@ function ProviderSetupActions({...@@ -276,7 +278,7 @@ function ProviderSetupActions({
276 max={installation.totalBytes}278 max={installation.totalBytes}
277 />279 />
278 ) : null}280 ) : null}
279 {installation?.message ? (281 {installation?.message && installation.message !== installationStatusMessage ? (
280 <p className="text-muted-foreground [overflow-wrap:anywhere]">{installation.message}</p>282 <p className="text-muted-foreground [overflow-wrap:anywhere]">{installation.message}</p>
281 ) : null}283 ) : null}
282 {usesCustomBinary ? (284 {usesCustomBinary ? (