From 8fbb322c19015a305cbd89f80e38b228e0e7e8ee Mon Sep 17 00:00:00 2001 From: sliptype Date: Thu, 17 Nov 2022 10:58:10 -0600 Subject: [PATCH 1/2] Allow repeat pushes via useNavigation inside nested navigator --- packages/mobile/src/hooks/useNavigation.ts | 13 ++++++++----- packages/mobile/src/utils/navigation.ts | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/packages/mobile/src/hooks/useNavigation.ts b/packages/mobile/src/hooks/useNavigation.ts index 282a13496c..7ea4af3e47 100644 --- a/packages/mobile/src/hooks/useNavigation.ts +++ b/packages/mobile/src/hooks/useNavigation.ts @@ -8,6 +8,8 @@ import { useNavigation as useNativeNavigation } from '@react-navigation/native' import type { NativeStackNavigationProp } from '@react-navigation/native-stack' import { isEqual } from 'lodash' +import { getNearestStackNavigator } from 'app/utils/navigation' + export type ContextualParams = { fromNotifications?: boolean } @@ -48,16 +50,17 @@ export function useNavigation< const performCustomPush = useCallback( (...config: PerformNavigationConfig) => { if (!isEqual(lastNavAction.current, config)) { - ;(navigation as NativeStackNavigationProp).push(...config) - lastNavAction.current = config + const stackNavigator: NativeStackNavigationProp = + getNearestStackNavigator(navigation) // Reset lastNavAction when the transition ends - const unsubscribe = ( - navigation as NativeStackNavigationProp - ).addListener('transitionEnd', (e) => { + const unsubscribe = stackNavigator.addListener('transitionEnd', (e) => { lastNavAction.current = undefined unsubscribe() }) + + stackNavigator.push(...config) + lastNavAction.current = config } }, [navigation, lastNavAction] diff --git a/packages/mobile/src/utils/navigation.ts b/packages/mobile/src/utils/navigation.ts index dd18bcfc3e..96ce6879d8 100644 --- a/packages/mobile/src/utils/navigation.ts +++ b/packages/mobile/src/utils/navigation.ts @@ -1,4 +1,4 @@ -import type { NavigationState } from '@react-navigation/native' +import type { NavigationProp, NavigationState } from '@react-navigation/native' /** * Navigation state selector that selects the current route @@ -21,3 +21,19 @@ export const getPrimaryRoute = (state: NavigationState) => { // The route at index 2 is the primary route return getRoutePath(state)?.[2] } + +/** + * Given a navigator, get the nearest stack navigator in the hierarchy + */ +export const getNearestStackNavigator = (navigator: NavigationProp) => { + if (navigator.getState?.()?.type === 'stack') { + return navigator + } + const parent = navigator.getParent() + + if (!parent) { + return undefined + } + + return getNearestStackNavigator(parent) +} From 1ddf60f9ae9c9df8bee1e3564b7cae4e9b1b7f9b Mon Sep 17 00:00:00 2001 From: sliptype Date: Thu, 17 Nov 2022 14:07:29 -0600 Subject: [PATCH 2/2] Improve types --- packages/mobile/src/hooks/useNavigation.ts | 22 +++++++++++++--------- packages/mobile/src/utils/navigation.ts | 8 ++++++-- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/mobile/src/hooks/useNavigation.ts b/packages/mobile/src/hooks/useNavigation.ts index 7ea4af3e47..d32f4d5e31 100644 --- a/packages/mobile/src/hooks/useNavigation.ts +++ b/packages/mobile/src/hooks/useNavigation.ts @@ -50,17 +50,21 @@ export function useNavigation< const performCustomPush = useCallback( (...config: PerformNavigationConfig) => { if (!isEqual(lastNavAction.current, config)) { - const stackNavigator: NativeStackNavigationProp = - getNearestStackNavigator(navigation) + const stackNavigator = getNearestStackNavigator(navigation) - // Reset lastNavAction when the transition ends - const unsubscribe = stackNavigator.addListener('transitionEnd', (e) => { - lastNavAction.current = undefined - unsubscribe() - }) + if (stackNavigator) { + // Reset lastNavAction when the transition ends + const unsubscribe = stackNavigator.addListener( + 'transitionEnd', + (e) => { + lastNavAction.current = undefined + unsubscribe() + } + ) - stackNavigator.push(...config) - lastNavAction.current = config + stackNavigator.push(...config) + lastNavAction.current = config + } } }, [navigation, lastNavAction] diff --git a/packages/mobile/src/utils/navigation.ts b/packages/mobile/src/utils/navigation.ts index 96ce6879d8..584eadc358 100644 --- a/packages/mobile/src/utils/navigation.ts +++ b/packages/mobile/src/utils/navigation.ts @@ -1,4 +1,6 @@ +import type { Maybe } from '@audius/common' import type { NavigationProp, NavigationState } from '@react-navigation/native' +import type { NativeStackNavigationProp } from '@react-navigation/native-stack' /** * Navigation state selector that selects the current route @@ -25,9 +27,11 @@ export const getPrimaryRoute = (state: NavigationState) => { /** * Given a navigator, get the nearest stack navigator in the hierarchy */ -export const getNearestStackNavigator = (navigator: NavigationProp) => { +export const getNearestStackNavigator = ( + navigator: NavigationProp +): Maybe> => { if (navigator.getState?.()?.type === 'stack') { - return navigator + return navigator as unknown as NativeStackNavigationProp } const parent = navigator.getParent()