@react-navigation/native 7.1.25 → 8.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/module/Link.js.map +1 -1
- package/lib/module/NavigationContainer.js +73 -63
- package/lib/module/NavigationContainer.js.map +1 -1
- package/lib/module/__stubs__/createStackNavigator.js.map +1 -1
- package/lib/module/extractPathFromURL.js +12 -7
- package/lib/module/extractPathFromURL.js.map +1 -1
- package/lib/module/getStateFromHref.js +30 -0
- package/lib/module/getStateFromHref.js.map +1 -0
- package/lib/module/index.js +0 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/theming/DarkTheme.js.map +1 -1
- package/lib/module/theming/DefaultTheme.js +1 -1
- package/lib/module/theming/DefaultTheme.js.map +1 -1
- package/lib/module/theming/fonts.js.map +1 -1
- package/lib/module/useLinkBuilder.js +5 -8
- package/lib/module/useLinkBuilder.js.map +1 -1
- package/lib/module/useLinkProps.js +20 -0
- package/lib/module/useLinkProps.js.map +1 -1
- package/lib/module/useLinking.js +23 -24
- package/lib/module/useLinking.js.map +1 -1
- package/lib/module/useLinking.native.js +21 -36
- package/lib/module/useLinking.native.js.map +1 -1
- package/lib/module/useScrollToTop.js +1 -0
- package/lib/module/useScrollToTop.js.map +1 -1
- package/lib/module/useThenable.js +9 -6
- package/lib/module/useThenable.js.map +1 -1
- package/lib/typescript/src/Link.d.ts +3 -2
- package/lib/typescript/src/Link.d.ts.map +1 -1
- package/lib/typescript/src/NavigationContainer.d.ts +35 -7
- package/lib/typescript/src/NavigationContainer.d.ts.map +1 -1
- package/lib/typescript/src/__stubs__/createStackNavigator.d.ts +1 -2
- package/lib/typescript/src/__stubs__/createStackNavigator.d.ts.map +1 -1
- package/lib/typescript/src/extractPathFromURL.d.ts +2 -1
- package/lib/typescript/src/extractPathFromURL.d.ts.map +1 -1
- package/lib/typescript/src/getStateFromHref.d.ts +4 -0
- package/lib/typescript/src/getStateFromHref.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +0 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/theming/DarkTheme.d.ts +63 -2
- package/lib/typescript/src/theming/DarkTheme.d.ts.map +1 -1
- package/lib/typescript/src/theming/DefaultTheme.d.ts +63 -2
- package/lib/typescript/src/theming/DefaultTheme.d.ts.map +1 -1
- package/lib/typescript/src/theming/fonts.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +49 -23
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useLinkBuilder.d.ts +14 -6
- package/lib/typescript/src/useLinkBuilder.d.ts.map +1 -1
- package/lib/typescript/src/useLinkProps.d.ts +3 -3
- package/lib/typescript/src/useLinkProps.d.ts.map +1 -1
- package/lib/typescript/src/useLinking.d.ts +48 -4
- package/lib/typescript/src/useLinking.d.ts.map +1 -1
- package/lib/typescript/src/useLinking.native.d.ts +69 -4
- package/lib/typescript/src/useLinking.native.d.ts.map +1 -1
- package/lib/typescript/src/useScrollToTop.d.ts.map +1 -1
- package/lib/typescript/src/useThenable.d.ts +4 -1
- package/lib/typescript/src/useThenable.d.ts.map +1 -1
- package/package.json +13 -13
- package/src/Link.tsx +18 -15
- package/src/NavigationContainer.tsx +141 -84
- package/src/__stubs__/createStackNavigator.tsx +0 -2
- package/src/extractPathFromURL.tsx +28 -18
- package/src/getStateFromHref.tsx +46 -0
- package/src/index.tsx +0 -1
- package/src/theming/DarkTheme.tsx +4 -3
- package/src/theming/DefaultTheme.tsx +5 -4
- package/src/theming/fonts.tsx +1 -2
- package/src/types.tsx +60 -22
- package/src/useLinkBuilder.tsx +6 -9
- package/src/useLinkProps.tsx +36 -7
- package/src/useLinking.native.tsx +25 -48
- package/src/useLinking.tsx +32 -38
- package/src/useScrollToTop.tsx +3 -1
- package/src/useThenable.tsx +14 -6
- package/lib/module/UnhandledLinkingContext.js +0 -14
- package/lib/module/UnhandledLinkingContext.js.map +0 -1
- package/lib/typescript/src/UnhandledLinkingContext.d.ts +0 -6
- package/lib/typescript/src/UnhandledLinkingContext.d.ts.map +0 -1
- package/src/UnhandledLinkingContext.tsx +0 -18
package/src/useLinkBuilder.tsx
CHANGED
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
findFocusedRoute,
|
|
4
4
|
getActionFromState,
|
|
5
5
|
getPathFromState,
|
|
6
|
-
getStateFromPath,
|
|
7
6
|
NavigationHelpersContext,
|
|
8
7
|
NavigationRouteContext,
|
|
9
8
|
useStateForPath,
|
|
10
9
|
} from '@react-navigation/core';
|
|
11
10
|
import * as React from 'react';
|
|
12
11
|
|
|
12
|
+
import { getStateFromHref } from './getStateFromHref';
|
|
13
13
|
import { LinkingContext } from './LinkingContext';
|
|
14
14
|
|
|
15
15
|
type MinimalState = {
|
|
@@ -30,7 +30,6 @@ export function useLinkBuilder() {
|
|
|
30
30
|
const focusedRouteState = useStateForPath();
|
|
31
31
|
|
|
32
32
|
const getPathFromStateHelper = options?.getPathFromState ?? getPathFromState;
|
|
33
|
-
const getStateFromPathHelper = options?.getStateFromPath ?? getStateFromPath;
|
|
34
33
|
const getActionFromStateHelper =
|
|
35
34
|
options?.getActionFromState ?? getActionFromState;
|
|
36
35
|
|
|
@@ -103,21 +102,19 @@ export function useLinkBuilder() {
|
|
|
103
102
|
|
|
104
103
|
const buildAction = React.useCallback(
|
|
105
104
|
(href: string) => {
|
|
106
|
-
|
|
107
|
-
throw new Error(`The href must start with '/' (${href}).`);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const state = getStateFromPathHelper(href, options?.config);
|
|
105
|
+
const state = getStateFromHref(href, options);
|
|
111
106
|
|
|
112
107
|
if (state) {
|
|
113
108
|
const action = getActionFromStateHelper(state, options?.config);
|
|
114
109
|
|
|
115
110
|
return action ?? CommonActions.reset(state);
|
|
116
111
|
} else {
|
|
117
|
-
throw new Error(
|
|
112
|
+
throw new Error(
|
|
113
|
+
`Failed to parse href '${href}' to a navigation state.`
|
|
114
|
+
);
|
|
118
115
|
}
|
|
119
116
|
},
|
|
120
|
-
[options
|
|
117
|
+
[options, getActionFromStateHelper]
|
|
121
118
|
);
|
|
122
119
|
|
|
123
120
|
return {
|
package/src/useLinkProps.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
NavigationHelpersContext,
|
|
6
6
|
type NavigatorScreenParams,
|
|
7
7
|
type ParamListBase,
|
|
8
|
+
type RootParamList,
|
|
8
9
|
} from '@react-navigation/core';
|
|
9
10
|
import type { NavigationState, PartialState } from '@react-navigation/routers';
|
|
10
11
|
import * as React from 'react';
|
|
@@ -13,7 +14,7 @@ import { type GestureResponderEvent, Platform } from 'react-native';
|
|
|
13
14
|
import { LinkingContext } from './LinkingContext';
|
|
14
15
|
|
|
15
16
|
export type LinkProps<
|
|
16
|
-
ParamList extends
|
|
17
|
+
ParamList extends {} = RootParamList,
|
|
17
18
|
RouteName extends keyof ParamList = keyof ParamList,
|
|
18
19
|
> =
|
|
19
20
|
| ({
|
|
@@ -68,12 +69,10 @@ const getStateFromParams = (
|
|
|
68
69
|
* @param props.href Optional absolute path to use for the href (e.g. `/feeds/hot`).
|
|
69
70
|
* @param props.action Optional action to use for in-page navigation. By default, the path is parsed to an action based on linking config.
|
|
70
71
|
*/
|
|
71
|
-
export function useLinkProps<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
action,
|
|
76
|
-
}: LinkProps<ParamList>) {
|
|
72
|
+
export function useLinkProps<
|
|
73
|
+
const ParamList extends {} = RootParamList,
|
|
74
|
+
const RouteName extends keyof ParamList = keyof ParamList,
|
|
75
|
+
>({ screen, params, href, action }: LinkProps<ParamList, RouteName>) {
|
|
77
76
|
const root = React.useContext(NavigationContainerRefContext);
|
|
78
77
|
const navigation = React.useContext(NavigationHelpersContext);
|
|
79
78
|
const { options } = React.useContext(LinkingContext);
|
|
@@ -130,6 +129,36 @@ export function useLinkProps<ParamList extends ReactNavigation.RootParamList>({
|
|
|
130
129
|
|
|
131
130
|
const getPathFromStateHelper = options?.getPathFromState ?? getPathFromState;
|
|
132
131
|
|
|
132
|
+
if (Platform.OS === 'web') {
|
|
133
|
+
if (screen == null && action != null && options?.config != null) {
|
|
134
|
+
switch (action.type) {
|
|
135
|
+
case 'NAVIGATE':
|
|
136
|
+
case 'PUSH':
|
|
137
|
+
case 'REPLACE':
|
|
138
|
+
case 'POP_TO':
|
|
139
|
+
case 'JUMP_TO': {
|
|
140
|
+
if (
|
|
141
|
+
action.payload != null &&
|
|
142
|
+
'name' in action.payload &&
|
|
143
|
+
typeof action.payload.name === 'string' &&
|
|
144
|
+
action.payload.name in options.config.screens
|
|
145
|
+
) {
|
|
146
|
+
screen = action.payload.name;
|
|
147
|
+
|
|
148
|
+
if (
|
|
149
|
+
'params' in action.payload &&
|
|
150
|
+
typeof action.payload.params === 'object' &&
|
|
151
|
+
action.payload.params != null
|
|
152
|
+
) {
|
|
153
|
+
// @ts-expect-error this is fine 🔥
|
|
154
|
+
params = action.payload.params;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
133
162
|
return {
|
|
134
163
|
href:
|
|
135
164
|
href ??
|
|
@@ -8,20 +8,21 @@ import {
|
|
|
8
8
|
import * as React from 'react';
|
|
9
9
|
import { Linking, Platform } from 'react-native';
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { getStateFromHref } from './getStateFromHref';
|
|
12
12
|
import type { LinkingOptions } from './types';
|
|
13
|
+
import type { Thenable } from './useThenable';
|
|
13
14
|
|
|
14
15
|
type ResultState = ReturnType<typeof getStateFromPathDefault>;
|
|
15
16
|
|
|
16
17
|
type Options = LinkingOptions<ParamListBase>;
|
|
17
18
|
|
|
18
|
-
const linkingHandlers
|
|
19
|
+
const linkingHandlers = new Set<symbol>();
|
|
19
20
|
|
|
20
21
|
export function useLinking(
|
|
21
22
|
ref: React.RefObject<NavigationContainerRef<ParamListBase> | null>,
|
|
22
23
|
{
|
|
23
24
|
enabled = true,
|
|
24
|
-
prefixes,
|
|
25
|
+
prefixes = ['*'],
|
|
25
26
|
filter,
|
|
26
27
|
config,
|
|
27
28
|
getInitialURL = () =>
|
|
@@ -36,27 +37,15 @@ export function useLinking(
|
|
|
36
37
|
subscribe = (listener) => {
|
|
37
38
|
const callback = ({ url }: { url: string }) => listener(url);
|
|
38
39
|
|
|
39
|
-
const subscription = Linking.addEventListener('url', callback)
|
|
40
|
-
| { remove(): void }
|
|
41
|
-
| undefined;
|
|
42
|
-
|
|
43
|
-
// Storing this in a local variable stops Jest from complaining about import after teardown
|
|
44
|
-
// @ts-expect-error: removeEventListener is not present in newer RN versions
|
|
45
|
-
const removeEventListener = Linking.removeEventListener?.bind(Linking);
|
|
40
|
+
const subscription = Linking.addEventListener('url', callback);
|
|
46
41
|
|
|
47
42
|
return () => {
|
|
48
|
-
|
|
49
|
-
if (subscription?.remove) {
|
|
50
|
-
subscription.remove();
|
|
51
|
-
} else {
|
|
52
|
-
removeEventListener?.('url', callback);
|
|
53
|
-
}
|
|
43
|
+
subscription.remove();
|
|
54
44
|
};
|
|
55
45
|
},
|
|
56
46
|
getStateFromPath = getStateFromPathDefault,
|
|
57
47
|
getActionFromState = getActionFromStateDefault,
|
|
58
|
-
}: Options
|
|
59
|
-
onUnhandledLinking: (lastUnhandledLining: string | undefined) => void
|
|
48
|
+
}: Options
|
|
60
49
|
) {
|
|
61
50
|
const independent = useNavigationIndependentTree();
|
|
62
51
|
|
|
@@ -69,7 +58,7 @@ export function useLinking(
|
|
|
69
58
|
return undefined;
|
|
70
59
|
}
|
|
71
60
|
|
|
72
|
-
if (enabled !== false && linkingHandlers.
|
|
61
|
+
if (enabled !== false && linkingHandlers.size) {
|
|
73
62
|
console.error(
|
|
74
63
|
[
|
|
75
64
|
'Looks like you have configured linking in multiple places. This is likely an error since deep links should only be handled in one place to avoid conflicts. Make sure that:',
|
|
@@ -87,15 +76,11 @@ export function useLinking(
|
|
|
87
76
|
const handler = Symbol();
|
|
88
77
|
|
|
89
78
|
if (enabled !== false) {
|
|
90
|
-
linkingHandlers.
|
|
79
|
+
linkingHandlers.add(handler);
|
|
91
80
|
}
|
|
92
81
|
|
|
93
82
|
return () => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (index > -1) {
|
|
97
|
-
linkingHandlers.splice(index, 1);
|
|
98
|
-
}
|
|
83
|
+
linkingHandlers.delete(handler);
|
|
99
84
|
};
|
|
100
85
|
}, [enabled, independent]);
|
|
101
86
|
|
|
@@ -122,15 +107,20 @@ export function useLinking(
|
|
|
122
107
|
|
|
123
108
|
const getStateFromURL = React.useCallback(
|
|
124
109
|
(url: string | null | undefined) => {
|
|
125
|
-
if (!url
|
|
110
|
+
if (!url) {
|
|
126
111
|
return undefined;
|
|
127
112
|
}
|
|
128
113
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
114
|
+
try {
|
|
115
|
+
return getStateFromHref(url, {
|
|
116
|
+
prefixes: prefixesRef.current,
|
|
117
|
+
filter: filterRef.current,
|
|
118
|
+
config: configRef.current,
|
|
119
|
+
getStateFromPath: getStateFromPathRef.current,
|
|
120
|
+
});
|
|
121
|
+
} catch (e) {
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
134
124
|
},
|
|
135
125
|
[]
|
|
136
126
|
);
|
|
@@ -146,32 +136,22 @@ export function useLinking(
|
|
|
146
136
|
return url.then((url) => {
|
|
147
137
|
const state = getStateFromURL(url);
|
|
148
138
|
|
|
149
|
-
if (typeof url === 'string') {
|
|
150
|
-
// If the link were handled, it gets cleared in NavigationContainer
|
|
151
|
-
onUnhandledLinking(extractPathFromURL(prefixes, url));
|
|
152
|
-
}
|
|
153
|
-
|
|
154
139
|
return state;
|
|
155
140
|
});
|
|
156
|
-
} else {
|
|
157
|
-
onUnhandledLinking(extractPathFromURL(prefixes, url));
|
|
158
141
|
}
|
|
159
142
|
}
|
|
160
143
|
|
|
161
144
|
state = getStateFromURL(url);
|
|
162
145
|
}
|
|
163
146
|
|
|
164
|
-
const thenable = {
|
|
147
|
+
const thenable: Thenable<ResultState | undefined> = {
|
|
165
148
|
then(onfulfilled?: (state: ResultState | undefined) => void) {
|
|
166
149
|
return Promise.resolve(onfulfilled ? onfulfilled(state) : state);
|
|
167
150
|
},
|
|
168
|
-
catch() {
|
|
169
|
-
return thenable;
|
|
170
|
-
},
|
|
171
151
|
};
|
|
172
152
|
|
|
173
|
-
return thenable
|
|
174
|
-
}, [getStateFromURL
|
|
153
|
+
return thenable;
|
|
154
|
+
}, [getStateFromURL]);
|
|
175
155
|
|
|
176
156
|
React.useEffect(() => {
|
|
177
157
|
const listener = (url: string) => {
|
|
@@ -183,9 +163,6 @@ export function useLinking(
|
|
|
183
163
|
const state = navigation ? getStateFromURL(url) : undefined;
|
|
184
164
|
|
|
185
165
|
if (navigation && state) {
|
|
186
|
-
// If the link were handled, it gets cleared in NavigationContainer
|
|
187
|
-
onUnhandledLinking(extractPathFromURL(prefixes, url));
|
|
188
|
-
|
|
189
166
|
const action = getActionFromStateRef.current(state, configRef.current);
|
|
190
167
|
|
|
191
168
|
if (action !== undefined) {
|
|
@@ -209,7 +186,7 @@ export function useLinking(
|
|
|
209
186
|
};
|
|
210
187
|
|
|
211
188
|
return subscribe(listener);
|
|
212
|
-
}, [enabled, getStateFromURL,
|
|
189
|
+
}, [enabled, getStateFromURL, prefixes, ref, subscribe]);
|
|
213
190
|
|
|
214
191
|
return {
|
|
215
192
|
getInitialState,
|
package/src/useLinking.tsx
CHANGED
|
@@ -14,9 +14,25 @@ import * as React from 'react';
|
|
|
14
14
|
import { createMemoryHistory } from './createMemoryHistory';
|
|
15
15
|
import { ServerContext } from './ServerContext';
|
|
16
16
|
import type { LinkingOptions } from './types';
|
|
17
|
+
import type { Thenable } from './useThenable';
|
|
17
18
|
|
|
18
19
|
type ResultState = ReturnType<typeof getStateFromPathDefault>;
|
|
19
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Calculate total history length including both navigator history and route history
|
|
23
|
+
*/
|
|
24
|
+
const getTotalHistoryLength = (state: NavigationState): number => {
|
|
25
|
+
const baseHistoryLength = state.history
|
|
26
|
+
? state.history.length
|
|
27
|
+
: state.routes.length;
|
|
28
|
+
|
|
29
|
+
const routeHistoryLength = state.routes.reduce((acc, r) => {
|
|
30
|
+
return acc + (r.history ? r.history.length : 0);
|
|
31
|
+
}, 0);
|
|
32
|
+
|
|
33
|
+
return baseHistoryLength + routeHistoryLength;
|
|
34
|
+
};
|
|
35
|
+
|
|
20
36
|
/**
|
|
21
37
|
* Find the matching navigation state that changed between 2 navigation states
|
|
22
38
|
* e.g.: a -> b -> c -> d and a -> b -> c -> e -> f, if history in b changed, b is the matching state
|
|
@@ -29,9 +45,8 @@ const findMatchingState = <T extends NavigationState>(
|
|
|
29
45
|
return [undefined, undefined];
|
|
30
46
|
}
|
|
31
47
|
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
const bHistoryLength = b.history ? b.history.length : b.routes.length;
|
|
48
|
+
const aHistoryLength = getTotalHistoryLength(a);
|
|
49
|
+
const bHistoryLength = getTotalHistoryLength(b);
|
|
35
50
|
|
|
36
51
|
const aRoute = a.routes[a.index];
|
|
37
52
|
const bRoute = b.routes[b.index];
|
|
@@ -40,13 +55,15 @@ const findMatchingState = <T extends NavigationState>(
|
|
|
40
55
|
const bChildState = bRoute.state as T | undefined;
|
|
41
56
|
|
|
42
57
|
// Stop here if this is the state object that changed:
|
|
43
|
-
// - history length is different
|
|
58
|
+
// - total history length is different (including route.history)
|
|
44
59
|
// - focused routes are different
|
|
60
|
+
// - route.history length is different
|
|
45
61
|
// - one of them doesn't have child state
|
|
46
62
|
// - child state keys are different
|
|
47
63
|
if (
|
|
48
64
|
aHistoryLength !== bHistoryLength ||
|
|
49
65
|
aRoute.key !== bRoute.key ||
|
|
66
|
+
(aRoute.history?.length || 0) !== (bRoute.history?.length || 0) ||
|
|
50
67
|
aChildState === undefined ||
|
|
51
68
|
bChildState === undefined ||
|
|
52
69
|
aChildState.key !== bChildState.key
|
|
@@ -69,7 +86,7 @@ export const series = (cb: () => Promise<void>) => {
|
|
|
69
86
|
return callback;
|
|
70
87
|
};
|
|
71
88
|
|
|
72
|
-
const linkingHandlers
|
|
89
|
+
const linkingHandlers = new Set<symbol>();
|
|
73
90
|
|
|
74
91
|
type Options = LinkingOptions<ParamListBase>;
|
|
75
92
|
|
|
@@ -81,8 +98,7 @@ export function useLinking(
|
|
|
81
98
|
getStateFromPath = getStateFromPathDefault,
|
|
82
99
|
getPathFromState = getPathFromStateDefault,
|
|
83
100
|
getActionFromState = getActionFromStateDefault,
|
|
84
|
-
}: Options
|
|
85
|
-
onUnhandledLinking: (lastUnhandledLining: string | undefined) => void
|
|
101
|
+
}: Options
|
|
86
102
|
) {
|
|
87
103
|
const independent = useNavigationIndependentTree();
|
|
88
104
|
|
|
@@ -95,7 +111,7 @@ export function useLinking(
|
|
|
95
111
|
return undefined;
|
|
96
112
|
}
|
|
97
113
|
|
|
98
|
-
if (enabled !== false && linkingHandlers.
|
|
114
|
+
if (enabled !== false && linkingHandlers.size) {
|
|
99
115
|
console.error(
|
|
100
116
|
[
|
|
101
117
|
'Looks like you have configured linking in multiple places. This is likely an error since deep links should only be handled in one place to avoid conflicts. Make sure that:',
|
|
@@ -110,15 +126,11 @@ export function useLinking(
|
|
|
110
126
|
const handler = Symbol();
|
|
111
127
|
|
|
112
128
|
if (enabled !== false) {
|
|
113
|
-
linkingHandlers.
|
|
129
|
+
linkingHandlers.add(handler);
|
|
114
130
|
}
|
|
115
131
|
|
|
116
132
|
return () => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (index > -1) {
|
|
120
|
-
linkingHandlers.splice(index, 1);
|
|
121
|
-
}
|
|
133
|
+
linkingHandlers.delete(handler);
|
|
122
134
|
};
|
|
123
135
|
}, [enabled, independent]);
|
|
124
136
|
|
|
@@ -167,21 +179,15 @@ export function useLinking(
|
|
|
167
179
|
if (path) {
|
|
168
180
|
value = getStateFromPathRef.current(path, configRef.current);
|
|
169
181
|
}
|
|
170
|
-
|
|
171
|
-
// If the link were handled, it gets cleared in NavigationContainer
|
|
172
|
-
onUnhandledLinking(path);
|
|
173
182
|
}
|
|
174
183
|
|
|
175
|
-
const thenable = {
|
|
176
|
-
then(onfulfilled
|
|
184
|
+
const thenable: Thenable<ResultState | undefined> = {
|
|
185
|
+
then(onfulfilled) {
|
|
177
186
|
return Promise.resolve(onfulfilled ? onfulfilled(value) : value);
|
|
178
187
|
},
|
|
179
|
-
catch() {
|
|
180
|
-
return thenable;
|
|
181
|
-
},
|
|
182
188
|
};
|
|
183
189
|
|
|
184
|
-
return thenable
|
|
190
|
+
return thenable;
|
|
185
191
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
186
192
|
}, []);
|
|
187
193
|
|
|
@@ -224,8 +230,6 @@ export function useLinking(
|
|
|
224
230
|
// We should only dispatch an action when going forward
|
|
225
231
|
// Otherwise the action will likely add items to history, which would mess things up
|
|
226
232
|
if (state) {
|
|
227
|
-
// If the link were handled, it gets cleared in NavigationContainer
|
|
228
|
-
onUnhandledLinking(path);
|
|
229
233
|
// Make sure that the routes in the state exist in the root navigator
|
|
230
234
|
// Otherwise there's an error in the linking configuration
|
|
231
235
|
if (validateRoutesNotExistInRootState(state)) {
|
|
@@ -263,13 +267,7 @@ export function useLinking(
|
|
|
263
267
|
navigation.resetRoot(state);
|
|
264
268
|
}
|
|
265
269
|
});
|
|
266
|
-
}, [
|
|
267
|
-
enabled,
|
|
268
|
-
history,
|
|
269
|
-
onUnhandledLinking,
|
|
270
|
-
ref,
|
|
271
|
-
validateRoutesNotExistInRootState,
|
|
272
|
-
]);
|
|
270
|
+
}, [enabled, history, ref, validateRoutesNotExistInRootState]);
|
|
273
271
|
|
|
274
272
|
React.useEffect(() => {
|
|
275
273
|
if (!enabled) {
|
|
@@ -381,12 +379,8 @@ export function useLinking(
|
|
|
381
379
|
path !== pendingPath
|
|
382
380
|
) {
|
|
383
381
|
const historyDelta =
|
|
384
|
-
(focusedState
|
|
385
|
-
|
|
386
|
-
: focusedState.routes.length) -
|
|
387
|
-
(previousFocusedState.history
|
|
388
|
-
? previousFocusedState.history.length
|
|
389
|
-
: previousFocusedState.routes.length);
|
|
382
|
+
getTotalHistoryLength(focusedState) -
|
|
383
|
+
getTotalHistoryLength(previousFocusedState);
|
|
390
384
|
|
|
391
385
|
if (historyDelta > 0) {
|
|
392
386
|
// If history length is increased, we should pushState
|
package/src/useScrollToTop.tsx
CHANGED
|
@@ -62,7 +62,9 @@ export function useScrollToTop(ref: React.RefObject<ScrollableWrapper>) {
|
|
|
62
62
|
|
|
63
63
|
React.useEffect(() => {
|
|
64
64
|
const tabNavigations: NavigationProp<ParamListBase>[] = [];
|
|
65
|
-
let currentNavigation =
|
|
65
|
+
let currentNavigation: NavigationProp<ParamListBase> | undefined =
|
|
66
|
+
navigation;
|
|
67
|
+
|
|
66
68
|
// If the screen is nested inside multiple tab navigators, we should scroll to top for any of them
|
|
67
69
|
// So we need to find all the parent tab navigators and add the listeners there
|
|
68
70
|
while (currentNavigation) {
|
package/src/useThenable.tsx
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export type Thenable<T> = {
|
|
4
|
+
then(onfulfilled?: (value: T) => unknown): PromiseLike<unknown>;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export function useThenable<T>(create: () => Thenable<T> | undefined) {
|
|
4
8
|
const [promise] = React.useState(create);
|
|
5
9
|
|
|
6
10
|
let initialState: [boolean, T | undefined] = [false, undefined];
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
if (promise == null) {
|
|
13
|
+
initialState = [true, undefined];
|
|
14
|
+
} else {
|
|
15
|
+
// Check if our thenable is synchronous
|
|
16
|
+
// eslint-disable-next-line promise/catch-or-return, promise/always-return
|
|
17
|
+
promise.then((result) => {
|
|
18
|
+
initialState = [true, result];
|
|
19
|
+
});
|
|
20
|
+
}
|
|
13
21
|
|
|
14
22
|
const [state, setState] = React.useState(initialState);
|
|
15
23
|
const [resolved] = state;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import * as React from 'react';
|
|
4
|
-
const MISSING_CONTEXT_ERROR = "Couldn't find an UnhandledLinkingContext context.";
|
|
5
|
-
export const UnhandledLinkingContext = /*#__PURE__*/React.createContext({
|
|
6
|
-
get lastUnhandledLink() {
|
|
7
|
-
throw new Error(MISSING_CONTEXT_ERROR);
|
|
8
|
-
},
|
|
9
|
-
get setLastUnhandledLink() {
|
|
10
|
-
throw new Error(MISSING_CONTEXT_ERROR);
|
|
11
|
-
}
|
|
12
|
-
});
|
|
13
|
-
UnhandledLinkingContext.displayName = 'UnhandledLinkingContext';
|
|
14
|
-
//# sourceMappingURL=UnhandledLinkingContext.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","MISSING_CONTEXT_ERROR","UnhandledLinkingContext","createContext","lastUnhandledLink","Error","setLastUnhandledLink","displayName"],"sourceRoot":"../../src","sources":["UnhandledLinkingContext.tsx"],"mappings":";;AAAA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAE9B,MAAMC,qBAAqB,GACzB,mDAAmD;AAErD,OAAO,MAAMC,uBAAuB,gBAAGF,KAAK,CAACG,aAAa,CAGvD;EACD,IAAIC,iBAAiBA,CAAA,EAAQ;IAC3B,MAAM,IAAIC,KAAK,CAACJ,qBAAqB,CAAC;EACxC,CAAC;EACD,IAAIK,oBAAoBA,CAAA,EAAQ;IAC9B,MAAM,IAAID,KAAK,CAACJ,qBAAqB,CAAC;EACxC;AACF,CAAC,CAAC;AAEFC,uBAAuB,CAACK,WAAW,GAAG,yBAAyB","ignoreList":[]}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
export declare const UnhandledLinkingContext: React.Context<{
|
|
3
|
-
lastUnhandledLink: string | undefined;
|
|
4
|
-
setLastUnhandledLink: (lastUnhandledUrl: string | undefined) => void;
|
|
5
|
-
}>;
|
|
6
|
-
//# sourceMappingURL=UnhandledLinkingContext.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"UnhandledLinkingContext.d.ts","sourceRoot":"","sources":["../../../src/UnhandledLinkingContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,eAAO,MAAM,uBAAuB;uBACf,MAAM,GAAG,SAAS;0BACf,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI;EAQpE,CAAC"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
|
|
3
|
-
const MISSING_CONTEXT_ERROR =
|
|
4
|
-
"Couldn't find an UnhandledLinkingContext context.";
|
|
5
|
-
|
|
6
|
-
export const UnhandledLinkingContext = React.createContext<{
|
|
7
|
-
lastUnhandledLink: string | undefined;
|
|
8
|
-
setLastUnhandledLink: (lastUnhandledUrl: string | undefined) => void;
|
|
9
|
-
}>({
|
|
10
|
-
get lastUnhandledLink(): any {
|
|
11
|
-
throw new Error(MISSING_CONTEXT_ERROR);
|
|
12
|
-
},
|
|
13
|
-
get setLastUnhandledLink(): any {
|
|
14
|
-
throw new Error(MISSING_CONTEXT_ERROR);
|
|
15
|
-
},
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
UnhandledLinkingContext.displayName = 'UnhandledLinkingContext';
|