my fork of the bluesky client
1import React from 'react'
2import {useNavigation} from '@react-navigation/core'
3import {NavigationState} from '@react-navigation/native'
4import type {NavigationAction} from '@react-navigation/routers'
5
6import {useDedupe} from '#/lib/hooks/useDedupe'
7import {AllNavigatorParams, NavigationProp} from '#/lib/routes/types'
8
9export type DebouncedNavigationProp = Pick<
10 NavigationProp,
11 | 'popToTop'
12 | 'push'
13 | 'navigate'
14 | 'canGoBack'
15 | 'replace'
16 | 'dispatch'
17 | 'goBack'
18 | 'getState'
19>
20
21export function useNavigationDeduped() {
22 const navigation = useNavigation<NavigationProp>()
23 const dedupe = useDedupe()
24
25 return React.useMemo(
26 (): DebouncedNavigationProp => ({
27 // Types from @react-navigation/routers/lib/typescript/src/StackRouter.ts
28 push: <RouteName extends keyof AllNavigatorParams>(
29 ...args: undefined extends AllNavigatorParams[RouteName]
30 ?
31 | [screen: RouteName]
32 | [screen: RouteName, params: AllNavigatorParams[RouteName]]
33 : [screen: RouteName, params: AllNavigatorParams[RouteName]]
34 ) => {
35 dedupe(() => navigation.push(...args))
36 },
37 // Types from @react-navigation/core/src/types.tsx
38 navigate: <RouteName extends keyof AllNavigatorParams>(
39 ...args: RouteName extends unknown
40 ? undefined extends AllNavigatorParams[RouteName]
41 ?
42 | [screen: RouteName]
43 | [screen: RouteName, params: AllNavigatorParams[RouteName]]
44 : [screen: RouteName, params: AllNavigatorParams[RouteName]]
45 : never
46 ) => {
47 dedupe(() => navigation.navigate(...args))
48 },
49 // Types from @react-navigation/routers/lib/typescript/src/StackRouter.ts
50 replace: <RouteName extends keyof AllNavigatorParams>(
51 ...args: undefined extends AllNavigatorParams[RouteName]
52 ?
53 | [screen: RouteName]
54 | [screen: RouteName, params: AllNavigatorParams[RouteName]]
55 : [screen: RouteName, params: AllNavigatorParams[RouteName]]
56 ) => {
57 dedupe(() => navigation.replace(...args))
58 },
59 dispatch: (
60 action:
61 | NavigationAction
62 | ((state: NavigationState) => NavigationAction),
63 ) => {
64 dedupe(() => navigation.dispatch(action))
65 },
66 popToTop: () => {
67 dedupe(() => navigation.popToTop())
68 },
69 goBack: () => {
70 dedupe(() => navigation.goBack())
71 },
72 canGoBack: () => {
73 return navigation.canGoBack()
74 },
75 getState: () => {
76 return navigation.getState()
77 },
78 }),
79 [dedupe, navigation],
80 )
81}