From b35e2e5ebb31b84341f8b1892022f6e787e55065 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 27 Jun 2026 14:03:11 +0000 Subject: [PATCH] Only request notification permission once per session On Android, denying the initial notification permission request could surface a second prompt later in the same session. The only guard against re-prompting was the OS-level canAskAgain flag, which on Android stays true after a single in-app denial (unlike iOS, where it flips to false). As a result a later call site (e.g. Home after Login/onboarding) would trigger another system dialog. Add a module-scoped, session-lifetime flag that is set the first time we actually invoke requestPermissionsAsync, and short-circuit subsequent calls. The guard is placed after the existing getPermissionsAsync checks so it is only consumed when a prompt is actually about to show, preserving the already-granted push-token registration path. Resets on app restart. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01NtBTPxwFTRgYrySHSUREva --- src/lib/notifications/notifications.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/lib/notifications/notifications.ts b/src/lib/notifications/notifications.ts index 1c2e6dbe5a..ccf966e367 100644 --- a/src/lib/notifications/notifications.ts +++ b/src/lib/notifications/notifications.ts @@ -225,6 +225,14 @@ export function useNotificationsRegistration() { }, [currentAccount, getAndRegisterPushToken, registerPushToken, aa]) } +/** + * Tracks whether we have already shown the OS notification permission prompt + * during this app session. On Android `canAskAgain` stays true after a single + * in-app denial, so without this guard a later call site (e.g. Home after + * Login) would surface a second prompt. Resets on app restart. + */ +let hasRequestedPermissionsThisSession = false + export function useRequestNotificationsPermission() { const ax = useAnalytics() const {currentAccount} = useSession() @@ -249,6 +257,11 @@ export function useRequestNotificationsPermission() { return } + if (hasRequestedPermissionsThisSession) { + return + } + hasRequestedPermissionsThisSession = true + const res = await Notifications.requestPermissionsAsync() ax.metric(`notifications:request`, {