Skip to content

fix(web): reconnect SSE stream when mobile tab becomes visible again - #39028

Closed
tecnico502 wants to merge 2 commits into
anomalyco:devfrom
tecnico502:fix/mobile-visibility-reconnect
Closed

tecnico502 wants to merge 2 commits into
anomalyco:devfrom
tecnico502:fix/mobile-visibility-reconnect

Conversation

@tecnico502

Copy link
Copy Markdown

Problem

When using opencode serve or opencode web from a mobile browser (Chrome), switching to another app and coming back leaves the chat frozen. No new messages appear until the user manually refreshes the page.

Root cause

The SSE event stream in server-sdk.tsx only handles tab lifecycle via pagehide/pageshow, which are designed for bfcache (back-forward cache) navigation between pages. On mobile:

  1. pagehide often does not fire when the tab is backgrounded by switching apps
  2. When it does fire, it calls stop() which aborts the SSE connection and cancels server-side generation
  3. pageshow fires with persisted=false on resume (not a bfcache restore), so resumeStreamAfterPageShow returns without restarting the stream
  4. The stream stays dead until manual refresh

Fix

  • Add a restart() helper that safely tears down and recreates the SSE connection
  • Listen to document.visibilitychange and call restart() when the page becomes visible
  • Do NOT stop the stream on hidden, preserving server-side generation
+  const restart = () => {
+    started = false
+    generation++
+    attempt?.abort()
+    return start()
+  }
+
   onMount(() => {
     makeEventListener(window, "pagehide", stop)
     makeEventListener(window, "pageshow", (event) => resumeStreamAfterPageShow(event, start))
+    makeEventListener(document, "visibilitychange", () => {
+      if (document.visibilityState === "visible") restart()
+    })
   })

Testing

Tested on Android Chrome by initiating a long response, switching to another app, waiting several seconds, and returning. The response appeared without manual refresh.

Files changed

  • packages/app/src/context/server-sdk.tsx — add restart() and visibilitychange listener

On mobile (Chrome), switching to another app and coming back leaves the
chat frozen until manual refresh. The existing pagehide/pageshow handlers
only cover bfcache navigation, not mobile tab suspension.

- Add restart() that safely tears down and recreates the SSE connection
- Listen to visibilitychange to trigger restart when tab becomes visible
- Do NOT stop the stream on hidden, which would abort server-side generation
@github-actions github-actions Bot added needs:issue needs:compliance This means the issue will auto-close after 2 hours. labels Jul 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions

Copy link
Copy Markdown
Contributor

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@tecnico502

Copy link
Copy Markdown
Author

Reopening to trigger compliance checks

@tecnico502 tecnico502 closed this Jul 27, 2026
@tecnico502 tecnico502 reopened this Jul 27, 2026
@tecnico502

Copy link
Copy Markdown
Author

Closing PR — fix confirmed not working. Need to investigate further.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs:compliance This means the issue will auto-close after 2 hours. needs:issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant