diff --git a/src/Navigation.tsx b/src/Navigation.tsx index 578ee71cb5..632eff958e 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -28,6 +28,7 @@ import { storePayloadForAccountSwitch, } from '#/lib/hooks/useNotificationHandler' import {useWebScrollRestoration} from '#/lib/hooks/useWebScrollRestoration' +import {useCallOnce} from '#/lib/once' import {buildStateObject} from '#/lib/routes/helpers' import { type AllNavigatorParams, @@ -41,7 +42,6 @@ import { type SearchTabNavigatorParams, type State, } from '#/lib/routes/types' -import {useRunCallbackOnce} from '#/lib/runCallbackOnce' import {bskyTitle} from '#/lib/strings/headings' import {useUnreadNotifications} from '#/state/queries/notifications/unread' import {useSession} from '#/state/session' @@ -980,7 +980,8 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) { } } - const onNavigationReady = useRunCallbackOnce(() => { + const onNavigationReady = useCallOnce(() => { + alert('test') prevLoggedRouteName.current = getCurrentRouteName() handlePushNotificationEntry() diff --git a/src/lib/once.ts b/src/lib/once.ts new file mode 100644 index 0000000000..e5ba056061 --- /dev/null +++ b/src/lib/once.ts @@ -0,0 +1,27 @@ +import {useCallback, useRef} from 'react' + +type Cb = () => void + +export function callOnce() { + let ran = false + return function runCallbackOnce(cb: Cb) { + if (ran) return + ran = true + cb() + } +} + +export function useCallOnce(cb: Cb): () => void +export function useCallOnce(cb?: undefined): (cb: Cb) => void +export function useCallOnce(cb?: Cb) { + const ran = useRef(false) + return useCallback( + (icb: Cb) => { + if (ran.current) return + ran.current = true + if (icb) icb() + else if (cb) cb() + }, + [cb], + ) +} diff --git a/src/lib/runCallbackOnce.ts b/src/lib/runCallbackOnce.ts deleted file mode 100644 index 4be1afb4da..0000000000 --- a/src/lib/runCallbackOnce.ts +++ /dev/null @@ -1,21 +0,0 @@ -import {useCallback, useRef} from 'react' - -export function createRunCallbackOnce() { - let hasRun = false - return function runCallbackOnce(callback: () => void) { - if (!hasRun) { - hasRun = true - callback() - } - } -} - -export function useRunCallbackOnce(callback: () => void) { - const hasRunRef = useRef(false) - return useCallback(() => { - if (!hasRunRef.current) { - hasRunRef.current = true - callback() - } - }, [callback]) -} diff --git a/src/screens/Onboarding/StepFindContacts/index.tsx b/src/screens/Onboarding/StepFindContacts/index.tsx index 9f1cac113b..404b9e9282 100644 --- a/src/screens/Onboarding/StepFindContacts/index.tsx +++ b/src/screens/Onboarding/StepFindContacts/index.tsx @@ -2,7 +2,7 @@ import {useCallback, useState} from 'react' import {LayoutAnimationConfig} from 'react-native-reanimated' import {SafeAreaView} from 'react-native-safe-area-context' -import {useRunCallbackOnce} from '#/lib/runCallbackOnce' +import {useCallOnce} from '#/lib/once' import {FindContactsFlow} from '#/components/contacts/FindContactsFlow' import {type Action, type State} from '#/components/contacts/state' import {ScreenTransition} from '#/components/ScreenTransition' @@ -19,9 +19,9 @@ export function StepFindContacts({ const {dispatch} = useOnboardingInternalState() const ax = useAnalytics() - useRunCallbackOnce(() => { + useCallOnce(() => { ax.metric('onboarding:contacts:begin', {}) - }) + })() const [transitionDirection, setTransitionDirection] = useState< 'Forward' | 'Backward' diff --git a/src/screens/Onboarding/StepFindContactsIntro/index.tsx b/src/screens/Onboarding/StepFindContactsIntro/index.tsx index c5b1728ccf..c5a47bd9ca 100644 --- a/src/screens/Onboarding/StepFindContactsIntro/index.tsx +++ b/src/screens/Onboarding/StepFindContactsIntro/index.tsx @@ -5,7 +5,7 @@ import {useLingui} from '@lingui/react' import {useQuery} from '@tanstack/react-query' import {urls} from '#/lib/constants' -import {useRunCallbackOnce} from '#/lib/runCallbackOnce' +import {useCallOnce} from '#/lib/once' import {atoms as a} from '#/alf' import {Admonition} from '#/components/Admonition' import {Button, ButtonText} from '#/components/Button' @@ -25,9 +25,9 @@ export function StepFindContactsIntro() { const {_} = useLingui() const {dispatch} = useOnboardingInternalState() - useRunCallbackOnce(() => { + useCallOnce(() => { ax.metric('onboarding:contacts:presented', {}) - }) + })() const {data: isAvailable, isSuccess} = useQuery({ queryKey: ['contacts-available'], diff --git a/src/state/queries/preferences/useThreadPreferences.ts b/src/state/queries/preferences/useThreadPreferences.ts index 4d8d8bab50..7825f4c688 100644 --- a/src/state/queries/preferences/useThreadPreferences.ts +++ b/src/state/queries/preferences/useThreadPreferences.ts @@ -2,7 +2,7 @@ import {useCallback, useMemo, useRef, useState} from 'react' import {type AppBskyUnspeccedGetPostThreadV2} from '@atproto/api' import debounce from 'lodash.debounce' -import {OnceKey, useCallOnce} from '#/lib/hooks/useCallOnce' +import {useCallOnce} from '#/lib/once' import { usePreferencesQuery, useSetThreadViewPreferencesMutation, @@ -31,7 +31,7 @@ export function useThreadPreferences({ const ax = useAnalytics() const {data: preferences} = usePreferencesQuery() const serverPrefs = preferences?.threadViewPrefs - const once = useCallOnce(OnceKey.PreferencesThread) + const once = useCallOnce() /* * Create local state representations of server state