fix(sw): focus the client before navigating on notification click - #914
Open
bitfactory-dk wants to merge 1 commit into
Open
fix(sw): focus the client before navigating on notification click#914bitfactory-dk wants to merge 1 commit into
bitfactory-dk wants to merge 1 commit into
Conversation
Clicking a push notification on Android closed the notification and did
nothing: the app never came to the front.
handleNotificationClick navigates an existing client and then focuses it:
if ("navigate" in client && targetUrl) {
await client.navigate(targetUrl);
}
return client.focus();
A notification click grants the service worker a transient user
activation, and both focus() and openWindow() refuse to run without one.
navigate() spends that activation, and it also replaces the client's
document, which invalidates the WindowClient handle the next line uses.
So navigating first breaks the click two ways over.
Instrumented on a device, against a backgrounded installed PWA:
client 1: navigate ok -> focus() threw NotFoundError (stale handle)
client 2: navigate ok -> focus() threw InvalidAccessError (activation spent)
openWindow() -> threw InvalidAccessError (same)
Every rejection was swallowed by the surrounding catch, so the toast
closed and nothing opened, with nothing in any log to say why.
Focusing first uses the activation while it is still live. navigate()
needs none of its own once the client is focused, and it is wrapped so a
failed navigation still leaves the app raised rather than falling through
to opening a second window.
Running in production since 2026-08-24.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Clicking a push notification on Android closes the notification and does nothing — the app never comes to the front.
Cause
handleNotificationClicknavigates an existing client and then focuses it:A notification click grants the service worker a transient user activation, and both
focus()andopenWindow()refuse to run without one.navigate()spends that activation — and it also replaces the client's document, which invalidates theWindowClienthandle the very next line uses. Navigating first therefore breaks the click two ways over.Instrumented on a device, against a backgrounded installed PWA:
Every rejection was swallowed by the surrounding
catch, so the notification closed and nothing opened, with nothing in any log to say why.Fix
Focus first, while the activation is still live, then navigate the focused client.
navigate()does not need an activation of its own once the client is focused, and it is wrapped so that a failed navigation still leaves the app raised rather than falling through to opening a second window.Testing
node --check public/sw.jspasses.public/sw.js; no build, dependency or configuration surface touched.Not in this PR
There is a second, unrelated defect in the same file:
badgepoints at/api/pwa-icon/192, and Android builds the status-bar badge from the alpha channel alone, so an opaque app icon masks to a featureless blob. I have kept it out of this PR because the fix involves choosing which of your own brand assets to use, which is your call rather than mine. I will open it as a separate issue with the measurements.