From a0ae6bbfe524fc41d5fae65d6af8efe870549681 Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Mon, 19 Oct 2026 12:54:01 -0700 Subject: [PATCH] fix(settings): Antigravity's sign-in reads as an Account line, never an empty box Settings > Chat > Providers showed Antigravity's sign-in as a filled grey box holding only a bright primary "Sign in" button. The host learns whether its chats are signed in only when a chat starts, so after launch the status line had nothing to say and the box sat empty. The area is now a plain row under the provider's name: "Account" on one line, the status on the next, and an outline "Sign in" button. Until the host knows, the status line says chats need an Antigravity sign-in separate from the agy terminal account. --- .../AntigravityChatSignInRow.test.tsx | 38 ++++++++++++++ .../settings/AntigravityChatSignInRow.tsx | 10 +++- .../AntigravityProviderSignInArea.tsx | 51 +++++++++++-------- src/renderer/src/i18n/locales/en.json | 4 +- src/renderer/src/i18n/locales/es.json | 4 +- src/renderer/src/i18n/locales/fr.json | 4 +- src/renderer/src/i18n/locales/ja.json | 4 +- src/renderer/src/i18n/locales/ko.json | 4 +- src/renderer/src/i18n/locales/zh.json | 4 +- 9 files changed, 94 insertions(+), 29 deletions(-) diff --git a/src/renderer/src/components/settings/AntigravityChatSignInRow.test.tsx b/src/renderer/src/components/settings/AntigravityChatSignInRow.test.tsx index 8d4393bb8c03..88980f2aa3c6 100644 --- a/src/renderer/src/components/settings/AntigravityChatSignInRow.test.tsx +++ b/src/renderer/src/components/settings/AntigravityChatSignInRow.test.tsx @@ -9,6 +9,7 @@ import type { import type { RuntimeClientTarget } from '../../../../shared/runtime-client-target' import { callAntigravityChatSignIn } from '@/runtime/runtime-antigravity-accounts-client' import { AntigravityChatSignInRow } from './AntigravityChatSignInRow' +import { AntigravityProviderSignInArea } from './AntigravityProviderSignInArea' import { TooltipProvider } from '../ui/tooltip' const url = 'https://accounts.google.com/o/oauth2/v2/auth?state=s' @@ -157,3 +158,40 @@ it('sends the address pasted from a browser on another computer to the host', as callbackUrl: pasted }) }) + +// A host learns its sign-in only when a chat starts, so after launch it has no answer to show. +it("names the account and why it's needed before the host knows its sign-in", async () => { + const owner = { kind: 'environment', environmentId: 'provider-unanswered' } as const + render( + + ) + await act(async () => undefined) + expect(screen.getByText('Account')).toBeTruthy() + expect(screen.getByRole('status').textContent).toBe( + 'Chats need an Antigravity sign-in, separate from your agy terminal account.' + ) + expect(screen.getByRole('button', { name: 'Sign in' }).hasAttribute('disabled')).toBe(false) + await act(async () => publish(owner, null, 'signedOut')) + expect(screen.getByRole('status').textContent).toMatch(/^Not signed in\./) +}) diff --git a/src/renderer/src/components/settings/AntigravityChatSignInRow.tsx b/src/renderer/src/components/settings/AntigravityChatSignInRow.tsx index bbfda57cfbca..e81a65b76043 100644 --- a/src/renderer/src/components/settings/AntigravityChatSignInRow.tsx +++ b/src/renderer/src/components/settings/AntigravityChatSignInRow.tsx @@ -203,11 +203,13 @@ export function PastedAddressForm(props: { } /** One host's chat sign-in as both Settings layouts show it. `signedOut` is the line for a host - * that answered it is not signed in. */ + * that answered it is not signed in; `unanswered` stands in while it has nothing else to say, as a + * host learns its sign-in only when a chat starts or asks to sign in. */ export function useAntigravityChatSignInControls(props: { owner: RuntimeClientTarget label: string signedOut: string + unanswered?: string disabled: boolean }) { const { owner, label } = props @@ -235,7 +237,11 @@ export function useAntigravityChatSignInControls(props: { /** The browser's link, while this client's sign-in waits on it. */ url: ownFlow && flow?.phase === 'waiting' ? (flow.url ?? null) : null, line: - status === 'known' ? chatSignInLine(flow, auth, openFailed, label, props.signedOut) : null, + status === 'known' + ? (chatSignInLine(flow, auth, openFailed, label, props.signedOut) ?? + props.unanswered ?? + null) + : null, alert: error ?? (status === 'readFailed' ? readFailed : null) ?? diff --git a/src/renderer/src/components/settings/AntigravityProviderSignInArea.tsx b/src/renderer/src/components/settings/AntigravityProviderSignInArea.tsx index 468589cd82da..25fba3d906f9 100644 --- a/src/renderer/src/components/settings/AntigravityProviderSignInArea.tsx +++ b/src/renderer/src/components/settings/AntigravityProviderSignInArea.tsx @@ -38,6 +38,10 @@ export function AntigravityProviderSignInArea(props: { 'settings.chat.providers.antigravityNotSignedIn', 'Not signed in. Chats need an Antigravity sign-in, separate from your agy terminal account.' ), + unanswered: translate( + 'settings.chat.providers.antigravitySignInNeeded', + 'Chats need an Antigravity sign-in, separate from your agy terminal account.' + ), disabled: antigravityChatSignInBlocked(props.install) }) const { alert, copy, copyLabel, ownFlow, url } = signIn @@ -45,26 +49,31 @@ export function AntigravityProviderSignInArea(props: { const line = alert && !ownFlow ? null : signIn.line return ( // Indented to the provider's name, past its icon. -
- {/* The line keeps its height until the host answers, so nothing shifts when it does. */} -
-
- {ownFlow ? : null} - - {line} - {line && alert ? ' ' : null} - {alert && ( - - {alert} - - )} - +
+
+
+

+ {translate('settings.chat.providers.antigravityAccount', 'Account')} +

+ {/* The line keeps its height until the host answers, so nothing shifts when it does. */} +
+ {ownFlow ? : null} + + {line} + {line && alert ? ' ' : null} + {alert && ( + + {alert} + + )} + +
{ownFlow ? ( - <> +
{url && ( - +
) : (