Bluesky app fork with some witchin' additions 💫 witchsky.app
bluesky fork client

Restructure notification/linking handling to use synchronous APIs (#9497)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Eric Bailey <git@esb.lol>

authored by samuel.fm

Claude Opus 4.6
Eric Bailey
and committed by
GitHub
bdf143ce adc079e0

+20 -24
+20 -24
src/Navigation.tsx
··· 1 1 import {type JSX, useCallback, useRef} from 'react' 2 - import {Linking} from 'react-native' 2 + import * as Linking from 'expo-linking' 3 3 import * as Notifications from 'expo-notifications' 4 4 import {i18n, type MessageDescriptor} from '@lingui/core' 5 5 import {msg} from '@lingui/macro' ··· 874 874 }, 875 875 } satisfies LinkingOptions<AllNavigatorParams> 876 876 877 - /** 878 - * Used to ensure we don't handle the same notification twice 879 - */ 880 - let lastHandledNotificationDateDedupe: number | undefined 881 - 882 877 function RoutesContainer({children}: React.PropsWithChildren<{}>) { 883 878 const ax = useAnalytics() 884 879 const notyLogger = ax.logger.useChild(ax.logger.Context.Notifications) ··· 889 884 const previousScreen = useRef<string | undefined>(undefined) 890 885 const emailDialogControl = useEmailDialogControl() 891 886 const closeAllActiveElements = useCloseAllActiveElements() 887 + const linkingUrl = Linking.useLinkingURL() 888 + const notificationResponse = Notifications.useLastNotificationResponse() 892 889 893 890 /** 894 891 * Handle navigation to a conversation, or prepares for account switch. ··· 923 920 }, 924 921 ) 925 922 926 - async function handlePushNotificationEntry() { 923 + function handlePushNotificationEntry() { 927 924 if (!IS_NATIVE) return 928 925 929 - // deep links take precedence - on android, 930 - // getLastNotificationResponseAsync returns a "notification" 931 - // that is actually a deep link. avoid handling it twice -sfn 932 - if (await Linking.getInitialURL()) { 933 - return 934 - } 935 - 936 - /** 937 - * The notification that caused the app to open, if applicable 938 - */ 939 - const response = await Notifications.getLastNotificationResponseAsync() 926 + // intent urls are handled by `useIntentHandler` 927 + if (linkingUrl) return 940 928 941 - if (response) { 942 - notyLogger.debug(`handlePushNotificationEntry: response`, {response}) 929 + if (notificationResponse) { 930 + notyLogger.debug(`handlePushNotificationEntry: response`, { 931 + response: notificationResponse, 932 + }) 943 933 944 - if (response.notification.date === lastHandledNotificationDateDedupe) 945 - return 946 - lastHandledNotificationDateDedupe = response.notification.date 934 + // Clear the last notification response to ensure it's not used again 935 + try { 936 + Notifications.clearLastNotificationResponse() 937 + } catch (error) { 938 + notyLogger.error( 939 + `handlePushNotificationEntry: error clearing notification response`, 940 + {error}, 941 + ) 942 + } 947 943 948 - const payload = getNotificationPayload(response.notification) 944 + const payload = getNotificationPayload(notificationResponse.notification) 949 945 950 946 if (payload) { 951 947 ax.metric('notifications:openApp', {