diff --git a/mobile/app/hybrid.tsx b/mobile/app/hybrid.tsx
index 27c6dcb2ff0..ac499326ab2 100644
--- a/mobile/app/hybrid.tsx
+++ b/mobile/app/hybrid.tsx
@@ -22,7 +22,6 @@ import { MobileWebHybridShellPresentation } from '../src/mobile-web/MobileWebHyb
import { mobileWebShellLoadFailureWarning } from '../src/mobile-web/mobile-web-shell-load-failure-warning'
import { useMobileWebNavigationIntentHandoff } from '../src/mobile-web/use-mobile-web-navigation-intent-handoff'
import { useMobileWebColdResumeRoute } from '../src/mobile-web/use-mobile-web-cold-resume-route'
-import { mobileWebBridgeConnectionState } from '../src/mobile-web/mobile-web-bridge-connection-state'
import { MobileWebOneShotResponseDrop } from '../src/mobile-web/mobile-web-one-shot-response-drop'
import { useMobileWebE2eHostSelection } from '../src/mobile-web/mobile-web-e2e-host-selection'
import { useMobileWebAppForegroundAuthority } from '../src/mobile-web/use-mobile-web-app-foreground-authority'
@@ -266,7 +265,7 @@ export default function HybridScreen() {
}, [postInit])
useEffect(() => {
- brokerRef.current?.updateConnectionState(mobileWebBridgeConnectionState(state))
+ brokerRef.current?.updateConnectionState(state)
const current = session
if (!current || pageDocument.initializedSessionRef.current !== current.sessionId) {
return
@@ -276,7 +275,7 @@ export default function HybridScreen() {
type: 'connection',
shellSessionId: current.sessionId,
buildId: current.buildId,
- state: mobileWebBridgeConnectionState(state),
+ state,
reconnectAttempts: reconnects,
lastConnectedAt: lastConnected
})
diff --git a/mobile/host-web-app/h/[hostId]/accounts.tsx b/mobile/host-web-app/h/[hostId]/accounts.tsx
index e539c86395b..201db4a8058 100644
--- a/mobile/host-web-app/h/[hostId]/accounts.tsx
+++ b/mobile/host-web-app/h/[hostId]/accounts.tsx
@@ -14,18 +14,12 @@ export default function HostMobileWebAccountsRoute() {
: undefined,
[shell.client, shell.hostDisplayName]
)
- const connectionState =
- shell.connection === 'offline'
- ? 'disconnected'
- : shell.connection === 'recovering'
- ? 'reconnecting'
- : shell.connection
return (
)
diff --git a/mobile/host-web-app/h/[hostId]/files/[worktreeId].tsx b/mobile/host-web-app/h/[hostId]/files/[worktreeId].tsx
index df3fd039e15..b75f361e723 100644
--- a/mobile/host-web-app/h/[hostId]/files/[worktreeId].tsx
+++ b/mobile/host-web-app/h/[hostId]/files/[worktreeId].tsx
@@ -9,17 +9,11 @@ export default function HostMobileWebFileExplorerRoute() {
() => (shell.client ? webHostFileExplorerOperations(shell.client) : undefined),
[shell.client]
)
- const connectionState =
- shell.connection === 'offline'
- ? 'disconnected'
- : shell.connection === 'recovering'
- ? 'reconnecting'
- : shell.connection
return (
)
diff --git a/mobile/host-web-app/h/[hostId]/files/preview/[worktreeId].tsx b/mobile/host-web-app/h/[hostId]/files/preview/[worktreeId].tsx
index b52bbde909e..438a53d9782 100644
--- a/mobile/host-web-app/h/[hostId]/files/preview/[worktreeId].tsx
+++ b/mobile/host-web-app/h/[hostId]/files/preview/[worktreeId].tsx
@@ -9,17 +9,11 @@ export default function HostMobileWebFilePreviewRoute() {
() => (shell.client ? webHostFilePreviewOperations(shell.client) : undefined),
[shell.client]
)
- const connectionState =
- shell.connection === 'offline'
- ? 'disconnected'
- : shell.connection === 'recovering'
- ? 'reconnecting'
- : shell.connection
return (
)
diff --git a/mobile/host-web-app/h/[hostId]/review/[worktreeId].tsx b/mobile/host-web-app/h/[hostId]/review/[worktreeId].tsx
index d1e57a20559..ba4fa52058e 100644
--- a/mobile/host-web-app/h/[hostId]/review/[worktreeId].tsx
+++ b/mobile/host-web-app/h/[hostId]/review/[worktreeId].tsx
@@ -16,19 +16,13 @@ export default function HostMobileWebDiffReviewRoute() {
() => (shell.client && workspaceId ? webHostDiffReviewClient(shell.client, workspaceId) : null),
[shell.client, workspaceId]
)
- const connectionState =
- shell.connection === 'offline'
- ? 'disconnected'
- : shell.connection === 'recovering'
- ? 'reconnecting'
- : shell.connection
return (
{
await shell.client?.navigationReconnect()
},
diff --git a/mobile/host-web-app/h/[hostId]/session/[worktreeId].tsx b/mobile/host-web-app/h/[hostId]/session/[worktreeId].tsx
index 2df9052100d..ac460129e36 100644
--- a/mobile/host-web-app/h/[hostId]/session/[worktreeId].tsx
+++ b/mobile/host-web-app/h/[hostId]/session/[worktreeId].tsx
@@ -83,12 +83,6 @@ export default function HostMobileWebSessionRoute() {
() => (shell.client ? webHostSessionChatPendingDeliveryOperations(shell.client) : undefined),
[shell.client]
)
- const connectionState =
- shell.connection === 'offline'
- ? 'disconnected'
- : shell.connection === 'recovering'
- ? 'reconnecting'
- : shell.connection
return (
shell.client
diff --git a/mobile/host-web-app/h/[hostId]/source-control/[worktreeId].tsx b/mobile/host-web-app/h/[hostId]/source-control/[worktreeId].tsx
index eeecd745a73..a92ec8416c8 100644
--- a/mobile/host-web-app/h/[hostId]/source-control/[worktreeId].tsx
+++ b/mobile/host-web-app/h/[hostId]/source-control/[worktreeId].tsx
@@ -17,19 +17,13 @@ export default function HostMobileWebSourceControlRoute() {
shell.client && workspaceId ? webHostSourceControlClient(shell.client, workspaceId) : null,
[shell.client, workspaceId]
)
- const connectionState =
- shell.connection === 'offline'
- ? 'disconnected'
- : shell.connection === 'recovering'
- ? 'reconnecting'
- : shell.connection
return (
{
await shell.client?.navigationReconnect()
},
diff --git a/mobile/host-web-app/h/[hostId]/tasks.tsx b/mobile/host-web-app/h/[hostId]/tasks.tsx
index 58974df04c2..2c069af31fe 100644
--- a/mobile/host-web-app/h/[hostId]/tasks.tsx
+++ b/mobile/host-web-app/h/[hostId]/tasks.tsx
@@ -41,12 +41,6 @@ export default function HostMobileWebTasksRoute() {
workspaceCreation: webHostWorkspaceCreationOperations(shell.client)
}
}, [shell.client])
- const connectionState =
- shell.connection === 'offline'
- ? 'disconnected'
- : shell.connection === 'recovering'
- ? 'reconnecting'
- : shell.connection
return (
{
type: 'connection',
shellSessionId: SHELL_SESSION_ID,
buildId: BUILD_ID,
- state: 'recovering'
+ state: 'reconnecting'
}
expect(
diff --git a/src/shared/mobile-web/bridge-contract.ts b/src/shared/mobile-web/bridge-contract.ts
index 76133e1b5ff..c53dc43d305 100644
--- a/src/shared/mobile-web/bridge-contract.ts
+++ b/src/shared/mobile-web/bridge-contract.ts
@@ -165,7 +165,16 @@ const ShellEnvelopeSchema = z.object({
buildId: BuildIdSchema
})
-const ConnectionStateSchema = z.enum(['connecting', 'connected', 'offline', 'recovering'])
+// The shell publishes the transport's own state; the page decides what to show for each.
+const ConnectionStateSchema = z.enum([
+ 'connecting',
+ 'handshaking',
+ 'connected',
+ 'disconnected',
+ 'reconnecting',
+ 'auth-failed'
+])
+export type MobileWebConnectionState = z.infer
const ConnectionMetricsShape = {
reconnectAttempts: z.number().int().nonnegative().max(1_000_000).optional(),
lastConnectedAt: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).nullable().optional()