1 | import {
|
2 | type NavigationProp,
|
3 | useNavigation as useUpstreamNavigation,
|
4 | } from '@react-navigation/native'
|
5 | import React from 'react'
|
6 |
|
7 | import { getNameFromFilePath } from './matchers'
|
8 | import { useContextKey } from './Route'
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | export function useNavigation<T = NavigationProp<ReactNavigation.RootParamList>>(
|
16 | parent?: string
|
17 | ): T {
|
18 | const navigation = useUpstreamNavigation<any>()
|
19 |
|
20 | const contextKey = useContextKey()
|
21 | const normalizedParent = React.useMemo(() => {
|
22 | if (!parent) {
|
23 | return null
|
24 | }
|
25 | const normalized = getNameFromFilePath(parent)
|
26 |
|
27 | if (parent.startsWith('.')) {
|
28 | return relativePaths(contextKey, parent)
|
29 | }
|
30 | return normalized
|
31 | }, [contextKey, parent])
|
32 |
|
33 | if (normalizedParent != null) {
|
34 | const parentNavigation = navigation.getParent(normalizedParent)
|
35 |
|
36 |
|
37 |
|
38 | if (!parentNavigation) {
|
39 | throw new Error(
|
40 | `Could not find parent navigation with route "${parent}".` +
|
41 | (normalizedParent !== parent ? ` (normalized: ${normalizedParent})` : '')
|
42 | )
|
43 | }
|
44 | return parentNavigation
|
45 | }
|
46 | return navigation
|
47 | }
|
48 |
|
49 | export function resolveParentId(contextKey: string, parentId?: string | null): string | null {
|
50 | if (!parentId) {
|
51 | return null
|
52 | }
|
53 |
|
54 | if (parentId.startsWith('.')) {
|
55 | return getNameFromFilePath(relativePaths(contextKey, parentId))
|
56 | }
|
57 | return getNameFromFilePath(parentId)
|
58 | }
|
59 |
|
60 |
|
61 | function relativePaths(from: string, to: string): string {
|
62 | const fromParts = from.split('/').filter(Boolean)
|
63 | const toParts = to.split('/').filter(Boolean)
|
64 |
|
65 | for (const part of toParts) {
|
66 | if (part === '..') {
|
67 | if (fromParts.length === 0) {
|
68 | throw new Error(`Cannot resolve path "${to}" relative to "${from}"`)
|
69 | }
|
70 | fromParts.pop()
|
71 | } else if (part === '.') {
|
72 |
|
73 | } else {
|
74 | fromParts.push(part)
|
75 | }
|
76 | }
|
77 |
|
78 | return '/' + fromParts.join('/')
|
79 | }
|