mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-25 05:18:15 +08:00
Compare commits
8 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e7cfc4ac0 | ||
|
|
5751e7f97a | ||
|
|
179e807a64 | ||
|
|
2f1f0af862 | ||
|
|
9976a888a0 | ||
|
|
16c64e7298 | ||
|
|
f1fe951cf9 | ||
|
|
14250851d1 |
@@ -3,6 +3,17 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.0.0-alpha.39](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.38...@react-navigation/bottom-tabs@5.0.0-alpha.39) (2020-01-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* use layout instead of dimensions for determining tab bar layout ([f1fe951](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/commit/f1fe951cf9d602e1b6d4932e3c6c77bbeaaec5c0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.0.0-alpha.38](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.37...@react-navigation/bottom-tabs@5.0.0-alpha.38) (2020-01-23)
|
# [5.0.0-alpha.38](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.37...@react-navigation/bottom-tabs@5.0.0-alpha.38) (2020-01-23)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"android",
|
"android",
|
||||||
"tab"
|
"tab"
|
||||||
],
|
],
|
||||||
"version": "5.0.0-alpha.38",
|
"version": "5.0.0-alpha.39",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs",
|
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/routers": "^5.0.0-alpha.26",
|
"@react-navigation/routers": "^5.0.0-alpha.27",
|
||||||
"color": "^3.1.2",
|
"color": "^3.1.2",
|
||||||
"react-native-iphone-x-helper": "^1.2.1"
|
"react-native-iphone-x-helper": "^1.2.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -176,14 +176,9 @@ export type BottomTabBarOptions = {
|
|||||||
tabStyle?: StyleProp<ViewStyle>;
|
tabStyle?: StyleProp<ViewStyle>;
|
||||||
/**
|
/**
|
||||||
* Whether the label is renderd below the icon or beside the icon.
|
* Whether the label is renderd below the icon or beside the icon.
|
||||||
* When a function is passed, it receives the device dimensions to render the label differently.
|
|
||||||
* By default, in `vertical` orinetation, label is rendered below and in `horizontal` orientation, it's renderd beside.
|
* By default, in `vertical` orinetation, label is rendered below and in `horizontal` orientation, it's renderd beside.
|
||||||
*/
|
*/
|
||||||
labelPosition?:
|
labelPosition?: LabelPosition;
|
||||||
| LabelPosition
|
|
||||||
| ((options: {
|
|
||||||
dimensions: { height: number; width: number };
|
|
||||||
}) => LabelPosition);
|
|
||||||
/**
|
/**
|
||||||
* Whether the label position should adapt to the orientation.
|
* Whether the label position should adapt to the orientation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -50,7 +50,10 @@ export default function BottomTabBar({
|
|||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
|
|
||||||
const [dimensions, setDimensions] = React.useState(Dimensions.get('window'));
|
const [dimensions, setDimensions] = React.useState(Dimensions.get('window'));
|
||||||
const [layout, setLayout] = React.useState({ height: 0, width: 0 });
|
const [layout, setLayout] = React.useState({
|
||||||
|
height: 0,
|
||||||
|
width: dimensions.width,
|
||||||
|
});
|
||||||
const [keyboardShown, setKeyboardShown] = React.useState(false);
|
const [keyboardShown, setKeyboardShown] = React.useState(false);
|
||||||
|
|
||||||
const [visible] = React.useState(() => new Animated.Value(0));
|
const [visible] = React.useState(() => new Animated.Value(0));
|
||||||
@@ -124,27 +127,15 @@ export default function BottomTabBar({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const shouldUseHorizontalLabels = () => {
|
const shouldUseHorizontalLabels = () => {
|
||||||
const isLandscape = dimensions.width > dimensions.height;
|
|
||||||
|
|
||||||
if (labelPosition) {
|
if (labelPosition) {
|
||||||
let position;
|
return labelPosition === 'beside-icon';
|
||||||
|
|
||||||
if (typeof labelPosition === 'string') {
|
|
||||||
position = labelPosition;
|
|
||||||
} else {
|
|
||||||
position = labelPosition({ dimensions });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position) {
|
|
||||||
return position === 'beside-icon';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!adaptive) {
|
if (!adaptive) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dimensions.width >= 768) {
|
if (layout.width >= 768) {
|
||||||
// Screen size matches a tablet
|
// Screen size matches a tablet
|
||||||
let maxTabItemWidth = DEFAULT_MAX_TAB_ITEM_WIDTH;
|
let maxTabItemWidth = DEFAULT_MAX_TAB_ITEM_WIDTH;
|
||||||
|
|
||||||
@@ -158,8 +149,10 @@ export default function BottomTabBar({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return routes.length * maxTabItemWidth <= dimensions.width;
|
return routes.length * maxTabItemWidth <= layout.width;
|
||||||
} else {
|
} else {
|
||||||
|
const isLandscape = dimensions.width > dimensions.height;
|
||||||
|
|
||||||
return isLandscape;
|
return isLandscape;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.0.0-alpha.28](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.27...@react-navigation/compat@5.0.0-alpha.28) (2020-01-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.0.0-alpha.27](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.26...@react-navigation/compat@5.0.0-alpha.27) (2020-01-23)
|
# [5.0.0-alpha.27](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.26...@react-navigation/compat@5.0.0-alpha.27) (2020-01-23)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/compat",
|
"name": "@react-navigation/compat",
|
||||||
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
||||||
"version": "5.0.0-alpha.27",
|
"version": "5.0.0-alpha.28",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/compat",
|
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/compat",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/routers": "^5.0.0-alpha.26"
|
"@react-navigation/routers": "^5.0.0-alpha.27"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^16.9.17",
|
"@types/react": "^16.9.17",
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export function replace({
|
|||||||
key?: string;
|
key?: string;
|
||||||
newKey?: string;
|
newKey?: string;
|
||||||
action?: never;
|
action?: never;
|
||||||
}): CommonActions.Action {
|
}): StackActionType {
|
||||||
if (action !== undefined) {
|
if (action !== undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Sub-actions are not supported for `replace`. Remove the `action` key from the options.'
|
'Sub-actions are not supported for `replace`. Remove the `action` key from the options.'
|
||||||
|
|||||||
@@ -3,6 +3,19 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.0.0-alpha.37](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.36...@react-navigation/core@5.0.0-alpha.37) (2020-01-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add error message when trying to use v4 API with v5 ([179e807](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/179e807a64a7d031d671c2c4b12edaee3c3440c5))
|
||||||
|
* validate screen configs ([2f1f0af](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/2f1f0af862ef8625da4c2aaf463d45fe17a4ac88))
|
||||||
|
* warn if non-serializable values found in state ([5751e7f](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/5751e7f97a1731a5c71862174dfd931b6ffe13e2))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.0.0-alpha.36](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.35...@react-navigation/core@5.0.0-alpha.36) (2020-01-23)
|
# [5.0.0-alpha.36](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.35...@react-navigation/core@5.0.0-alpha.36) (2020-01-23)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"react-native",
|
"react-native",
|
||||||
"react-navigation"
|
"react-navigation"
|
||||||
],
|
],
|
||||||
"version": "5.0.0-alpha.36",
|
"version": "5.0.0-alpha.37",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/core",
|
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/core",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"escape-string-regexp": "^2.0.0",
|
"escape-string-regexp": "^2.0.0",
|
||||||
"query-string": "^6.9.0",
|
"query-string": "^6.9.0",
|
||||||
|
"react-is": "^16.12.0",
|
||||||
"shortid": "^2.2.15",
|
"shortid": "^2.2.15",
|
||||||
"use-subscription": "^1.3.0"
|
"use-subscription": "^1.3.0"
|
||||||
},
|
},
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
"@babel/core": "^7.7.7",
|
"@babel/core": "^7.7.7",
|
||||||
"@react-native-community/bob": "^0.8.0",
|
"@react-native-community/bob": "^0.8.0",
|
||||||
"@types/react": "^16.9.17",
|
"@types/react": "^16.9.17",
|
||||||
|
"@types/react-is": "^16.7.1",
|
||||||
"@types/shortid": "^0.0.29",
|
"@types/shortid": "^0.0.29",
|
||||||
"@types/use-subscription": "^1.0.0",
|
"@types/use-subscription": "^1.0.0",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import shortid from 'shortid';
|
|
||||||
import { CommonAction, NavigationState, PartialState } from './types';
|
import { CommonAction, NavigationState, PartialState } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,35 +10,6 @@ const BaseRouter = {
|
|||||||
action: CommonAction
|
action: CommonAction
|
||||||
): State | PartialState<State> | null {
|
): State | PartialState<State> | null {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'REPLACE': {
|
|
||||||
const index = action.source
|
|
||||||
? state.routes.findIndex(r => r.key === action.source)
|
|
||||||
: state.index;
|
|
||||||
|
|
||||||
if (index === -1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { name, key, params } = action.payload;
|
|
||||||
|
|
||||||
if (!state.routeNames.includes(name)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
routes: state.routes.map((route, i) =>
|
|
||||||
i === index
|
|
||||||
? {
|
|
||||||
key: key !== undefined ? key : `${name}-${shortid()}`,
|
|
||||||
name,
|
|
||||||
params,
|
|
||||||
}
|
|
||||||
: route
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'SET_PARAMS': {
|
case 'SET_PARAMS': {
|
||||||
const index = action.source
|
const index = action.source
|
||||||
? state.routes.findIndex(r => r.key === action.source)
|
? state.routes.findIndex(r => r.key === action.source)
|
||||||
|
|||||||
@@ -14,12 +14,6 @@ export type Action =
|
|||||||
source?: string;
|
source?: string;
|
||||||
target?: string;
|
target?: string;
|
||||||
}
|
}
|
||||||
| {
|
|
||||||
type: 'REPLACE';
|
|
||||||
payload: { name: string; key?: string; params?: object };
|
|
||||||
source?: string;
|
|
||||||
target?: string;
|
|
||||||
}
|
|
||||||
| {
|
| {
|
||||||
type: 'RESET';
|
type: 'RESET';
|
||||||
payload: PartialState<NavigationState>;
|
payload: PartialState<NavigationState>;
|
||||||
@@ -59,10 +53,6 @@ export function navigate(...args: any): Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function replace(name: string, params?: object): Action {
|
|
||||||
return { type: 'REPLACE', payload: { name, params } };
|
|
||||||
}
|
|
||||||
|
|
||||||
export function reset(state: PartialState<NavigationState>): Action {
|
export function reset(state: PartialState<NavigationState>): Action {
|
||||||
return { type: 'RESET', payload: state };
|
return { type: 'RESET', payload: state };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import * as React from 'react';
|
|||||||
import * as CommonActions from './CommonActions';
|
import * as CommonActions from './CommonActions';
|
||||||
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
||||||
import NavigationBuilderContext from './NavigationBuilderContext';
|
import NavigationBuilderContext from './NavigationBuilderContext';
|
||||||
import ResetRootContext from './ResetRootContext';
|
|
||||||
import useFocusedListeners from './useFocusedListeners';
|
import useFocusedListeners from './useFocusedListeners';
|
||||||
import useDevTools from './useDevTools';
|
import useDevTools from './useDevTools';
|
||||||
import useStateGetters from './useStateGetters';
|
import useStateGetters from './useStateGetters';
|
||||||
|
import isSerializable from './isSerializable';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Route,
|
Route,
|
||||||
@@ -45,6 +45,8 @@ export const NavigationStateContext = React.createContext<{
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let hasWarnedForSerialization = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove `key` and `routeNames` from the state objects recursively to get partial state.
|
* Remove `key` and `routeNames` from the state objects recursively to get partial state.
|
||||||
*
|
*
|
||||||
@@ -242,6 +244,20 @@ const Container = React.forwardRef(function NavigationContainer(
|
|||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
if (
|
||||||
|
state !== undefined &&
|
||||||
|
!isSerializable(state) &&
|
||||||
|
!hasWarnedForSerialization
|
||||||
|
) {
|
||||||
|
hasWarnedForSerialization = true;
|
||||||
|
|
||||||
|
console.warn(
|
||||||
|
"We found non-serializable values in the navigation state, which can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params. If you need to use functions in your options, you can use 'navigation.setOptions' instead."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (skipTrackingRef.current) {
|
if (skipTrackingRef.current) {
|
||||||
skipTrackingRef.current = false;
|
skipTrackingRef.current = false;
|
||||||
} else {
|
} else {
|
||||||
@@ -261,9 +277,7 @@ const Container = React.forwardRef(function NavigationContainer(
|
|||||||
return (
|
return (
|
||||||
<NavigationBuilderContext.Provider value={builderContext}>
|
<NavigationBuilderContext.Provider value={builderContext}>
|
||||||
<NavigationStateContext.Provider value={context}>
|
<NavigationStateContext.Provider value={context}>
|
||||||
<ResetRootContext.Provider value={resetRoot}>
|
<EnsureSingleNavigator>{children}</EnsureSingleNavigator>
|
||||||
<EnsureSingleNavigator>{children}</EnsureSingleNavigator>
|
|
||||||
</ResetRootContext.Provider>
|
|
||||||
</NavigationStateContext.Provider>
|
</NavigationStateContext.Provider>
|
||||||
</NavigationBuilderContext.Provider>
|
</NavigationBuilderContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import { NavigationState, PartialState } from './types';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Context which holds the method to reset root navigator state.
|
|
||||||
*/
|
|
||||||
const ResetRootContext = React.createContext<
|
|
||||||
(state: PartialState<NavigationState> | NavigationState) => void
|
|
||||||
>(() => {
|
|
||||||
throw new Error(
|
|
||||||
"We couldn't find a way to reset root state. Have you wrapped your app with 'NavigationContainer'?"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default ResetRootContext;
|
|
||||||
@@ -16,64 +16,6 @@ const STATE = {
|
|||||||
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||||
};
|
};
|
||||||
|
|
||||||
it('replaces focused screen with REPLACE', () => {
|
|
||||||
const result = BaseRouter.getStateForAction(
|
|
||||||
STATE,
|
|
||||||
CommonActions.replace('qux', { answer: 42 })
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toEqual({
|
|
||||||
stale: false,
|
|
||||||
type: 'test',
|
|
||||||
key: 'root',
|
|
||||||
index: 1,
|
|
||||||
routes: [
|
|
||||||
{ key: 'foo', name: 'foo' },
|
|
||||||
{ key: 'qux-test', name: 'qux', params: { answer: 42 } },
|
|
||||||
{ key: 'baz', name: 'baz' },
|
|
||||||
],
|
|
||||||
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('replaces source screen with REPLACE', () => {
|
|
||||||
const result = BaseRouter.getStateForAction(STATE, {
|
|
||||||
...CommonActions.replace('qux', { answer: 42 }),
|
|
||||||
source: 'baz',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result).toEqual({
|
|
||||||
stale: false,
|
|
||||||
type: 'test',
|
|
||||||
key: 'root',
|
|
||||||
index: 1,
|
|
||||||
routes: [
|
|
||||||
{ key: 'foo', name: 'foo' },
|
|
||||||
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
|
|
||||||
{ key: 'qux-test', name: 'qux', params: { answer: 42 } },
|
|
||||||
],
|
|
||||||
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("doesn't handle REPLACE if source key isn't present", () => {
|
|
||||||
const result = BaseRouter.getStateForAction(STATE, {
|
|
||||||
...CommonActions.replace('qux', { answer: 42 }),
|
|
||||||
source: 'magic',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result).toBe(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("doesn't handle REPLACE if screen to replace with isn't present", () => {
|
|
||||||
const result = BaseRouter.getStateForAction(
|
|
||||||
STATE,
|
|
||||||
CommonActions.replace('nonexistent', { answer: 42 })
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toBe(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sets params for the focused screen with SET_PARAMS', () => {
|
it('sets params for the focused screen with SET_PARAMS', () => {
|
||||||
const result = BaseRouter.getStateForAction(
|
const result = BaseRouter.getStateForAction(
|
||||||
STATE,
|
STATE,
|
||||||
|
|||||||
12
packages/core/src/__tests__/createNavigatorFactory.test.tsx
Normal file
12
packages/core/src/__tests__/createNavigatorFactory.test.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import createNavigatorFactory from '../createNavigatorFactory';
|
||||||
|
|
||||||
|
it('throws descriptive error if an argument is passed', () => {
|
||||||
|
const createDummyNavigator = createNavigatorFactory(() => null);
|
||||||
|
|
||||||
|
expect(() => createDummyNavigator()).not.toThrowError();
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
expect(() => createDummyNavigator({})).toThrowError(
|
||||||
|
"Creating a navigator doesn't take an argument."
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -936,3 +936,100 @@ it('switches rendered navigators', () => {
|
|||||||
'Another navigator is already registered for this container.'
|
'Another navigator is already registered for this container.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('throws if both children and component are passed', () => {
|
||||||
|
const TestNavigator = (props: any) => {
|
||||||
|
useNavigationBuilder(MockRouter, props);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const element = (
|
||||||
|
<NavigationContainer>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="foo" component={jest.fn()}>
|
||||||
|
{jest.fn()}
|
||||||
|
</Screen>
|
||||||
|
</TestNavigator>
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(() => render(element).update(element)).toThrowError(
|
||||||
|
"We got both 'component' and 'children' props for 'Screen'. You must pass only one of them."
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws descriptive error for undefined screen component', () => {
|
||||||
|
const TestNavigator = (props: any) => {
|
||||||
|
useNavigationBuilder(MockRouter, props);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const element = (
|
||||||
|
<NavigationContainer>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="foo" component={undefined as any} />
|
||||||
|
</TestNavigator>
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(() => render(element).update(element)).toThrowError(
|
||||||
|
"We couldn't find a 'component' or 'children' prop for 'Screen'"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws descriptive error for invalid screen component', () => {
|
||||||
|
const TestNavigator = (props: any) => {
|
||||||
|
useNavigationBuilder(MockRouter, props);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const element = (
|
||||||
|
<NavigationContainer>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="foo" component={{} as any} />
|
||||||
|
</TestNavigator>
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(() => render(element).update(element)).toThrowError(
|
||||||
|
"We got an invalid value for 'component' prop for 'Screen'. It must be a a valid React Component."
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws descriptive error for invalid children', () => {
|
||||||
|
const TestNavigator = (props: any) => {
|
||||||
|
useNavigationBuilder(MockRouter, props);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const element = (
|
||||||
|
<NavigationContainer>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="foo">{[] as any}</Screen>
|
||||||
|
</TestNavigator>
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(() => render(element).update(element)).toThrowError(
|
||||||
|
"We got an invalid value for 'children' prop for 'Screen'. It must be a function returning a React Element."
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("doesn't throw if children is null", () => {
|
||||||
|
const TestNavigator = (props: any) => {
|
||||||
|
useNavigationBuilder(MockRouter, props);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const element = (
|
||||||
|
<NavigationContainer>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="foo" component={jest.fn()}>
|
||||||
|
{null as any}
|
||||||
|
</Screen>
|
||||||
|
</TestNavigator>
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(() => render(element).update(element)).not.toThrowError();
|
||||||
|
});
|
||||||
|
|||||||
@@ -13,11 +13,17 @@ export default function createNavigatorFactory<
|
|||||||
ScreenOptions extends object,
|
ScreenOptions extends object,
|
||||||
NavigatorComponent extends React.ComponentType<any>
|
NavigatorComponent extends React.ComponentType<any>
|
||||||
>(Navigator: NavigatorComponent) {
|
>(Navigator: NavigatorComponent) {
|
||||||
return <ParamList extends ParamListBase>(): TypedNavigator<
|
return function<ParamList extends ParamListBase>(): TypedNavigator<
|
||||||
ParamList,
|
ParamList,
|
||||||
ScreenOptions,
|
ScreenOptions,
|
||||||
typeof Navigator
|
typeof Navigator
|
||||||
> => {
|
> {
|
||||||
|
if (arguments[0] !== undefined) {
|
||||||
|
throw new Error(
|
||||||
|
"Creating a navigator doesn't take an argument. Maybe you are trying to use React Navigation 4 API with React Navigation 5?"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Navigator,
|
Navigator,
|
||||||
Screen,
|
Screen,
|
||||||
|
|||||||
34
packages/core/src/isSerializable.tsx
Normal file
34
packages/core/src/isSerializable.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
export default function isSerializable(o: { [key: string]: any }): boolean {
|
||||||
|
if (
|
||||||
|
o === undefined ||
|
||||||
|
o === null ||
|
||||||
|
typeof o === 'boolean' ||
|
||||||
|
typeof o === 'number' ||
|
||||||
|
typeof o === 'string'
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
Object.prototype.toString.call(o) !== '[object Object]' &&
|
||||||
|
!Array.isArray(o)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(o)) {
|
||||||
|
for (const it of o) {
|
||||||
|
if (!isSerializable(it)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const key in o) {
|
||||||
|
if (!isSerializable(o[key])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -365,13 +365,6 @@ type NavigationHelpersCommon<
|
|||||||
*/
|
*/
|
||||||
reset(state: PartialState<State> | State): void;
|
reset(state: PartialState<State> | State): void;
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the navigation state of the root navigator to the provided state.
|
|
||||||
*
|
|
||||||
* @param state Navigation state object.
|
|
||||||
*/
|
|
||||||
resetRoot(state?: PartialState<NavigationState> | NavigationState): void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Go back to the previous route in history.
|
* Go back to the previous route in history.
|
||||||
*/
|
*/
|
||||||
@@ -593,6 +586,9 @@ export type NavigationContainerRef =
|
|||||||
* @param state Navigation state object.
|
* @param state Navigation state object.
|
||||||
*/
|
*/
|
||||||
resetRoot(state?: PartialState<NavigationState> | NavigationState): void;
|
resetRoot(state?: PartialState<NavigationState> | NavigationState): void;
|
||||||
|
/**
|
||||||
|
* Get the rehydrated navigation state of the navigation tree.
|
||||||
|
*/
|
||||||
getRootState(): NavigationState;
|
getRootState(): NavigationState;
|
||||||
})
|
})
|
||||||
| undefined
|
| undefined
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { isValidElementType } from 'react-is';
|
||||||
import { NavigationStateContext } from './NavigationContainer';
|
import { NavigationStateContext } from './NavigationContainer';
|
||||||
import NavigationRouteContext from './NavigationRouteContext';
|
import NavigationRouteContext from './NavigationRouteContext';
|
||||||
import Screen from './Screen';
|
import Screen from './Screen';
|
||||||
@@ -53,8 +54,8 @@ const isArrayEqual = (a: any[], b: any[]) =>
|
|||||||
*/
|
*/
|
||||||
const getRouteConfigsFromChildren = <ScreenOptions extends object>(
|
const getRouteConfigsFromChildren = <ScreenOptions extends object>(
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
) =>
|
) => {
|
||||||
React.Children.toArray(children).reduce<
|
const configs = React.Children.toArray(children).reduce<
|
||||||
RouteConfig<ParamListBase, string, ScreenOptions>[]
|
RouteConfig<ParamListBase, string, ScreenOptions>[]
|
||||||
>((acc, child) => {
|
>((acc, child) => {
|
||||||
if (React.isValidElement(child)) {
|
if (React.isValidElement(child)) {
|
||||||
@@ -85,6 +86,39 @@ const getRouteConfigsFromChildren = <ScreenOptions extends object>(
|
|||||||
);
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
configs.forEach(config => {
|
||||||
|
const { children, component } = config as any;
|
||||||
|
|
||||||
|
if (children != null || component !== undefined) {
|
||||||
|
if (children != null && component !== undefined) {
|
||||||
|
throw new Error(
|
||||||
|
"We got both 'component' and 'children' props for 'Screen'. You must pass only one of them."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (children != null && typeof children !== 'function') {
|
||||||
|
throw new Error(
|
||||||
|
`We got an invalid value for 'children' prop for 'Screen'. It must be a function returning a React Element.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (component !== undefined && !isValidElementType(component)) {
|
||||||
|
throw new Error(
|
||||||
|
`We got an invalid value for 'component' prop for 'Screen'. It must be a a valid React Component.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"We couldn't find a 'component' or 'children' prop for 'Screen'. This can happen if you passed 'undefined'. You likely forgot to export your component from the file it's defined in, or mixed up default import and named import when importing."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return configs;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook for building navigators.
|
* Hook for building navigators.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as CommonActions from './CommonActions';
|
import * as CommonActions from './CommonActions';
|
||||||
import NavigationContext from './NavigationContext';
|
import NavigationContext from './NavigationContext';
|
||||||
import ResetRootContext from './ResetRootContext';
|
|
||||||
import { NavigationStateContext } from './NavigationContainer';
|
import { NavigationStateContext } from './NavigationContainer';
|
||||||
import { NavigationEventEmitter } from './useEventEmitter';
|
import { NavigationEventEmitter } from './useEventEmitter';
|
||||||
import {
|
import {
|
||||||
@@ -37,7 +36,6 @@ export default function useNavigationHelpers<
|
|||||||
Action extends NavigationAction,
|
Action extends NavigationAction,
|
||||||
EventMap extends Record<string, any>
|
EventMap extends Record<string, any>
|
||||||
>({ onAction, getState, emitter, router }: Options<State, Action>) {
|
>({ onAction, getState, emitter, router }: Options<State, Action>) {
|
||||||
const resetRoot = React.useContext(ResetRootContext);
|
|
||||||
const parentNavigationHelpers = React.useContext(NavigationContext);
|
const parentNavigationHelpers = React.useContext(NavigationContext);
|
||||||
const { performTransaction } = React.useContext(NavigationStateContext);
|
const { performTransaction } = React.useContext(NavigationStateContext);
|
||||||
|
|
||||||
@@ -76,7 +74,6 @@ export default function useNavigationHelpers<
|
|||||||
return {
|
return {
|
||||||
...parentNavigationHelpers,
|
...parentNavigationHelpers,
|
||||||
...helpers,
|
...helpers,
|
||||||
resetRoot,
|
|
||||||
dispatch,
|
dispatch,
|
||||||
emit: emitter.emit,
|
emit: emitter.emit,
|
||||||
isFocused: parentNavigationHelpers
|
isFocused: parentNavigationHelpers
|
||||||
@@ -100,7 +97,6 @@ export default function useNavigationHelpers<
|
|||||||
router,
|
router,
|
||||||
getState,
|
getState,
|
||||||
parentNavigationHelpers,
|
parentNavigationHelpers,
|
||||||
resetRoot,
|
|
||||||
emitter.emit,
|
emitter.emit,
|
||||||
performTransaction,
|
performTransaction,
|
||||||
onAction,
|
onAction,
|
||||||
|
|||||||
@@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.0.0-alpha.41](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/compare/@react-navigation/drawer@5.0.0-alpha.40...@react-navigation/drawer@5.0.0-alpha.41) (2020-01-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.0.0-alpha.40](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/compare/@react-navigation/drawer@5.0.0-alpha.39...@react-navigation/drawer@5.0.0-alpha.40) (2020-01-23)
|
# [5.0.0-alpha.40](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/compare/@react-navigation/drawer@5.0.0-alpha.39...@react-navigation/drawer@5.0.0-alpha.40) (2020-01-23)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"material",
|
"material",
|
||||||
"drawer"
|
"drawer"
|
||||||
],
|
],
|
||||||
"version": "5.0.0-alpha.40",
|
"version": "5.0.0-alpha.41",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer",
|
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/routers": "^5.0.0-alpha.26",
|
"@react-navigation/routers": "^5.0.0-alpha.27",
|
||||||
"color": "^3.1.2",
|
"color": "^3.1.2",
|
||||||
"react-native-iphone-x-helper": "^1.2.1"
|
"react-native-iphone-x-helper": "^1.2.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.0.0-alpha.36](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.35...@react-navigation/material-bottom-tabs@5.0.0-alpha.36) (2020-01-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.0.0-alpha.35](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.34...@react-navigation/material-bottom-tabs@5.0.0-alpha.35) (2020-01-23)
|
# [5.0.0-alpha.35](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.34...@react-navigation/material-bottom-tabs@5.0.0-alpha.35) (2020-01-23)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"material",
|
"material",
|
||||||
"tab"
|
"tab"
|
||||||
],
|
],
|
||||||
"version": "5.0.0-alpha.35",
|
"version": "5.0.0-alpha.36",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs",
|
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/routers": "^5.0.0-alpha.26"
|
"@react-navigation/routers": "^5.0.0-alpha.27"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.8.0",
|
"@react-native-community/bob": "^0.8.0",
|
||||||
|
|||||||
@@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.0.0-alpha.35](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.0.0-alpha.34...@react-navigation/material-top-tabs@5.0.0-alpha.35) (2020-01-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.0.0-alpha.34](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.0.0-alpha.33...@react-navigation/material-top-tabs@5.0.0-alpha.34) (2020-01-23)
|
# [5.0.0-alpha.34](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.0.0-alpha.33...@react-navigation/material-top-tabs@5.0.0-alpha.34) (2020-01-23)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"material",
|
"material",
|
||||||
"tab"
|
"tab"
|
||||||
],
|
],
|
||||||
"version": "5.0.0-alpha.34",
|
"version": "5.0.0-alpha.35",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs",
|
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/routers": "^5.0.0-alpha.26",
|
"@react-navigation/routers": "^5.0.0-alpha.27",
|
||||||
"color": "^3.1.2"
|
"color": "^3.1.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.0.0-alpha.29](https://github.com/react-navigation/navigation-ex/tree/master/packages/native-stack/compare/@react-navigation/native-stack@5.0.0-alpha.28...@react-navigation/native-stack@5.0.0-alpha.29) (2020-01-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/native-stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.0.0-alpha.28](https://github.com/react-navigation/navigation-ex/tree/master/packages/native-stack/compare/@react-navigation/native-stack@5.0.0-alpha.27...@react-navigation/native-stack@5.0.0-alpha.28) (2020-01-23)
|
# [5.0.0-alpha.28](https://github.com/react-navigation/navigation-ex/tree/master/packages/native-stack/compare/@react-navigation/native-stack@5.0.0-alpha.27...@react-navigation/native-stack@5.0.0-alpha.28) (2020-01-23)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"react-native",
|
"react-native",
|
||||||
"react-navigation"
|
"react-navigation"
|
||||||
],
|
],
|
||||||
"version": "5.0.0-alpha.28",
|
"version": "5.0.0-alpha.29",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/native-stack",
|
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/native-stack",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/routers": "^5.0.0-alpha.26"
|
"@react-navigation/routers": "^5.0.0-alpha.27"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.8.0",
|
"@react-native-community/bob": "^0.8.0",
|
||||||
|
|||||||
@@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.0.0-alpha.29](https://github.com/react-navigation/navigation-ex/tree/master/packages/native/compare/@react-navigation/native@5.0.0-alpha.28...@react-navigation/native@5.0.0-alpha.29) (2020-01-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/native
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.0.0-alpha.28](https://github.com/react-navigation/navigation-ex/tree/master/packages/native/compare/@react-navigation/native@5.0.0-alpha.27...@react-navigation/native@5.0.0-alpha.28) (2020-01-23)
|
# [5.0.0-alpha.28](https://github.com/react-navigation/navigation-ex/tree/master/packages/native/compare/@react-navigation/native@5.0.0-alpha.27...@react-navigation/native@5.0.0-alpha.28) (2020-01-23)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"ios",
|
"ios",
|
||||||
"android"
|
"android"
|
||||||
],
|
],
|
||||||
"version": "5.0.0-alpha.28",
|
"version": "5.0.0-alpha.29",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/native",
|
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/native",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/core": "^5.0.0-alpha.36"
|
"@react-navigation/core": "^5.0.0-alpha.37"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.8.0",
|
"@react-native-community/bob": "^0.8.0",
|
||||||
|
|||||||
@@ -3,6 +3,14 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.0.0-alpha.27](https://github.com/react-navigation/navigation-ex/tree/master/packages/routers/compare/@react-navigation/routers@5.0.0-alpha.26...@react-navigation/routers@5.0.0-alpha.27) (2020-01-24)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/routers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.0.0-alpha.26](https://github.com/react-navigation/navigation-ex/tree/master/packages/routers/compare/@react-navigation/routers@5.0.0-alpha.25...@react-navigation/routers@5.0.0-alpha.26) (2020-01-23)
|
# [5.0.0-alpha.26](https://github.com/react-navigation/navigation-ex/tree/master/packages/routers/compare/@react-navigation/routers@5.0.0-alpha.25...@react-navigation/routers@5.0.0-alpha.26) (2020-01-23)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -683,6 +683,145 @@ it('handles pop to top action', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('replaces focused screen with replace', () => {
|
||||||
|
const router = StackRouter({});
|
||||||
|
const options = {
|
||||||
|
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||||
|
routeParamList: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
router.getStateForAction(
|
||||||
|
{
|
||||||
|
stale: false,
|
||||||
|
type: 'stack',
|
||||||
|
key: 'root',
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{ key: 'foo', name: 'foo' },
|
||||||
|
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
|
||||||
|
{ key: 'baz', name: 'baz' },
|
||||||
|
],
|
||||||
|
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||||
|
},
|
||||||
|
StackActions.replace('qux', { answer: 42 }),
|
||||||
|
options
|
||||||
|
)
|
||||||
|
).toEqual({
|
||||||
|
stale: false,
|
||||||
|
type: 'stack',
|
||||||
|
key: 'root',
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{ key: 'foo', name: 'foo' },
|
||||||
|
{ key: 'qux-test', name: 'qux', params: { answer: 42 } },
|
||||||
|
{ key: 'baz', name: 'baz' },
|
||||||
|
],
|
||||||
|
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('replaces source screen with replace', () => {
|
||||||
|
const router = StackRouter({});
|
||||||
|
const options = {
|
||||||
|
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||||
|
routeParamList: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
router.getStateForAction(
|
||||||
|
{
|
||||||
|
stale: false,
|
||||||
|
type: 'stack',
|
||||||
|
key: 'root',
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{ key: 'foo', name: 'foo' },
|
||||||
|
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
|
||||||
|
{ key: 'baz', name: 'baz' },
|
||||||
|
],
|
||||||
|
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...StackActions.replace('qux', { answer: 42 }),
|
||||||
|
source: 'baz',
|
||||||
|
},
|
||||||
|
options
|
||||||
|
)
|
||||||
|
).toEqual({
|
||||||
|
stale: false,
|
||||||
|
type: 'stack',
|
||||||
|
key: 'root',
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{ key: 'foo', name: 'foo' },
|
||||||
|
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
|
||||||
|
{ key: 'qux-test', name: 'qux', params: { answer: 42 } },
|
||||||
|
],
|
||||||
|
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("doesn't handle replace if source key isn't present", () => {
|
||||||
|
const router = StackRouter({});
|
||||||
|
const options = {
|
||||||
|
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||||
|
routeParamList: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
router.getStateForAction(
|
||||||
|
{
|
||||||
|
stale: false,
|
||||||
|
type: 'stack',
|
||||||
|
key: 'root',
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{ key: 'foo', name: 'foo' },
|
||||||
|
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
|
||||||
|
{ key: 'baz', name: 'baz' },
|
||||||
|
],
|
||||||
|
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...StackActions.replace('qux', { answer: 42 }),
|
||||||
|
source: 'magic',
|
||||||
|
},
|
||||||
|
options
|
||||||
|
)
|
||||||
|
).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("doesn't handle replace if screen to replace with isn't present", () => {
|
||||||
|
const router = StackRouter({});
|
||||||
|
const options = {
|
||||||
|
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||||
|
routeParamList: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
router.getStateForAction(
|
||||||
|
{
|
||||||
|
stale: false,
|
||||||
|
type: 'stack',
|
||||||
|
key: 'root',
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{ key: 'foo', name: 'foo' },
|
||||||
|
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
|
||||||
|
{ key: 'baz', name: 'baz' },
|
||||||
|
],
|
||||||
|
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...StackActions.replace('nonexistent', { answer: 42 }),
|
||||||
|
source: 'magic',
|
||||||
|
},
|
||||||
|
options
|
||||||
|
)
|
||||||
|
).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
it('handles push action', () => {
|
it('handles push action', () => {
|
||||||
const router = StackRouter({});
|
const router = StackRouter({});
|
||||||
const options = {
|
const options = {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"react-native",
|
"react-native",
|
||||||
"react-navigation"
|
"react-navigation"
|
||||||
],
|
],
|
||||||
"version": "5.0.0-alpha.26",
|
"version": "5.0.0-alpha.27",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/routers",
|
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/routers",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/core": "^5.0.0-alpha.36",
|
"@react-navigation/core": "^5.0.0-alpha.37",
|
||||||
"shortid": "^2.2.15"
|
"shortid": "^2.2.15"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ import {
|
|||||||
} from '@react-navigation/core';
|
} from '@react-navigation/core';
|
||||||
|
|
||||||
export type StackActionType =
|
export type StackActionType =
|
||||||
|
| {
|
||||||
|
type: 'REPLACE';
|
||||||
|
payload: { name: string; key?: string | undefined; params?: object };
|
||||||
|
source?: string;
|
||||||
|
target?: string;
|
||||||
|
}
|
||||||
| {
|
| {
|
||||||
type: 'PUSH';
|
type: 'PUSH';
|
||||||
payload: { name: string; key?: string | undefined; params?: object };
|
payload: { name: string; key?: string | undefined; params?: object };
|
||||||
@@ -37,6 +43,9 @@ export type StackNavigationState = NavigationState & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const StackActions = {
|
export const StackActions = {
|
||||||
|
replace(name: string, params?: object): StackActionType {
|
||||||
|
return { type: 'REPLACE', payload: { name, params } };
|
||||||
|
},
|
||||||
push(name: string, params?: object): StackActionType {
|
push(name: string, params?: object): StackActionType {
|
||||||
return { type: 'PUSH', payload: { name, params } };
|
return { type: 'PUSH', payload: { name, params } };
|
||||||
},
|
},
|
||||||
@@ -169,6 +178,35 @@ export default function StackRouter(options: StackRouterOptions) {
|
|||||||
const { routeParamList } = options;
|
const { routeParamList } = options;
|
||||||
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case 'REPLACE': {
|
||||||
|
const index = action.source
|
||||||
|
? state.routes.findIndex(r => r.key === action.source)
|
||||||
|
: state.index;
|
||||||
|
|
||||||
|
if (index === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { name, key, params } = action.payload;
|
||||||
|
|
||||||
|
if (!state.routeNames.includes(name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
routes: state.routes.map((route, i) =>
|
||||||
|
i === index
|
||||||
|
? {
|
||||||
|
key: key !== undefined ? key : `${name}-${shortid()}`,
|
||||||
|
name,
|
||||||
|
params,
|
||||||
|
}
|
||||||
|
: route
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case 'PUSH':
|
case 'PUSH':
|
||||||
if (state.routeNames.includes(action.payload.name)) {
|
if (state.routeNames.includes(action.payload.name)) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -3,6 +3,17 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.0.0-alpha.63](https://github.com/react-navigation/navigation-ex/tree/master/packages/stack/compare/@react-navigation/stack@5.0.0-alpha.62...@react-navigation/stack@5.0.0-alpha.63) (2020-01-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* pass correct previous scene to header with headerMode: screen ([16c64e7](https://github.com/react-navigation/navigation-ex/tree/master/packages/stack/commit/16c64e729896a157b2b5bb96d6e3eead827626a0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.0.0-alpha.62](https://github.com/react-navigation/navigation-ex/tree/master/packages/stack/compare/@react-navigation/stack@5.0.0-alpha.61...@react-navigation/stack@5.0.0-alpha.62) (2020-01-23)
|
# [5.0.0-alpha.62](https://github.com/react-navigation/navigation-ex/tree/master/packages/stack/compare/@react-navigation/stack@5.0.0-alpha.61...@react-navigation/stack@5.0.0-alpha.62) (2020-01-23)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"android",
|
"android",
|
||||||
"stack"
|
"stack"
|
||||||
],
|
],
|
||||||
"version": "5.0.0-alpha.62",
|
"version": "5.0.0-alpha.63",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/stack",
|
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/stack",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/routers": "^5.0.0-alpha.26",
|
"@react-navigation/routers": "^5.0.0-alpha.27",
|
||||||
"color": "^3.1.2",
|
"color": "^3.1.2",
|
||||||
"react-native-iphone-x-helper": "^1.2.1"
|
"react-native-iphone-x-helper": "^1.2.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -533,6 +533,23 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
left: safeAreaInsetLeft = insets.left,
|
left: safeAreaInsetLeft = insets.left,
|
||||||
} = safeAreaInsets || {};
|
} = safeAreaInsets || {};
|
||||||
|
|
||||||
|
const previousRoute = getPreviousRoute({ route: scene.route });
|
||||||
|
|
||||||
|
let previousScene = scenes[index - 1];
|
||||||
|
|
||||||
|
if (previousRoute) {
|
||||||
|
// The previous scene will be shortly before the current scene in the array
|
||||||
|
// So loop back from current index to avoid looping over the full array
|
||||||
|
for (let j = index - 1; j >= 0; j--) {
|
||||||
|
const s = scenes[j];
|
||||||
|
|
||||||
|
if (s && s.route.key === previousRoute.key) {
|
||||||
|
previousScene = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MaybeScreen
|
<MaybeScreen
|
||||||
key={route.key}
|
key={route.key}
|
||||||
@@ -549,7 +566,7 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
layout={layout}
|
layout={layout}
|
||||||
gesture={gesture}
|
gesture={gesture}
|
||||||
scene={scene}
|
scene={scene}
|
||||||
previousScene={scenes[index - 1]}
|
previousScene={previousScene}
|
||||||
state={state}
|
state={state}
|
||||||
safeAreaInsetTop={safeAreaInsetTop}
|
safeAreaInsetTop={safeAreaInsetTop}
|
||||||
safeAreaInsetRight={safeAreaInsetRight}
|
safeAreaInsetRight={safeAreaInsetRight}
|
||||||
|
|||||||
@@ -244,6 +244,7 @@ class StackView extends React.Component<Props, State> {
|
|||||||
(!closingRouteKeys.includes(r.key) &&
|
(!closingRouteKeys.includes(r.key) &&
|
||||||
!replacingRouteKeys.includes(r.key))
|
!replacingRouteKeys.includes(r.key))
|
||||||
);
|
);
|
||||||
|
|
||||||
const index = routes.findIndex(r => r.key === route.key);
|
const index = routes.findIndex(r => r.key === route.key);
|
||||||
|
|
||||||
return routes[index - 1];
|
return routes[index - 1];
|
||||||
|
|||||||
@@ -3081,6 +3081,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.0.tgz#2a5fa918786d07d3725726f7f650527e1cfeaffd"
|
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.0.tgz#2a5fa918786d07d3725726f7f650527e1cfeaffd"
|
||||||
integrity sha512-c4zji5CjWv1tJxIZkz1oUtGcdOlsH3aza28Nqmm+uNDWBRHoMsjooBEN4czZp1V3iXPihE/VRUOBqg+4Xq0W4g==
|
integrity sha512-c4zji5CjWv1tJxIZkz1oUtGcdOlsH3aza28Nqmm+uNDWBRHoMsjooBEN4czZp1V3iXPihE/VRUOBqg+4Xq0W4g==
|
||||||
|
|
||||||
|
"@types/react-is@^16.7.1":
|
||||||
|
version "16.7.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-16.7.1.tgz#d3f1c68c358c00ce116b55ef5410cf486dd08539"
|
||||||
|
integrity sha512-dMLFD2cCsxtDgMkTydQCM0PxDq8vwc6uN5M/jRktDfYvH3nQj6pjC9OrCXS2lKlYoYTNJorI/dI8x9dpLshexQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react-native-vector-icons@^6.4.5":
|
"@types/react-native-vector-icons@^6.4.5":
|
||||||
version "6.4.5"
|
version "6.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.5.tgz#74cbfc564bd8435e43ad6728572a0e5b49c335d1"
|
resolved "https://registry.yarnpkg.com/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.5.tgz#74cbfc564bd8435e43ad6728572a0e5b49c335d1"
|
||||||
@@ -13535,7 +13542,7 @@ react-error-overlay@^6.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.4.tgz#0d165d6d27488e660bc08e57bdabaad741366f7a"
|
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.4.tgz#0d165d6d27488e660bc08e57bdabaad741366f7a"
|
||||||
integrity sha512-ueZzLmHltszTshDMwyfELDq8zOA803wQ1ZuzCccXa1m57k1PxSHfflPD5W9YIiTXLs0JTLzoj6o1LuM5N6zzNA==
|
integrity sha512-ueZzLmHltszTshDMwyfELDq8zOA803wQ1ZuzCccXa1m57k1PxSHfflPD5W9YIiTXLs0JTLzoj6o1LuM5N6zzNA==
|
||||||
|
|
||||||
react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
|
react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
|
||||||
version "16.12.0"
|
version "16.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c"
|
||||||
integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==
|
integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==
|
||||||
|
|||||||
Reference in New Issue
Block a user