Compare commits
89 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76de32f441 | ||
|
|
4ee19bcdb9 | ||
|
|
06cc8b9142 | ||
|
|
2f66556b10 | ||
|
|
f39813626a | ||
|
|
089390ce87 | ||
|
|
d09c9ae643 | ||
|
|
8920da68a7 | ||
|
|
98a9487cda | ||
|
|
ff502820c7 | ||
|
|
30e510d123 | ||
|
|
114a5dc888 | ||
|
|
b4bbf9b0c3 | ||
|
|
98f0de088f | ||
|
|
2537145d81 | ||
|
|
6af8400421 | ||
|
|
d83d3de697 | ||
|
|
88a560aacb | ||
|
|
e0f28a432d | ||
|
|
438692d661 | ||
|
|
849d952703 | ||
|
|
17045f5b6d | ||
|
|
d16c20cd39 | ||
|
|
9563a27284 | ||
|
|
f57a91c417 | ||
|
|
8e8b7eef36 | ||
|
|
44020452fb | ||
|
|
ceaf18edd6 | ||
|
|
faaf855717 | ||
|
|
196cce0803 | ||
|
|
a022860317 | ||
|
|
167d58ce27 | ||
|
|
798a905d0a | ||
|
|
aa6313c0e9 | ||
|
|
2563924f53 | ||
|
|
55ec815247 | ||
|
|
c7a79a62fa | ||
|
|
5c6e85cec8 | ||
|
|
3f853d458f | ||
|
|
06b3e6bda7 | ||
|
|
3c840bbae3 | ||
|
|
d4ad9d48f9 | ||
|
|
a0e9784d98 | ||
|
|
eff0c0464f | ||
|
|
fe9ba2bf71 | ||
|
|
b0a3756d18 | ||
|
|
4e0ebb05f9 | ||
|
|
bf0b408238 | ||
|
|
1b2983eaa9 | ||
|
|
b38ee1c162 | ||
|
|
fdc24d2523 | ||
|
|
6a8242c31a | ||
|
|
3ad2e6ebcf | ||
|
|
5c8d183d68 | ||
|
|
f1b976b68c | ||
|
|
6b75cbaaa6 | ||
|
|
c951027ebb | ||
|
|
cdbf1e97f9 | ||
|
|
56a2ee99f9 | ||
|
|
a9d4813b47 | ||
|
|
74c3377b63 | ||
|
|
8c1acc33c6 | ||
|
|
d72a96d1ef | ||
|
|
f9e8c7e80f | ||
|
|
9245c79990 | ||
|
|
ea4c753d0a | ||
|
|
01196d7b48 | ||
|
|
b4a5c3c35e | ||
|
|
f302416631 | ||
|
|
dead4e826a | ||
|
|
d5b4210eb2 | ||
|
|
38336b0290 | ||
|
|
fc37e93b5b | ||
|
|
093858b68b | ||
|
|
3703ab6353 | ||
|
|
7990cf2575 | ||
|
|
fb9d1837a1 | ||
|
|
935c588000 | ||
|
|
7d526e5881 | ||
|
|
2adccdef1d | ||
|
|
dee25057e8 | ||
|
|
9e1104c31f | ||
|
|
469ec31cc5 | ||
|
|
d26b77f9c9 | ||
|
|
1bbd6ac422 | ||
|
|
1a8281d37d | ||
|
|
b0a0857b0a | ||
|
|
4e07461526 | ||
|
|
f18231541b |
@@ -42,6 +42,13 @@ jobs:
|
||||
- store_artifacts:
|
||||
path: coverage
|
||||
destination: coverage
|
||||
build-packages:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/project
|
||||
- run: |
|
||||
yarn lerna run prepare
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
@@ -54,3 +61,6 @@ workflows:
|
||||
- unit-test:
|
||||
requires:
|
||||
- install-dependencies
|
||||
- build-packages:
|
||||
requires:
|
||||
- install-dependencies
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"@react-navigation/core",
|
||||
"@react-navigation/native",
|
||||
"@react-navigation/routers",
|
||||
"@react-navigation/compat",
|
||||
"@react-navigation/stack",
|
||||
"@react-navigation/drawer",
|
||||
"@react-navigation/bottom-tabs",
|
||||
|
||||
40
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
## The issue tracker is reserved for bug reports only.
|
||||
|
||||
If you have a question, feature request, or an idea for improving the library or its related tools, please try one of the following resources:
|
||||
|
||||
- [Read the documentation](https://reactnavigation.org/)
|
||||
- [Post an issue to the website repository if you'd like to see a documentation change](http://github.com/react-navigation/website)
|
||||
- [Post a feature request to Canny](https://react-navigation.canny.io/feature-requests)
|
||||
- [Write a RFC if you have ideas for how to implement a feature request](https://github.com/react-navigation/rfcs)
|
||||
- [Get help on Discord chat (#react-navigation on Reactiflux)](https://discord.gg/4xEK3nD) or [on StackOverflow](https://stackoverflow.com/questions/tagged/react-navigation)
|
||||
- Search for your issue - it may have already been answered or even fixed in the development branch. However, if you find that an old, closed issue still persists in the latest version, you should open a new issue.
|
||||
|
||||
Bugs with react-navigation must be reproducible *without any external libraries that operate on it*. This means that if you are attempting to use Redux or MobX with it and you think you have found a bug, you must be able to reproduce it without Redux or MobX in this report.
|
||||
|
||||
---
|
||||
|
||||
### Current Behavior
|
||||
|
||||
- What code are you running and what is happening?
|
||||
- Include a screenshot if it makes sense.
|
||||
|
||||
### Expected Behavior
|
||||
|
||||
- What do you expect should be happening?
|
||||
- Include a screenshot if it makes sense.
|
||||
|
||||
### How to reproduce
|
||||
|
||||
- You must provide a way to reproduce the problem. If you are having an issue with your machine or build tools, the issue belongs on another repository as that is outside of the scope of React Navigation.
|
||||
- Either re-create the bug on [Snack](https://snack.expo.io) or link to a GitHub repository with code that reproduces the bug.
|
||||
- Explain how to run the example app and any steps that we need to take to reproduce the issue from the example app.
|
||||
|
||||
### Your Environment
|
||||
|
||||
| software | version
|
||||
| ---------------- | -------
|
||||
| react-navigation |
|
||||
| react-native |
|
||||
| expo |
|
||||
| node |
|
||||
| npm or yarn |
|
||||
17
.github/PULL_REQUEST.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
Please provide enough information so that others can review your pull request:
|
||||
|
||||
## Motivation
|
||||
|
||||
Explain the **motivation** for making this change. What existing problem does the pull request solve?
|
||||
|
||||
## Test plan
|
||||
|
||||
Demonstrate the code is solid. Example: the exact commands you ran and their output, screenshots / videos if the pull request changes UI.
|
||||
|
||||
Make sure you test on both platforms if your change affects both platforms.
|
||||
|
||||
The code must pass tests.
|
||||
|
||||
## Code formatting
|
||||
|
||||
Look around. Match the style of the rest of the codebase. Run `yarn lint --fix` before committing.
|
||||
7
.gitignore
vendored
@@ -3,17 +3,22 @@
|
||||
.vscode
|
||||
.idea
|
||||
.expo
|
||||
.gradle
|
||||
|
||||
/coverage/
|
||||
/types/
|
||||
/dist/
|
||||
/lib/
|
||||
/packages/**/lib/
|
||||
|
||||
node_modules/
|
||||
web-build/
|
||||
web-report/
|
||||
|
||||
xcuserdata
|
||||
generated
|
||||
lib
|
||||
build
|
||||
|
||||
npm-debug.*
|
||||
|
||||
*.log
|
||||
|
||||
68
README.md
@@ -1,5 +1,9 @@
|
||||
# Rethinking Navigation
|
||||
|
||||
[![Build Status][build-badge]][build]
|
||||
[![Code Coverage][coverage-badge]][coverage]
|
||||
[![MIT License][license-badge]][license]
|
||||
|
||||
An exploration of a component-first API for React Navigation for building more dynamic navigation solutions.
|
||||
|
||||
## Considerations
|
||||
@@ -31,6 +35,8 @@ Navigators bundle a router and a view which takes the navigation state and decid
|
||||
A simple navigator could look like this:
|
||||
|
||||
```js
|
||||
import { createNavigator } from '@react-navigation/core';
|
||||
|
||||
function StackNavigator({ initialRouteName, children, ...rest }) {
|
||||
// The `navigation` object contains the navigation state and some helpers (e.g. push, pop)
|
||||
// The `descriptors` object contains the screen options and a helper for rendering a screen
|
||||
@@ -127,8 +133,11 @@ It's also possible to disable bubbling of actions when dispatching them by addin
|
||||
## Basic usage
|
||||
|
||||
```js
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||
|
||||
const Stack = createStackNavigator();
|
||||
const Tab = createTabNavigator();
|
||||
const Tab = createBottomTabNavigator();
|
||||
|
||||
function App() {
|
||||
return (
|
||||
@@ -210,6 +219,8 @@ function Profile({ navigation }) {
|
||||
}
|
||||
```
|
||||
|
||||
The `navigation.addListener` method returns a function to remove the listener which can be returned as the cleanup function in an effect.
|
||||
|
||||
Navigators can also emit custom events using the `emit` method in the `navigation` object passed:
|
||||
|
||||
```js
|
||||
@@ -245,6 +256,8 @@ Sometimes we want to run side-effects when a screen is focused. A side effect ma
|
||||
To make this easier, the library exports a `useFocusEffect` hook:
|
||||
|
||||
```js
|
||||
import { useFocusEffect } from '@react-navigation/core';
|
||||
|
||||
function Profile({ userId }) {
|
||||
const [user, setUser] = React.useState(null);
|
||||
|
||||
@@ -272,6 +285,10 @@ The `useFocusEffect` is analogous to React's `useEffect` hook. The only differen
|
||||
We might want to render different content based on the current focus state of the screen. The library exports a `useIsFocused` hook to make this easier:
|
||||
|
||||
```js
|
||||
import { useIsFocused } from '@react-navigation/core';
|
||||
|
||||
// ...
|
||||
|
||||
const isFocused = useIsFocused();
|
||||
```
|
||||
|
||||
@@ -284,6 +301,10 @@ For proper UX in React Native, we need to respect platform behavior such as the
|
||||
When the back button on the device is pressed, we also want to navigate back in the focused navigator. The library exports a `useBackButton` hook to handle this:
|
||||
|
||||
```js
|
||||
import { useBackButton } from '@react-navigation/native';
|
||||
|
||||
// ...
|
||||
|
||||
const ref = React.useRef();
|
||||
|
||||
useBackButton(ref);
|
||||
@@ -291,6 +312,24 @@ useBackButton(ref);
|
||||
return <NavigationContainer ref={ref}>{/* content */}</NavigationContainer>;
|
||||
```
|
||||
|
||||
### Scroll to top on tab button press
|
||||
|
||||
When there's a scroll view in a tab and the user taps on the already focused tab bar again, we might want to scroll to top in our scroll view. The library exports a `useScrollToTop` hook to handle this:
|
||||
|
||||
```js
|
||||
import { useScrollToTop } from '@react-navigation/native';
|
||||
|
||||
// ...
|
||||
|
||||
const ref = React.useRef();
|
||||
|
||||
useScrollToTop(ref);
|
||||
|
||||
return <ScrollView ref={ref}>{/* content */}</ScrollView>;
|
||||
```
|
||||
|
||||
The hook can accept a ref object to any view that has a `scrollTo` method.
|
||||
|
||||
### Deep-link integration
|
||||
|
||||
To handle incoming links, we need to handle 2 scenarios:
|
||||
@@ -325,6 +364,10 @@ For example, the path `/rooms/chat?user=jane` will be translated to a state obje
|
||||
The `useLinking` hooks makes it easier to handle incoming links:
|
||||
|
||||
```js
|
||||
import { useLinking } from '@react-navigation/native';
|
||||
|
||||
// ...
|
||||
|
||||
const ref = React.useRef();
|
||||
|
||||
const { getInitialState } = useLinking(ref, {
|
||||
@@ -451,10 +494,10 @@ Unfortunately it's not possible to verify that the type of children elements are
|
||||
|
||||
## Contributing
|
||||
|
||||
The project uses a monorepo structure for the packages managed by [yarn workspaces](https://yarnpkg.com/lang/en/docs/workspaces/) and [lerna](https://lerna.js.org). To get started with the project, run `lerna bootstrap` to install the required dependencies for each package:
|
||||
The project uses a monorepo structure for the packages managed by [yarn workspaces](https://yarnpkg.com/lang/en/docs/workspaces/) and [lerna](https://lerna.js.org). To get started with the project, run `yarn` in the root directory to install the required dependencies for each package:
|
||||
|
||||
```sh
|
||||
lerna bootstrap
|
||||
yarn
|
||||
```
|
||||
|
||||
While developing, you can run the [example app](/example/) with [Expo](https://expo.io/) to test your changes:
|
||||
@@ -476,13 +519,7 @@ To fix formatting errors, run the following:
|
||||
yarn lint --fix
|
||||
```
|
||||
|
||||
Remember to add tests for your change if possible. To run tests, first build all the files:
|
||||
|
||||
```sh
|
||||
lerna run prepare
|
||||
```
|
||||
|
||||
Then run the tests:
|
||||
Remember to add tests for your change if possible. Run the tests by:
|
||||
|
||||
```sh
|
||||
yarn test
|
||||
@@ -493,7 +530,16 @@ yarn test
|
||||
To publish a new version, first we need to export a `GH_TOKEN` environment variable as mentioned [here](https://github.com/lerna/lerna/tree/master/commands/version#--create-release-type). Then run:
|
||||
|
||||
```sh
|
||||
lerna publish
|
||||
yarn lerna publish
|
||||
```
|
||||
|
||||
This will automatically bump the version and publish the packages. It'll also publish the changelogs on GitHub for each package.
|
||||
|
||||
<!-- badges -->
|
||||
|
||||
[build-badge]: https://img.shields.io/circleci/project/github/react-navigation/navigation-ex/master.svg?style=flat-square
|
||||
[build]: https://circleci.com/gh/react-navigation/navigation-ex
|
||||
[coverage-badge]: https://img.shields.io/codecov/c/github/react-navigation/navigation-ex.svg?style=flat-square
|
||||
[coverage]: https://codecov.io/github/react-navigation/navigation-ex
|
||||
[license-badge]: https://img.shields.io/npm/l/@react-navigation/core.svg?style=flat-square
|
||||
[license]: https://opensource.org/licenses/MIT
|
||||
|
||||
20
package.json
@@ -14,7 +14,7 @@
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/satya164/react-navigation.git"
|
||||
},
|
||||
"author": "Satyajit Sahoo <satyajit.happy@gmail.com> (https://github.com/satya164/)",
|
||||
"author": "Satyajit Sahoo <satyajit.happy@gmail.com> (https://github.com/satya164/), Michał Osadnik <micosa97@gmail.com> (https://github.com/osdnk/)",
|
||||
"scripts": {
|
||||
"lint": "eslint --ext '.js,.ts,.tsx' .",
|
||||
"typescript": "tsc --noEmit",
|
||||
@@ -31,7 +31,7 @@
|
||||
"@types/jest": "^24.0.13",
|
||||
"codecov": "^3.5.0",
|
||||
"commitlint": "^8.0.0",
|
||||
"core-js": "^3.1.4",
|
||||
"core-js": "^3.2.1",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-satya164": "^2.4.1",
|
||||
"husky": "^2.4.0",
|
||||
@@ -42,8 +42,8 @@
|
||||
},
|
||||
"resolutions": {
|
||||
"react": "16.8.3",
|
||||
"react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz",
|
||||
"react-native-safe-area-view": "0.14.6"
|
||||
"react-native": "0.59.10",
|
||||
"react-native-safe-area-view": "0.14.7"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
@@ -59,7 +59,15 @@
|
||||
},
|
||||
"setupFiles": [
|
||||
"<rootDir>/jest/setup.js"
|
||||
]
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"@react-navigation/([^/]+)": "<rootDir>/packages/$1/src"
|
||||
}
|
||||
},
|
||||
"name": "react-navigation"
|
||||
"prettier": {
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,78 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.9](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.8...@react-navigation/bottom-tabs@5.0.0-alpha.9) (2019-09-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* provide navigation prop in header ([30e510d](https://github.com/react-navigation/navigation-ex/commit/30e510d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.8](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.7...@react-navigation/bottom-tabs@5.0.0-alpha.8) (2019-09-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* make example run as bare react-native project as well ([#85](https://github.com/react-navigation/navigation-ex/issues/85)) ([d16c20c](https://github.com/react-navigation/navigation-ex/commit/d16c20c))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.7](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.6...@react-navigation/bottom-tabs@5.0.0-alpha.7) (2019-08-31)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.6](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.5...@react-navigation/bottom-tabs@5.0.0-alpha.6) (2019-08-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow making params optional. fixes [#80](https://github.com/react-navigation/navigation-ex/issues/80) ([a9d4813](https://github.com/react-navigation/navigation-ex/commit/a9d4813))
|
||||
* types path ([#75](https://github.com/react-navigation/navigation-ex/issues/75)) ([b4a5c3c](https://github.com/react-navigation/navigation-ex/commit/b4a5c3c))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.5](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.4...@react-navigation/bottom-tabs@5.0.0-alpha.5) (2019-08-28)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.4](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.3...@react-navigation/bottom-tabs@5.0.0-alpha.4) (2019-08-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add hook to scroll to top on tab press ([9e1104c](https://github.com/react-navigation/navigation-ex/commit/9e1104c))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.3](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.2...@react-navigation/bottom-tabs@5.0.0-alpha.3) (2019-08-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix path to typescript definitions ([f182315](https://github.com/react-navigation/navigation-ex/commit/f182315))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.2](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.1...@react-navigation/bottom-tabs@5.0.0-alpha.2) (2019-08-22)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"android",
|
||||
"tab"
|
||||
],
|
||||
"version": "5.0.0-alpha.2",
|
||||
"version": "5.0.0-alpha.9",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -20,7 +20,7 @@
|
||||
"main": "lib/commonjs/index.js",
|
||||
"react-native": "src/index.tsx",
|
||||
"module": "lib/module/index.js",
|
||||
"types": "lib/typescript/src/index.d.ts",
|
||||
"types": "lib/typescript/bottom-tabs/src/index.d.ts",
|
||||
"files": [
|
||||
"src",
|
||||
"lib"
|
||||
@@ -33,7 +33,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.2",
|
||||
"@react-navigation/routers": "^5.0.0-alpha.7",
|
||||
"react-native-safe-area-view": "^0.14.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -42,7 +42,7 @@
|
||||
"@types/react-native": "^0.60.2",
|
||||
"del-cli": "^2.0.0",
|
||||
"react": "16.8.3",
|
||||
"react-native": "^0.59.8",
|
||||
"react-native": "0.59.10",
|
||||
"typescript": "^3.5.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -13,6 +13,7 @@ import BottomTabView from '../views/BottomTabView';
|
||||
import {
|
||||
BottomTabNavigationConfig,
|
||||
BottomTabNavigationOptions,
|
||||
BottomTabNavigationEventMap,
|
||||
} from '../types';
|
||||
|
||||
type Props = DefaultNavigatorOptions<BottomTabNavigationOptions> &
|
||||
@@ -28,8 +29,9 @@ function BottomTabNavigator({
|
||||
}: Props) {
|
||||
const { state, descriptors, navigation } = useNavigationBuilder<
|
||||
TabNavigationState,
|
||||
TabRouterOptions,
|
||||
BottomTabNavigationOptions,
|
||||
TabRouterOptions
|
||||
BottomTabNavigationEventMap
|
||||
>(TabRouter, {
|
||||
initialRouteName,
|
||||
backBehavior,
|
||||
|
||||
@@ -17,10 +17,6 @@ import {
|
||||
import { TabNavigationState } from '@react-navigation/routers';
|
||||
|
||||
export type BottomTabNavigationEventMap = {
|
||||
/**
|
||||
* Event which fires on tapping on the tab for an already focused screen.
|
||||
*/
|
||||
refocus: undefined;
|
||||
/**
|
||||
* Event which fires on tapping on the tab in the tab bar.
|
||||
*/
|
||||
@@ -35,6 +31,11 @@ export type Orientation = 'horizontal' | 'vertical';
|
||||
|
||||
export type LabelPosition = 'beside-icon' | 'below-icon';
|
||||
|
||||
export type BottomTabNavigationHelpers = NavigationHelpers<
|
||||
ParamListBase,
|
||||
BottomTabNavigationEventMap
|
||||
>;
|
||||
|
||||
export type BottomTabNavigationProp<
|
||||
ParamList extends ParamListBase,
|
||||
RouteName extends keyof ParamList = string
|
||||
@@ -52,8 +53,8 @@ export type BottomTabNavigationProp<
|
||||
* @param [params] Params object for the route.
|
||||
*/
|
||||
jumpTo<RouteName extends Extract<keyof ParamList, string>>(
|
||||
...args: ParamList[RouteName] extends void
|
||||
? [RouteName]
|
||||
...args: ParamList[RouteName] extends (undefined | any)
|
||||
? [RouteName] | [RouteName, ParamList[RouteName]]
|
||||
: [RouteName, ParamList[RouteName]]
|
||||
): void;
|
||||
};
|
||||
@@ -198,6 +199,7 @@ export type BottomTabBarOptions = {
|
||||
|
||||
export type BottomTabBarProps = BottomTabBarOptions & {
|
||||
state: TabNavigationState;
|
||||
descriptors: BottomTabDescriptorMap;
|
||||
navigation: NavigationHelpers<ParamListBase>;
|
||||
onTabPress: (props: { route: Route<string> }) => void;
|
||||
onTabLongPress: (props: { route: Route<string> }) => void;
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
Dimensions,
|
||||
} from 'react-native';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Route, NavigationContext } from '@react-navigation/core';
|
||||
|
||||
import TabBarIcon from './TabBarIcon';
|
||||
import TouchableWithoutFeedbackWrapper from './TouchableWithoutFeedbackWrapper';
|
||||
@@ -261,6 +261,7 @@ export default class TabBarBottom extends React.Component<Props, State> {
|
||||
render() {
|
||||
const {
|
||||
state,
|
||||
descriptors,
|
||||
keyboardHidesTabBar,
|
||||
activeBackgroundColor,
|
||||
inactiveBackgroundColor,
|
||||
@@ -337,26 +338,30 @@ export default class TabBarBottom extends React.Component<Props, State> {
|
||||
getButtonComponent({ route }) || TouchableWithoutFeedbackWrapper;
|
||||
|
||||
return (
|
||||
<ButtonComponent
|
||||
<NavigationContext.Provider
|
||||
key={route.key}
|
||||
onPress={() => onTabPress({ route })}
|
||||
onLongPress={() => onTabLongPress({ route })}
|
||||
testID={testID}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
accessibilityRole={accessibilityRole}
|
||||
accessibilityStates={accessibilityStates}
|
||||
style={[
|
||||
styles.tab,
|
||||
{ backgroundColor },
|
||||
this.shouldUseHorizontalLabels()
|
||||
? styles.tabLandscape
|
||||
: styles.tabPortrait,
|
||||
tabStyle,
|
||||
]}
|
||||
value={descriptors[route.key].navigation}
|
||||
>
|
||||
{this.renderIcon(scene)}
|
||||
{this.renderLabel(scene)}
|
||||
</ButtonComponent>
|
||||
<ButtonComponent
|
||||
onPress={() => onTabPress({ route })}
|
||||
onLongPress={() => onTabLongPress({ route })}
|
||||
testID={testID}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
accessibilityRole={accessibilityRole}
|
||||
accessibilityStates={accessibilityStates}
|
||||
style={[
|
||||
styles.tab,
|
||||
{ backgroundColor },
|
||||
this.shouldUseHorizontalLabels()
|
||||
? styles.tabLandscape
|
||||
: styles.tabPortrait,
|
||||
tabStyle,
|
||||
]}
|
||||
>
|
||||
{this.renderIcon(scene)}
|
||||
{this.renderLabel(scene)}
|
||||
</ButtonComponent>
|
||||
</NavigationContext.Provider>
|
||||
);
|
||||
})}
|
||||
</SafeAreaView>
|
||||
|
||||
@@ -5,23 +5,22 @@ import {
|
||||
AccessibilityRole,
|
||||
AccessibilityStates,
|
||||
} from 'react-native';
|
||||
import {
|
||||
NavigationHelpers,
|
||||
ParamListBase,
|
||||
Route,
|
||||
BaseActions,
|
||||
} from '@react-navigation/core';
|
||||
import { Route, CommonActions } from '@react-navigation/core';
|
||||
import { TabNavigationState } from '@react-navigation/routers';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { ScreenContainer } from 'react-native-screens';
|
||||
|
||||
import BottomTabBar from './BottomTabBar';
|
||||
import { BottomTabNavigationConfig, BottomTabDescriptorMap } from '../types';
|
||||
import {
|
||||
BottomTabNavigationConfig,
|
||||
BottomTabDescriptorMap,
|
||||
BottomTabNavigationHelpers,
|
||||
} from '../types';
|
||||
import ResourceSavingScene from './ResourceSavingScene';
|
||||
|
||||
type Props = BottomTabNavigationConfig & {
|
||||
state: TabNavigationState;
|
||||
navigation: NavigationHelpers<ParamListBase>;
|
||||
navigation: BottomTabNavigationHelpers;
|
||||
descriptors: BottomTabDescriptorMap;
|
||||
};
|
||||
|
||||
@@ -139,14 +138,12 @@ export default class BottomTabView extends React.Component<Props, State> {
|
||||
target: route.key,
|
||||
});
|
||||
|
||||
if (state.routes[state.index].key === route.key) {
|
||||
navigation.emit({
|
||||
type: 'refocus',
|
||||
target: route.key,
|
||||
});
|
||||
} else if (!event.defaultPrevented) {
|
||||
if (
|
||||
state.routes[state.index].key !== route.key &&
|
||||
!event.defaultPrevented
|
||||
) {
|
||||
navigation.dispatch({
|
||||
...BaseActions.navigate(route.name),
|
||||
...CommonActions.navigate(route.name),
|
||||
target: state.key,
|
||||
});
|
||||
}
|
||||
@@ -180,6 +177,7 @@ export default class BottomTabView extends React.Component<Props, State> {
|
||||
<TabBarComponent
|
||||
{...tabBarOptions}
|
||||
state={state}
|
||||
descriptors={descriptors}
|
||||
navigation={navigation}
|
||||
onTabPress={this.handleTabPress}
|
||||
onTabLongPress={this.handleTabLongPress}
|
||||
|
||||
45
packages/compat/CHANGELOG.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.3](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/compat@5.0.0-alpha.2...@react-navigation/compat@5.0.0-alpha.3) (2019-09-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* throw when wrapping a compat navigatofor compat ([8920da6](https://github.com/react-navigation/navigation-ex/commit/8920da6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.2](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/compat@5.0.0-alpha.1...@react-navigation/compat@5.0.0-alpha.2) (2019-09-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* provide navigation prop in header ([30e510d](https://github.com/react-navigation/navigation-ex/commit/30e510d))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add createSwitchNavigator ([ff50282](https://github.com/react-navigation/navigation-ex/commit/ff50282))
|
||||
* add withNavigation and withNavigationFocus ([114a5dc](https://github.com/react-navigation/navigation-ex/commit/114a5dc))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 5.0.0-alpha.1 (2019-09-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix dispatching compat actions ([88a560a](https://github.com/react-navigation/navigation-ex/commit/88a560a))
|
||||
* support legacy goBack method ([d83d3de](https://github.com/react-navigation/navigation-ex/commit/d83d3de))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* compatibility layer ([e0f28a4](https://github.com/react-navigation/navigation-ex/commit/e0f28a4))
|
||||
28
packages/compat/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# `@react-navigation/compat`
|
||||
|
||||
Compatibility layer to write navigator definitions in static configuration format.
|
||||
|
||||
## Installation
|
||||
|
||||
Open a Terminal in your project's folder and run,
|
||||
|
||||
```sh
|
||||
yarn add @react-navigation/core @react-navigation/compat
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import { createCompatNavigatorFactory } from '@react-navigation/compat';
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
|
||||
const RootStack = createCompatNavigatorFactory(createStackNavigator)(
|
||||
{
|
||||
Home: { screen: HomeScreen },
|
||||
Profile: { screen: ProfileScreen },
|
||||
},
|
||||
{
|
||||
initialRouteName: 'Profile',
|
||||
}
|
||||
);
|
||||
```
|
||||
47
packages/compat/package.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "@react-navigation/compat",
|
||||
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
||||
"version": "5.0.0-alpha.3",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/react-navigation/navigation-ex.git",
|
||||
"directory": "packages/compat"
|
||||
},
|
||||
"main": "lib/commonjs/index.js",
|
||||
"react-native": "src/index.tsx",
|
||||
"module": "lib/module/index.js",
|
||||
"types": "lib/typescript/compat/src/index.d.ts",
|
||||
"files": [
|
||||
"src",
|
||||
"lib"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "bob build",
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^16.8.19",
|
||||
"react": "^16.8.3",
|
||||
"typescript": "^3.5.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.0",
|
||||
"react": "^16.8.3"
|
||||
},
|
||||
"@react-native-community/bob": {
|
||||
"source": "src",
|
||||
"output": "lib",
|
||||
"targets": [
|
||||
"commonjs",
|
||||
"module",
|
||||
"typescript"
|
||||
]
|
||||
}
|
||||
}
|
||||
30
packages/compat/src/CompatScreen.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
NavigationProp,
|
||||
ParamListBase,
|
||||
RouteProp,
|
||||
} from '@react-navigation/core';
|
||||
import ScreenPropsContext from './ScreenPropsContext';
|
||||
import createCompatNavigationProp from './createCompatNavigationProp';
|
||||
|
||||
type Props<ParamList extends ParamListBase> = {
|
||||
navigation: NavigationProp<ParamList>;
|
||||
route: RouteProp<ParamList, string>;
|
||||
component: React.ComponentType<any>;
|
||||
};
|
||||
|
||||
function ScreenComponent<ParamList extends ParamListBase>(
|
||||
props: Props<ParamList>
|
||||
) {
|
||||
const navigation = React.useMemo(
|
||||
() =>
|
||||
createCompatNavigationProp(props.navigation as any, props.route as any),
|
||||
[props.navigation, props.route]
|
||||
);
|
||||
|
||||
const screenProps = React.useContext(ScreenPropsContext);
|
||||
|
||||
return <props.component navigation={navigation} screenProps={screenProps} />;
|
||||
}
|
||||
|
||||
export default React.memo(ScreenComponent);
|
||||
13
packages/compat/src/DrawerActions.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { DrawerActions, DrawerActionType } from '@react-navigation/routers';
|
||||
|
||||
export function openDrawer(): DrawerActionType {
|
||||
return DrawerActions.openDrawer();
|
||||
}
|
||||
|
||||
export function closeDrawer(): DrawerActionType {
|
||||
return DrawerActions.closeDrawer();
|
||||
}
|
||||
|
||||
export function toggleDrawer(): DrawerActionType {
|
||||
return DrawerActions.toggleDrawer();
|
||||
}
|
||||
48
packages/compat/src/NavigationActions.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { CommonActions, NavigationState } from '@react-navigation/core';
|
||||
|
||||
export function navigate({
|
||||
routeName,
|
||||
params,
|
||||
key,
|
||||
action,
|
||||
}: {
|
||||
routeName: string;
|
||||
params?: object;
|
||||
key?: string;
|
||||
action?: never;
|
||||
}): CommonActions.Action {
|
||||
if (action !== undefined) {
|
||||
throw new Error(
|
||||
'Sub-actions are not supported for `navigate`. Remove the `action` key from the options.'
|
||||
);
|
||||
}
|
||||
|
||||
return CommonActions.navigate({
|
||||
name: routeName,
|
||||
key: key,
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
export function back(options?: { key?: null | string }) {
|
||||
return options && options.key != null
|
||||
? (state: NavigationState) => ({
|
||||
...CommonActions.goBack(),
|
||||
source: options.key,
|
||||
target: state.key,
|
||||
})
|
||||
: CommonActions.goBack();
|
||||
}
|
||||
|
||||
export function setParams({
|
||||
params,
|
||||
key,
|
||||
}: {
|
||||
params: object;
|
||||
key?: string;
|
||||
}): CommonActions.Action {
|
||||
return {
|
||||
...CommonActions.setParams(params),
|
||||
...(key !== undefined ? { source: key } : null),
|
||||
};
|
||||
}
|
||||
3
packages/compat/src/ScreenPropsContext.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export default React.createContext<unknown>(undefined);
|
||||
68
packages/compat/src/StackActions.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
import { CommonActions } from '@react-navigation/core';
|
||||
import { StackActions, StackActionType } from '@react-navigation/routers';
|
||||
|
||||
export function reset(): CommonActions.Action {
|
||||
throw new Error(
|
||||
'The legacy `reset` action is not supported. Use the new reset API by accessing the original navigation object at `navigation.original`.'
|
||||
);
|
||||
}
|
||||
|
||||
export function replace({
|
||||
routeName,
|
||||
params,
|
||||
key,
|
||||
newKey,
|
||||
action,
|
||||
}: {
|
||||
routeName: string;
|
||||
params?: object;
|
||||
key?: string;
|
||||
newKey?: string;
|
||||
action?: never;
|
||||
}): CommonActions.Action {
|
||||
if (action !== undefined) {
|
||||
throw new Error(
|
||||
'Sub-actions are not supported for `replace`. Remove the `action` key from the options.'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'REPLACE',
|
||||
payload: {
|
||||
name: routeName,
|
||||
key: newKey,
|
||||
params,
|
||||
},
|
||||
...(key !== undefined ? { source: key } : null),
|
||||
};
|
||||
}
|
||||
|
||||
export function push({
|
||||
routeName,
|
||||
params,
|
||||
action,
|
||||
}: {
|
||||
routeName: string;
|
||||
params?: object;
|
||||
action?: never;
|
||||
}): StackActionType {
|
||||
if (action !== undefined) {
|
||||
throw new Error(
|
||||
'Sub-actions are not supported for `push`. Remove the `action` key from the options.'
|
||||
);
|
||||
}
|
||||
|
||||
return StackActions.push(routeName, params);
|
||||
}
|
||||
|
||||
export function pop({ n = 1 }: { n: number }): StackActionType {
|
||||
return StackActions.pop(n);
|
||||
}
|
||||
|
||||
export function popToTop(): StackActionType {
|
||||
return StackActions.popToTop();
|
||||
}
|
||||
|
||||
export function dismiss(): CommonActions.Action {
|
||||
throw new Error('The legacy `dismiss` action is not supported.');
|
||||
}
|
||||
18
packages/compat/src/SwitchActions.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { TabActions, TabActionType } from '@react-navigation/routers';
|
||||
|
||||
export function jumpTo({
|
||||
routeName,
|
||||
key,
|
||||
}: {
|
||||
routeName: string;
|
||||
key?: string;
|
||||
}): TabActionType {
|
||||
if (key === undefined) {
|
||||
return TabActions.jumpTo(routeName);
|
||||
} else {
|
||||
return {
|
||||
...TabActions.jumpTo(routeName),
|
||||
target: key,
|
||||
};
|
||||
}
|
||||
}
|
||||
189
packages/compat/src/createCompatNavigationProp.tsx
Normal file
@@ -0,0 +1,189 @@
|
||||
import {
|
||||
NavigationState,
|
||||
PartialState,
|
||||
ParamListBase,
|
||||
NavigationProp,
|
||||
RouteProp,
|
||||
} from '@react-navigation/core';
|
||||
import * as helpers from './helpers';
|
||||
import { CompatNavigationProp } from './types';
|
||||
|
||||
type EventName = 'willFocus' | 'willBlur' | 'didFocus' | 'didBlur' | 'refocus';
|
||||
|
||||
const focusSubscriptions = new WeakMap<() => void, () => void>();
|
||||
const blurSubscriptions = new WeakMap<() => void, () => void>();
|
||||
const refocusSubscriptions = new WeakMap<() => void, () => void>();
|
||||
|
||||
export default function createCompatNavigationProp<
|
||||
NavigationPropType extends NavigationProp<ParamListBase>,
|
||||
ParamList extends ParamListBase = NavigationPropType extends NavigationProp<
|
||||
infer P
|
||||
>
|
||||
? P
|
||||
: ParamListBase
|
||||
>(
|
||||
navigation: NavigationPropType,
|
||||
state:
|
||||
| (RouteProp<ParamList, keyof ParamList> & {
|
||||
state?: NavigationState | PartialState<NavigationState>;
|
||||
})
|
||||
| NavigationState
|
||||
| PartialState<NavigationState>
|
||||
): CompatNavigationProp<NavigationPropType> {
|
||||
return {
|
||||
...navigation,
|
||||
...Object.entries(helpers).reduce<{
|
||||
[key: string]: (...args: any[]) => void;
|
||||
}>((acc, [name, method]: [string, Function]) => {
|
||||
if (name in navigation) {
|
||||
acc[name] = (...args: any[]) => navigation.dispatch(method(...args));
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {}),
|
||||
original: navigation,
|
||||
addListener(type: EventName, callback: () => void) {
|
||||
let unsubscribe: () => void;
|
||||
|
||||
switch (type) {
|
||||
case 'willFocus':
|
||||
unsubscribe = navigation.addListener('focus', callback);
|
||||
break;
|
||||
case 'willBlur':
|
||||
unsubscribe = navigation.addListener('blur', callback);
|
||||
break;
|
||||
case 'didFocus': {
|
||||
const listener = () => {
|
||||
if (navigation.isFocused()) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
unsubscribe = navigation.addListener('transitionEnd', listener);
|
||||
focusSubscriptions.set(callback, unsubscribe);
|
||||
break;
|
||||
}
|
||||
case 'didBlur': {
|
||||
const listener = () => {
|
||||
if (!navigation.isFocused()) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
unsubscribe = navigation.addListener('transitionEnd', listener);
|
||||
blurSubscriptions.set(callback, unsubscribe);
|
||||
break;
|
||||
}
|
||||
case 'refocus': {
|
||||
const listener = () => {
|
||||
if (navigation.isFocused()) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
unsubscribe = navigation.addListener('tabPress', listener);
|
||||
refocusSubscriptions.set(callback, unsubscribe);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// @ts-ignore
|
||||
unsubscribe = navigation.addListener(type, callback);
|
||||
}
|
||||
|
||||
const subscription = () => unsubscribe();
|
||||
|
||||
subscription.remove = unsubscribe;
|
||||
|
||||
return subscription;
|
||||
},
|
||||
removeListener(type: EventName, callback: () => void) {
|
||||
switch (type) {
|
||||
case 'willFocus':
|
||||
navigation.removeListener('focus', callback);
|
||||
break;
|
||||
case 'willBlur':
|
||||
navigation.removeListener('blur', callback);
|
||||
break;
|
||||
case 'didFocus': {
|
||||
const unsubscribe = focusSubscriptions.get(callback);
|
||||
unsubscribe && unsubscribe();
|
||||
break;
|
||||
}
|
||||
case 'didBlur': {
|
||||
const unsubscribe = blurSubscriptions.get(callback);
|
||||
unsubscribe && unsubscribe();
|
||||
break;
|
||||
}
|
||||
case 'refocus': {
|
||||
const unsubscribe = refocusSubscriptions.get(callback);
|
||||
unsubscribe && unsubscribe();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// @ts-ignore
|
||||
navigation.removeListener(type, callback);
|
||||
}
|
||||
},
|
||||
state: {
|
||||
...state,
|
||||
// @ts-ignore
|
||||
routeName: state.name,
|
||||
get index() {
|
||||
// @ts-ignore
|
||||
if (state.index !== undefined) {
|
||||
// @ts-ignore
|
||||
return state.index;
|
||||
}
|
||||
|
||||
console.warn(
|
||||
"Accessing child navigation state for a route is not safe and won't work correctly."
|
||||
);
|
||||
|
||||
// @ts-ignore
|
||||
return state.state ? state.state.index : undefined;
|
||||
},
|
||||
get routes() {
|
||||
// @ts-ignore
|
||||
if (state.routes !== undefined) {
|
||||
// @ts-ignore
|
||||
return state.routes;
|
||||
}
|
||||
|
||||
console.warn(
|
||||
"Accessing child navigation state for a route is not safe and won't work correctly."
|
||||
);
|
||||
|
||||
// @ts-ignore
|
||||
return state.state ? state.state.routes : undefined;
|
||||
},
|
||||
},
|
||||
getParam<T extends keyof ParamList>(
|
||||
paramName: T,
|
||||
defaultValue: ParamList[T]
|
||||
): ParamList[T] {
|
||||
// @ts-ignore
|
||||
const params = state.params;
|
||||
|
||||
if (params && paramName in params) {
|
||||
return params[paramName];
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
},
|
||||
dangerouslyGetParent() {
|
||||
const parent = navigation.dangerouslyGetParent();
|
||||
|
||||
if (parent) {
|
||||
return createCompatNavigationProp(
|
||||
parent,
|
||||
navigation.dangerouslyGetState()
|
||||
);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
} as any;
|
||||
}
|
||||
171
packages/compat/src/createCompatNavigatorFactory.tsx
Normal file
@@ -0,0 +1,171 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
NavigationState,
|
||||
PartialState,
|
||||
ParamListBase,
|
||||
TypedNavigator,
|
||||
NavigationProp,
|
||||
RouteProp,
|
||||
} from '@react-navigation/core';
|
||||
import CompatScreen from './CompatScreen';
|
||||
import ScreenPropsContext from './ScreenPropsContext';
|
||||
import createCompatNavigationProp from './createCompatNavigationProp';
|
||||
import { CompatScreenType, CompatRouteConfig } from './types';
|
||||
|
||||
export default function createCompatNavigatorFactory<
|
||||
CreateNavigator extends () => TypedNavigator<
|
||||
ParamListBase,
|
||||
{},
|
||||
React.ComponentType<any>
|
||||
>
|
||||
>(createNavigator: CreateNavigator) {
|
||||
// @ts-ignore
|
||||
if (createNavigator.isCompat) {
|
||||
throw new Error(
|
||||
`The navigator is already in compat mode. You don't need to wrap it in 'createCompatNavigatorFactory'.`
|
||||
);
|
||||
}
|
||||
|
||||
const createCompatNavigator = <
|
||||
NavigationPropType extends NavigationProp<any, any, any, any, any>,
|
||||
ParamList extends ParamListBase = NavigationPropType extends NavigationProp<
|
||||
infer P
|
||||
>
|
||||
? P
|
||||
: ParamListBase,
|
||||
ScreenOptions extends {} = NavigationPropType extends NavigationProp<
|
||||
any,
|
||||
any,
|
||||
any,
|
||||
infer O
|
||||
>
|
||||
? O
|
||||
: {},
|
||||
NavigationConfig extends {} = React.ComponentProps<
|
||||
ReturnType<CreateNavigator>['Navigator']
|
||||
>
|
||||
>(
|
||||
routeConfig: CompatRouteConfig<NavigationPropType>,
|
||||
navigationConfig: Partial<Omit<NavigationConfig, 'screenOptions'>> & {
|
||||
order?: Array<Extract<keyof ParamList, string>>;
|
||||
defaultNavigationOptions?: ScreenOptions;
|
||||
navigationOptions?: { [key: string]: any };
|
||||
} = {}
|
||||
) => {
|
||||
const Pair = createNavigator();
|
||||
|
||||
const {
|
||||
order,
|
||||
defaultNavigationOptions,
|
||||
navigationOptions: parentNavigationOptions,
|
||||
...restConfig
|
||||
} = navigationConfig;
|
||||
|
||||
const routeNames = order !== undefined ? order : Object.keys(routeConfig);
|
||||
|
||||
function Navigator({ screenProps }: { screenProps?: unknown }) {
|
||||
const screens = React.useMemo(
|
||||
() =>
|
||||
routeNames.map(name => {
|
||||
let getScreenComponent: () => CompatScreenType<NavigationPropType>;
|
||||
|
||||
let initialParams;
|
||||
|
||||
const routeConfigItem = routeConfig[name];
|
||||
|
||||
if ('getScreen' in routeConfigItem) {
|
||||
getScreenComponent = routeConfigItem.getScreen;
|
||||
initialParams = routeConfigItem.params;
|
||||
} else if ('screen' in routeConfigItem) {
|
||||
getScreenComponent = () => routeConfigItem.screen;
|
||||
initialParams = routeConfigItem.params;
|
||||
} else {
|
||||
getScreenComponent = () => routeConfigItem;
|
||||
}
|
||||
|
||||
const screenOptions = ({
|
||||
navigation,
|
||||
route,
|
||||
}: {
|
||||
navigation: NavigationPropType;
|
||||
route: RouteProp<ParamList, keyof ParamList> & {
|
||||
state?: NavigationState | PartialState<NavigationState>;
|
||||
};
|
||||
}) => {
|
||||
// @ts-ignore
|
||||
const routeNavigationOptions = routeConfigItem.navigationOptions;
|
||||
const screenNavigationOptions = getScreenComponent()
|
||||
.navigationOptions;
|
||||
|
||||
if (
|
||||
routeNavigationOptions == null &&
|
||||
screenNavigationOptions == null
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const options =
|
||||
typeof routeNavigationOptions === 'function' ||
|
||||
typeof screenNavigationOptions === 'function'
|
||||
? {
|
||||
navigation: createCompatNavigationProp<
|
||||
NavigationPropType
|
||||
>(navigation, route),
|
||||
navigationOptions: defaultNavigationOptions || {},
|
||||
screenProps,
|
||||
}
|
||||
: {};
|
||||
|
||||
return {
|
||||
...(typeof routeNavigationOptions === 'function'
|
||||
? routeNavigationOptions(options)
|
||||
: routeNavigationOptions),
|
||||
...(typeof screenNavigationOptions === 'function'
|
||||
? (screenNavigationOptions as (o: any) => ScreenOptions)(
|
||||
options
|
||||
)
|
||||
: screenNavigationOptions),
|
||||
} as ScreenOptions;
|
||||
};
|
||||
|
||||
return (
|
||||
<Pair.Screen
|
||||
key={name}
|
||||
name={name}
|
||||
initialParams={initialParams}
|
||||
options={screenOptions}
|
||||
>
|
||||
{({ navigation, route }) => (
|
||||
<CompatScreen
|
||||
navigation={navigation}
|
||||
route={route}
|
||||
component={getScreenComponent()}
|
||||
/>
|
||||
)}
|
||||
</Pair.Screen>
|
||||
);
|
||||
}),
|
||||
[screenProps]
|
||||
);
|
||||
|
||||
return (
|
||||
<ScreenPropsContext.Provider value={screenProps}>
|
||||
<Pair.Navigator
|
||||
{...(restConfig as NavigationConfig)}
|
||||
screenOptions={defaultNavigationOptions}
|
||||
>
|
||||
{screens}
|
||||
</Pair.Navigator>
|
||||
</ScreenPropsContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
Navigator.navigationOtions = parentNavigationOptions;
|
||||
|
||||
return Navigator;
|
||||
};
|
||||
|
||||
createCompatNavigator.isCompat = true;
|
||||
|
||||
return createCompatNavigator;
|
||||
}
|
||||
28
packages/compat/src/createSwitchNavigator.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import {
|
||||
useNavigationBuilder,
|
||||
createNavigator,
|
||||
DefaultNavigatorOptions,
|
||||
} from '@react-navigation/core';
|
||||
import {
|
||||
TabRouter,
|
||||
TabRouterOptions,
|
||||
TabNavigationState,
|
||||
} from '@react-navigation/routers';
|
||||
import createCompatNavigatorFactory from './createCompatNavigatorFactory';
|
||||
|
||||
type Props = DefaultNavigatorOptions<{}> & TabRouterOptions;
|
||||
|
||||
function SwitchNavigator(props: Props) {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
TabNavigationState,
|
||||
TabRouterOptions,
|
||||
{},
|
||||
{}
|
||||
>(TabRouter, props);
|
||||
|
||||
return descriptors[state.routes[state.index].key].render();
|
||||
}
|
||||
|
||||
export default createCompatNavigatorFactory(
|
||||
createNavigator<{}, typeof SwitchNavigator>(SwitchNavigator)
|
||||
);
|
||||
86
packages/compat/src/helpers.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import * as NavigationActions from './NavigationActions';
|
||||
import * as StackActions from './StackActions';
|
||||
import * as SwitchActions from './SwitchActions';
|
||||
import * as DrawerActions from './DrawerActions';
|
||||
|
||||
type NavigateActionPayload = Parameters<typeof NavigationActions.navigate>['0'];
|
||||
|
||||
type NavigateActionType = ReturnType<typeof NavigationActions.navigate>;
|
||||
|
||||
export function navigate(
|
||||
routeName: string,
|
||||
params?: object,
|
||||
action?: never
|
||||
): NavigateActionType;
|
||||
export function navigate(options: NavigateActionPayload): NavigateActionType;
|
||||
export function navigate(
|
||||
options: string | NavigateActionPayload,
|
||||
params?: object,
|
||||
action?: never
|
||||
): NavigateActionType {
|
||||
if (typeof options === 'string') {
|
||||
return NavigationActions.navigate({
|
||||
routeName: options,
|
||||
params,
|
||||
action,
|
||||
});
|
||||
}
|
||||
|
||||
return NavigationActions.navigate(options);
|
||||
}
|
||||
|
||||
export function goBack(fromKey?: null | string) {
|
||||
return NavigationActions.back({ key: fromKey });
|
||||
}
|
||||
|
||||
export function setParams(params: object) {
|
||||
return NavigationActions.setParams({ params });
|
||||
}
|
||||
|
||||
export function reset() {
|
||||
return StackActions.reset();
|
||||
}
|
||||
|
||||
export function replace(routeName: string, params?: object, action?: never) {
|
||||
return StackActions.replace({
|
||||
routeName,
|
||||
params,
|
||||
action,
|
||||
});
|
||||
}
|
||||
|
||||
export function push(routeName: string, params?: object, action?: never) {
|
||||
return StackActions.push({
|
||||
routeName,
|
||||
params,
|
||||
action,
|
||||
});
|
||||
}
|
||||
|
||||
export function pop(n: number) {
|
||||
return StackActions.pop(typeof n === 'number' ? { n } : n);
|
||||
}
|
||||
|
||||
export function popToTop() {
|
||||
return StackActions.popToTop();
|
||||
}
|
||||
|
||||
export function dismiss() {
|
||||
return StackActions.dismiss();
|
||||
}
|
||||
|
||||
export function jumpTo(routeName: string) {
|
||||
return SwitchActions.jumpTo({ routeName });
|
||||
}
|
||||
|
||||
export function openDrawer() {
|
||||
return DrawerActions.openDrawer();
|
||||
}
|
||||
|
||||
export function closeDrawer() {
|
||||
return DrawerActions.closeDrawer();
|
||||
}
|
||||
|
||||
export function toggleDrawer() {
|
||||
return DrawerActions.toggleDrawer();
|
||||
}
|
||||
21
packages/compat/src/index.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import * as NavigationActions from './NavigationActions';
|
||||
import * as StackActions from './StackActions';
|
||||
import * as DrawerActions from './DrawerActions';
|
||||
import * as SwitchActions from './SwitchActions';
|
||||
|
||||
export { NavigationActions, StackActions, DrawerActions, SwitchActions };
|
||||
|
||||
export {
|
||||
default as createCompatNavigatorFactory,
|
||||
} from './createCompatNavigatorFactory';
|
||||
|
||||
export {
|
||||
default as createCompatNavigationProp,
|
||||
} from './createCompatNavigationProp';
|
||||
|
||||
export { default as createSwitchNavigator } from './createSwitchNavigator';
|
||||
|
||||
export { default as withNavigation } from './withNavigation';
|
||||
export { default as withNavigationFocus } from './withNavigationFocus';
|
||||
|
||||
export * from './types';
|
||||
79
packages/compat/src/types.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import { ParamListBase, NavigationProp, Route } from '@react-navigation/core';
|
||||
import * as helpers from './helpers';
|
||||
|
||||
export type CompatNavigationProp<
|
||||
NavigationPropType extends NavigationProp<ParamListBase>,
|
||||
ParamList extends ParamListBase = NavigationPropType extends NavigationProp<
|
||||
infer P
|
||||
>
|
||||
? P
|
||||
: ParamListBase,
|
||||
RouteName extends Extract<keyof ParamList, string> = Extract<
|
||||
NavigationPropType extends NavigationProp<any, infer R> ? R : string,
|
||||
string
|
||||
>
|
||||
> = Omit<NavigationPropType, keyof typeof helpers> &
|
||||
{
|
||||
[method in Extract<keyof NavigationPropType, keyof typeof helpers>]: (
|
||||
...args: Parameters<typeof helpers[method]>
|
||||
) => void;
|
||||
} & {
|
||||
state: Route<RouteName> & {
|
||||
routeName: RouteName;
|
||||
};
|
||||
getParam<T extends keyof ParamList[RouteName]>(
|
||||
paramName: T,
|
||||
defaultValue?: ParamList[RouteName][T]
|
||||
): ParamList[RouteName][T];
|
||||
dangerouslyGetParent<
|
||||
T = NavigationProp<ParamListBase> | undefined
|
||||
>(): T extends NavigationProp<ParamListBase>
|
||||
? CompatNavigationProp<T>
|
||||
: undefined;
|
||||
};
|
||||
|
||||
export type CompatNavigationOptions<
|
||||
NavigationPropType extends NavigationProp<ParamListBase>,
|
||||
ScreenOptions extends {} = NavigationPropType extends NavigationProp<
|
||||
any,
|
||||
any,
|
||||
any,
|
||||
infer O
|
||||
>
|
||||
? O
|
||||
: {}
|
||||
> =
|
||||
| ((options: {
|
||||
navigation: CompatNavigationProp<NavigationPropType>;
|
||||
navigationOptions: Partial<ScreenOptions>;
|
||||
screenProps: unknown;
|
||||
}) => ScreenOptions)
|
||||
| ScreenOptions;
|
||||
|
||||
export type CompatScreenType<
|
||||
NavigationPropType extends NavigationProp<ParamListBase>
|
||||
> = React.ComponentType<{
|
||||
navigation: CompatNavigationProp<NavigationPropType>;
|
||||
screenProps: unknown;
|
||||
}> & {
|
||||
navigationOptions?: CompatNavigationOptions<NavigationPropType>;
|
||||
};
|
||||
|
||||
export type CompatRouteConfig<
|
||||
NavigationPropType extends NavigationProp<ParamListBase>,
|
||||
ParamList extends ParamListBase = NavigationPropType extends NavigationProp<
|
||||
infer P
|
||||
>
|
||||
? P
|
||||
: ParamListBase
|
||||
> = {
|
||||
[RouteName in keyof ParamList]:
|
||||
| React.ComponentType<any>
|
||||
| ((
|
||||
| { screen: React.ComponentType<any> }
|
||||
| { getScreen(): React.ComponentType<any> }
|
||||
) & {
|
||||
navigationOptions?: CompatNavigationOptions<NavigationPropType>;
|
||||
params?: ParamList[RouteName];
|
||||
});
|
||||
};
|
||||
25
packages/compat/src/useCompatNavigation.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
useNavigation,
|
||||
useRoute,
|
||||
NavigationProp,
|
||||
ParamListBase,
|
||||
} from '@react-navigation/core';
|
||||
import createCompatNavigationProp from './createCompatNavigationProp';
|
||||
import { CompatNavigationProp } from './types';
|
||||
|
||||
export default function useCompatNavigation<
|
||||
T extends NavigationProp<ParamListBase>
|
||||
>() {
|
||||
const navigation = useNavigation();
|
||||
const route = useRoute();
|
||||
|
||||
return React.useMemo(
|
||||
() =>
|
||||
createCompatNavigationProp(
|
||||
navigation,
|
||||
route as any
|
||||
) as CompatNavigationProp<T>,
|
||||
[navigation, route]
|
||||
);
|
||||
}
|
||||
33
packages/compat/src/withNavigation.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import * as React from 'react';
|
||||
import { NavigationProp, ParamListBase } from '@react-navigation/core';
|
||||
import useCompatNavigation from './useCompatNavigation';
|
||||
import { CompatNavigationProp } from './types';
|
||||
|
||||
type InjectedProps<T extends NavigationProp<ParamListBase>> = {
|
||||
navigation: CompatNavigationProp<T>;
|
||||
};
|
||||
|
||||
export default function withNavigation<
|
||||
T extends NavigationProp<ParamListBase>,
|
||||
P extends InjectedProps<T>,
|
||||
C extends React.ComponentType<P>
|
||||
>(Comp: C) {
|
||||
const WrappedComponent = ({
|
||||
onRef,
|
||||
...rest
|
||||
}: Exclude<P, InjectedProps<T>> & {
|
||||
onRef?: C extends React.ComponentClass<any>
|
||||
? React.Ref<InstanceType<C>>
|
||||
: never;
|
||||
}): React.ReactElement => {
|
||||
const navigation = useCompatNavigation<T>();
|
||||
|
||||
// @ts-ignore
|
||||
return <Comp ref={onRef} navigation={navigation} {...rest} />;
|
||||
};
|
||||
|
||||
WrappedComponent.displayName = `withNavigation(${Comp.displayName ||
|
||||
Comp.name})`;
|
||||
|
||||
return WrappedComponent;
|
||||
}
|
||||
30
packages/compat/src/withNavigationFocus.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import * as React from 'react';
|
||||
import { useIsFocused } from '@react-navigation/core';
|
||||
|
||||
type InjectedProps = {
|
||||
isFocused: boolean;
|
||||
};
|
||||
|
||||
export default function withNavigationFocus<
|
||||
P extends InjectedProps,
|
||||
C extends React.ComponentType<P>
|
||||
>(Comp: C) {
|
||||
const WrappedComponent = ({
|
||||
onRef,
|
||||
...rest
|
||||
}: Exclude<P, InjectedProps> & {
|
||||
onRef?: C extends React.ComponentClass<any>
|
||||
? React.Ref<InstanceType<C>>
|
||||
: never;
|
||||
}): React.ReactElement => {
|
||||
const isFocused = useIsFocused();
|
||||
|
||||
// @ts-ignore
|
||||
return <Comp ref={onRef} isFocused={isFocused} {...rest} />;
|
||||
};
|
||||
|
||||
WrappedComponent.displayName = `withNavigationFocus(${Comp.displayName ||
|
||||
Comp.name})`;
|
||||
|
||||
return WrappedComponent;
|
||||
}
|
||||
3
packages/compat/tsconfig.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../../tsconfig"
|
||||
}
|
||||
@@ -3,6 +3,112 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.10](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.9...@react-navigation/core@5.0.0-alpha.10) (2019-09-17)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.9](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.8...@react-navigation/core@5.0.0-alpha.9) (2019-09-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* compatibility layer ([e0f28a4](https://github.com/react-navigation/navigation-ex/commit/e0f28a4))
|
||||
* make deep link handling more flexible ([849d952](https://github.com/react-navigation/navigation-ex/commit/849d952))
|
||||
* make example run as bare react-native project as well ([#85](https://github.com/react-navigation/navigation-ex/issues/85)) ([d16c20c](https://github.com/react-navigation/navigation-ex/commit/d16c20c))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.8](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.7...@react-navigation/core@5.0.0-alpha.8) (2019-09-04)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.7](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.5...@react-navigation/core@5.0.0-alpha.7) (2019-08-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix navigation object changing too often ([3c840bb](https://github.com/react-navigation/navigation-ex/commit/3c840bb))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add useRoute ([#89](https://github.com/react-navigation/navigation-ex/issues/89)) ([b0a3756](https://github.com/react-navigation/navigation-ex/commit/b0a3756))
|
||||
* support function in screenOptions ([eff0c04](https://github.com/react-navigation/navigation-ex/commit/eff0c04))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.6](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.5...@react-navigation/core@5.0.0-alpha.6) (2019-08-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add useRoute ([#89](https://github.com/react-navigation/navigation-ex/issues/89)) ([b0a3756](https://github.com/react-navigation/navigation-ex/commit/b0a3756))
|
||||
* support function in screenOptions ([eff0c04](https://github.com/react-navigation/navigation-ex/commit/eff0c04))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.5](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.4...@react-navigation/core@5.0.0-alpha.5) (2019-08-30)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.4](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.3...@react-navigation/core@5.0.0-alpha.4) (2019-08-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow making params optional. fixes [#80](https://github.com/react-navigation/navigation-ex/issues/80) ([a9d4813](https://github.com/react-navigation/navigation-ex/commit/a9d4813))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* export NavigationContext ([9245c79](https://github.com/react-navigation/navigation-ex/commit/9245c79))
|
||||
* handle navigating with both with both key and name ([#83](https://github.com/react-navigation/navigation-ex/issues/83)) ([6b75cba](https://github.com/react-navigation/navigation-ex/commit/6b75cba))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.3](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.2...@react-navigation/core@5.0.0-alpha.3) (2019-08-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add hook to scroll to top on tab press ([9e1104c](https://github.com/react-navigation/navigation-ex/commit/9e1104c))
|
||||
* add native container ([d26b77f](https://github.com/react-navigation/navigation-ex/commit/d26b77f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.2](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.1...@react-navigation/core@5.0.0-alpha.2) (2019-08-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix path to typescript definitions ([f182315](https://github.com/react-navigation/navigation-ex/commit/f182315))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 5.0.0-alpha.1 (2019-08-21)
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"react-native",
|
||||
"react-navigation"
|
||||
],
|
||||
"version": "5.0.0-alpha.1",
|
||||
"version": "5.0.0-alpha.10",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -16,7 +16,7 @@
|
||||
"main": "lib/commonjs/index.js",
|
||||
"react-native": "src/index.tsx",
|
||||
"module": "lib/module/index.js",
|
||||
"types": "lib/typescript/src/index.d.ts",
|
||||
"types": "lib/typescript/index.d.ts",
|
||||
"files": [
|
||||
"src",
|
||||
"lib"
|
||||
@@ -29,6 +29,8 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"escape-string-regexp": "^2.0.0",
|
||||
"query-string": "^6.8.3",
|
||||
"shortid": "^2.2.14",
|
||||
"use-subscription": "^1.0.0"
|
||||
},
|
||||
@@ -40,7 +42,7 @@
|
||||
"del-cli": "^2.0.0",
|
||||
"react": "^16.8.3",
|
||||
"react-native-testing-library": "^1.9.1",
|
||||
"react-test-renderer": "^16.8.3",
|
||||
"react-test-renderer": "16.8.3",
|
||||
"typescript": "^3.5.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -20,14 +20,16 @@ const BaseRouter = {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { name, key, params } = action.payload;
|
||||
|
||||
return {
|
||||
...state,
|
||||
routes: state.routes.map((route, i) =>
|
||||
i === index
|
||||
? {
|
||||
key: `${action.payload.name}-${shortid()}`,
|
||||
name: action.payload.name,
|
||||
params: action.payload.params,
|
||||
key: key !== undefined ? key : `${name}-${shortid()}`,
|
||||
name,
|
||||
params,
|
||||
}
|
||||
: route
|
||||
),
|
||||
|
||||
@@ -9,14 +9,14 @@ export type Action =
|
||||
| {
|
||||
type: 'NAVIGATE';
|
||||
payload:
|
||||
| { name: string; key?: undefined; params?: object }
|
||||
| { key: string; name?: undefined; params?: object };
|
||||
| { key: string; name?: undefined; params?: object }
|
||||
| { name: string; key?: string; params?: object };
|
||||
source?: string;
|
||||
target?: string;
|
||||
}
|
||||
| {
|
||||
type: 'REPLACE';
|
||||
payload: { name: string; params?: object };
|
||||
payload: { name: string; key?: string; params?: object };
|
||||
source?: string;
|
||||
target?: string;
|
||||
}
|
||||
@@ -38,7 +38,9 @@ export function goBack(): Action {
|
||||
}
|
||||
|
||||
export function navigate(
|
||||
route: { key: string; params?: object } | { name: string; params?: object }
|
||||
route:
|
||||
| { key: string; params?: object }
|
||||
| { name: string; key?: string; params?: object }
|
||||
): Action;
|
||||
export function navigate(name: string, params?: object): Action;
|
||||
export function navigate(...args: any): Action {
|
||||
@@ -47,12 +49,9 @@ export function navigate(...args: any): Action {
|
||||
} else {
|
||||
const payload = args[0];
|
||||
|
||||
if (
|
||||
(payload.hasOwnProperty('key') && payload.hasOwnProperty('name')) ||
|
||||
(!payload.hasOwnProperty('key') && !payload.hasOwnProperty('name'))
|
||||
) {
|
||||
if (!payload.hasOwnProperty('key') && !payload.hasOwnProperty('name')) {
|
||||
throw new Error(
|
||||
'While calling navigate with an object as the argument, you need to specify either name or key'
|
||||
'While calling navigate with an object as the argument, you need to specify name or key'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import * as BaseActions from './BaseActions';
|
||||
import * as CommonActions from './CommonActions';
|
||||
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
||||
import NavigationBuilderContext from './NavigationBuilderContext';
|
||||
import useFocusedListeners from './useFocusedListeners';
|
||||
@@ -12,16 +12,11 @@ import {
|
||||
PartialState,
|
||||
NavigationAction,
|
||||
NavigationContainerRef,
|
||||
NavigationContainerProps,
|
||||
} from './types';
|
||||
|
||||
type State = NavigationState | PartialState<NavigationState> | undefined;
|
||||
|
||||
type Props = {
|
||||
initialState?: InitialState;
|
||||
onStateChange?: (state: State) => void;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
const MISSING_CONTEXT_ERROR =
|
||||
"We couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'?";
|
||||
|
||||
@@ -84,7 +79,7 @@ const getPartialState = (
|
||||
* @param props.ref Ref object which refers to the navigation object containing helper methods.
|
||||
*/
|
||||
const Container = React.forwardRef(function NavigationContainer(
|
||||
{ initialState, onStateChange, children }: Props,
|
||||
{ initialState, onStateChange, children }: NavigationContainerProps,
|
||||
ref: React.Ref<NavigationContainerRef>
|
||||
) {
|
||||
const [state, setNavigationState] = React.useState<State>(() =>
|
||||
@@ -93,7 +88,9 @@ const Container = React.forwardRef(function NavigationContainer(
|
||||
|
||||
const { listeners, addListener: addFocusedListener } = useFocusedListeners();
|
||||
|
||||
const dispatch = (action: NavigationAction) => {
|
||||
const dispatch = (
|
||||
action: NavigationAction | ((state: NavigationState) => NavigationAction)
|
||||
) => {
|
||||
listeners[0](navigation => navigation.dispatch(action));
|
||||
};
|
||||
|
||||
@@ -110,13 +107,13 @@ const Container = React.forwardRef(function NavigationContainer(
|
||||
};
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
...(Object.keys(BaseActions) as Array<keyof typeof BaseActions>).reduce<
|
||||
...(Object.keys(CommonActions) as Array<keyof typeof CommonActions>).reduce<
|
||||
any
|
||||
>((acc, name) => {
|
||||
acc[name] = (...args: any[]) =>
|
||||
dispatch(
|
||||
// eslint-disable-next-line import/namespace
|
||||
BaseActions[name](
|
||||
CommonActions[name](
|
||||
// @ts-ignore
|
||||
...args
|
||||
)
|
||||
|
||||
11
packages/core/src/NavigationRouteContext.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import * as React from 'react';
|
||||
import { Route } from './types';
|
||||
|
||||
/**
|
||||
* Context which holds the route prop for a screen.
|
||||
*/
|
||||
const NavigationContext = React.createContext<Route<string> | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
export default NavigationContext;
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { NavigationStateContext } from './NavigationContainer';
|
||||
import NavigationContext from './NavigationContext';
|
||||
import NavigationRouteContext from './NavigationRouteContext';
|
||||
import StaticContainer from './StaticContainer';
|
||||
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
||||
import {
|
||||
@@ -18,8 +19,8 @@ type Props<State extends NavigationState, ScreenOptions extends object> = {
|
||||
route: Route<string> & {
|
||||
state?: NavigationState | PartialState<NavigationState>;
|
||||
};
|
||||
getState: () => NavigationState;
|
||||
setState: (state: NavigationState) => void;
|
||||
getState: () => State;
|
||||
setState: (state: State) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -56,7 +57,7 @@ export default function SceneView<
|
||||
),
|
||||
});
|
||||
},
|
||||
[getState, route, setState]
|
||||
[getState, route.key, setState]
|
||||
);
|
||||
|
||||
const context = React.useMemo(
|
||||
@@ -78,23 +79,25 @@ export default function SceneView<
|
||||
|
||||
return (
|
||||
<NavigationContext.Provider value={navigation}>
|
||||
<NavigationStateContext.Provider value={context}>
|
||||
<EnsureSingleNavigator>
|
||||
<StaticContainer
|
||||
name={screen.name}
|
||||
// @ts-ignore
|
||||
render={screen.component || screen.children}
|
||||
navigation={navigation}
|
||||
route={route}
|
||||
>
|
||||
{'component' in screen && screen.component !== undefined ? (
|
||||
<screen.component navigation={navigation} route={route} />
|
||||
) : 'children' in screen && screen.children !== undefined ? (
|
||||
screen.children({ navigation, route })
|
||||
) : null}
|
||||
</StaticContainer>
|
||||
</EnsureSingleNavigator>
|
||||
</NavigationStateContext.Provider>
|
||||
<NavigationRouteContext.Provider value={route}>
|
||||
<NavigationStateContext.Provider value={context}>
|
||||
<EnsureSingleNavigator>
|
||||
<StaticContainer
|
||||
name={screen.name}
|
||||
// @ts-ignore
|
||||
render={screen.component || screen.children}
|
||||
navigation={navigation}
|
||||
route={route}
|
||||
>
|
||||
{'component' in screen && screen.component !== undefined ? (
|
||||
<screen.component navigation={navigation} route={route} />
|
||||
) : 'children' in screen && screen.children !== undefined ? (
|
||||
screen.children({ navigation, route })
|
||||
) : null}
|
||||
</StaticContainer>
|
||||
</EnsureSingleNavigator>
|
||||
</NavigationStateContext.Provider>
|
||||
</NavigationRouteContext.Provider>
|
||||
</NavigationContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import BaseRouter from '../BaseRouter';
|
||||
import * as BaseActions from '../BaseActions';
|
||||
import * as CommonActions from '../CommonActions';
|
||||
|
||||
jest.mock('shortid', () => () => 'test');
|
||||
|
||||
@@ -18,7 +18,7 @@ const STATE = {
|
||||
it('replaces focused screen with REPLACE', () => {
|
||||
const result = BaseRouter.getStateForAction(
|
||||
STATE,
|
||||
BaseActions.replace('qux', { answer: 42 })
|
||||
CommonActions.replace('qux', { answer: 42 })
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
@@ -36,7 +36,7 @@ it('replaces focused screen with REPLACE', () => {
|
||||
|
||||
it('replaces source screen with REPLACE', () => {
|
||||
const result = BaseRouter.getStateForAction(STATE, {
|
||||
...BaseActions.replace('qux', { answer: 42 }),
|
||||
...CommonActions.replace('qux', { answer: 42 }),
|
||||
source: 'baz',
|
||||
});
|
||||
|
||||
@@ -55,7 +55,7 @@ it('replaces source screen with REPLACE', () => {
|
||||
|
||||
it("doesn't handle REPLACE if source key isn't present", () => {
|
||||
const result = BaseRouter.getStateForAction(STATE, {
|
||||
...BaseActions.replace('qux', { answer: 42 }),
|
||||
...CommonActions.replace('qux', { answer: 42 }),
|
||||
source: 'magic',
|
||||
});
|
||||
|
||||
@@ -65,7 +65,7 @@ it("doesn't handle REPLACE if source key isn't present", () => {
|
||||
it('sets params for the focused screen with SET_PARAMS', () => {
|
||||
const result = BaseRouter.getStateForAction(
|
||||
STATE,
|
||||
BaseActions.setParams({ answer: 42 })
|
||||
CommonActions.setParams({ answer: 42 })
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
@@ -83,7 +83,7 @@ it('sets params for the focused screen with SET_PARAMS', () => {
|
||||
|
||||
it('sets params for the source screen with SET_PARAMS', () => {
|
||||
const result = BaseRouter.getStateForAction(STATE, {
|
||||
...BaseActions.setParams({ answer: 42 }),
|
||||
...CommonActions.setParams({ answer: 42 }),
|
||||
source: 'foo',
|
||||
});
|
||||
|
||||
@@ -102,7 +102,7 @@ it('sets params for the source screen with SET_PARAMS', () => {
|
||||
|
||||
it("doesn't handle SET_PARAMS if source key isn't present", () => {
|
||||
const result = BaseRouter.getStateForAction(STATE, {
|
||||
...BaseActions.setParams({ answer: 42 }),
|
||||
...CommonActions.setParams({ answer: 42 }),
|
||||
source: 'magic',
|
||||
});
|
||||
|
||||
@@ -119,7 +119,7 @@ it('resets state to new state with RESET', () => {
|
||||
|
||||
const result = BaseRouter.getStateForAction(
|
||||
STATE,
|
||||
BaseActions.reset({
|
||||
CommonActions.reset({
|
||||
index: 0,
|
||||
routes,
|
||||
})
|
||||
@@ -132,7 +132,7 @@ it('ignores key and routeNames when resetting with RESET', () => {
|
||||
const result = BaseRouter.getStateForAction(
|
||||
STATE,
|
||||
// @ts-ignore
|
||||
BaseActions.reset({ index: 2, key: 'foo', routeNames: ['test'] })
|
||||
CommonActions.reset({ index: 2, key: 'foo', routeNames: ['test'] })
|
||||
);
|
||||
|
||||
expect(result).toEqual({ ...STATE, index: 2 });
|
||||
|
||||
@@ -7,42 +7,7 @@ import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
|
||||
|
||||
beforeEach(() => (MockRouterKey.current = 0));
|
||||
|
||||
it('throws if NAVIGATE dispatched with both key and name', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
return descriptors[state.routes[state.index].key].render();
|
||||
};
|
||||
|
||||
const FooScreen = (props: any) => {
|
||||
React.useEffect(() => {
|
||||
props.navigation.navigate({ key: '1', name: '2' });
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator initialRouteName="foo">
|
||||
<Screen
|
||||
name="foo"
|
||||
component={FooScreen}
|
||||
initialParams={{ count: 10 }}
|
||||
/>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
'While calling navigate with an object as the argument, you need to specify either name or key'
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if NAVIGATE dispatched neither both key nor name', () => {
|
||||
it('throws if NAVIGATE dispatched neither key nor name', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
@@ -73,6 +38,6 @@ it('throws if NAVIGATE dispatched neither both key nor name', () => {
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
'While calling navigate with an object as the argument, you need to specify either name or key'
|
||||
'While calling navigate with an object as the argument, you need to specify name or key'
|
||||
);
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
import getPathFromState from '../getPathFromState';
|
||||
|
||||
it('converts path string to initial state', () => {
|
||||
it('converts state to path string', () => {
|
||||
expect(
|
||||
getPathFromState({
|
||||
routes: [
|
||||
@@ -12,11 +12,12 @@ it('converts path string to initial state', () => {
|
||||
{ name: 'boo' },
|
||||
{
|
||||
name: 'bar',
|
||||
params: { fruit: 'apple' },
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'baz qux',
|
||||
params: { author: 'jane & co', valid: true },
|
||||
params: { author: 'jane', valid: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -26,9 +27,50 @@ it('converts path string to initial state', () => {
|
||||
},
|
||||
],
|
||||
})
|
||||
).toMatchInlineSnapshot(
|
||||
`"/foo/bar/baz%20qux?author=%22jane%20%26%20co%22&valid=true"`
|
||||
);
|
||||
).toMatchInlineSnapshot(`"/foo/bar/baz%20qux?author=jane&valid=true"`);
|
||||
});
|
||||
|
||||
it('converts state to path string with config', () => {
|
||||
expect(
|
||||
getPathFromState(
|
||||
{
|
||||
routes: [
|
||||
{
|
||||
name: 'Foo',
|
||||
state: {
|
||||
index: 1,
|
||||
routes: [
|
||||
{ name: 'boo' },
|
||||
{
|
||||
name: 'Bar',
|
||||
params: { fruit: 'apple', type: 'sweet', avaliable: false },
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Baz',
|
||||
params: { author: 'Jane', valid: true, id: 10 },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
Foo: 'few',
|
||||
Bar: 'bar/:type/:fruit',
|
||||
Baz: {
|
||||
path: 'baz/:author',
|
||||
stringify: {
|
||||
author: author => author.toLowerCase(),
|
||||
id: id => `x${id}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
).toMatchInlineSnapshot(`"/few/bar/sweet/apple/baz/jane?id=x10&valid=true"`);
|
||||
});
|
||||
|
||||
it('handles route without param', () => {
|
||||
|
||||
@@ -2,9 +2,7 @@ import getStateFromPath from '../getStateFromPath';
|
||||
|
||||
it('converts path string to initial state', () => {
|
||||
expect(
|
||||
getStateFromPath(
|
||||
'foo/bar/baz%20qux?author=%22jane%20%26%20co%22&valid=true'
|
||||
)
|
||||
getStateFromPath('foo/bar/baz%20qux?author=jane%20%26%20co&valid=true')
|
||||
).toEqual({
|
||||
routes: [
|
||||
{
|
||||
@@ -17,7 +15,55 @@ it('converts path string to initial state', () => {
|
||||
routes: [
|
||||
{
|
||||
name: 'baz qux',
|
||||
params: { author: 'jane & co', valid: true },
|
||||
params: { author: 'jane & co', valid: 'true' },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('converts path string to initial state with config', () => {
|
||||
expect(
|
||||
getStateFromPath(
|
||||
'/few/bar/sweet/apple/baz/jane?count=10&answer=42&valid=true',
|
||||
{
|
||||
Foo: 'few',
|
||||
Bar: 'bar/:type/:fruit',
|
||||
Baz: {
|
||||
path: 'baz/:author',
|
||||
parse: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
).toEqual({
|
||||
routes: [
|
||||
{
|
||||
name: 'Foo',
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Bar',
|
||||
params: { fruit: 'apple', type: 'sweet' },
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Baz',
|
||||
params: {
|
||||
author: 'Jane',
|
||||
count: 10,
|
||||
answer: '42',
|
||||
valid: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -38,7 +84,7 @@ it('handles leading slash when converting', () => {
|
||||
routes: [
|
||||
{
|
||||
name: 'bar',
|
||||
params: { count: 42 },
|
||||
params: { count: '42' },
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -56,7 +102,7 @@ it('handles ending slash when converting', () => {
|
||||
routes: [
|
||||
{
|
||||
name: 'bar',
|
||||
params: { count: 42 },
|
||||
params: { count: '42' },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -3,8 +3,8 @@ import { render, act } from 'react-native-testing-library';
|
||||
import Screen from '../Screen';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
|
||||
import useNavigation from '../useNavigation';
|
||||
import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
|
||||
import { NavigationState } from '../types';
|
||||
|
||||
beforeEach(() => (MockRouterKey.current = 0));
|
||||
@@ -323,7 +323,7 @@ it('cleans up state when the navigator unmounts', () => {
|
||||
expect(onStateChange).lastCalledWith(undefined);
|
||||
});
|
||||
|
||||
it('allows arbitrary state updates by dispatching a function', () => {
|
||||
it('allows state updates by dispatching a function returning an action', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
@@ -332,11 +332,11 @@ it('allows arbitrary state updates by dispatching a function', () => {
|
||||
|
||||
const FooScreen = (props: any) => {
|
||||
React.useEffect(() => {
|
||||
props.navigation.dispatch((state: any) => ({
|
||||
...state,
|
||||
routes: state.routes.slice().reverse(),
|
||||
index: 1,
|
||||
}));
|
||||
props.navigation.dispatch((state: NavigationState) =>
|
||||
state.index === 0
|
||||
? { type: 'NAVIGATE', payload: { name: state.routeNames[1] } }
|
||||
: { type: 'NOOP' }
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
@@ -364,7 +364,7 @@ it('allows arbitrary state updates by dispatching a function', () => {
|
||||
index: 1,
|
||||
key: '0',
|
||||
routeNames: ['foo', 'bar'],
|
||||
routes: [{ key: 'bar', name: 'bar' }, { key: 'foo', name: 'foo' }],
|
||||
routes: [{ key: 'foo', name: 'foo' }, { key: 'bar', name: 'bar' }],
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ it('sets options with options prop as an object', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
{ title?: string },
|
||||
any
|
||||
>(MockRouter, props);
|
||||
@@ -45,11 +46,320 @@ it('sets options with options prop as an object', () => {
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
<main>
|
||||
<h1>
|
||||
Hello world
|
||||
</h1>
|
||||
<div>
|
||||
Test screen
|
||||
</div>
|
||||
</main>
|
||||
`);
|
||||
});
|
||||
|
||||
it('sets options with options prop as a fuction', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
{ title?: string },
|
||||
any
|
||||
>(MockRouter, props);
|
||||
const { render, options } = descriptors[state.routes[state.index].key];
|
||||
|
||||
return (
|
||||
<main>
|
||||
<h1>{options.title}</h1>
|
||||
<div>{render()}</div>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
const TestScreen = (): any => 'Test screen';
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen
|
||||
name="foo"
|
||||
component={TestScreen}
|
||||
options={({ route }: any) => ({ title: route.params.author })}
|
||||
initialParams={{ author: 'Jane' }}
|
||||
/>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
<main>
|
||||
<h1>
|
||||
Jane
|
||||
</h1>
|
||||
<div>
|
||||
Test screen
|
||||
</div>
|
||||
</main>
|
||||
`);
|
||||
});
|
||||
|
||||
it('sets options with screenOptions prop as an object', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
{ title?: string },
|
||||
any
|
||||
>(MockRouter, props);
|
||||
|
||||
return (
|
||||
<>
|
||||
{state.routes.map(route => {
|
||||
const { render, options } = descriptors[route.key];
|
||||
|
||||
return (
|
||||
<main key={route.key}>
|
||||
<h1>{options.title}</h1>
|
||||
<div>{render()}</div>
|
||||
</main>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const TestScreenA = (): any => 'Test screen A';
|
||||
|
||||
const TestScreenB = (): any => 'Test screen B';
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer>
|
||||
<TestNavigator screenOptions={{ title: 'Hello world' }}>
|
||||
<Screen name="foo" component={TestScreenA} />
|
||||
<Screen name="bar" component={TestScreenB} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
<main>
|
||||
<h1>
|
||||
Hello world
|
||||
</h1>
|
||||
<div>
|
||||
Test screen A
|
||||
</div>
|
||||
</main>,
|
||||
<main>
|
||||
<h1>
|
||||
Hello world
|
||||
</h1>
|
||||
<div>
|
||||
Test screen B
|
||||
</div>
|
||||
</main>,
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('sets options with screenOptions prop as a fuction', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
{ title?: string },
|
||||
any
|
||||
>(MockRouter, props);
|
||||
|
||||
return (
|
||||
<>
|
||||
{state.routes.map(route => {
|
||||
const { render, options } = descriptors[route.key];
|
||||
|
||||
return (
|
||||
<main key={route.key}>
|
||||
<h1>{options.title}</h1>
|
||||
<div>{render()}</div>
|
||||
</main>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const TestScreenA = (): any => 'Test screen A';
|
||||
|
||||
const TestScreenB = (): any => 'Test screen B';
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer>
|
||||
<TestNavigator
|
||||
screenOptions={({ route }: any) => ({
|
||||
title: `${route.name}: ${route.params.author || route.params.fruit}`,
|
||||
})}
|
||||
>
|
||||
<Screen
|
||||
name="foo"
|
||||
component={TestScreenA}
|
||||
initialParams={{ author: 'Jane' }}
|
||||
/>
|
||||
<Screen
|
||||
name="bar"
|
||||
component={TestScreenB}
|
||||
initialParams={{ fruit: 'Apple' }}
|
||||
/>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
<main>
|
||||
<h1>
|
||||
foo: Jane
|
||||
</h1>
|
||||
<div>
|
||||
Test screen A
|
||||
</div>
|
||||
</main>,
|
||||
<main>
|
||||
<h1>
|
||||
bar: Apple
|
||||
</h1>
|
||||
<div>
|
||||
Test screen B
|
||||
</div>
|
||||
</main>,
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('sets initial options with setOptions', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
{
|
||||
title?: string;
|
||||
color?: string;
|
||||
},
|
||||
any
|
||||
>(MockRouter, props);
|
||||
const { render, options } = descriptors[state.routes[state.index].key];
|
||||
|
||||
return (
|
||||
<main>
|
||||
<h1 color={options.color}>{options.title}</h1>
|
||||
<div>{render()}</div>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
const TestScreen = ({ navigation }: any): any => {
|
||||
navigation.setOptions({
|
||||
title: 'Hello world',
|
||||
});
|
||||
|
||||
return 'Test screen';
|
||||
};
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" options={{ color: 'blue' }}>
|
||||
{props => <TestScreen {...props} />}
|
||||
</Screen>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
<main>
|
||||
<h1
|
||||
color="blue"
|
||||
>
|
||||
Hello world
|
||||
</h1>
|
||||
<div>
|
||||
Test screen
|
||||
</div>
|
||||
</main>
|
||||
`);
|
||||
});
|
||||
|
||||
it('updates options with setOptions', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
any,
|
||||
any
|
||||
>(MockRouter, props);
|
||||
const { render, options } = descriptors[state.routes[state.index].key];
|
||||
|
||||
return (
|
||||
<main>
|
||||
<h1 color={options.color}>{options.title}</h1>
|
||||
<p>{options.description}</p>
|
||||
<caption>{options.author}</caption>
|
||||
<div>{render()}</div>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
const TestScreen = ({ navigation }: any): any => {
|
||||
navigation.setOptions({
|
||||
title: 'Hello world',
|
||||
description: 'Something here',
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
const timer = setTimeout(() =>
|
||||
navigation.setOptions({
|
||||
title: 'Hello again',
|
||||
author: 'Jane',
|
||||
})
|
||||
);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
});
|
||||
|
||||
return 'Test screen';
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" options={{ color: 'blue' }}>
|
||||
{props => <TestScreen {...props} />}
|
||||
</Screen>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
const root = render(element);
|
||||
|
||||
act(() => jest.runAllTimers());
|
||||
|
||||
root.update(element);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
<main>
|
||||
<h1>
|
||||
Hello world
|
||||
<h1
|
||||
color="blue"
|
||||
>
|
||||
Hello again
|
||||
</h1>
|
||||
<p>
|
||||
Something here
|
||||
</p>
|
||||
<caption>
|
||||
Jane
|
||||
</caption>
|
||||
<div>
|
||||
Test screen
|
||||
</div>
|
||||
@@ -61,6 +371,7 @@ it("returns correct value for canGoBack when it's not overridden", () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
{ title?: string },
|
||||
any
|
||||
>(MockRouter, props);
|
||||
@@ -123,6 +434,7 @@ it(`returns false for canGoBack when current router doesn't handle GO_BACK`, ()
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
any,
|
||||
any
|
||||
>(TestRouter, props);
|
||||
|
||||
@@ -172,6 +484,7 @@ it('returns true for canGoBack when current router handles GO_BACK', () => {
|
||||
const ParentNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
{ title?: string },
|
||||
any
|
||||
>(ParentRouter, props);
|
||||
@@ -181,6 +494,7 @@ it('returns true for canGoBack when current router handles GO_BACK', () => {
|
||||
const ChildNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
{ title?: string },
|
||||
any
|
||||
>(MockRouter, props);
|
||||
@@ -237,6 +551,7 @@ it('returns true for canGoBack when parent router handles GO_BACK', () => {
|
||||
const OverrodeNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
{ title?: string },
|
||||
any
|
||||
>(OverrodeRouter, props);
|
||||
@@ -246,6 +561,7 @@ it('returns true for canGoBack when parent router handles GO_BACK', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
{ title?: string },
|
||||
any
|
||||
>(MockRouter, props);
|
||||
@@ -288,177 +604,3 @@ it('returns true for canGoBack when parent router handles GO_BACK', () => {
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('sets options with options prop as a fuction', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
{ title?: string },
|
||||
any
|
||||
>(MockRouter, props);
|
||||
const { render, options } = descriptors[state.routes[state.index].key];
|
||||
|
||||
return (
|
||||
<main>
|
||||
<h1>{options.title}</h1>
|
||||
<div>{render()}</div>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
const TestScreen = (): any => 'Test screen';
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen
|
||||
name="foo"
|
||||
component={TestScreen}
|
||||
options={({ route }: any) => ({ title: route.params.author })}
|
||||
initialParams={{ author: 'Jane' }}
|
||||
/>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
<main>
|
||||
<h1>
|
||||
Jane
|
||||
</h1>
|
||||
<div>
|
||||
Test screen
|
||||
</div>
|
||||
</main>
|
||||
`);
|
||||
});
|
||||
|
||||
it('sets initial options with setOptions', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
{
|
||||
title?: string;
|
||||
color?: string;
|
||||
},
|
||||
any
|
||||
>(MockRouter, props);
|
||||
const { render, options } = descriptors[state.routes[state.index].key];
|
||||
|
||||
return (
|
||||
<main>
|
||||
<h1 color={options.color}>{options.title}</h1>
|
||||
<div>{render()}</div>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
const TestScreen = ({ navigation }: any): any => {
|
||||
navigation.setOptions({
|
||||
title: 'Hello world',
|
||||
});
|
||||
|
||||
return 'Test screen';
|
||||
};
|
||||
|
||||
const root = render(
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" options={{ color: 'blue' }}>
|
||||
{props => <TestScreen {...props} />}
|
||||
</Screen>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
<main>
|
||||
<h1
|
||||
color="blue"
|
||||
>
|
||||
Hello world
|
||||
</h1>
|
||||
<div>
|
||||
Test screen
|
||||
</div>
|
||||
</main>
|
||||
`);
|
||||
});
|
||||
|
||||
it('updates options with setOptions', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
NavigationState,
|
||||
any,
|
||||
any
|
||||
>(MockRouter, props);
|
||||
const { render, options } = descriptors[state.routes[state.index].key];
|
||||
|
||||
return (
|
||||
<main>
|
||||
<h1 color={options.color}>{options.title}</h1>
|
||||
<p>{options.description}</p>
|
||||
<caption>{options.author}</caption>
|
||||
<div>{render()}</div>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
const TestScreen = ({ navigation }: any): any => {
|
||||
navigation.setOptions({
|
||||
title: 'Hello world',
|
||||
description: 'Something here',
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
const timer = setTimeout(() =>
|
||||
navigation.setOptions({
|
||||
title: 'Hello again',
|
||||
author: 'Jane',
|
||||
})
|
||||
);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
});
|
||||
|
||||
return 'Test screen';
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" options={{ color: 'blue' }}>
|
||||
{props => <TestScreen {...props} />}
|
||||
</Screen>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
const root = render(element);
|
||||
|
||||
act(() => jest.runAllTimers());
|
||||
|
||||
root.update(element);
|
||||
|
||||
expect(root).toMatchInlineSnapshot(`
|
||||
<main>
|
||||
<h1
|
||||
color="blue"
|
||||
>
|
||||
Hello again
|
||||
</h1>
|
||||
<p>
|
||||
Something here
|
||||
</p>
|
||||
<caption>
|
||||
Jane
|
||||
</caption>
|
||||
<div>
|
||||
Test screen
|
||||
</div>
|
||||
</main>
|
||||
`);
|
||||
});
|
||||
|
||||
34
packages/core/src/__tests__/useRoute.test.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import * as React from 'react';
|
||||
import { render } from 'react-native-testing-library';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import useRoute from '../useRoute';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import Screen from '../Screen';
|
||||
import MockRouter from './__fixtures__/MockRouter';
|
||||
import { RouteProp } from '../types';
|
||||
|
||||
it('gets route prop from context', () => {
|
||||
expect.assertions(1);
|
||||
|
||||
const TestNavigator = (props: any): any => {
|
||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
return state.routes.map(route => descriptors[route.key].render());
|
||||
};
|
||||
|
||||
const Test = () => {
|
||||
const route = useRoute<RouteProp<{ sample: { x: string } }, 'sample'>>();
|
||||
|
||||
expect(route && route.params && route.params.x).toEqual(1);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
render(
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={Test} initialParams={{ x: 1 }} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
});
|
||||
@@ -1,14 +1,45 @@
|
||||
import queryString from 'query-string';
|
||||
import { NavigationState, PartialState, Route } from './types';
|
||||
|
||||
type State = NavigationState | Omit<PartialState<NavigationState>, 'stale'>;
|
||||
|
||||
type StringifyConfig = { [key: string]: (value: any) => string };
|
||||
|
||||
type Options = {
|
||||
[routeName: string]: string | { path: string; stringify?: StringifyConfig };
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility to serialize a navigation state object to a path string.
|
||||
*
|
||||
* Example:
|
||||
* ```js
|
||||
* getPathFromState(
|
||||
* {
|
||||
* routes: [
|
||||
* {
|
||||
* name: 'Chat',
|
||||
* params: { author: 'Jane', id: 42 },
|
||||
* },
|
||||
* ],
|
||||
* },
|
||||
* {
|
||||
* Chat: {
|
||||
* path: 'chat/:author/:id',
|
||||
* stringify: { author: author => author.toLowerCase() }
|
||||
* }
|
||||
* }
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* @param state Navigation state to serialize.
|
||||
* @param options Extra options to fine-tune how to serialize the path.
|
||||
* @returns Path representing the state, e.g. /foo/bar?count=42.
|
||||
*/
|
||||
export default function getPathFromState(state: State): string {
|
||||
export default function getPathFromState(
|
||||
state: State,
|
||||
options: Options = {}
|
||||
): string {
|
||||
let path = '/';
|
||||
|
||||
let current: State | undefined = state;
|
||||
@@ -19,24 +50,51 @@ export default function getPathFromState(state: State): string {
|
||||
state?: State | undefined;
|
||||
};
|
||||
|
||||
path += encodeURIComponent(route.name);
|
||||
const config =
|
||||
options[route.name] !== undefined
|
||||
? (options[route.name] as { stringify?: StringifyConfig }).stringify
|
||||
: undefined;
|
||||
|
||||
const params = route.params
|
||||
? // Stringify all of the param values before we use them
|
||||
Object.entries(route.params).reduce<{
|
||||
[key: string]: string;
|
||||
}>((acc, [key, value]) => {
|
||||
acc[key] = config && config[key] ? config[key](value) : String(value);
|
||||
return acc;
|
||||
}, {})
|
||||
: undefined;
|
||||
|
||||
if (options[route.name] !== undefined) {
|
||||
const pattern =
|
||||
typeof options[route.name] === 'string'
|
||||
? (options[route.name] as string)
|
||||
: (options[route.name] as { path: string }).path;
|
||||
|
||||
path += pattern
|
||||
.split('/')
|
||||
.map(p => {
|
||||
const name = p.replace(/^:/, '');
|
||||
|
||||
// If the path has a pattern for a param, put the param in the path
|
||||
if (params && name in params && p.startsWith(':')) {
|
||||
const value = params[name];
|
||||
// Remove the used value from the params object since we'll use the rest for query string
|
||||
delete params[name];
|
||||
return encodeURIComponent(value);
|
||||
}
|
||||
|
||||
return encodeURIComponent(p);
|
||||
})
|
||||
.join('/');
|
||||
} else {
|
||||
path += encodeURIComponent(route.name);
|
||||
}
|
||||
|
||||
if (route.state) {
|
||||
path += '/';
|
||||
} else if (route.params) {
|
||||
const query = [];
|
||||
|
||||
for (const param in route.params) {
|
||||
const value = (route.params as { [key: string]: any })[param];
|
||||
|
||||
query.push(
|
||||
`${encodeURIComponent(param)}=${encodeURIComponent(
|
||||
JSON.stringify(value)
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
path += `?${query.join('&')}`;
|
||||
} else if (params) {
|
||||
path += `?${queryString.stringify(params)}`;
|
||||
}
|
||||
|
||||
current = route.state;
|
||||
|
||||
@@ -1,50 +1,149 @@
|
||||
import escape from 'escape-string-regexp';
|
||||
import queryString from 'query-string';
|
||||
import { NavigationState, PartialState } from './types';
|
||||
|
||||
type ParseConfig = { [key: string]: (value: string) => any };
|
||||
|
||||
type Options = {
|
||||
[routeName: string]: string | { path: string; parse?: ParseConfig };
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility to parse a path string to initial state object accepted by the container.
|
||||
* This is useful for deep linking when we need to handle the incoming URL.
|
||||
*
|
||||
* Example:
|
||||
* ```js
|
||||
* getStateFromPath(
|
||||
* '/chat/jane/42',
|
||||
* {
|
||||
* Chat: {
|
||||
* path: 'chat/:author/:id',
|
||||
* parse: { id: Number }
|
||||
* }
|
||||
* }
|
||||
* )
|
||||
* ```
|
||||
* @param path Path string to parse and convert, e.g. /foo/bar?count=42.
|
||||
* @param options Extra options to fine-tune how to parse the path.
|
||||
*/
|
||||
export default function getStateFromPath(
|
||||
path: string
|
||||
path: string,
|
||||
options: Options = {}
|
||||
): PartialState<NavigationState> | undefined {
|
||||
const parts = path.split('?');
|
||||
const segments = parts[0].split('/').filter(Boolean);
|
||||
const query = parts[1] ? parts[1].split('&') : undefined;
|
||||
// Create a normalized config array which will be easier to use
|
||||
const routeConfig = Object.keys(options).map(key => {
|
||||
const pattern =
|
||||
typeof options[key] === 'string'
|
||||
? (options[key] as string)
|
||||
: (options[key] as { path: string }).path;
|
||||
|
||||
// Create a regex from the provided path pattern
|
||||
// With the pattern, we can match segements containing params and extract them
|
||||
const match = new RegExp(
|
||||
'^' + escape(pattern).replace(/:[a-z0-9]+/gi, '([^/]+)') + '/?'
|
||||
);
|
||||
|
||||
return {
|
||||
match,
|
||||
pattern,
|
||||
routeName: key,
|
||||
// @ts-ignore
|
||||
parse: options[key].parse,
|
||||
};
|
||||
});
|
||||
|
||||
let result: PartialState<NavigationState> | undefined;
|
||||
let current: PartialState<NavigationState> | undefined;
|
||||
|
||||
while (segments.length) {
|
||||
let remaining = path
|
||||
.replace(/[/]+/, '/') // Replace multiple slash (//) with single ones
|
||||
.replace(/^\//, '') // Remove extra leading slash
|
||||
.replace(/\?.*/, ''); // Remove query params which we will handle later
|
||||
|
||||
while (remaining) {
|
||||
let routeName;
|
||||
let params;
|
||||
|
||||
// Go through all configs, and see if the next path segment matches our regex
|
||||
for (const config of routeConfig) {
|
||||
const match = remaining.match(config.match);
|
||||
|
||||
// If our regex matches, we need to extract params from the path
|
||||
if (match) {
|
||||
routeName = config.routeName;
|
||||
|
||||
const paramPatterns = config.pattern
|
||||
.split('/')
|
||||
.filter(p => p.startsWith(':'));
|
||||
|
||||
if (paramPatterns.length) {
|
||||
params = paramPatterns.reduce<{ [key: string]: any }>((acc, p, i) => {
|
||||
const key = p.replace(/^:/, '');
|
||||
const value = match[i + 1]; // The param segments start from index 1 in the regex match result
|
||||
|
||||
acc[key] =
|
||||
config.parse && config.parse[key]
|
||||
? config.parse[key](value)
|
||||
: value;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
// Remove the matched segment from the remaining path
|
||||
remaining = remaining.replace(match[0], '');
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we hadn't matched any segments earlier, use the path as route name
|
||||
if (routeName === undefined) {
|
||||
const segments = remaining.split('/');
|
||||
|
||||
routeName = decodeURIComponent(segments[0]);
|
||||
segments.shift();
|
||||
remaining = segments.join('/');
|
||||
}
|
||||
|
||||
const state = {
|
||||
routes: [{ name: decodeURIComponent(segments[0]) }],
|
||||
routes: [{ name: routeName, params }],
|
||||
};
|
||||
|
||||
if (current) {
|
||||
// The state should be nested inside the route we parsed before
|
||||
current.routes[0].state = state;
|
||||
} else {
|
||||
result = state;
|
||||
}
|
||||
|
||||
current = state;
|
||||
segments.shift();
|
||||
}
|
||||
|
||||
if (current == null || result == null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const query = path.split('?')[1];
|
||||
|
||||
if (query) {
|
||||
const params = query.reduce<{ [key: string]: any }>((acc, curr) => {
|
||||
const [key, value] = curr.split('=');
|
||||
const route = current.routes[0];
|
||||
|
||||
acc[decodeURIComponent(key)] = JSON.parse(decodeURIComponent(value));
|
||||
const params = queryString.parse(query);
|
||||
const config = options[route.name]
|
||||
? (options[route.name] as { parse?: ParseConfig }).parse
|
||||
: undefined;
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
if (config) {
|
||||
Object.keys(params).forEach(name => {
|
||||
if (config[name] && typeof params[name] === 'string') {
|
||||
params[name] = config[name](params[name] as string);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
current.routes[0].params = params;
|
||||
route.params = { ...route.params, ...params };
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import * as BaseActions from './BaseActions';
|
||||
import * as CommonActions from './CommonActions';
|
||||
|
||||
export { BaseActions };
|
||||
export { CommonActions };
|
||||
|
||||
export { default as BaseRouter } from './BaseRouter';
|
||||
export { default as NavigationContainer } from './NavigationContainer';
|
||||
export { default as createNavigator } from './createNavigator';
|
||||
|
||||
export { default as NavigationContext } from './NavigationContext';
|
||||
export { default as NavigationRouteContext } from './NavigationRouteContext';
|
||||
|
||||
export { default as useNavigationBuilder } from './useNavigationBuilder';
|
||||
export { default as useNavigation } from './useNavigation';
|
||||
export { default as useRoute } from './useRoute';
|
||||
export { default as useFocusEffect } from './useFocusEffect';
|
||||
export { default as useIsFocused } from './useIsFocused';
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as BaseActions from './BaseActions';
|
||||
import * as CommonActions from './CommonActions';
|
||||
import * as React from 'react';
|
||||
|
||||
export type CommonAction = BaseActions.Action;
|
||||
export type CommonAction = CommonActions.Action;
|
||||
|
||||
export type NavigationState = {
|
||||
/**
|
||||
@@ -95,7 +96,12 @@ export type DefaultNavigatorOptions<
|
||||
/**
|
||||
* Default options for all screens under this navigator.
|
||||
*/
|
||||
screenOptions?: ScreenOptions;
|
||||
screenOptions?:
|
||||
| ScreenOptions
|
||||
| ((props: {
|
||||
route: RouteProp<ParamListBase, string>;
|
||||
navigation: any;
|
||||
}) => ScreenOptions);
|
||||
};
|
||||
|
||||
export type RouterFactory<
|
||||
@@ -186,7 +192,7 @@ export type EventMapBase = {
|
||||
blur: undefined;
|
||||
};
|
||||
|
||||
export type EventArg<EventName extends string, Data> = {
|
||||
export type EventArg<EventName extends string, Data = undefined> = {
|
||||
/**
|
||||
* Type of the event (e.g. `focus`, `blur`)
|
||||
*/
|
||||
@@ -231,11 +237,14 @@ export type EventEmitter<EventMap extends { [key: string]: any }> = {
|
||||
* @param [options.target] Key of the target route which should receive the event.
|
||||
* If not specified, all routes receive the event.
|
||||
*/
|
||||
emit<EventName extends Extract<keyof EventMap, string>>(options: {
|
||||
type: EventName;
|
||||
data?: EventMap[EventName];
|
||||
target?: string;
|
||||
}): EventArg<EventName, EventMap[EventName]>;
|
||||
emit<EventName extends Extract<keyof EventMap, string>>(
|
||||
options: {
|
||||
type: EventName;
|
||||
target?: string;
|
||||
} & (EventMap[EventName] extends undefined
|
||||
? {}
|
||||
: { data: EventMap[EventName] })
|
||||
): EventArg<EventName, EventMap[EventName]>;
|
||||
};
|
||||
|
||||
export class PrivateValueStore<A, B, C> {
|
||||
@@ -261,7 +270,9 @@ type NavigationHelpersCommon<
|
||||
*
|
||||
* @param action Action object or update function.
|
||||
*/
|
||||
dispatch(action: NavigationAction | ((state: State) => State)): void;
|
||||
dispatch(
|
||||
action: NavigationAction | ((state: State) => NavigationAction)
|
||||
): void;
|
||||
|
||||
/**
|
||||
* Navigate to a route in current navigation tree.
|
||||
@@ -270,8 +281,8 @@ type NavigationHelpersCommon<
|
||||
* @param [params] Params object for the route.
|
||||
*/
|
||||
navigate<RouteName extends keyof ParamList>(
|
||||
...args: ParamList[RouteName] extends undefined
|
||||
? [RouteName] | [RouteName, undefined]
|
||||
...args: ParamList[RouteName] extends (undefined | any)
|
||||
? [RouteName] | [RouteName, ParamList[RouteName]]
|
||||
: [RouteName, ParamList[RouteName]]
|
||||
): void;
|
||||
|
||||
@@ -283,7 +294,7 @@ type NavigationHelpersCommon<
|
||||
navigate<RouteName extends keyof ParamList>(
|
||||
route:
|
||||
| { key: string; params?: ParamList[RouteName] }
|
||||
| { name: RouteName; params: ParamList[RouteName] }
|
||||
| { name: RouteName; key?: string; params: ParamList[RouteName] }
|
||||
): void;
|
||||
|
||||
/**
|
||||
@@ -294,7 +305,7 @@ type NavigationHelpersCommon<
|
||||
*/
|
||||
replace<RouteName extends keyof ParamList>(
|
||||
...args: ParamList[RouteName] extends undefined
|
||||
? [RouteName] | [RouteName, undefined]
|
||||
? [RouteName] | [RouteName, ParamList[RouteName]]
|
||||
: [RouteName, ParamList[RouteName]]
|
||||
): void;
|
||||
|
||||
@@ -326,9 +337,10 @@ type NavigationHelpersCommon<
|
||||
} & PrivateValueStore<ParamList, keyof ParamList, {}>;
|
||||
|
||||
export type NavigationHelpers<
|
||||
ParamList extends ParamListBase
|
||||
ParamList extends ParamListBase,
|
||||
EventMap extends { [key: string]: any } = {}
|
||||
> = NavigationHelpersCommon<ParamList> &
|
||||
EventEmitter<{ [key: string]: any }> & {
|
||||
EventEmitter<EventMap> & {
|
||||
/**
|
||||
* Update the param object for the route.
|
||||
* The new params will be shallow merged with the old one.
|
||||
@@ -340,6 +352,14 @@ export type NavigationHelpers<
|
||||
): void;
|
||||
};
|
||||
|
||||
export type NavigationContainerProps = {
|
||||
initialState?: InitialState;
|
||||
onStateChange?: (
|
||||
state: NavigationState | PartialState<NavigationState> | undefined
|
||||
) => void;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export type NavigationProp<
|
||||
ParamList extends ParamListBase,
|
||||
RouteName extends keyof ParamList = string,
|
||||
@@ -369,14 +389,13 @@ export type NavigationProp<
|
||||
* It can be useful to decide whether to display a back button in a stack.
|
||||
*/
|
||||
isFirstRouteInParent(): boolean;
|
||||
|
||||
/**
|
||||
* Returns the parent navigator, if any. Reason why the function is called
|
||||
* dangerouslyGetParent is to warn developers against overusing it to eg. get parent
|
||||
* of parent and other hard-to-follow patterns.
|
||||
*/
|
||||
dangerouslyGetParent():
|
||||
| NavigationProp<ParamListBase, string, any, any>
|
||||
| undefined;
|
||||
dangerouslyGetParent<T = NavigationProp<ParamListBase> | undefined>(): T;
|
||||
|
||||
/**
|
||||
* Returns the navigator's state. Reason why the function is called
|
||||
@@ -521,11 +540,24 @@ export type TypedNavigator<
|
||||
* Navigator component which manages the child screens.
|
||||
*/
|
||||
Navigator: React.ComponentType<
|
||||
React.ComponentProps<Navigator> & {
|
||||
Omit<
|
||||
React.ComponentProps<Navigator>,
|
||||
'initialRouteName' | 'screenOptions'
|
||||
> & {
|
||||
/**
|
||||
* Route to focus on initial render.
|
||||
* Name of the route to focus by on initial render.
|
||||
* If not specified, usually the first route is used.
|
||||
*/
|
||||
initialRouteName?: keyof ParamList;
|
||||
/**
|
||||
* Default options for all screens under this navigator.
|
||||
*/
|
||||
screenOptions?:
|
||||
| ScreenOptions
|
||||
| ((props: {
|
||||
route: RouteProp<ParamList, keyof ParamList>;
|
||||
navigation: any;
|
||||
}) => ScreenOptions);
|
||||
}
|
||||
>;
|
||||
/**
|
||||
|
||||
@@ -13,24 +13,30 @@ import {
|
||||
NavigationState,
|
||||
ParamListBase,
|
||||
RouteConfig,
|
||||
RouteProp,
|
||||
Router,
|
||||
} from './types';
|
||||
|
||||
type Options<ScreenOptions extends object> = {
|
||||
state: NavigationState;
|
||||
type Options<State extends NavigationState, ScreenOptions extends object> = {
|
||||
state: State;
|
||||
screens: { [key: string]: RouteConfig<ParamListBase, string, ScreenOptions> };
|
||||
navigation: NavigationHelpers<ParamListBase>;
|
||||
screenOptions?: ScreenOptions;
|
||||
screenOptions?:
|
||||
| ScreenOptions
|
||||
| ((props: {
|
||||
route: RouteProp<ParamListBase, string>;
|
||||
navigation: any;
|
||||
}) => ScreenOptions);
|
||||
onAction: (
|
||||
action: NavigationAction,
|
||||
visitedNavigators?: Set<string>
|
||||
) => boolean;
|
||||
getState: () => NavigationState;
|
||||
setState: (state: NavigationState) => void;
|
||||
getState: () => State;
|
||||
setState: (state: State) => void;
|
||||
addActionListener: (listener: ChildActionListener) => void;
|
||||
addFocusedListener: (listener: FocusedNavigationListener) => void;
|
||||
onRouteFocus: (key: string) => void;
|
||||
router: Router<NavigationState, NavigationAction>;
|
||||
router: Router<State, NavigationAction>;
|
||||
emitter: NavigationEventEmitter;
|
||||
};
|
||||
|
||||
@@ -58,7 +64,7 @@ export default function useDescriptors<
|
||||
onRouteFocus,
|
||||
router,
|
||||
emitter,
|
||||
}: Options<ScreenOptions>) {
|
||||
}: Options<State, ScreenOptions>) {
|
||||
const [options, setOptions] = React.useState<{ [key: string]: object }>({});
|
||||
const { trackAction } = React.useContext(NavigationBuilderContext);
|
||||
|
||||
@@ -93,13 +99,15 @@ export default function useDescriptors<
|
||||
return state.routes.reduce(
|
||||
(acc, route) => {
|
||||
const screen = screens[route.name];
|
||||
const navigation = navigations[route.key];
|
||||
|
||||
acc[route.key] = {
|
||||
navigation,
|
||||
render() {
|
||||
return (
|
||||
<NavigationBuilderContext.Provider key={route.key} value={context}>
|
||||
<SceneView
|
||||
navigation={navigations[route.key]}
|
||||
navigation={navigation}
|
||||
route={route}
|
||||
screen={screen}
|
||||
getState={getState}
|
||||
@@ -108,22 +116,30 @@ export default function useDescriptors<
|
||||
</NavigationBuilderContext.Provider>
|
||||
);
|
||||
},
|
||||
options: {
|
||||
// The default `screenOptions` passed to the navigator
|
||||
...screenOptions,
|
||||
// The `options` prop passed to `Screen` elements
|
||||
...(typeof screen.options === 'object' || screen.options == null
|
||||
? screen.options
|
||||
: screen.options({
|
||||
// @ts-ignore
|
||||
route,
|
||||
navigation: navigations[route.key],
|
||||
})),
|
||||
// The options set via `navigation.setOptions`
|
||||
...options[route.key],
|
||||
get options() {
|
||||
return {
|
||||
// The default `screenOptions` passed to the navigator
|
||||
...(typeof screenOptions === 'object' || screenOptions == null
|
||||
? screenOptions
|
||||
: screenOptions({
|
||||
// @ts-ignore
|
||||
route,
|
||||
navigation,
|
||||
})),
|
||||
// The `options` prop passed to `Screen` elements
|
||||
...(typeof screen.options === 'object' || screen.options == null
|
||||
? screen.options
|
||||
: screen.options({
|
||||
// @ts-ignore
|
||||
route,
|
||||
navigation,
|
||||
})),
|
||||
// The options set via `navigation.setOptions`
|
||||
...options[route.key],
|
||||
};
|
||||
},
|
||||
navigation: navigations[route.key],
|
||||
};
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as {
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
RouterFactory,
|
||||
PartialState,
|
||||
PrivateValueStore,
|
||||
NavigationAction,
|
||||
} from './types';
|
||||
|
||||
// This is to make TypeScript compiler happy
|
||||
@@ -84,8 +85,9 @@ const getRouteConfigsFromChildren = <ScreenOptions extends object>(
|
||||
*/
|
||||
export default function useNavigationBuilder<
|
||||
State extends NavigationState,
|
||||
RouterOptions extends DefaultRouterOptions,
|
||||
ScreenOptions extends object,
|
||||
RouterOptions extends DefaultRouterOptions
|
||||
EventMap extends { [key: string]: any }
|
||||
>(
|
||||
createRouter: RouterFactory<State, any, RouterOptions>,
|
||||
options: DefaultNavigatorOptions<ScreenOptions> & RouterOptions
|
||||
@@ -240,10 +242,9 @@ export default function useNavigationBuilder<
|
||||
setState,
|
||||
});
|
||||
|
||||
const navigation = useNavigationHelpers({
|
||||
const navigation = useNavigationHelpers<State, NavigationAction, EventMap>({
|
||||
onAction,
|
||||
getState,
|
||||
setState,
|
||||
emitter,
|
||||
router,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import * as BaseActions from './BaseActions';
|
||||
import * as CommonActions from './CommonActions';
|
||||
import { NavigationEventEmitter } from './useEventEmitter';
|
||||
import NavigationContext from './NavigationContext';
|
||||
|
||||
@@ -12,15 +12,15 @@ import {
|
||||
Router,
|
||||
} from './types';
|
||||
|
||||
type Options = {
|
||||
state: NavigationState;
|
||||
getState: () => NavigationState;
|
||||
type Options<State extends NavigationState> = {
|
||||
state: State;
|
||||
getState: () => State;
|
||||
navigation: NavigationHelpers<ParamListBase> &
|
||||
Partial<NavigationProp<ParamListBase, string, any, any, any>>;
|
||||
setOptions: (
|
||||
cb: (options: { [key: string]: object }) => { [key: string]: object }
|
||||
) => void;
|
||||
router: Router<NavigationState, NavigationAction>;
|
||||
router: Router<State, NavigationAction>;
|
||||
emitter: NavigationEventEmitter;
|
||||
};
|
||||
|
||||
@@ -39,7 +39,14 @@ type NavigationCache<
|
||||
export default function useNavigationCache<
|
||||
State extends NavigationState,
|
||||
ScreenOptions extends object
|
||||
>({ state, getState, navigation, setOptions, router, emitter }: Options) {
|
||||
>({
|
||||
state,
|
||||
getState,
|
||||
navigation,
|
||||
setOptions,
|
||||
router,
|
||||
emitter,
|
||||
}: Options<State>) {
|
||||
// Cache object which holds navigation objects for each screen
|
||||
// We use `React.useMemo` instead of `React.useRef` coz we want to invalidate it when deps change
|
||||
// In reality, these deps will rarely change, if ever
|
||||
@@ -53,7 +60,7 @@ export default function useNavigationCache<
|
||||
|
||||
const actions = {
|
||||
...router.actionCreators,
|
||||
...BaseActions,
|
||||
...CommonActions,
|
||||
};
|
||||
|
||||
cache.current = state.routes.reduce<NavigationCache<State, ScreenOptions>>(
|
||||
@@ -70,13 +77,17 @@ export default function useNavigationCache<
|
||||
const { emit, ...rest } = navigation;
|
||||
|
||||
const dispatch = (
|
||||
action: NavigationAction | ((state: State) => State)
|
||||
) =>
|
||||
action: NavigationAction | ((state: State) => NavigationAction)
|
||||
) => {
|
||||
const payload =
|
||||
typeof action === 'function' ? action(getState()) : action;
|
||||
|
||||
navigation.dispatch(
|
||||
typeof action === 'object' && action != null
|
||||
? { source: route.key, ...action }
|
||||
: action
|
||||
typeof payload === 'object' && payload != null
|
||||
? { source: route.key, ...payload }
|
||||
: payload
|
||||
);
|
||||
};
|
||||
|
||||
const helpers = Object.keys(actions).reduce(
|
||||
(acc, name) => {
|
||||
@@ -91,8 +102,8 @@ export default function useNavigationCache<
|
||||
...rest,
|
||||
...helpers,
|
||||
...emitter.create(route.key),
|
||||
dangerouslyGetParent: () => parentNavigation,
|
||||
dangerouslyGetState: getState as () => State,
|
||||
dangerouslyGetParent: () => parentNavigation as any,
|
||||
dangerouslyGetState: getState,
|
||||
dispatch,
|
||||
setOptions: (options: object) =>
|
||||
setOptions(o => ({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import * as BaseActions from './BaseActions';
|
||||
import * as CommonActions from './CommonActions';
|
||||
import NavigationContext from './NavigationContext';
|
||||
import { NavigationStateContext } from './NavigationContainer';
|
||||
import { NavigationEventEmitter } from './useEventEmitter';
|
||||
@@ -23,7 +23,6 @@ type Options<State extends NavigationState, Action extends NavigationAction> = {
|
||||
visitedNavigators?: Set<string>
|
||||
) => boolean;
|
||||
getState: () => State;
|
||||
setState: (state: State) => void;
|
||||
emitter: NavigationEventEmitter;
|
||||
router: Router<State, Action>;
|
||||
};
|
||||
@@ -34,24 +33,24 @@ type Options<State extends NavigationState, Action extends NavigationAction> = {
|
||||
*/
|
||||
export default function useNavigationHelpers<
|
||||
State extends NavigationState,
|
||||
Action extends NavigationAction
|
||||
>({ onAction, getState, setState, emitter, router }: Options<State, Action>) {
|
||||
Action extends NavigationAction,
|
||||
EventMap extends { [key: string]: any }
|
||||
>({ onAction, getState, emitter, router }: Options<State, Action>) {
|
||||
const parentNavigationHelpers = React.useContext(NavigationContext);
|
||||
const { performTransaction } = React.useContext(NavigationStateContext);
|
||||
|
||||
return React.useMemo(() => {
|
||||
const dispatch = (action: Action | ((state: State) => State)) =>
|
||||
const dispatch = (action: Action | ((state: State) => Action)) =>
|
||||
performTransaction(() => {
|
||||
if (typeof action === 'function') {
|
||||
setState(action(getState()));
|
||||
} else {
|
||||
onAction(action);
|
||||
}
|
||||
const payload =
|
||||
typeof action === 'function' ? action(getState()) : action;
|
||||
|
||||
onAction(payload);
|
||||
});
|
||||
|
||||
const actions = {
|
||||
...router.actionCreators,
|
||||
...BaseActions,
|
||||
...CommonActions,
|
||||
};
|
||||
|
||||
const helpers = Object.keys(actions).reduce(
|
||||
@@ -72,11 +71,13 @@ export default function useNavigationHelpers<
|
||||
? parentNavigationHelpers.isFocused
|
||||
: () => true,
|
||||
canGoBack: () =>
|
||||
router.getStateForAction(getState(), BaseActions.goBack() as Action) !==
|
||||
null ||
|
||||
router.getStateForAction(
|
||||
getState(),
|
||||
CommonActions.goBack() as Action
|
||||
) !== null ||
|
||||
(parentNavigationHelpers && parentNavigationHelpers.canGoBack()) ||
|
||||
false,
|
||||
} as NavigationHelpers<ParamListBase> &
|
||||
} as NavigationHelpers<ParamListBase, EventMap> &
|
||||
(NavigationProp<ParamListBase, string, any, any, any> | undefined);
|
||||
}, [
|
||||
router,
|
||||
@@ -84,7 +85,6 @@ export default function useNavigationHelpers<
|
||||
parentNavigationHelpers,
|
||||
emitter.emit,
|
||||
performTransaction,
|
||||
setState,
|
||||
onAction,
|
||||
]);
|
||||
}
|
||||
|
||||
22
packages/core/src/useRoute.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import * as React from 'react';
|
||||
import NavigationRouteContext from './NavigationRouteContext';
|
||||
import { ParamListBase, RouteProp } from './types';
|
||||
|
||||
/**
|
||||
* Hook to access the route prop of the parent screen anywhere.
|
||||
*
|
||||
* @returns Route prop of the parent screen.
|
||||
*/
|
||||
export default function useRoute<
|
||||
T extends RouteProp<ParamListBase, string>
|
||||
>(): T {
|
||||
const route = React.useContext(NavigationRouteContext);
|
||||
|
||||
if (route === undefined) {
|
||||
throw new Error(
|
||||
"We couldn't find a route object. Is your component inside a navigator?"
|
||||
);
|
||||
}
|
||||
|
||||
return route as T;
|
||||
}
|
||||
@@ -3,6 +3,71 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.9](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.8...@react-navigation/drawer@5.0.0-alpha.9) (2019-09-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* make example run as bare react-native project as well ([#85](https://github.com/react-navigation/navigation-ex/issues/85)) ([d16c20c](https://github.com/react-navigation/navigation-ex/commit/d16c20c))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.8](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.7...@react-navigation/drawer@5.0.0-alpha.8) (2019-08-31)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.7](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.6...@react-navigation/drawer@5.0.0-alpha.7) (2019-08-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* rename contentContainerStyle to sceneContainerStyle for drawer ([fdc24d2](https://github.com/react-navigation/navigation-ex/commit/fdc24d2))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.6](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.5...@react-navigation/drawer@5.0.0-alpha.6) (2019-08-29)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.5](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.4...@react-navigation/drawer@5.0.0-alpha.5) (2019-08-28)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.4](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.3...@react-navigation/drawer@5.0.0-alpha.4) (2019-08-27)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.3](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.2...@react-navigation/drawer@5.0.0-alpha.3) (2019-08-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix path to typescript definitions ([f182315](https://github.com/react-navigation/navigation-ex/commit/f182315))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.2](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.1...@react-navigation/drawer@5.0.0-alpha.2) (2019-08-22)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"material",
|
||||
"drawer"
|
||||
],
|
||||
"version": "5.0.0-alpha.2",
|
||||
"version": "5.0.0-alpha.9",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -21,7 +21,7 @@
|
||||
"main": "lib/commonjs/index.js",
|
||||
"react-native": "src/index.tsx",
|
||||
"module": "lib/module/index.js",
|
||||
"types": "lib/typescript/src/index.d.ts",
|
||||
"types": "lib/typescript/drawer/src/index.d.ts",
|
||||
"files": [
|
||||
"src",
|
||||
"lib"
|
||||
@@ -34,7 +34,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.2",
|
||||
"@react-navigation/routers": "^5.0.0-alpha.7",
|
||||
"react-native-safe-area-view": "^0.14.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -43,7 +43,7 @@
|
||||
"@types/react-native": "^0.60.2",
|
||||
"del-cli": "^2.0.0",
|
||||
"react": "16.8.3",
|
||||
"react-native": "^0.59.8",
|
||||
"react-native": "0.59.10",
|
||||
"react-native-gesture-handler": "^1.3.0",
|
||||
"react-native-reanimated": "^1.1.0",
|
||||
"react-native-screens": "^1.0.0-alpha.22",
|
||||
|
||||
@@ -11,7 +11,11 @@ import {
|
||||
} from '@react-navigation/routers';
|
||||
|
||||
import DrawerView from '../views/DrawerView';
|
||||
import { DrawerNavigationOptions, DrawerNavigationConfig } from '../types';
|
||||
import {
|
||||
DrawerNavigationOptions,
|
||||
DrawerNavigationConfig,
|
||||
DrawerNavigationEventMap,
|
||||
} from '../types';
|
||||
|
||||
type Props = DefaultNavigatorOptions<DrawerNavigationOptions> &
|
||||
DrawerRouterOptions &
|
||||
@@ -25,8 +29,9 @@ function DrawerNavigator({
|
||||
}: Props) {
|
||||
const { state, descriptors, navigation } = useNavigationBuilder<
|
||||
DrawerNavigationState,
|
||||
DrawerRouterOptions,
|
||||
DrawerNavigationOptions,
|
||||
DrawerRouterOptions
|
||||
DrawerNavigationEventMap
|
||||
>(DrawerRouter, {
|
||||
initialRouteName,
|
||||
children,
|
||||
|
||||
@@ -75,7 +75,7 @@ export type DrawerNavigationConfig = {
|
||||
lazy: boolean;
|
||||
/**
|
||||
* Whether a screen should be unmounted when navigating away from it.
|
||||
* Defaults to `false`..
|
||||
* Defaults to `false`.
|
||||
*/
|
||||
unmountInactiveRoutes?: boolean;
|
||||
/**
|
||||
@@ -87,7 +87,10 @@ export type DrawerNavigationConfig = {
|
||||
* Options for the content component which will be passed as props.
|
||||
*/
|
||||
contentOptions?: object;
|
||||
contentContainerStyle?: StyleProp<ViewStyle>;
|
||||
/**
|
||||
* Style object for the component wrapping the screen content.
|
||||
*/
|
||||
sceneContainerStyle?: StyleProp<ViewStyle>;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
};
|
||||
|
||||
@@ -182,6 +185,11 @@ export type DrawerNavigationEventMap = {
|
||||
drawerClose: undefined;
|
||||
};
|
||||
|
||||
export type DrawerNavigationHelpers = NavigationHelpers<
|
||||
ParamListBase,
|
||||
DrawerNavigationEventMap
|
||||
>;
|
||||
|
||||
export type DrawerNavigationProp<
|
||||
ParamList extends ParamListBase,
|
||||
RouteName extends keyof ParamList = string
|
||||
|
||||
@@ -88,7 +88,7 @@ type Props = {
|
||||
statusBarAnimation: 'slide' | 'none' | 'fade';
|
||||
overlayStyle?: StyleProp<ViewStyle>;
|
||||
drawerStyle?: StyleProp<ViewStyle>;
|
||||
contentContainerStyle?: StyleProp<ViewStyle>;
|
||||
sceneContainerStyle?: StyleProp<ViewStyle>;
|
||||
renderDrawerContent: Renderer;
|
||||
renderSceneContent: Renderer;
|
||||
gestureHandlerProps?: React.ComponentProps<typeof PanGestureHandler>;
|
||||
@@ -484,7 +484,7 @@ export default class DrawerView extends React.PureComponent<Props> {
|
||||
drawerPosition,
|
||||
drawerType,
|
||||
swipeEdgeWidth,
|
||||
contentContainerStyle,
|
||||
sceneContainerStyle,
|
||||
drawerStyle,
|
||||
overlayStyle,
|
||||
onGestureRef,
|
||||
@@ -534,7 +534,7 @@ export default class DrawerView extends React.PureComponent<Props> {
|
||||
{
|
||||
transform: [{ translateX: contentTranslateX }],
|
||||
},
|
||||
contentContainerStyle as any,
|
||||
sceneContainerStyle as any,
|
||||
]}
|
||||
>
|
||||
{renderSceneContent({ progress: this.progress })}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
import * as React from 'react';
|
||||
import { StyleSheet, View, ViewStyle, StyleProp } from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import {
|
||||
NavigationHelpers,
|
||||
ParamListBase,
|
||||
Route,
|
||||
BaseActions,
|
||||
} from '@react-navigation/core';
|
||||
import { Route, CommonActions } from '@react-navigation/core';
|
||||
import {
|
||||
DrawerActions,
|
||||
DrawerNavigationState,
|
||||
} from '@react-navigation/routers';
|
||||
|
||||
import { Scene, ContentComponentProps, DrawerDescriptorMap } from '../types';
|
||||
import {
|
||||
Scene,
|
||||
ContentComponentProps,
|
||||
DrawerDescriptorMap,
|
||||
DrawerNavigationHelpers,
|
||||
} from '../types';
|
||||
|
||||
type Props = {
|
||||
contentComponent?: React.ComponentType<ContentComponentProps>;
|
||||
contentOptions?: object;
|
||||
state: DrawerNavigationState;
|
||||
navigation: NavigationHelpers<ParamListBase>;
|
||||
navigation: DrawerNavigationHelpers;
|
||||
descriptors: DrawerDescriptorMap;
|
||||
drawerOpenProgress: Animated.Node<number>;
|
||||
drawerPosition: 'left' | 'right';
|
||||
@@ -78,7 +78,7 @@ class DrawerSidebar extends React.PureComponent<Props> {
|
||||
navigation.dispatch({
|
||||
...(focused
|
||||
? DrawerActions.closeDrawer()
|
||||
: BaseActions.navigate(route.name)),
|
||||
: CommonActions.navigate(route.name)),
|
||||
target: state.key,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -4,7 +4,6 @@ import { Dimensions, StyleSheet, I18nManager, Platform } from 'react-native';
|
||||
import { ScreenContainer } from 'react-native-screens';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
import { PanGestureHandler, ScrollView } from 'react-native-gesture-handler';
|
||||
import { ParamListBase, NavigationHelpers } from '@react-navigation/core';
|
||||
import {
|
||||
DrawerNavigationState,
|
||||
DrawerActions,
|
||||
@@ -19,11 +18,12 @@ import {
|
||||
DrawerDescriptorMap,
|
||||
DrawerNavigationConfig,
|
||||
ContentComponentProps,
|
||||
DrawerNavigationHelpers,
|
||||
} from '../types';
|
||||
|
||||
type Props = DrawerNavigationConfig & {
|
||||
state: DrawerNavigationState;
|
||||
navigation: NavigationHelpers<ParamListBase>;
|
||||
navigation: DrawerNavigationHelpers;
|
||||
descriptors: DrawerDescriptorMap;
|
||||
};
|
||||
|
||||
@@ -190,7 +190,7 @@ export default class DrawerView extends React.PureComponent<Props, State> {
|
||||
drawerPosition,
|
||||
drawerBackgroundColor,
|
||||
overlayColor,
|
||||
contentContainerStyle,
|
||||
sceneContainerStyle,
|
||||
edgeWidth,
|
||||
minSwipeDistance,
|
||||
hideStatusBar,
|
||||
@@ -222,7 +222,7 @@ export default class DrawerView extends React.PureComponent<Props, State> {
|
||||
gestureHandlerProps={gestureHandlerProps}
|
||||
drawerType={drawerType}
|
||||
drawerPosition={drawerPosition}
|
||||
contentContainerStyle={contentContainerStyle}
|
||||
sceneContainerStyle={sceneContainerStyle}
|
||||
drawerStyle={{
|
||||
backgroundColor: drawerBackgroundColor || 'white',
|
||||
width: this.state.drawerWidth,
|
||||
|
||||
1
packages/example/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
ios/Pods
|
||||
@@ -3,6 +3,67 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.7](https://github.com/satya164/navigation-ex/compare/@react-navigation/example@5.0.0-alpha.6...@react-navigation/example@5.0.0-alpha.7) (2019-09-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* compatibility layer ([e0f28a4](https://github.com/satya164/navigation-ex/commit/e0f28a4))
|
||||
* make example run as bare react-native project as well ([#85](https://github.com/satya164/navigation-ex/issues/85)) ([d16c20c](https://github.com/satya164/navigation-ex/commit/d16c20c))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.6](https://github.com/satya164/navigation-ex/compare/@react-navigation/example@5.0.0-alpha.4...@react-navigation/example@5.0.0-alpha.6) (2019-08-31)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/example
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.5](https://github.com/satya164/navigation-ex/compare/@react-navigation/example@5.0.0-alpha.4...@react-navigation/example@5.0.0-alpha.5) (2019-08-31)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/example
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.4](https://github.com/satya164/navigation-ex/compare/@react-navigation/example@5.0.0-alpha.3...@react-navigation/example@5.0.0-alpha.4) (2019-08-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* handle route names change when all routes are removed ([#86](https://github.com/satya164/navigation-ex/issues/86)) ([1b2983e](https://github.com/satya164/navigation-ex/commit/1b2983e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.3](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/example@5.0.0-alpha.2...@react-navigation/example@5.0.0-alpha.3) (2019-08-29)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* handle more methods in useScrollToTop ([f9e8c7e](https://github.com/react-navigation/navigation-ex/commit/f9e8c7e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.2](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/example@5.0.0-alpha.1...@react-navigation/example@5.0.0-alpha.2) (2019-08-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add native container ([d26b77f](https://github.com/react-navigation/navigation-ex/commit/d26b77f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 5.0.0-alpha.1 (2019-08-21)
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
If you want to run the example from the repo,
|
||||
|
||||
- Clone the repository and run `lerna bootstrap` in the root
|
||||
- Clone the repository and run `yarn` in the project root
|
||||
- Run `yarn example start` to start the packager
|
||||
- Follow the instructions to open it with the [Expo app](https://expo.io/)
|
||||
|
||||
65
packages/example/android/app/BUCK
Normal file
@@ -0,0 +1,65 @@
|
||||
# To learn about Buck see [Docs](https://buckbuild.com/).
|
||||
# To run your application with Buck:
|
||||
# - install Buck
|
||||
# - `npm start` - to start the packager
|
||||
# - `cd android`
|
||||
# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
|
||||
# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
|
||||
# - `buck install -r android/app` - compile, install and run application
|
||||
#
|
||||
|
||||
lib_deps = []
|
||||
|
||||
for jarfile in glob(['libs/*.jar']):
|
||||
name = 'jars__' + jarfile[jarfile.rindex('/') + 1: jarfile.rindex('.jar')]
|
||||
lib_deps.append(':' + name)
|
||||
prebuilt_jar(
|
||||
name = name,
|
||||
binary_jar = jarfile,
|
||||
)
|
||||
|
||||
for aarfile in glob(['libs/*.aar']):
|
||||
name = 'aars__' + aarfile[aarfile.rindex('/') + 1: aarfile.rindex('.aar')]
|
||||
lib_deps.append(':' + name)
|
||||
android_prebuilt_aar(
|
||||
name = name,
|
||||
aar = aarfile,
|
||||
)
|
||||
|
||||
android_library(
|
||||
name = "all-libs",
|
||||
exported_deps = lib_deps,
|
||||
)
|
||||
|
||||
android_library(
|
||||
name = "app-code",
|
||||
srcs = glob([
|
||||
"src/main/java/**/*.java",
|
||||
]),
|
||||
deps = [
|
||||
":all-libs",
|
||||
":build_config",
|
||||
":res",
|
||||
],
|
||||
)
|
||||
|
||||
android_build_config(
|
||||
name = "build_config",
|
||||
package = "com.reactnavigationexample",
|
||||
)
|
||||
|
||||
android_resource(
|
||||
name = "res",
|
||||
package = "com.reactnavigationexample",
|
||||
res = "src/main/res",
|
||||
)
|
||||
|
||||
android_binary(
|
||||
name = "app",
|
||||
keystore = "//android/keystores:debug",
|
||||
manifest = "src/main/AndroidManifest.xml",
|
||||
package_type = "debug",
|
||||
deps = [
|
||||
":app-code",
|
||||
],
|
||||
)
|
||||
155
packages/example/android/app/build.gradle
Normal file
@@ -0,0 +1,155 @@
|
||||
apply plugin: "com.android.application"
|
||||
|
||||
import com.android.build.OutputFile
|
||||
|
||||
/**
|
||||
* The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
|
||||
* and bundleReleaseJsAndAssets).
|
||||
* These basically call `react-native bundle` with the correct arguments during the Android build
|
||||
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
|
||||
* bundle directly from the development server. Below you can see all the possible configurations
|
||||
* and their defaults. If you decide to add a configuration block, make sure to add it before the
|
||||
* `apply from: "../../node_modules/react-native/react.gradle"` line.
|
||||
*
|
||||
* project.ext.react = [
|
||||
* // the name of the generated asset file containing your JS bundle
|
||||
* bundleAssetName: "index.android.bundle",
|
||||
*
|
||||
* // the entry file for bundle generation
|
||||
* entryFile: "index.android.js",
|
||||
*
|
||||
* // whether to bundle JS and assets in debug mode
|
||||
* bundleInDebug: false,
|
||||
*
|
||||
* // whether to bundle JS and assets in release mode
|
||||
* bundleInRelease: true,
|
||||
*
|
||||
* // whether to bundle JS and assets in another build variant (if configured).
|
||||
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
|
||||
* // The configuration property can be in the following formats
|
||||
* // 'bundleIn${productFlavor}${buildType}'
|
||||
* // 'bundleIn${buildType}'
|
||||
* // bundleInFreeDebug: true,
|
||||
* // bundleInPaidRelease: true,
|
||||
* // bundleInBeta: true,
|
||||
*
|
||||
* // whether to disable dev mode in custom build variants (by default only disabled in release)
|
||||
* // for example: to disable dev mode in the staging build type (if configured)
|
||||
* devDisabledInStaging: true,
|
||||
* // The configuration property can be in the following formats
|
||||
* // 'devDisabledIn${productFlavor}${buildType}'
|
||||
* // 'devDisabledIn${buildType}'
|
||||
*
|
||||
* // the root of your project, i.e. where "package.json" lives
|
||||
* root: "../../",
|
||||
*
|
||||
* // where to put the JS bundle asset in debug mode
|
||||
* jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
|
||||
*
|
||||
* // where to put the JS bundle asset in release mode
|
||||
* jsBundleDirRelease: "$buildDir/intermediates/assets/release",
|
||||
*
|
||||
* // where to put drawable resources / React Native assets, e.g. the ones you use via
|
||||
* // require('./image.png')), in debug mode
|
||||
* resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
|
||||
*
|
||||
* // where to put drawable resources / React Native assets, e.g. the ones you use via
|
||||
* // require('./image.png')), in release mode
|
||||
* resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
|
||||
*
|
||||
* // by default the gradle tasks are skipped if none of the JS files or assets change; this means
|
||||
* // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
|
||||
* // date; if you have any other folders that you want to ignore for performance reasons (gradle
|
||||
* // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
|
||||
* // for example, you might want to remove it from here.
|
||||
* inputExcludes: ["android/**", "ios/**"],
|
||||
*
|
||||
* // override which node gets called and with what additional arguments
|
||||
* nodeExecutableAndArgs: ["node"],
|
||||
*
|
||||
* // supply additional arguments to the packager
|
||||
* extraPackagerArgs: []
|
||||
* ]
|
||||
*/
|
||||
|
||||
project.ext.react = [
|
||||
entryFile: "index.js"
|
||||
]
|
||||
|
||||
apply from: '../../node_modules/react-native-unimodules/gradle.groovy'
|
||||
apply from: "../../node_modules/react-native/react.gradle"
|
||||
|
||||
/**
|
||||
* Set this to true to create two separate APKs instead of one:
|
||||
* - An APK that only works on ARM devices
|
||||
* - An APK that only works on x86 devices
|
||||
* The advantage is the size of the APK is reduced by about 4MB.
|
||||
* Upload all the APKs to the Play Store and people will download
|
||||
* the correct one based on the CPU architecture of their device.
|
||||
*/
|
||||
def enableSeparateBuildPerCPUArchitecture = false
|
||||
|
||||
/**
|
||||
* Run Proguard to shrink the Java bytecode in release builds.
|
||||
*/
|
||||
def enableProguardInReleaseBuilds = false
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.reactnavigationexample"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
splits {
|
||||
abi {
|
||||
reset()
|
||||
enable enableSeparateBuildPerCPUArchitecture
|
||||
universalApk false // If true, also generate a universal APK
|
||||
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled enableProguardInReleaseBuilds
|
||||
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
||||
}
|
||||
}
|
||||
// applicationVariants are e.g. debug, release
|
||||
applicationVariants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
// For each separate APK per architecture, set a unique version code as described here:
|
||||
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
|
||||
def versionCodes = ["armeabi-v7a":1, "x86":2, "arm64-v8a": 3, "x86_64": 4]
|
||||
def abi = output.getFilter(OutputFile.ABI)
|
||||
if (abi != null) { // null for the universal-debug, universal-release variants
|
||||
output.versionCodeOverride =
|
||||
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
|
||||
}
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':react-native-reanimated')
|
||||
implementation project(':react-native-gesture-handler')
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
|
||||
implementation "com.facebook.react:react-native:+" // From node_modules
|
||||
addUnimodulesDependencies()
|
||||
}
|
||||
|
||||
// Run this once to be able to run the application with BUCK
|
||||
// puts all compile dependencies into folder libs for BUCK to use
|
||||
task copyDownloadableDepsToLibs(type: Copy) {
|
||||
from configurations.compile
|
||||
into 'libs'
|
||||
}
|
||||
19
packages/example/android/app/build_defs.bzl
Normal file
@@ -0,0 +1,19 @@
|
||||
"""Helper definitions to glob .aar and .jar targets"""
|
||||
|
||||
def create_aar_targets(aarfiles):
|
||||
for aarfile in aarfiles:
|
||||
name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
|
||||
lib_deps.append(":" + name)
|
||||
android_prebuilt_aar(
|
||||
name = name,
|
||||
aar = aarfile,
|
||||
)
|
||||
|
||||
def create_jar_targets(jarfiles):
|
||||
for jarfile in jarfiles:
|
||||
name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
|
||||
lib_deps.append(":" + name)
|
||||
prebuilt_jar(
|
||||
name = name,
|
||||
binary_jar = jarfile,
|
||||
)
|
||||
17
packages/example/android/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
48
packages/example/android/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.reactnavigationexample">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
|
||||
<!-- OPTIONAL PERMISSIONS, REMOVE WHATEVER YOU DO NOT NEED -->
|
||||
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
|
||||
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
|
||||
<!-- These require runtime permissions on M -->
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
||||
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||
<!-- END OPTIONAL PERMISSIONS -->
|
||||
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:allowBackup="false"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.reactnavigationexample;
|
||||
|
||||
import com.facebook.react.ReactActivity;
|
||||
import com.facebook.react.ReactActivityDelegate;
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
|
||||
|
||||
public class MainActivity extends ReactActivity {
|
||||
|
||||
/**
|
||||
* Returns the name of the main component registered from JavaScript.
|
||||
* This is used to schedule rendering of the component.
|
||||
*/
|
||||
@Override
|
||||
protected String getMainComponentName() {
|
||||
return "ReactNavigationExample";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReactActivityDelegate createReactActivityDelegate() {
|
||||
return new ReactActivityDelegate(this, getMainComponentName()) {
|
||||
@Override
|
||||
protected ReactRootView createRootView() {
|
||||
return new RNGestureHandlerEnabledRootView(MainActivity.this);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.reactnavigationexample;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import com.facebook.react.ReactApplication;
|
||||
import com.swmansion.reanimated.ReanimatedPackage;
|
||||
import com.facebook.react.ReactNativeHost;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.shell.MainReactPackage;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import com.reactnavigationexample.generated.BasePackageList;
|
||||
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
|
||||
|
||||
import org.unimodules.adapters.react.ReactAdapterPackage;
|
||||
import org.unimodules.adapters.react.ModuleRegistryAdapter;
|
||||
import org.unimodules.adapters.react.ReactModuleRegistryProvider;
|
||||
import org.unimodules.core.interfaces.Package;
|
||||
import org.unimodules.core.interfaces.SingletonModule;
|
||||
import expo.modules.constants.ConstantsPackage;
|
||||
import expo.modules.permissions.PermissionsPackage;
|
||||
import expo.modules.filesystem.FileSystemPackage;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
private final ReactModuleRegistryProvider mModuleRegistryProvider = new ReactModuleRegistryProvider(
|
||||
new BasePackageList().getPackageList(),
|
||||
Arrays.<SingletonModule>asList()
|
||||
);
|
||||
|
||||
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new MainReactPackage(),
|
||||
new ReanimatedPackage(),
|
||||
new RNGestureHandlerPackage(),
|
||||
new ModuleRegistryAdapter(mModuleRegistryProvider)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getJSMainModuleName() {
|
||||
return "index";
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">React Navigation Example</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,8 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
39
packages/example/android/build.gradle
Normal file
@@ -0,0 +1,39 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
buildToolsVersion = "28.0.3"
|
||||
minSdkVersion = 21
|
||||
compileSdkVersion = 28
|
||||
targetSdkVersion = 27
|
||||
supportLibVersion = "28.0.0"
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
google()
|
||||
jcenter()
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
url "$rootDir/../node_modules/react-native/android"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '4.7'
|
||||
distributionUrl = distributionUrl.replace("bin", "all")
|
||||
}
|
||||
18
packages/example/android/gradle.properties
Normal file
@@ -0,0 +1,18 @@
|
||||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
||||
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
BIN
packages/example/android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
5
packages/example/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
172
packages/example/android/gradlew
vendored
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
84
packages/example/android/gradlew.bat
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
8
packages/example/android/keystores/BUCK
Normal file
@@ -0,0 +1,8 @@
|
||||
keystore(
|
||||
name = "debug",
|
||||
properties = "debug.keystore.properties",
|
||||
store = "debug.keystore",
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,4 @@
|
||||
key.store=debug.keystore
|
||||
key.alias=androiddebugkey
|
||||
key.store.password=android
|
||||
key.alias.password=android
|
||||
11
packages/example/android/settings.gradle
Normal file
@@ -0,0 +1,11 @@
|
||||
apply from: '../node_modules/react-native-unimodules/gradle.groovy'
|
||||
include ':react-native-reanimated'
|
||||
project(':react-native-reanimated').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-reanimated/android')
|
||||
includeUnimodulesProjects()
|
||||
|
||||
include ':react-native-gesture-handler'
|
||||
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')
|
||||
|
||||
rootProject.name = 'ReactNavigationExample'
|
||||
|
||||
include ':app'
|
||||
@@ -25,6 +25,9 @@
|
||||
],
|
||||
"ios": {
|
||||
"supportsTablet": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"entryPoint": "node_modules/expo/AppEntry.js"
|
||||
},
|
||||
"displayName": "React Navigation Example",
|
||||
"name": "ReactNavigationExample"
|
||||
}
|
||||
6
packages/example/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import { AppRegistry } from 'react-native';
|
||||
|
||||
// Need to add extension or eslint confuses it with app.json
|
||||
import App from './App.tsx';
|
||||
|
||||
AppRegistry.registerComponent('ReactNavigationExample', () => App);
|
||||
33
packages/example/ios/Podfile
Normal file
@@ -0,0 +1,33 @@
|
||||
platform :ios, '10.0'
|
||||
|
||||
require_relative '../node_modules/react-native-unimodules/cocoapods'
|
||||
|
||||
target 'ReactNavigationExample' do
|
||||
# Pods for ReactNavigationExample
|
||||
pod 'React', :path => '../node_modules/react-native', :subspecs => [
|
||||
'Core',
|
||||
'CxxBridge',
|
||||
'DevSupport',
|
||||
'RCTActionSheet',
|
||||
'RCTAnimation',
|
||||
'RCTBlob',
|
||||
'RCTGeolocation',
|
||||
'RCTImage',
|
||||
'RCTLinkingIOS',
|
||||
'RCTNetwork',
|
||||
'RCTSettings',
|
||||
'RCTText',
|
||||
'RCTVibration',
|
||||
'RCTWebSocket',
|
||||
]
|
||||
|
||||
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
|
||||
|
||||
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
|
||||
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
|
||||
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
|
||||
pod 'RNGestureHandler', :podspec => '../node_modules/react-native-gesture-handler/RNGestureHandler.podspec'
|
||||
pod 'RNReanimated', :podspec => '../node_modules/react-native-reanimated/RNReanimated.podspec'
|
||||
|
||||
use_unimodules!
|
||||
end
|
||||
275
packages/example/ios/Podfile.lock
Normal file
@@ -0,0 +1,275 @@
|
||||
PODS:
|
||||
- boost-for-react-native (1.63.0)
|
||||
- DoubleConversion (1.1.6)
|
||||
- EXAppLoaderProvider (6.0.0)
|
||||
- EXConstants (6.0.0):
|
||||
- UMConstantsInterface
|
||||
- UMCore
|
||||
- EXFileSystem (6.0.2):
|
||||
- UMCore
|
||||
- UMFileSystemInterface
|
||||
- EXFont (6.0.1):
|
||||
- UMCore
|
||||
- UMFontInterface
|
||||
- EXKeepAwake (6.0.0):
|
||||
- UMCore
|
||||
- EXLinearGradient (6.0.0):
|
||||
- UMCore
|
||||
- EXLocation (6.0.0):
|
||||
- UMCore
|
||||
- UMPermissionsInterface
|
||||
- UMTaskManagerInterface
|
||||
- EXPermissions (6.0.0):
|
||||
- UMCore
|
||||
- UMPermissionsInterface
|
||||
- EXSQLite (6.0.0):
|
||||
- UMCore
|
||||
- UMFileSystemInterface
|
||||
- EXWebBrowser (6.0.0):
|
||||
- UMCore
|
||||
- Folly (2018.10.22.00):
|
||||
- boost-for-react-native
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- glog (0.3.5)
|
||||
- React (0.59.10):
|
||||
- React/Core (= 0.59.10)
|
||||
- React/Core (0.59.10):
|
||||
- yoga (= 0.59.10.React)
|
||||
- React/CxxBridge (0.59.10):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- React/Core
|
||||
- React/cxxreact
|
||||
- React/jsiexecutor
|
||||
- React/cxxreact (0.59.10):
|
||||
- boost-for-react-native (= 1.63.0)
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React/jsinspector
|
||||
- React/DevSupport (0.59.10):
|
||||
- React/Core
|
||||
- React/RCTWebSocket
|
||||
- React/fishhook (0.59.10)
|
||||
- React/jsi (0.59.10):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React/jsiexecutor (0.59.10):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React/cxxreact
|
||||
- React/jsi
|
||||
- React/jsinspector (0.59.10)
|
||||
- React/RCTActionSheet (0.59.10):
|
||||
- React/Core
|
||||
- React/RCTAnimation (0.59.10):
|
||||
- React/Core
|
||||
- React/RCTBlob (0.59.10):
|
||||
- React/Core
|
||||
- React/RCTGeolocation (0.59.10):
|
||||
- React/Core
|
||||
- React/RCTImage (0.59.10):
|
||||
- React/Core
|
||||
- React/RCTNetwork
|
||||
- React/RCTLinkingIOS (0.59.10):
|
||||
- React/Core
|
||||
- React/RCTNetwork (0.59.10):
|
||||
- React/Core
|
||||
- React/RCTSettings (0.59.10):
|
||||
- React/Core
|
||||
- React/RCTText (0.59.10):
|
||||
- React/Core
|
||||
- React/RCTVibration (0.59.10):
|
||||
- React/Core
|
||||
- React/RCTWebSocket (0.59.10):
|
||||
- React/Core
|
||||
- React/fishhook
|
||||
- React/RCTBlob
|
||||
- RNGestureHandler (1.3.0):
|
||||
- React
|
||||
- RNReanimated (1.1.0):
|
||||
- React
|
||||
- UMBarCodeScannerInterface (3.0.0)
|
||||
- UMCameraInterface (3.0.0)
|
||||
- UMConstantsInterface (3.0.0)
|
||||
- UMCore (3.0.2)
|
||||
- UMFaceDetectorInterface (3.0.0)
|
||||
- UMFileSystemInterface (3.0.0)
|
||||
- UMFontInterface (3.0.0)
|
||||
- UMImageLoaderInterface (3.0.0)
|
||||
- UMPermissionsInterface (3.0.0)
|
||||
- UMReactNativeAdapter (3.0.0):
|
||||
- React
|
||||
- UMCore
|
||||
- UMFontInterface
|
||||
- UMSensorsInterface (3.0.0)
|
||||
- UMTaskManagerInterface (3.0.0)
|
||||
- yoga (0.59.10.React)
|
||||
|
||||
DEPENDENCIES:
|
||||
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
||||
- EXAppLoaderProvider (from `../node_modules/expo-app-loader-provider/ios`)
|
||||
- EXConstants (from `../node_modules/expo-constants/ios`)
|
||||
- EXFileSystem (from `../node_modules/expo-file-system/ios`)
|
||||
- EXFont (from `../node_modules/expo-font/ios`)
|
||||
- EXKeepAwake (from `../node_modules/expo-keep-awake/ios`)
|
||||
- EXLinearGradient (from `../node_modules/expo-linear-gradient/ios`)
|
||||
- EXLocation (from `../node_modules/expo-location/ios`)
|
||||
- EXPermissions (from `../node_modules/expo-permissions/ios`)
|
||||
- EXSQLite (from `../node_modules/expo-sqlite/ios`)
|
||||
- EXWebBrowser (from `../node_modules/expo-web-browser/ios`)
|
||||
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
||||
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||
- React/Core (from `../node_modules/react-native`)
|
||||
- React/CxxBridge (from `../node_modules/react-native`)
|
||||
- React/DevSupport (from `../node_modules/react-native`)
|
||||
- React/RCTActionSheet (from `../node_modules/react-native`)
|
||||
- React/RCTAnimation (from `../node_modules/react-native`)
|
||||
- React/RCTBlob (from `../node_modules/react-native`)
|
||||
- React/RCTGeolocation (from `../node_modules/react-native`)
|
||||
- React/RCTImage (from `../node_modules/react-native`)
|
||||
- React/RCTLinkingIOS (from `../node_modules/react-native`)
|
||||
- React/RCTNetwork (from `../node_modules/react-native`)
|
||||
- React/RCTSettings (from `../node_modules/react-native`)
|
||||
- React/RCTText (from `../node_modules/react-native`)
|
||||
- React/RCTVibration (from `../node_modules/react-native`)
|
||||
- React/RCTWebSocket (from `../node_modules/react-native`)
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler/RNGestureHandler.podspec`)
|
||||
- RNReanimated (from `../node_modules/react-native-reanimated/RNReanimated.podspec`)
|
||||
- UMBarCodeScannerInterface (from `../node_modules/unimodules-barcode-scanner-interface/ios`)
|
||||
- UMCameraInterface (from `../node_modules/unimodules-camera-interface/ios`)
|
||||
- UMConstantsInterface (from `../node_modules/unimodules-constants-interface/ios`)
|
||||
- "UMCore (from `../node_modules/@unimodules/core/ios`)"
|
||||
- UMFaceDetectorInterface (from `../node_modules/unimodules-face-detector-interface/ios`)
|
||||
- UMFileSystemInterface (from `../node_modules/unimodules-file-system-interface/ios`)
|
||||
- UMFontInterface (from `../node_modules/unimodules-font-interface/ios`)
|
||||
- UMImageLoaderInterface (from `../node_modules/unimodules-image-loader-interface/ios`)
|
||||
- UMPermissionsInterface (from `../node_modules/unimodules-permissions-interface/ios`)
|
||||
- "UMReactNativeAdapter (from `../node_modules/@unimodules/react-native-adapter/ios`)"
|
||||
- UMSensorsInterface (from `../node_modules/unimodules-sensors-interface/ios`)
|
||||
- UMTaskManagerInterface (from `../node_modules/unimodules-task-manager-interface/ios`)
|
||||
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- boost-for-react-native
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
DoubleConversion:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
|
||||
EXAppLoaderProvider:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/expo-app-loader-provider/ios"
|
||||
EXConstants:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/expo-constants/ios"
|
||||
EXFileSystem:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/expo-file-system/ios"
|
||||
EXFont:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/expo-font/ios"
|
||||
EXKeepAwake:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/expo-keep-awake/ios"
|
||||
EXLinearGradient:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/expo-linear-gradient/ios"
|
||||
EXLocation:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/expo-location/ios"
|
||||
EXPermissions:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/expo-permissions/ios"
|
||||
EXSQLite:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/expo-sqlite/ios"
|
||||
EXWebBrowser:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/expo-web-browser/ios"
|
||||
Folly:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
|
||||
glog:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
|
||||
React:
|
||||
:path: "../node_modules/react-native"
|
||||
RNGestureHandler:
|
||||
:podspec: "../node_modules/react-native-gesture-handler/RNGestureHandler.podspec"
|
||||
RNReanimated:
|
||||
:podspec: "../node_modules/react-native-reanimated/RNReanimated.podspec"
|
||||
UMBarCodeScannerInterface:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/unimodules-barcode-scanner-interface/ios"
|
||||
UMCameraInterface:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/unimodules-camera-interface/ios"
|
||||
UMConstantsInterface:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/unimodules-constants-interface/ios"
|
||||
UMCore:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/@unimodules/core/ios"
|
||||
UMFaceDetectorInterface:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/unimodules-face-detector-interface/ios"
|
||||
UMFileSystemInterface:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/unimodules-file-system-interface/ios"
|
||||
UMFontInterface:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/unimodules-font-interface/ios"
|
||||
UMImageLoaderInterface:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/unimodules-image-loader-interface/ios"
|
||||
UMPermissionsInterface:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/unimodules-permissions-interface/ios"
|
||||
UMReactNativeAdapter:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/@unimodules/react-native-adapter/ios"
|
||||
UMSensorsInterface:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/unimodules-sensors-interface/ios"
|
||||
UMTaskManagerInterface:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../node_modules/unimodules-task-manager-interface/ios"
|
||||
yoga:
|
||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
|
||||
DoubleConversion: bb338842f62ab1d708ceb63ec3d999f0f3d98ecd
|
||||
EXAppLoaderProvider: 7a8185228d8ba9e689a0e2d6d957fe9bdd49c8a0
|
||||
EXConstants: 5d81e84ca71b9a552529889cc798b4a04e9e22b3
|
||||
EXFileSystem: 091907902fcec9f9182b656fdead41a82f30986a
|
||||
EXFont: c862449210fc86aa11d24a202cb22c71a0d39609
|
||||
EXKeepAwake: e7cb6516675052b12a7d23291e33078b4239653a
|
||||
EXLinearGradient: 40781b77e58f844c8dc4ad310dc9755b4d3792a7
|
||||
EXLocation: 4eb76115832f08b1e78003b335c210e18fa60424
|
||||
EXPermissions: 99e52dc3e5f8e55153f1958004f6df2a30a1f2f5
|
||||
EXSQLite: 8dab6a5ab1b78be7925073d6071eb22095d4dda6
|
||||
EXWebBrowser: def838b95aa9d396f9ce71ace4e614ee16e7ee30
|
||||
Folly: de497beb10f102453a1afa9edbf8cf8a251890de
|
||||
glog: aefd1eb5dda2ab95ba0938556f34b98e2da3a60d
|
||||
React: 36d0768f9e93be2473b37e7fa64f92c1d5341eef
|
||||
RNGestureHandler: 5329a942fce3d41c68b84c2c2276ce06a696d8b0
|
||||
RNReanimated: 7a52c90473b5e81c13408d40d797b98387eaddde
|
||||
UMBarCodeScannerInterface: 84ea2d6b58ff0dc27ef9b68bab71286be18ee020
|
||||
UMCameraInterface: 26b26005d1756a0d5f4f04f1e168e39ea9154535
|
||||
UMConstantsInterface: 038bacb19de12b6fd328c589122c8dc977cccf61
|
||||
UMCore: 733094f43f7244c60ce1f0592d00013ed68fa52c
|
||||
UMFaceDetectorInterface: c9c3ae4cb045421283667a1698c2f31331f55e3f
|
||||
UMFileSystemInterface: e9adc71027017de38eaf7d05fa58b2848ecb3797
|
||||
UMFontInterface: f0c5846977ee8a93d7cfa8ae7e666772c727d195
|
||||
UMImageLoaderInterface: 36e54e570acc4d720856f03ceebc441f73ea472c
|
||||
UMPermissionsInterface: 938d010c74c43fcefc9bb990633a7c5a1631267e
|
||||
UMReactNativeAdapter: 131ea2b944ade8035f0b54c6570c405f6000548d
|
||||
UMSensorsInterface: 0ed023ce9b96f2ca6fada7bda05b7760da60b293
|
||||
UMTaskManagerInterface: 8664abd37a00715727e60df9ecd65e42ba47b548
|
||||
yoga: 684513b14b03201579ba3cee20218c9d1298b0cc
|
||||
|
||||
PODFILE CHECKSUM: 41592ff50a43d56f905dbf9c7eded4b358264eba
|
||||
|
||||
COCOAPODS: 1.7.5
|
||||
@@ -0,0 +1,423 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
B211EF582D59B69B78F6C84D /* libPods-ReactNavigationExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 04B0CC70F350992AD0879D2F /* libPods-ReactNavigationExample.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
|
||||
04B0CC70F350992AD0879D2F /* libPods-ReactNavigationExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ReactNavigationExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07F961A680F5B00A75B9A /* ReactNavigationExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReactNavigationExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ReactNavigationExample/AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = ReactNavigationExample/AppDelegate.m; sourceTree = "<group>"; };
|
||||
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = ReactNavigationExample/Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ReactNavigationExample/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ReactNavigationExample/main.m; sourceTree = "<group>"; };
|
||||
2D16E6891FA4F8E400B85C8A /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
33CD2CD6C65F08A126C2108C /* Pods-ReactNavigationExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNavigationExample.release.xcconfig"; path = "Target Support Files/Pods-ReactNavigationExample/Pods-ReactNavigationExample.release.xcconfig"; sourceTree = "<group>"; };
|
||||
5B6B5D3BFF8449A39461DB6B /* Pods-ReactNavigationExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReactNavigationExample.debug.xcconfig"; path = "Target Support Files/Pods-ReactNavigationExample/Pods-ReactNavigationExample.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B211EF582D59B69B78F6C84D /* libPods-ReactNavigationExample.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
13B07FAE1A68108700A75B9A /* ReactNavigationExample */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
);
|
||||
name = ReactNavigationExample;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1CD117872707E2627AD2A012 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B6B5D3BFF8449A39461DB6B /* Pods-ReactNavigationExample.debug.xcconfig */,
|
||||
33CD2CD6C65F08A126C2108C /* Pods-ReactNavigationExample.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||
ED2971642150620600B7C4FE /* JavaScriptCore.framework */,
|
||||
2D16E6891FA4F8E400B85C8A /* libReact.a */,
|
||||
04B0CC70F350992AD0879D2F /* libPods-ReactNavigationExample.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAE1A68108700A75B9A /* ReactNavigationExample */,
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
||||
1CD117872707E2627AD2A012 /* Pods */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 2;
|
||||
usesTabs = 0;
|
||||
};
|
||||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* ReactNavigationExample.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
13B07F861A680F5B00A75B9A /* ReactNavigationExample */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactNavigationExample" */;
|
||||
buildPhases = (
|
||||
FC67D3D0567CD942E3DA69B7 /* [CP] Check Pods Manifest.lock */,
|
||||
FD4C38642228810C00325AF5 /* Start Packager */,
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = ReactNavigationExample;
|
||||
productName = "Hello World";
|
||||
productReference = 13B07F961A680F5B00A75B9A /* ReactNavigationExample.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
83CBB9F71A601CBA00E9B192 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0940;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
00E356ED1AD99517003FC87E = {
|
||||
CreatedOnToolsVersion = 6.2;
|
||||
TestTargetID = 13B07F861A680F5B00A75B9A;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "ReactNavigationExample" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 83CBB9F61A601CBA00E9B192;
|
||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* ReactNavigationExample */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Bundle React Native code and images";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh";
|
||||
};
|
||||
FC67D3D0567CD942E3DA69B7 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-ReactNavigationExample-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
FD4C38642228810C00325AF5 /* Start Packager */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Start Packager";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
13B07FB21A68108700A75B9A /* Base */,
|
||||
);
|
||||
name = LaunchScreen.xib;
|
||||
path = ReactNavigationExample;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 5B6B5D3BFF8449A39461DB6B /* Pods-ReactNavigationExample.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEAD_CODE_STRIPPING = NO;
|
||||
INFOPLIST_FILE = ReactNavigationExample/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = ReactNavigationExample;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33CD2CD6C65F08A126C2108C /* Pods-ReactNavigationExample.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
INFOPLIST_FILE = ReactNavigationExample/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = ReactNavigationExample;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
83CBBA211A601CBA00E9B192 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactNavigationExample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13B07F941A680F5B00A75B9A /* Debug */,
|
||||
13B07F951A680F5B00A75B9A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "ReactNavigationExample" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||
83CBBA211A601CBA00E9B192 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0940"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "NO"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
|
||||
BuildableName = "libReact.a"
|
||||
BlueprintName = "React"
|
||||
ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "ReactNavigationExample.app"
|
||||
BlueprintName = "ReactNavigationExample"
|
||||
ReferencedContainer = "container:ReactNavigationExample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||
BuildableName = "ReactNavigationExampleTests.xctest"
|
||||
BlueprintName = "ReactNavigationExampleTests"
|
||||
ReferencedContainer = "container:ReactNavigationExample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||
BuildableName = "ReactNavigationExampleTests.xctest"
|
||||
BlueprintName = "ReactNavigationExampleTests"
|
||||
ReferencedContainer = "container:ReactNavigationExample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "ReactNavigationExample.app"
|
||||
BlueprintName = "ReactNavigationExample"
|
||||
ReferencedContainer = "container:ReactNavigationExample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "ReactNavigationExample.app"
|
||||
BlueprintName = "ReactNavigationExample"
|
||||
ReferencedContainer = "container:ReactNavigationExample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "ReactNavigationExample.app"
|
||||
BlueprintName = "ReactNavigationExample"
|
||||
ReferencedContainer = "container:ReactNavigationExample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
10
packages/example/ios/ReactNavigationExample.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:ReactNavigationExample.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||