1 | function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
2 |
|
3 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
4 |
|
5 | import { HeaderShownContext, SafeAreaProviderCompat } from '@react-navigation/elements';
|
6 | import { StackActions } from '@react-navigation/native';
|
7 | import * as React from 'react';
|
8 | import { StyleSheet, View } from 'react-native';
|
9 | import { SafeAreaInsetsContext } from 'react-native-safe-area-context';
|
10 | import ModalPresentationContext from '../../utils/ModalPresentationContext';
|
11 | import { GestureHandlerRootView } from '../GestureHandler';
|
12 | import HeaderContainer from '../Header/HeaderContainer';
|
13 | import CardStack from './CardStack';
|
14 | const GestureHandlerWrapper = GestureHandlerRootView !== null && GestureHandlerRootView !== void 0 ? GestureHandlerRootView : View;
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | const isArrayEqual = (a, b) => a.length === b.length && a.every((it, index) => it === b[index]);
|
21 |
|
22 | export default class StackView extends React.Component {
|
23 | constructor() {
|
24 | super(...arguments);
|
25 |
|
26 | _defineProperty(this, "state", {
|
27 | routes: [],
|
28 | previousRoutes: [],
|
29 | previousDescriptors: {},
|
30 | openingRouteKeys: [],
|
31 | closingRouteKeys: [],
|
32 | replacingRouteKeys: [],
|
33 | descriptors: {}
|
34 | });
|
35 |
|
36 | _defineProperty(this, "getPreviousRoute", _ref => {
|
37 | let {
|
38 | route
|
39 | } = _ref;
|
40 | const {
|
41 | closingRouteKeys,
|
42 | replacingRouteKeys
|
43 | } = this.state;
|
44 | const routes = this.state.routes.filter(r => r.key === route.key || !closingRouteKeys.includes(r.key) && !replacingRouteKeys.includes(r.key));
|
45 | const index = routes.findIndex(r => r.key === route.key);
|
46 | return routes[index - 1];
|
47 | });
|
48 |
|
49 | _defineProperty(this, "renderScene", _ref2 => {
|
50 | let {
|
51 | route
|
52 | } = _ref2;
|
53 | const descriptor = this.state.descriptors[route.key] || this.props.descriptors[route.key];
|
54 |
|
55 | if (!descriptor) {
|
56 | return null;
|
57 | }
|
58 |
|
59 | return descriptor.render();
|
60 | });
|
61 |
|
62 | _defineProperty(this, "renderHeader", props => {
|
63 | return React.createElement(HeaderContainer, props);
|
64 | });
|
65 |
|
66 | _defineProperty(this, "handleOpenRoute", _ref3 => {
|
67 | let {
|
68 | route
|
69 | } = _ref3;
|
70 | const {
|
71 | state,
|
72 | navigation
|
73 | } = this.props;
|
74 | const {
|
75 | closingRouteKeys,
|
76 | replacingRouteKeys
|
77 | } = this.state;
|
78 |
|
79 | if (closingRouteKeys.some(key => key === route.key) && replacingRouteKeys.every(key => key !== route.key) && state.routeNames.includes(route.name) && !state.routes.some(r => r.key === route.key)) {
|
80 |
|
81 |
|
82 | navigation.navigate(route);
|
83 | } else {
|
84 | this.setState(state => ({
|
85 | routes: state.replacingRouteKeys.length ? state.routes.filter(r => !state.replacingRouteKeys.includes(r.key)) : state.routes,
|
86 | openingRouteKeys: state.openingRouteKeys.filter(key => key !== route.key),
|
87 | closingRouteKeys: state.closingRouteKeys.filter(key => key !== route.key),
|
88 | replacingRouteKeys: []
|
89 | }));
|
90 | }
|
91 | });
|
92 |
|
93 | _defineProperty(this, "handleCloseRoute", _ref4 => {
|
94 | let {
|
95 | route
|
96 | } = _ref4;
|
97 | const {
|
98 | state,
|
99 | navigation
|
100 | } = this.props;
|
101 |
|
102 | if (state.routes.some(r => r.key === route.key)) {
|
103 |
|
104 |
|
105 |
|
106 | navigation.dispatch({ ...StackActions.pop(),
|
107 | source: route.key,
|
108 | target: state.key
|
109 | });
|
110 | } else {
|
111 |
|
112 | this.setState(state => ({
|
113 | routes: state.routes.filter(r => r.key !== route.key),
|
114 | openingRouteKeys: state.openingRouteKeys.filter(key => key !== route.key),
|
115 | closingRouteKeys: state.closingRouteKeys.filter(key => key !== route.key)
|
116 | }));
|
117 | }
|
118 | });
|
119 |
|
120 | _defineProperty(this, "handleTransitionStart", (_ref5, closing) => {
|
121 | let {
|
122 | route
|
123 | } = _ref5;
|
124 | return this.props.navigation.emit({
|
125 | type: 'transitionStart',
|
126 | data: {
|
127 | closing
|
128 | },
|
129 | target: route.key
|
130 | });
|
131 | });
|
132 |
|
133 | _defineProperty(this, "handleTransitionEnd", (_ref6, closing) => {
|
134 | let {
|
135 | route
|
136 | } = _ref6;
|
137 | return this.props.navigation.emit({
|
138 | type: 'transitionEnd',
|
139 | data: {
|
140 | closing
|
141 | },
|
142 | target: route.key
|
143 | });
|
144 | });
|
145 |
|
146 | _defineProperty(this, "handleGestureStart", _ref7 => {
|
147 | let {
|
148 | route
|
149 | } = _ref7;
|
150 | this.props.navigation.emit({
|
151 | type: 'gestureStart',
|
152 | target: route.key
|
153 | });
|
154 | });
|
155 |
|
156 | _defineProperty(this, "handleGestureEnd", _ref8 => {
|
157 | let {
|
158 | route
|
159 | } = _ref8;
|
160 | this.props.navigation.emit({
|
161 | type: 'gestureEnd',
|
162 | target: route.key
|
163 | });
|
164 | });
|
165 |
|
166 | _defineProperty(this, "handleGestureCancel", _ref9 => {
|
167 | let {
|
168 | route
|
169 | } = _ref9;
|
170 | this.props.navigation.emit({
|
171 | type: 'gestureCancel',
|
172 | target: route.key
|
173 | });
|
174 | });
|
175 | }
|
176 |
|
177 | static getDerivedStateFromProps(props, state) {
|
178 |
|
179 | if ((props.state.routes === state.previousRoutes || isArrayEqual(props.state.routes.map(r => r.key), state.previousRoutes.map(r => r.key))) && state.routes.length) {
|
180 | let routes = state.routes;
|
181 | let previousRoutes = state.previousRoutes;
|
182 | let descriptors = props.descriptors;
|
183 | let previousDescriptors = state.previousDescriptors;
|
184 |
|
185 | if (props.descriptors !== state.previousDescriptors) {
|
186 | descriptors = state.routes.reduce((acc, route) => {
|
187 | acc[route.key] = props.descriptors[route.key] || state.descriptors[route.key];
|
188 | return acc;
|
189 | }, {});
|
190 | previousDescriptors = props.descriptors;
|
191 | }
|
192 |
|
193 | if (props.state.routes !== state.previousRoutes) {
|
194 |
|
195 | const map = props.state.routes.reduce((acc, route) => {
|
196 | acc[route.key] = route;
|
197 | return acc;
|
198 | }, {});
|
199 | routes = state.routes.map(route => map[route.key] || route);
|
200 | previousRoutes = props.state.routes;
|
201 | }
|
202 |
|
203 | return {
|
204 | routes,
|
205 | previousRoutes,
|
206 | descriptors,
|
207 | previousDescriptors
|
208 | };
|
209 | }
|
210 |
|
211 |
|
212 |
|
213 | let routes = props.state.index < props.state.routes.length - 1 ?
|
214 |
|
215 | props.state.routes.slice(0, props.state.index + 1) : props.state.routes;
|
216 |
|
217 | let {
|
218 | openingRouteKeys,
|
219 | closingRouteKeys,
|
220 | replacingRouteKeys,
|
221 | previousRoutes
|
222 | } = state;
|
223 | const previousFocusedRoute = previousRoutes[previousRoutes.length - 1];
|
224 | const nextFocusedRoute = routes[routes.length - 1];
|
225 |
|
226 | const isAnimationEnabled = key => {
|
227 | const descriptor = props.descriptors[key] || state.descriptors[key];
|
228 | return descriptor ? descriptor.options.animationEnabled !== false : true;
|
229 | };
|
230 |
|
231 | const getAnimationTypeForReplace = key => {
|
232 | var _descriptor$options$a;
|
233 |
|
234 | const descriptor = props.descriptors[key] || state.descriptors[key];
|
235 | return (_descriptor$options$a = descriptor.options.animationTypeForReplace) !== null && _descriptor$options$a !== void 0 ? _descriptor$options$a : 'push';
|
236 | };
|
237 |
|
238 | if (previousFocusedRoute && previousFocusedRoute.key !== nextFocusedRoute.key) {
|
239 |
|
240 |
|
241 | if (!previousRoutes.some(r => r.key === nextFocusedRoute.key)) {
|
242 |
|
243 |
|
244 | if (isAnimationEnabled(nextFocusedRoute.key) && !openingRouteKeys.includes(nextFocusedRoute.key)) {
|
245 |
|
246 |
|
247 | openingRouteKeys = [...openingRouteKeys, nextFocusedRoute.key];
|
248 | closingRouteKeys = closingRouteKeys.filter(key => key !== nextFocusedRoute.key);
|
249 | replacingRouteKeys = replacingRouteKeys.filter(key => key !== nextFocusedRoute.key);
|
250 |
|
251 | if (!routes.some(r => r.key === previousFocusedRoute.key)) {
|
252 |
|
253 | openingRouteKeys = openingRouteKeys.filter(key => key !== previousFocusedRoute.key);
|
254 |
|
255 | if (getAnimationTypeForReplace(nextFocusedRoute.key) === 'pop') {
|
256 | closingRouteKeys = [...closingRouteKeys, previousFocusedRoute.key];
|
257 |
|
258 |
|
259 |
|
260 | openingRouteKeys = openingRouteKeys.filter(key => key !== nextFocusedRoute.key);
|
261 |
|
262 | routes = [...routes, previousFocusedRoute];
|
263 | } else {
|
264 | replacingRouteKeys = [...replacingRouteKeys, previousFocusedRoute.key];
|
265 | closingRouteKeys = closingRouteKeys.filter(key => key !== previousFocusedRoute.key);
|
266 |
|
267 |
|
268 |
|
269 | routes = routes.slice();
|
270 | routes.splice(routes.length - 1, 0, previousFocusedRoute);
|
271 | }
|
272 | }
|
273 | }
|
274 | } else if (!routes.some(r => r.key === previousFocusedRoute.key)) {
|
275 |
|
276 | if (isAnimationEnabled(previousFocusedRoute.key) && !closingRouteKeys.includes(previousFocusedRoute.key)) {
|
277 | closingRouteKeys = [...closingRouteKeys, previousFocusedRoute.key];
|
278 |
|
279 |
|
280 | openingRouteKeys = openingRouteKeys.filter(key => key !== previousFocusedRoute.key);
|
281 | replacingRouteKeys = replacingRouteKeys.filter(key => key !== previousFocusedRoute.key);
|
282 |
|
283 | routes = [...routes, previousFocusedRoute];
|
284 | }
|
285 | } else {
|
286 |
|
287 |
|
288 | }
|
289 | } else if (replacingRouteKeys.length || closingRouteKeys.length) {
|
290 |
|
291 | routes = routes.slice();
|
292 | routes.splice(routes.length - 1, 0, ...state.routes.filter(_ref10 => {
|
293 | let {
|
294 | key
|
295 | } = _ref10;
|
296 | return isAnimationEnabled(key) ? replacingRouteKeys.includes(key) || closingRouteKeys.includes(key) : false;
|
297 | }));
|
298 | }
|
299 |
|
300 | if (!routes.length) {
|
301 | throw new Error('There should always be at least one route in the navigation state.');
|
302 | }
|
303 |
|
304 | const descriptors = routes.reduce((acc, route) => {
|
305 | acc[route.key] = props.descriptors[route.key] || state.descriptors[route.key];
|
306 | return acc;
|
307 | }, {});
|
308 | return {
|
309 | routes,
|
310 | previousRoutes: props.state.routes,
|
311 | previousDescriptors: props.descriptors,
|
312 | openingRouteKeys,
|
313 | closingRouteKeys,
|
314 | replacingRouteKeys,
|
315 | descriptors
|
316 | };
|
317 | }
|
318 |
|
319 | render() {
|
320 | const {
|
321 | state,
|
322 |
|
323 | descriptors: _,
|
324 | ...rest
|
325 | } = this.props;
|
326 | const {
|
327 | routes,
|
328 | descriptors,
|
329 | openingRouteKeys,
|
330 | closingRouteKeys
|
331 | } = this.state;
|
332 | return React.createElement(GestureHandlerWrapper, {
|
333 | style: styles.container
|
334 | }, React.createElement(SafeAreaProviderCompat, null, React.createElement(SafeAreaInsetsContext.Consumer, null, insets => React.createElement(ModalPresentationContext.Consumer, null, isParentModal => React.createElement(HeaderShownContext.Consumer, null, isParentHeaderShown => React.createElement(CardStack, _extends({
|
335 | insets: insets,
|
336 | isParentHeaderShown: isParentHeaderShown,
|
337 | isParentModal: isParentModal,
|
338 | getPreviousRoute: this.getPreviousRoute,
|
339 | routes: routes,
|
340 | openingRouteKeys: openingRouteKeys,
|
341 | closingRouteKeys: closingRouteKeys,
|
342 | onOpenRoute: this.handleOpenRoute,
|
343 | onCloseRoute: this.handleCloseRoute,
|
344 | onTransitionStart: this.handleTransitionStart,
|
345 | onTransitionEnd: this.handleTransitionEnd,
|
346 | renderHeader: this.renderHeader,
|
347 | renderScene: this.renderScene,
|
348 | state: state,
|
349 | descriptors: descriptors,
|
350 | onGestureStart: this.handleGestureStart,
|
351 | onGestureEnd: this.handleGestureEnd,
|
352 | onGestureCancel: this.handleGestureCancel
|
353 | }, rest)))))));
|
354 | }
|
355 |
|
356 | }
|
357 | const styles = StyleSheet.create({
|
358 | container: {
|
359 | flex: 1
|
360 | }
|
361 | });
|
362 |
|
\ | No newline at end of file |