fix(tui): suppress transient reconnect overlay flashes (#34924)

This commit is contained in:
Shoubhit Dash 2026-07-02 18:54:51 +05:30 committed by GitHub
commit 7ec7413fdb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 98 additions and 2 deletions

View file

@ -1116,6 +1116,34 @@ function App(props: { onSnapshot?: () => Promise<string[]>; pluginHost: TuiPlugi
return render({ params: route.data.data })
})
// Suppress the full-screen reconnecting overlay for transient disconnects (initial startup, host
// reload, sub-second event-stream blips). After the first successful connect, show it only once the
// connection has been lost for a full second; before the first connect give a longer grace period so
// startup never flashes it, but a server that dies before ever connecting still surfaces instead of
// leaving a silent empty app. Hide it immediately the moment status leaves "connecting".
const [showReconnecting, setShowReconnecting] = createSignal(false)
let reconnectTimer: ReturnType<typeof setTimeout> | undefined
createEffect(() => {
if (reconnectTimer) {
clearTimeout(reconnectTimer)
reconnectTimer = undefined
}
if (sdk.connection.status() !== "connecting") {
setShowReconnecting(false)
return
}
reconnectTimer = setTimeout(
() => {
reconnectTimer = undefined
setShowReconnecting(true)
},
sdk.connection.connectedOnce() ? 1000 : 5000,
).unref()
})
onCleanup(() => {
if (reconnectTimer) clearTimeout(reconnectTimer)
})
return (
<box
width={dimensions().width}
@ -1161,7 +1189,7 @@ function App(props: { onSnapshot?: () => Promise<string[]>; pluginHost: TuiPlugi
<Show when={!startup.skipInitialLoading}>
<StartupLoading ready={ready} />
</Show>
<Show when={sdk.connection.status() === "connecting"}>
<Show when={showReconnecting()}>
<Reconnecting attempt={sdk.connection.attempt()} error={sdk.connection.error()} />
</Show>
</box>

View file

@ -636,6 +636,9 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
error() {
return sdk.connection.error()
},
connectedOnce() {
return sdk.connection.connectedOnce()
},
},
session: {
list() {

View file

@ -25,9 +25,11 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
status: SDKConnectionStatus
attempt: number
error?: string
connectedOnce: boolean
}>({
status: "connecting",
attempt: 0,
connectedOnce: false,
})
let stream: AbortController | undefined
let pending: Promise<void> | undefined
@ -68,7 +70,7 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
clearTimeout(timeout)
attempt = 0
events.emit(first.value.type, first.value)
setConnection({ status: "connected", attempt: 0, error: undefined })
setConnection({ status: "connected", attempt: 0, error: undefined, connectedOnce: true })
connected()
while (!abort.signal.aborted && !controller.signal.aborted) {
const event = await iterator.next()
@ -140,6 +142,9 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
error() {
return connection.error
},
connectedOnce() {
return connection.connectedOnce
},
},
reload,
}