mirror of
https://github.com/status-im/react-native.git
synced 2025-01-14 19:44:13 +00:00
Kill NavigationExperimental Containers
Summary: The containers in NavigationExperimental are not appropraite because the state should be held by the app's architecture, be it redux, flux, or simple component state. This diff moves the examples over to simple component state, but there are several other examples of how to use NavigationAnimatedView and the navigation reducers with redux: - https://github.com/jlyman/RN-NavigationExperimental-Redux-Example - Switching the f8 app with redux to navigation experimental: https://github.com/fbsamples/f8app/pull/14 Reviewed By: hedgerwang Differential Revision: D3219911 fb-gh-sync-id: eb0b323e2c165c32027fbd00dc6197ad441d6552 fbshipit-source-id: eb0b323e2c165c32027fbd00dc6197ad441d6552
This commit is contained in:
parent
a412fd1504
commit
14eb427a80
@ -37,10 +37,9 @@ const {
|
||||
Card: NavigationCard,
|
||||
Header: NavigationHeader,
|
||||
Reducer: NavigationReducer,
|
||||
RootContainer: NavigationRootContainer,
|
||||
} = NavigationExperimental;
|
||||
|
||||
const NavigationBasicReducer = NavigationReducer.StackReducer({
|
||||
const ExampleReducer = NavigationReducer.StackReducer({
|
||||
getPushedReducerForAction: (action) => {
|
||||
if (action.type === 'push') {
|
||||
return (state) => state || {key: action.key};
|
||||
@ -58,37 +57,41 @@ const NavigationBasicReducer = NavigationReducer.StackReducer({
|
||||
});
|
||||
|
||||
class NavigationAnimatedExample extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.state = ExampleReducer();
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this._renderCard = this._renderCard.bind(this);
|
||||
this._renderHeader = this._renderHeader.bind(this);
|
||||
this._renderNavigation = this._renderNavigation.bind(this);
|
||||
this._renderScene = this._renderScene.bind(this);
|
||||
this._renderTitleComponent = this._renderTitleComponent.bind(this);
|
||||
this._handleAction = this._handleAction.bind(this);
|
||||
}
|
||||
|
||||
_handleAction(action): boolean {
|
||||
if (!action) {
|
||||
return false;
|
||||
}
|
||||
const newState = ExampleReducer(this.state, action);
|
||||
if (newState === this.state) {
|
||||
return false;
|
||||
}
|
||||
this.setState(newState);
|
||||
return true;
|
||||
}
|
||||
|
||||
handleBackAction(): boolean {
|
||||
return this._handleAction({ type: 'BackAction', });
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<NavigationRootContainer
|
||||
reducer={NavigationBasicReducer}
|
||||
ref={navRootContainer => { this.navRootContainer = navRootContainer; }}
|
||||
persistenceKey="NavigationAnimExampleState"
|
||||
renderNavigation={this._renderNavigation}
|
||||
/>
|
||||
);
|
||||
}
|
||||
handleBackAction() {
|
||||
return (
|
||||
this.navRootContainer &&
|
||||
this.navRootContainer.handleNavigation(NavigationRootContainer.getBackAction())
|
||||
);
|
||||
}
|
||||
_renderNavigation(navigationState, onNavigate) {
|
||||
if (!navigationState) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<NavigationAnimatedView
|
||||
navigationState={navigationState}
|
||||
navigationState={this.state}
|
||||
style={styles.animatedView}
|
||||
onNavigate={this._handleAction}
|
||||
renderOverlay={this._renderHeader}
|
||||
applyAnimation={(pos, navState) => {
|
||||
Animated.timing(pos, {toValue: navState.index, duration: 500}).start();
|
||||
|
@ -1,4 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
@ -22,12 +29,10 @@ const {
|
||||
} = ReactNative;
|
||||
const NavigationExampleRow = require('./NavigationExampleRow');
|
||||
const {
|
||||
RootContainer: NavigationRootContainer,
|
||||
Reducer: NavigationReducer,
|
||||
} = NavigationExperimental;
|
||||
const StackReducer = NavigationReducer.StackReducer;
|
||||
|
||||
const NavigationBasicReducer = NavigationReducer.StackReducer({
|
||||
const ExampleReducer = NavigationReducer.StackReducer({
|
||||
getPushedReducerForAction: (action) => {
|
||||
if (action.type === 'push') {
|
||||
return (state) => state || {key: action.key};
|
||||
@ -45,47 +50,51 @@ const NavigationBasicReducer = NavigationReducer.StackReducer({
|
||||
});
|
||||
|
||||
const NavigationBasicExample = React.createClass({
|
||||
|
||||
getInitialState: function() {
|
||||
return ExampleReducer();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<NavigationRootContainer
|
||||
reducer={NavigationBasicReducer}
|
||||
persistenceKey="NavigationBasicExampleState"
|
||||
ref={navRootContainer => { this.navRootContainer = navRootContainer; }}
|
||||
renderNavigation={(navState, onNavigate) => {
|
||||
if (!navState) { return null; }
|
||||
return (
|
||||
<ScrollView style={styles.topView}>
|
||||
<NavigationExampleRow
|
||||
text={`Current page: ${navState.children[navState.index].key}`}
|
||||
/>
|
||||
<NavigationExampleRow
|
||||
text={`Push page #${navState.children.length}`}
|
||||
onPress={() => {
|
||||
onNavigate({ type: 'push', key: 'page #' + navState.children.length });
|
||||
}}
|
||||
/>
|
||||
<NavigationExampleRow
|
||||
text="pop"
|
||||
onPress={() => {
|
||||
onNavigate(NavigationRootContainer.getBackAction());
|
||||
}}
|
||||
/>
|
||||
<NavigationExampleRow
|
||||
text="Exit Basic Nav Example"
|
||||
onPress={this.props.onExampleExit}
|
||||
/>
|
||||
</ScrollView>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<ScrollView style={styles.topView}>
|
||||
<NavigationExampleRow
|
||||
text={`Current page: ${this.state.children[this.state.index].key}`}
|
||||
/>
|
||||
<NavigationExampleRow
|
||||
text={`Push page #${this.state.children.length}`}
|
||||
onPress={() => {
|
||||
this._handleAction({ type: 'push', key: 'page #' + this.state.children.length });
|
||||
}}
|
||||
/>
|
||||
<NavigationExampleRow
|
||||
text="pop"
|
||||
onPress={() => {
|
||||
this._handleAction({ type: 'BackAction' });
|
||||
}}
|
||||
/>
|
||||
<NavigationExampleRow
|
||||
text="Exit Basic Nav Example"
|
||||
onPress={this.props.onExampleExit}
|
||||
/>
|
||||
</ScrollView>
|
||||
);
|
||||
},
|
||||
|
||||
handleBackAction: function() {
|
||||
return (
|
||||
this.navRootContainer &&
|
||||
this.navRootContainer.handleNavigation(NavigationRootContainer.getBackAction())
|
||||
);
|
||||
_handleAction(action) {
|
||||
if (!action) {
|
||||
return false;
|
||||
}
|
||||
const newState = ExampleReducer(this.state, action);
|
||||
if (newState === this.state) {
|
||||
return false;
|
||||
}
|
||||
this.setState(newState);
|
||||
return true;
|
||||
},
|
||||
|
||||
handleBackAction() {
|
||||
return this._handleAction({ type: 'BackAction' });
|
||||
},
|
||||
|
||||
});
|
||||
|
@ -33,18 +33,15 @@ const {
|
||||
const {
|
||||
CardStack: NavigationCardStack,
|
||||
StateUtils: NavigationStateUtils,
|
||||
RootContainer: NavigationRootContainer,
|
||||
} = NavigationExperimental;
|
||||
|
||||
function createReducer(initialState) {
|
||||
return (currentState, action) => {
|
||||
return (currentState = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case 'RootContainerInitialAction':
|
||||
return initialState;
|
||||
|
||||
case 'push':
|
||||
return NavigationStateUtils.push(currentState, {key: action.key});
|
||||
|
||||
case 'BackAction':
|
||||
case 'back':
|
||||
case 'pop':
|
||||
return currentState.index > 0 ?
|
||||
@ -67,35 +64,46 @@ class NavigationCardStackExample extends React.Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.state = {isHorizontal: true};
|
||||
this.state = {
|
||||
isHorizontal: true,
|
||||
navState: ExampleReducer(undefined, {}),
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this._renderNavigation = this._renderNavigation.bind(this);
|
||||
this._renderScene = this._renderScene.bind(this);
|
||||
this._toggleDirection = this._toggleDirection.bind(this);
|
||||
this._handleAction = this._handleAction.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<NavigationRootContainer
|
||||
reducer={ExampleReducer}
|
||||
renderNavigation={this._renderNavigation}
|
||||
<NavigationCardStack
|
||||
direction={this.state.isHorizontal ? 'horizontal' : 'vertical'}
|
||||
navigationState={this.state.navState}
|
||||
onNavigate={this._handleAction}
|
||||
renderScene={this._renderScene}
|
||||
style={styles.main}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
_renderNavigation(navigationState, onNavigate) {
|
||||
return (
|
||||
<NavigationCardStack
|
||||
direction={this.state.isHorizontal ? 'horizontal' : 'vertical'}
|
||||
navigationState={navigationState}
|
||||
onNavigate={onNavigate}
|
||||
renderScene={this._renderScene}
|
||||
style={styles.main}
|
||||
/>
|
||||
);
|
||||
_handleAction(action): boolean {
|
||||
if (!action) {
|
||||
return false;
|
||||
}
|
||||
const newState = ExampleReducer(this.state.navState, action);
|
||||
if (newState === this.state.navState) {
|
||||
return false;
|
||||
}
|
||||
this.setState({
|
||||
navState: newState,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
handleBackAction(): boolean {
|
||||
return this._handleAction({ type: 'BackAction', });
|
||||
}
|
||||
|
||||
_renderScene(/*NavigationSceneRendererProps*/ props) {
|
||||
|
@ -36,10 +36,8 @@ const {
|
||||
|
||||
const {
|
||||
CardStack: NavigationCardStack,
|
||||
Container: NavigationContainer,
|
||||
Header: NavigationHeader,
|
||||
Reducer: NavigationReducer,
|
||||
RootContainer: NavigationRootContainer,
|
||||
View: NavigationView,
|
||||
} = NavigationExperimental;
|
||||
|
||||
@ -177,6 +175,7 @@ class ExampleTabScreen extends React.Component {
|
||||
<NavigationCardStack
|
||||
style={styles.tabContent}
|
||||
navigationState={this.props.navigationState}
|
||||
onNavigate={this.props.onNavigate}
|
||||
renderOverlay={this._renderHeader}
|
||||
renderScene={this._renderScene}
|
||||
/>
|
||||
@ -225,40 +224,42 @@ class ExampleTabScreen extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
ExampleTabScreen = NavigationContainer.create(ExampleTabScreen);
|
||||
|
||||
class NavigationCompositionExample extends React.Component {
|
||||
navRootContainer: NavigationRootContainer;
|
||||
|
||||
render() {
|
||||
return (
|
||||
<NavigationRootContainer
|
||||
reducer={ExampleAppReducer}
|
||||
persistenceKey="NavigationCompositionState"
|
||||
ref={navRootContainer => { this.navRootContainer = navRootContainer; }}
|
||||
renderNavigation={this.renderApp.bind(this)}
|
||||
/>
|
||||
);
|
||||
state: NavigationParentState;
|
||||
constructor() {
|
||||
super();
|
||||
this.state = ExampleAppReducer(undefined, {});
|
||||
}
|
||||
handleAction(action: Object): boolean {
|
||||
if (!action) {
|
||||
return false;
|
||||
}
|
||||
const newState = ExampleAppReducer(this.state, action);
|
||||
if (newState === this.state) {
|
||||
return false;
|
||||
}
|
||||
this.setState(newState);
|
||||
return true;
|
||||
}
|
||||
handleBackAction(): boolean {
|
||||
return (
|
||||
this.navRootContainer &&
|
||||
this.navRootContainer.handleNavigation(NavigationRootContainer.getBackAction())
|
||||
);
|
||||
return this.handleAction({ type: 'BackAction' });
|
||||
}
|
||||
renderApp(navigationState: NavigationParentState, onNavigate: Function) {
|
||||
if (!navigationState) {
|
||||
render() {
|
||||
if (!this.state) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<View style={styles.topView}>
|
||||
<ExampleMainView
|
||||
navigationState={navigationState}
|
||||
navigationState={this.state}
|
||||
onExampleExit={this.props.onExampleExit}
|
||||
onNavigate={this.handleAction.bind(this)}
|
||||
/>
|
||||
<NavigationExampleTabBar
|
||||
tabs={navigationState.children}
|
||||
index={navigationState.index}
|
||||
tabs={this.state.children}
|
||||
index={this.state.index}
|
||||
onNavigate={this.handleAction.bind(this)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
@ -267,15 +268,18 @@ class NavigationCompositionExample extends React.Component {
|
||||
|
||||
class ExampleMainView extends React.Component {
|
||||
_renderScene: NavigationSceneRenderer;
|
||||
_handleNavigation: Function;
|
||||
|
||||
componentWillMount() {
|
||||
this._renderScene = this._renderScene.bind(this);
|
||||
this._handleNavigation = this._handleNavigation.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<NavigationView
|
||||
navigationState={this.props.navigationState}
|
||||
onNavigate={this._handleNavigation}
|
||||
style={styles.tabsContent}
|
||||
renderScene={this._renderScene}
|
||||
/>
|
||||
@ -288,12 +292,12 @@ class ExampleMainView extends React.Component {
|
||||
<ExampleTabScreen
|
||||
key={'tab_screen' + scene.key}
|
||||
navigationState={scene.navigationState}
|
||||
onNavigate={this._handleNavigation.bind(this, scene.key)}
|
||||
onNavigate={this._handleNavigation}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
_handleNavigation(tabKey, action) {
|
||||
_handleNavigation(action: Object) {
|
||||
if (ExampleExitAction.match(action)) {
|
||||
this.props.onExampleExit();
|
||||
return;
|
||||
@ -302,8 +306,6 @@ class ExampleMainView extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
ExampleMainView = NavigationContainer.create(ExampleMainView);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
topView: {
|
||||
flex: 1,
|
||||
|
@ -1,4 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
@ -13,24 +20,20 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
NavigationExperimental,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} = ReactNative;
|
||||
const NavigationExperimental = require('NavigationExperimental');
|
||||
const React = require('react');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const Text = require('Text');
|
||||
const TouchableOpacity = require('TouchableOpacity');
|
||||
const View = require('View');
|
||||
const {
|
||||
Container: NavigationContainer,
|
||||
Reducer: NavigationReducer,
|
||||
} = NavigationExperimental;
|
||||
const {
|
||||
JumpToAction,
|
||||
} = NavigationReducer.TabsReducer;
|
||||
|
||||
var NavigationExampleTabBar = React.createClass({
|
||||
const NavigationExampleTabBar = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.tabBar}>
|
||||
@ -39,7 +42,7 @@ var NavigationExampleTabBar = React.createClass({
|
||||
);
|
||||
},
|
||||
_renderTab: function(tab, index) {
|
||||
var textStyle = [styles.tabButtonText];
|
||||
const textStyle = [styles.tabButtonText];
|
||||
if (this.props.index === index) {
|
||||
textStyle.push(styles.selectedTabButtonText);
|
||||
}
|
||||
@ -58,8 +61,6 @@ var NavigationExampleTabBar = React.createClass({
|
||||
},
|
||||
});
|
||||
|
||||
NavigationExampleTabBar = NavigationContainer.create(NavigationExampleTabBar);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
tabBar: {
|
||||
height: 50,
|
||||
|
@ -1,4 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
@ -13,22 +20,19 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
AsyncStorage,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
View,
|
||||
} = ReactNative;
|
||||
var NavigationExampleRow = require('./NavigationExampleRow');
|
||||
const AsyncStorage = require('AsyncStorage');
|
||||
const NavigationExampleRow = require('./NavigationExampleRow');
|
||||
const React = require('react');
|
||||
const ScrollView = require('ScrollView');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const View = require('View');
|
||||
|
||||
/*
|
||||
* Heads up! This file is not the real navigation example- only a utility to switch between them.
|
||||
*
|
||||
* To learn how to use the Navigation API, take a look at the following example files:
|
||||
*/
|
||||
var EXAMPLES = {
|
||||
const EXAMPLES = {
|
||||
'Tabs': require('./NavigationTabsExample'),
|
||||
'Basic': require('./NavigationBasicExample'),
|
||||
'Animated Example': require('./NavigationAnimatedExample'),
|
||||
@ -37,9 +41,9 @@ var EXAMPLES = {
|
||||
'Tic Tac Toe': require('./NavigationTicTacToeExample'),
|
||||
};
|
||||
|
||||
var EXAMPLE_STORAGE_KEY = 'NavigationExperimentalExample';
|
||||
const EXAMPLE_STORAGE_KEY = 'NavigationExperimentalExample';
|
||||
|
||||
var NavigationExperimentalExample = React.createClass({
|
||||
const NavigationExperimentalExample = React.createClass({
|
||||
statics: {
|
||||
title: 'Navigation (Experimental)',
|
||||
description: 'Upcoming navigation APIs and animated navigation views',
|
||||
@ -74,7 +78,7 @@ var NavigationExperimentalExample = React.createClass({
|
||||
},
|
||||
|
||||
_renderMenu: function() {
|
||||
var exitRow = null;
|
||||
let exitRow = null;
|
||||
if (this.props.onExampleExit) {
|
||||
exitRow = (
|
||||
<NavigationExampleRow
|
||||
@ -130,7 +134,7 @@ var NavigationExperimentalExample = React.createClass({
|
||||
return this._renderMenu();
|
||||
}
|
||||
if (EXAMPLES[this.state.example]) {
|
||||
var Component = EXAMPLES[this.state.example];
|
||||
const Component = EXAMPLES[this.state.example];
|
||||
return (
|
||||
<Component
|
||||
onExampleExit={this._exitInnerExample}
|
||||
|
@ -1,4 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
@ -22,8 +29,6 @@ const {
|
||||
View,
|
||||
} = ReactNative;
|
||||
const {
|
||||
Container: NavigationContainer,
|
||||
RootContainer: NavigationRootContainer,
|
||||
Reducer: NavigationReducer,
|
||||
} = NavigationExperimental;
|
||||
|
||||
@ -55,7 +60,6 @@ class ExmpleTabPage extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
ExmpleTabPage = NavigationContainer.create(ExmpleTabPage);
|
||||
|
||||
const ExampleTabsReducer = NavigationReducer.TabsReducer({
|
||||
tabReducers: [
|
||||
@ -66,36 +70,40 @@ const ExampleTabsReducer = NavigationReducer.TabsReducer({
|
||||
});
|
||||
|
||||
class NavigationTabsExample extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = ExampleTabsReducer(undefined, {});
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<NavigationRootContainer
|
||||
reducer={ExampleTabsReducer}
|
||||
persistenceKey="NAV_EXAMPLE_STATE_TABS"
|
||||
ref={navRootContainer => { this.navRootContainer = navRootContainer; }}
|
||||
renderNavigation={(navigationState) => {
|
||||
if (!navigationState) { return null; }
|
||||
return (
|
||||
<View style={styles.topView}>
|
||||
<ExmpleTabPage
|
||||
tabs={navigationState.children}
|
||||
index={navigationState.index}
|
||||
onExampleExit={this.props.onExampleExit}
|
||||
/>
|
||||
<NavigationExampleTabBar
|
||||
tabs={navigationState.children}
|
||||
index={navigationState.index}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<View style={styles.topView}>
|
||||
<ExmpleTabPage
|
||||
tabs={this.state.children}
|
||||
index={this.state.index}
|
||||
onExampleExit={this.props.onExampleExit}
|
||||
onNavigate={this.handleAction.bind(this)}
|
||||
/>
|
||||
<NavigationExampleTabBar
|
||||
tabs={this.state.children}
|
||||
index={this.state.index}
|
||||
onNavigate={this.handleAction.bind(this)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
handleAction(action) {
|
||||
if (!action) {
|
||||
return false;
|
||||
}
|
||||
const newState = ExampleTabsReducer(this.state, action);
|
||||
if (newState === this.state) {
|
||||
return false;
|
||||
}
|
||||
this.setState(newState);
|
||||
return true;
|
||||
}
|
||||
handleBackAction() {
|
||||
return (
|
||||
this.navRootContainer &&
|
||||
this.navRootContainer.handleNavigation(NavigationRootContainer.getBackAction())
|
||||
);
|
||||
return this.handleAction({ type: 'BackAction' });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
@ -16,19 +23,11 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
NavigationExperimental,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
} = ReactNative;
|
||||
const {
|
||||
Container: NavigationContainer,
|
||||
RootContainer: NavigationRootContainer,
|
||||
} = NavigationExperimental;
|
||||
const React = require('react');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const Text = require('Text');
|
||||
const TouchableHighlight = require('TouchableHighlight');
|
||||
const View = require('View');
|
||||
|
||||
type GameGrid = Array<Array<?string>>;
|
||||
|
||||
@ -41,7 +40,7 @@ function parseGame(game: string): GameGrid {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const row = Array(3);
|
||||
for (let j = 0; j < 3; j++) {
|
||||
const turnIndex = gameTurns.indexOf(rowLetterMap[i]+j);
|
||||
const turnIndex = gameTurns.indexOf(rowLetterMap[i] + j);
|
||||
if (turnIndex === -1) {
|
||||
row[j] = null;
|
||||
} else {
|
||||
@ -60,13 +59,13 @@ function playTurn(game: string, row: number, col: number): string {
|
||||
|
||||
function getWinner(gameString: string): ?string {
|
||||
const game = parseGame(gameString);
|
||||
for (var i = 0; i < 3; i++) {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
if (game[i][0] !== null && game[i][0] === game[i][1] &&
|
||||
game[i][0] === game[i][2]) {
|
||||
return game[i][0];
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < 3; i++) {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
if (game[0][i] !== null && game[0][i] === game[1][i] &&
|
||||
game[0][i] === game[2][i]) {
|
||||
return game[0][i];
|
||||
@ -88,8 +87,8 @@ function isGameOver(gameString: string): boolean {
|
||||
return true;
|
||||
}
|
||||
const game = parseGame(gameString);
|
||||
for (var i = 0; i < 3; i++) {
|
||||
for (var j = 0; j < 3; j++) {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let j = 0; j < 3; j++) {
|
||||
if (game[i][j] === null) {
|
||||
return false;
|
||||
}
|
||||
@ -157,10 +156,9 @@ function GameEndOverlay(props) {
|
||||
</View>
|
||||
);
|
||||
}
|
||||
GameEndOverlay = NavigationContainer.create(GameEndOverlay);
|
||||
|
||||
function TicTacToeGame(props) {
|
||||
var rows = parseGame(props.game).map((cells, row) =>
|
||||
const rows = parseGame(props.game).map((cells, row) =>
|
||||
<View key={'row' + row} style={styles.row}>
|
||||
{cells.map((player, col) =>
|
||||
<Cell
|
||||
@ -184,11 +182,11 @@ function TicTacToeGame(props) {
|
||||
</View>
|
||||
<GameEndOverlay
|
||||
game={props.game}
|
||||
onNavigate={props.onNavigate}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
TicTacToeGame = NavigationContainer.create(TicTacToeGame);
|
||||
|
||||
const GameActions = {
|
||||
Turn: (row, col) => ({type: 'TicTacToeTurnAction', row, col }),
|
||||
@ -208,21 +206,34 @@ function GameReducer(lastGame: ?string, action: Object): string {
|
||||
return lastGame;
|
||||
}
|
||||
|
||||
type AppState = {
|
||||
game: string,
|
||||
};
|
||||
|
||||
class NavigationTicTacToeExample extends React.Component {
|
||||
static GameView = TicTacToeGame;
|
||||
static GameReducer = GameReducer;
|
||||
static GameActions = GameActions;
|
||||
_handleAction: Function;
|
||||
state: AppState;
|
||||
constructor() {
|
||||
super();
|
||||
this._handleAction = this._handleAction.bind(this);
|
||||
this.state = {
|
||||
game: ''
|
||||
};
|
||||
}
|
||||
_handleAction(action: Object) {
|
||||
const newState = GameReducer(this.state.game, action);
|
||||
if (newState !== this.state.game) {
|
||||
this.setState({
|
||||
game: newState,
|
||||
});
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<NavigationRootContainer
|
||||
reducer={GameReducer}
|
||||
persistenceKey="TicTacToeGameState"
|
||||
renderNavigation={(game) => (
|
||||
<TicTacToeGame
|
||||
game={game}
|
||||
onExampleExit={this.props.onExampleExit}
|
||||
/>
|
||||
)}
|
||||
<TicTacToeGame
|
||||
game={this.state && this.state.game}
|
||||
onExampleExit={this.props.onExampleExit}
|
||||
onNavigate={this._handleAction}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
@ -25,9 +32,7 @@ export type UIExplorerExampleAction = {
|
||||
openExample: string;
|
||||
};
|
||||
|
||||
import type {BackAction} from 'NavigationRootContainer';
|
||||
|
||||
export type UIExplorerAction = BackAction | UIExplorerListWithFilterAction | UIExplorerExampleAction;
|
||||
export type UIExplorerAction = UIExplorerListWithFilterAction | UIExplorerExampleAction;
|
||||
|
||||
function ExampleListWithFilter(filter: ?string): UIExplorerListWithFilterAction {
|
||||
return {
|
||||
|
@ -1,4 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
@ -16,29 +23,24 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const AppRegistry = require('AppRegistry');
|
||||
const AsyncStorage = require('AsyncStorage');
|
||||
const BackAndroid = require('BackAndroid');
|
||||
const Dimensions = require('Dimensions');
|
||||
const DrawerLayoutAndroid = require('DrawerLayoutAndroid');
|
||||
const Linking = require('Linking');
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {
|
||||
AppRegistry,
|
||||
BackAndroid,
|
||||
Dimensions,
|
||||
DrawerLayoutAndroid,
|
||||
NavigationExperimental,
|
||||
StyleSheet,
|
||||
ToolbarAndroid,
|
||||
View,
|
||||
StatusBar,
|
||||
} = ReactNative;
|
||||
const {
|
||||
RootContainer: NavigationRootContainer,
|
||||
} = NavigationExperimental;
|
||||
const StatusBar = require('StatusBar');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const ToolbarAndroid = require('ToolbarAndroid');
|
||||
const UIExplorerExampleList = require('./UIExplorerExampleList');
|
||||
const UIExplorerList = require('./UIExplorerList');
|
||||
const UIExplorerNavigationReducer = require('./UIExplorerNavigationReducer');
|
||||
const UIExplorerStateTitleMap = require('./UIExplorerStateTitleMap');
|
||||
const URIActionMap = require('./URIActionMap');
|
||||
const View = require('View');
|
||||
|
||||
var DRAWER_WIDTH_LEFT = 56;
|
||||
const DRAWER_WIDTH_LEFT = 56;
|
||||
|
||||
type Props = {
|
||||
exampleFromAppetizeParams: string,
|
||||
@ -49,14 +51,13 @@ type State = {
|
||||
};
|
||||
|
||||
class UIExplorerApp extends React.Component {
|
||||
_handleOpenInitialExample: Function;
|
||||
_handleAction: Function;
|
||||
_renderDrawerContent: Function;
|
||||
state: State;
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this._handleOpenInitialExample = this._handleOpenInitialExample.bind(this);
|
||||
this.state = {
|
||||
initialExampleUri: props.exampleFromAppetizeParams,
|
||||
};
|
||||
this._handleAction = this._handleAction.bind(this);
|
||||
this._renderDrawerContent = this._renderDrawerContent.bind(this);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
@ -64,38 +65,28 @@ class UIExplorerApp extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// There's a race condition if we try to navigate to the specified example
|
||||
// from the initial props at the same time the navigation logic is setting
|
||||
// up the initial navigation state. This hack adds a delay to avoid this
|
||||
// scenario. So after the initial example list is shown, we then transition
|
||||
// to the initial example.
|
||||
setTimeout(this._handleOpenInitialExample, 500);
|
||||
Linking.getInitialURL().then((url) => {
|
||||
AsyncStorage.getItem('UIExplorerAppState', (err, storedString) => {
|
||||
const exampleAction = URIActionMap(this.props.exampleFromAppetizeParams);
|
||||
const urlAction = URIActionMap(url);
|
||||
const launchAction = exampleAction || urlAction;
|
||||
if (err || !storedString) {
|
||||
const initialAction = launchAction || {type: 'InitialAction'};
|
||||
this.setState(UIExplorerNavigationReducer(null, initialAction));
|
||||
return;
|
||||
}
|
||||
const storedState = JSON.parse(storedString);
|
||||
if (launchAction) {
|
||||
this.setState(UIExplorerNavigationReducer(storedState, launchAction));
|
||||
return;
|
||||
}
|
||||
this.setState(storedState);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<NavigationRootContainer
|
||||
persistenceKey="UIExplorerStateNavState"
|
||||
ref={navRootRef => { this._navigationRootRef = navRootRef; }}
|
||||
reducer={UIExplorerNavigationReducer}
|
||||
renderNavigation={this._renderApp.bind(this)}
|
||||
linkingActionMap={URIActionMap}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
_handleOpenInitialExample() {
|
||||
if (this.state.initialExampleUri) {
|
||||
const exampleAction = URIActionMap(this.state.initialExampleUri);
|
||||
if (exampleAction && this._navigationRootRef) {
|
||||
this._navigationRootRef.handleNavigation(exampleAction);
|
||||
}
|
||||
}
|
||||
this.setState({initialExampleUri: null});
|
||||
}
|
||||
|
||||
_renderApp(navigationState, onNavigate) {
|
||||
if (!navigationState) {
|
||||
if (!this.state) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
@ -110,42 +101,42 @@ class UIExplorerApp extends React.Component {
|
||||
this._overrideBackPressForDrawerLayout = false;
|
||||
}}
|
||||
ref={(drawer) => { this.drawer = drawer; }}
|
||||
renderNavigationView={this._renderDrawerContent.bind(this, onNavigate)}
|
||||
renderNavigationView={this._renderDrawerContent}
|
||||
statusBarBackgroundColor="#589c90">
|
||||
{this._renderNavigation(navigationState, onNavigate)}
|
||||
{this._renderApp()}
|
||||
</DrawerLayoutAndroid>
|
||||
);
|
||||
}
|
||||
|
||||
_renderDrawerContent(onNavigate) {
|
||||
_renderDrawerContent() {
|
||||
return (
|
||||
<View style={styles.drawerContentWrapper}>
|
||||
<UIExplorerExampleList
|
||||
list={UIExplorerList}
|
||||
displayTitleRow={true}
|
||||
disableSearch={true}
|
||||
onNavigate={(action) => {
|
||||
this.drawer && this.drawer.closeDrawer();
|
||||
onNavigate(action);
|
||||
}}
|
||||
onNavigate={this._handleAction}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_renderNavigation(navigationState, onNavigate) {
|
||||
if (navigationState.externalExample) {
|
||||
var Component = UIExplorerList.Modules[navigationState.externalExample];
|
||||
_renderApp() {
|
||||
const {
|
||||
externalExample,
|
||||
stack,
|
||||
} = this.state;
|
||||
if (externalExample) {
|
||||
const Component = UIExplorerList.Modules[externalExample];
|
||||
return (
|
||||
<Component
|
||||
onExampleExit={() => {
|
||||
onNavigate(NavigationRootContainer.getBackAction());
|
||||
this._handleAction({ type: 'BackAction' });
|
||||
}}
|
||||
ref={(example) => { this._exampleRef = example; }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
const {stack} = navigationState;
|
||||
const title = UIExplorerStateTitleMap(stack.children[stack.index]);
|
||||
const index = stack.children.length <= 1 ? 1 : stack.index;
|
||||
|
||||
@ -178,6 +169,7 @@ class UIExplorerApp extends React.Component {
|
||||
title={title}
|
||||
/>
|
||||
<UIExplorerExampleList
|
||||
onNavigate={this._handleAction}
|
||||
list={UIExplorerList}
|
||||
{...stack.children[0]}
|
||||
/>
|
||||
@ -185,6 +177,17 @@ class UIExplorerApp extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
_handleAction(action: Object): boolean {
|
||||
this.drawer && this.drawer.closeDrawer();
|
||||
const newState = UIExplorerNavigationReducer(this.state, action);
|
||||
if (this.state !== newState) {
|
||||
this.setState(newState);
|
||||
AsyncStorage.setItem('UIExplorerAppState', JSON.stringify(this.state));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_handleBackButtonPress() {
|
||||
if (this._overrideBackPressForDrawerLayout) {
|
||||
// This hack is necessary because drawer layout provides an imperative API
|
||||
@ -200,12 +203,7 @@ class UIExplorerApp extends React.Component {
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (this._navigationRootRef) {
|
||||
return this._navigationRootRef.handleNavigation(
|
||||
NavigationRootContainer.getBackAction()
|
||||
);
|
||||
}
|
||||
return false;
|
||||
return this._handleAction({ type: 'BackAction' });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,8 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const AsyncStorage = require('AsyncStorage');
|
||||
const Linking = require('Linking');
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const UIExplorerList = require('./UIExplorerList.ios');
|
||||
@ -42,7 +44,6 @@ const {
|
||||
const {
|
||||
CardStack: NavigationCardStack,
|
||||
Header: NavigationHeader,
|
||||
RootContainer: NavigationRootContainer,
|
||||
} = NavigationExperimental;
|
||||
|
||||
import type { NavigationSceneRendererProps } from 'NavigationTypeDefinition';
|
||||
@ -55,81 +56,86 @@ type Props = {
|
||||
exampleFromAppetizeParams: string,
|
||||
};
|
||||
|
||||
type State = {
|
||||
initialExampleUri: ?string,
|
||||
type State = UIExplorerNavigationState & {
|
||||
externalExample?: string,
|
||||
};
|
||||
|
||||
class UIExplorerApp extends React.Component {
|
||||
_navigationRootRef: ?NavigationRootContainer;
|
||||
_renderNavigation: Function;
|
||||
_renderOverlay: Function;
|
||||
_renderScene: Function;
|
||||
_renderCard: Function;
|
||||
_renderTitleComponent: Function;
|
||||
_handleOpenInitialExample: Function;
|
||||
_handleAction: Function;
|
||||
state: State;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this._handleOpenInitialExample = this._handleOpenInitialExample.bind(this);
|
||||
this.state = {
|
||||
initialExampleUri: props.exampleFromAppetizeParams,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this._renderNavigation = this._renderNavigation.bind(this);
|
||||
this._handleAction = this._handleAction.bind(this);
|
||||
this._renderOverlay = this._renderOverlay.bind(this);
|
||||
this._renderScene = this._renderScene.bind(this);
|
||||
this._renderTitleComponent = this._renderTitleComponent.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// There's a race condition if we try to navigate to the specified example
|
||||
// from the initial props at the same time the navigation logic is setting
|
||||
// up the initial navigation state. This hack adds a delay to avoid this
|
||||
// scenario. So after the initial example list is shown, we then transition
|
||||
// to the initial example.
|
||||
setTimeout(this._handleOpenInitialExample, 500);
|
||||
Linking.getInitialURL().then((url) => {
|
||||
AsyncStorage.getItem('UIExplorerAppState', (err, storedString) => {
|
||||
const exampleAction = URIActionMap(this.props.exampleFromAppetizeParams);
|
||||
const urlAction = URIActionMap(url);
|
||||
const launchAction = exampleAction || urlAction;
|
||||
if (err || !storedString) {
|
||||
const initialAction = launchAction || {type: 'InitialAction'};
|
||||
this.setState(UIExplorerNavigationReducer(null, initialAction));
|
||||
return;
|
||||
}
|
||||
const storedState = JSON.parse(storedString);
|
||||
if (launchAction) {
|
||||
this.setState(UIExplorerNavigationReducer(storedState, launchAction));
|
||||
return;
|
||||
}
|
||||
this.setState(storedState);
|
||||
});
|
||||
});
|
||||
|
||||
Linking.addEventListener('url', (url) => {
|
||||
this._handleAction(URIActionMap(url));
|
||||
});
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<NavigationRootContainer
|
||||
persistenceKey="UIExplorerState"
|
||||
reducer={UIExplorerNavigationReducer}
|
||||
ref={navRootRef => { this._navigationRootRef = navRootRef; }}
|
||||
renderNavigation={this._renderNavigation}
|
||||
linkingActionMap={URIActionMap}
|
||||
/>
|
||||
);
|
||||
}
|
||||
_handleOpenInitialExample() {
|
||||
if (this.state.initialExampleUri) {
|
||||
const exampleAction = URIActionMap(this.state.initialExampleUri);
|
||||
if (exampleAction && this._navigationRootRef) {
|
||||
this._navigationRootRef.handleNavigation(exampleAction);
|
||||
}
|
||||
|
||||
_handleAction(action: Object) {
|
||||
if (!action) {
|
||||
return;
|
||||
}
|
||||
const newState = UIExplorerNavigationReducer(this.state, action);
|
||||
if (this.state !== newState) {
|
||||
this.setState(newState);
|
||||
AsyncStorage.setItem('UIExplorerAppState', JSON.stringify(this.state));
|
||||
}
|
||||
this.setState({initialExampleUri: null});
|
||||
}
|
||||
_renderNavigation(navigationState: UIExplorerNavigationState, onNavigate: Function) {
|
||||
if (!navigationState) {
|
||||
|
||||
render() {
|
||||
if (!this.state) {
|
||||
return null;
|
||||
}
|
||||
if (navigationState.externalExample) {
|
||||
var Component = UIExplorerList.Modules[navigationState.externalExample];
|
||||
if (this.state.externalExample) {
|
||||
const Component = UIExplorerList.Modules[this.state.externalExample];
|
||||
return (
|
||||
<Component
|
||||
onExampleExit={() => {
|
||||
onNavigate(NavigationRootContainer.getBackAction());
|
||||
this._handleAction({ type: 'BackAction' });
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
const {stack} = navigationState;
|
||||
return (
|
||||
<NavigationCardStack
|
||||
navigationState={stack}
|
||||
navigationState={this.state.stack}
|
||||
style={styles.container}
|
||||
renderOverlay={this._renderOverlay}
|
||||
renderScene={this._renderScene}
|
||||
onNavigate={this._handleAction}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -156,6 +162,7 @@ class UIExplorerApp extends React.Component {
|
||||
if (state.key === 'AppList') {
|
||||
return (
|
||||
<UIExplorerExampleList
|
||||
onNavigate={this._handleAction}
|
||||
list={UIExplorerList}
|
||||
style={styles.exampleContainer}
|
||||
{...state}
|
||||
@ -194,9 +201,9 @@ AppRegistry.registerComponent('UIExplorerApp', () => UIExplorerApp);
|
||||
UIExplorerList.ComponentExamples.concat(UIExplorerList.APIExamples).forEach((Example: UIExplorerExample) => {
|
||||
const ExampleModule = Example.module;
|
||||
if (ExampleModule.displayName) {
|
||||
var Snapshotter = React.createClass({
|
||||
const Snapshotter = React.createClass({
|
||||
render: function() {
|
||||
var Renderable = UIExplorerExampleList.makeRenderable(ExampleModule);
|
||||
const Renderable = UIExplorerExampleList.makeRenderable(ExampleModule);
|
||||
return (
|
||||
<SnapshotViewIOS>
|
||||
<Renderable />
|
||||
|
@ -27,7 +27,6 @@ const React = require('react');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const Text = require('Text');
|
||||
const TextInput = require('TextInput');
|
||||
const NavigationContainer = require('NavigationContainer');
|
||||
const TouchableHighlight = require('TouchableHighlight');
|
||||
const View = require('View');
|
||||
const UIExplorerActions = require('./UIExplorerActions');
|
||||
@ -56,6 +55,13 @@ class UIExplorerExampleList extends React.Component {
|
||||
}) {
|
||||
|
||||
}
|
||||
|
||||
static makeRenderable(example: any): ReactClass<any> {
|
||||
return example.examples ?
|
||||
createExamplePage(null, example) :
|
||||
example;
|
||||
}
|
||||
|
||||
render(): ?ReactElement {
|
||||
const filterText = this.props.filter || '';
|
||||
const filterRegex = new RegExp(String(filterText), 'i');
|
||||
@ -160,15 +166,6 @@ class UIExplorerExampleList extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
function makeRenderable(example: any): ReactClass<any> {
|
||||
return example.examples ?
|
||||
createExamplePage(null, example) :
|
||||
example;
|
||||
}
|
||||
|
||||
UIExplorerExampleList = NavigationContainer.create(UIExplorerExampleList);
|
||||
UIExplorerExampleList.makeRenderable = makeRenderable;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
listContainer: {
|
||||
flex: 1,
|
||||
|
@ -35,7 +35,6 @@
|
||||
const Animated = require('Animated');
|
||||
const NavigationCardStackPanResponder = require('NavigationCardStackPanResponder');
|
||||
const NavigationCardStackStyleInterpolator = require('NavigationCardStackStyleInterpolator');
|
||||
const NavigationContainer = require('NavigationContainer');
|
||||
const NavigationPagerPanResponder = require('NavigationPagerPanResponder');
|
||||
const NavigationPagerStyleInterpolator = require('NavigationPagerStyleInterpolator');
|
||||
const NavigationPointerEventsContainer = require('NavigationPointerEventsContainer');
|
||||
@ -139,6 +138,11 @@ class NavigationCard extends React.Component<any, Props, any> {
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
|
||||
static CardStackPanResponder = NavigationCardStackPanResponder;
|
||||
static CardStackStyleInterpolator = NavigationCardStackStyleInterpolator;
|
||||
static PagerPanResponder = NavigationPagerPanResponder;
|
||||
static PagerStyleInterpolator = NavigationPagerStyleInterpolator;
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
@ -157,12 +161,5 @@ const styles = StyleSheet.create({
|
||||
});
|
||||
|
||||
NavigationCard = NavigationPointerEventsContainer.create(NavigationCard);
|
||||
NavigationCard = NavigationContainer.create(NavigationCard);
|
||||
|
||||
// Export these buil-in interaction modules.
|
||||
NavigationCard.CardStackPanResponder = NavigationCardStackPanResponder;
|
||||
NavigationCard.CardStackStyleInterpolator = NavigationCardStackStyleInterpolator;
|
||||
NavigationCard.PagerPanResponder = NavigationPagerPanResponder;
|
||||
NavigationCard.PagerStyleInterpolator = NavigationPagerStyleInterpolator;
|
||||
|
||||
module.exports = NavigationCard;
|
||||
|
@ -35,7 +35,6 @@
|
||||
const NavigationAnimatedView = require('NavigationAnimatedView');
|
||||
const NavigationCard = require('NavigationCard');
|
||||
const NavigationCardStackStyleInterpolator = require('NavigationCardStackStyleInterpolator');
|
||||
const NavigationContainer = require('NavigationContainer');
|
||||
const NavigationCardStackPanResponder = require('NavigationCardStackPanResponder');
|
||||
const NavigationPropTypes = require('NavigationPropTypes');
|
||||
const React = require('React');
|
||||
@ -48,6 +47,7 @@ const {PropTypes} = React;
|
||||
const {Directions} = NavigationCardStackPanResponder;
|
||||
|
||||
import type {
|
||||
NavigationActionCaller,
|
||||
NavigationParentState,
|
||||
NavigationSceneRenderer,
|
||||
NavigationSceneRendererProps,
|
||||
@ -60,6 +60,7 @@ import type {
|
||||
type Props = {
|
||||
direction: NavigationGestureDirection,
|
||||
navigationState: NavigationParentState,
|
||||
onNavigate: NavigationActionCaller,
|
||||
renderOverlay: ?NavigationSceneRenderer,
|
||||
renderScene: NavigationSceneRenderer,
|
||||
};
|
||||
@ -89,6 +90,7 @@ class NavigationCardStack extends React.Component<DefaultProps, Props, void> {
|
||||
static propTypes = {
|
||||
direction: PropTypes.oneOf([Directions.HORIZONTAL, Directions.VERTICAL]),
|
||||
navigationState: NavigationPropTypes.navigationParentState.isRequired,
|
||||
onNavigate: NavigationPropTypes.SceneRenderer.onNavigate,
|
||||
renderOverlay: PropTypes.func,
|
||||
renderScene: PropTypes.func.isRequired,
|
||||
};
|
||||
@ -120,6 +122,7 @@ class NavigationCardStack extends React.Component<DefaultProps, Props, void> {
|
||||
navigationState={this.props.navigationState}
|
||||
renderOverlay={this.props.renderOverlay}
|
||||
renderScene={this._renderScene}
|
||||
onNavigate={this.props.onNavigate}
|
||||
// $FlowFixMe - style should be declared
|
||||
style={[styles.animatedView, this.props.style]}
|
||||
/>
|
||||
@ -155,4 +158,4 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = NavigationContainer.create(NavigationCardStack);
|
||||
module.exports = NavigationCardStack;
|
||||
|
@ -34,7 +34,6 @@
|
||||
|
||||
const React = require('React');
|
||||
const ReactNative = require('react-native');
|
||||
const NavigationContainer = require('NavigationContainer');
|
||||
const NavigationHeaderTitle = require('NavigationHeaderTitle');
|
||||
const NavigationHeaderBackButton = require('NavigationHeaderBackButton');
|
||||
const NavigationPropTypes = require('NavigationPropTypes');
|
||||
@ -49,6 +48,7 @@ const {
|
||||
} = ReactNative;
|
||||
|
||||
import type {
|
||||
NavigationActionCaller,
|
||||
NavigationSceneRenderer,
|
||||
NavigationSceneRendererProps,
|
||||
NavigationStyleInterpolator,
|
||||
@ -64,8 +64,9 @@ type Props = NavigationSceneRendererProps & {
|
||||
renderLeftComponent: NavigationSceneRenderer,
|
||||
renderRightComponent: NavigationSceneRenderer,
|
||||
renderTitleComponent: NavigationSceneRenderer,
|
||||
style?: any;
|
||||
viewProps?: any;
|
||||
onNavigate: NavigationActionCaller,
|
||||
style?: any,
|
||||
viewProps?: any,
|
||||
};
|
||||
|
||||
type SubViewName = 'left' | 'title' | 'right';
|
||||
@ -86,7 +87,14 @@ class NavigationHeader extends React.Component<DefaultProps, Props, any> {
|
||||
},
|
||||
|
||||
renderLeftComponent: (props: NavigationSceneRendererProps) => {
|
||||
return props.scene.index > 0 ? <NavigationHeaderBackButton /> : null;
|
||||
if (props.scene.index === 0) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<NavigationHeaderBackButton
|
||||
onNavigate={props.onNavigate}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
renderRightComponent: (props: NavigationSceneRendererProps) => {
|
||||
@ -199,6 +207,11 @@ class NavigationHeader extends React.Component<DefaultProps, Props, any> {
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
|
||||
static HEIGHT = APPBAR_HEIGHT + STATUSBAR_HEIGHT;
|
||||
static Title = NavigationHeaderTitle;
|
||||
static BackButton = NavigationHeaderBackButton;
|
||||
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
@ -244,10 +257,4 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
const NavigationHeaderContainer = NavigationContainer.create(NavigationHeader);
|
||||
|
||||
NavigationHeaderContainer.HEIGHT = APPBAR_HEIGHT + STATUSBAR_HEIGHT;
|
||||
NavigationHeaderContainer.Title = NavigationHeaderTitle;
|
||||
NavigationHeaderContainer.BackButton = NavigationHeaderBackButton;
|
||||
|
||||
module.exports = NavigationHeaderContainer;
|
||||
module.exports = NavigationHeader;
|
||||
|
@ -1,4 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
@ -18,8 +25,6 @@
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const NavigationContainer = require('NavigationContainer');
|
||||
const NavigationRootContainer = require('NavigationRootContainer');
|
||||
|
||||
const {
|
||||
Image,
|
||||
@ -33,7 +38,7 @@ type Props = {
|
||||
}
|
||||
|
||||
const NavigationHeaderBackButton = (props: Props) => (
|
||||
<TouchableOpacity style={styles.buttonContainer} onPress={() => props.onNavigate(NavigationRootContainer.getBackAction())}>
|
||||
<TouchableOpacity style={styles.buttonContainer} onPress={() => props.onNavigate({type: 'BackAction'})}>
|
||||
<Image style={styles.button} source={require('./assets/back-icon.png')} />
|
||||
</TouchableOpacity>
|
||||
);
|
||||
@ -57,4 +62,4 @@ const styles = StyleSheet.create({
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = NavigationContainer.create(NavigationHeaderBackButton);
|
||||
module.exports = NavigationHeaderBackButton;
|
||||
|
@ -12,7 +12,6 @@
|
||||
'use strict';
|
||||
|
||||
const Animated = require('Animated');
|
||||
const NavigationContainer = require('NavigationContainer');
|
||||
const NavigationPropTypes = require('NavigationPropTypes');
|
||||
const NavigationScenesReducer = require('NavigationScenesReducer');
|
||||
const React = require('React');
|
||||
@ -243,6 +242,4 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
NavigationAnimatedView = NavigationContainer.create(NavigationAnimatedView);
|
||||
|
||||
module.exports = NavigationAnimatedView;
|
||||
|
@ -1,53 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule NavigationContainer
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
var NavigationRootContainer = require('NavigationRootContainer');
|
||||
|
||||
function createNavigationContainer(
|
||||
Component: ReactClass<any>,
|
||||
): ReactClass & Object {
|
||||
class NavigationComponent extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Component
|
||||
onNavigate={this.getNavigationHandler()}
|
||||
{...this.props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
getNavigationHandler() {
|
||||
return this.props.onNavigate || this.context.onNavigate;
|
||||
}
|
||||
getChildContext() {
|
||||
return {
|
||||
onNavigate: this.getNavigationHandler(),
|
||||
};
|
||||
}
|
||||
}
|
||||
NavigationComponent.contextTypes = {
|
||||
onNavigate: React.PropTypes.func,
|
||||
};
|
||||
NavigationComponent.childContextTypes = {
|
||||
onNavigate: React.PropTypes.func,
|
||||
};
|
||||
return NavigationComponent;
|
||||
}
|
||||
|
||||
var NavigationContainer = {
|
||||
create: createNavigationContainer,
|
||||
RootContainer: NavigationRootContainer,
|
||||
};
|
||||
|
||||
|
||||
module.exports = NavigationContainer;
|
@ -14,10 +14,8 @@
|
||||
const NavigationAnimatedView = require('NavigationAnimatedView');
|
||||
const NavigationCard = require('NavigationCard');
|
||||
const NavigationCardStack = require('NavigationCardStack');
|
||||
const NavigationContainer = require('NavigationContainer');
|
||||
const NavigationHeader = require('NavigationHeader');
|
||||
const NavigationReducer = require('NavigationReducer');
|
||||
const NavigationRootContainer = require('NavigationRootContainer');
|
||||
const NavigationStateUtils = require('NavigationStateUtils');
|
||||
const NavigationView = require('NavigationView');
|
||||
const NavigationPropTypes = require('NavigationPropTypes');
|
||||
@ -27,10 +25,6 @@ const NavigationExperimental = {
|
||||
StateUtils: NavigationStateUtils,
|
||||
Reducer: NavigationReducer,
|
||||
|
||||
// Containers
|
||||
Container: NavigationContainer,
|
||||
RootContainer: NavigationRootContainer,
|
||||
|
||||
// Views
|
||||
View: NavigationView,
|
||||
AnimatedView: NavigationAnimatedView,
|
||||
|
@ -1,191 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule NavigationRootContainer
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const AsyncStorage = require('AsyncStorage');
|
||||
const Linking = require('Linking');
|
||||
const NavigationPropTypes = require('NavigationPropTypes');
|
||||
const NavigationStateUtils = require('NavigationStateUtils');
|
||||
const Platform = require('Platform');
|
||||
const React = require('React');
|
||||
|
||||
import type {
|
||||
NavigationAction,
|
||||
NavigationParentState,
|
||||
NavigationReducer,
|
||||
NavigationRenderer,
|
||||
} from 'NavigationTypeDefinition';
|
||||
|
||||
export type BackAction = {
|
||||
type: 'BackAction',
|
||||
};
|
||||
|
||||
type Props = {
|
||||
/*
|
||||
* The default action to be passed into the reducer when getting the first
|
||||
* state. Defaults to {type: 'RootContainerInitialAction'}
|
||||
*/
|
||||
initialAction: NavigationAction,
|
||||
|
||||
/*
|
||||
* Provide linkingActionMap to instruct the container to subscribe to linking
|
||||
* events, and use this mapper to convert URIs into actions that your app can
|
||||
* handle
|
||||
*/
|
||||
linkingActionMap: ?((uri: ?string) => NavigationAction),
|
||||
|
||||
/*
|
||||
* Provide this key, and the container will store the navigation state in
|
||||
* AsyncStorage through refreshes, with the provided key
|
||||
*/
|
||||
persistenceKey: ?string,
|
||||
|
||||
|
||||
/*
|
||||
* A function that will output the latest navigation state as a function of
|
||||
* the (optional) previous state, and an action
|
||||
*/
|
||||
reducer: NavigationReducer,
|
||||
|
||||
|
||||
/*
|
||||
* Set up the rendering of the app for a given navigation state
|
||||
*/
|
||||
renderNavigation: NavigationRenderer,
|
||||
};
|
||||
|
||||
type State = {
|
||||
navState: ?NavigationParentState,
|
||||
};
|
||||
|
||||
function getBackAction(): BackAction {
|
||||
return { type: 'BackAction' };
|
||||
}
|
||||
|
||||
const {PropTypes} = React;
|
||||
|
||||
class NavigationRootContainer extends React.Component<any, Props, State> {
|
||||
_handleOpenURLEvent: Function;
|
||||
|
||||
props: Props;
|
||||
state: State;
|
||||
|
||||
static propTypes = {
|
||||
initialAction: NavigationPropTypes.action.isRequired,
|
||||
linkingActionMap: PropTypes.func,
|
||||
persistenceKey: PropTypes.string,
|
||||
reducer: PropTypes.func.isRequired,
|
||||
renderNavigation: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
initialAction: { type: 'RootContainerInitialAction' },
|
||||
};
|
||||
|
||||
static childContextTypes = {
|
||||
onNavigate: PropTypes.func,
|
||||
};
|
||||
|
||||
|
||||
static getBackAction = getBackAction;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
let navState = null;
|
||||
if (!this.props.persistenceKey) {
|
||||
navState = NavigationStateUtils.getParent(
|
||||
this.props.reducer(null, props.initialAction)
|
||||
);
|
||||
}
|
||||
this.state = { navState };
|
||||
}
|
||||
|
||||
componentWillMount(): void {
|
||||
(this: any).handleNavigation = this.handleNavigation.bind(this);
|
||||
(this: any)._handleOpenURLEvent = this._handleOpenURLEvent.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
if (this.props.linkingActionMap) {
|
||||
Linking.getInitialURL().then(this._handleOpenURL.bind(this));
|
||||
Platform.OS === 'ios' && Linking.addEventListener('url', this._handleOpenURLEvent);
|
||||
}
|
||||
if (this.props.persistenceKey) {
|
||||
AsyncStorage.getItem(this.props.persistenceKey, (err, storedString) => {
|
||||
if (err || !storedString) {
|
||||
this.setState({
|
||||
// $FlowFixMe - navState is missing properties :(
|
||||
navState: this.props.reducer(null, this.props.initialAction),
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
navState: JSON.parse(storedString),
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
if (Platform.OS === 'ios') {
|
||||
Linking.removeEventListener('url', this._handleOpenURLEvent);
|
||||
}
|
||||
}
|
||||
|
||||
_handleOpenURLEvent(event: {url: string}): void {
|
||||
this._handleOpenURL(event.url);
|
||||
}
|
||||
|
||||
_handleOpenURL(url: ?string): void {
|
||||
if (!this.props.linkingActionMap) {
|
||||
return;
|
||||
}
|
||||
const action = this.props.linkingActionMap(url);
|
||||
if (action) {
|
||||
this.handleNavigation(action);
|
||||
}
|
||||
}
|
||||
|
||||
getChildContext(): Object {
|
||||
return {
|
||||
onNavigate: this.handleNavigation,
|
||||
};
|
||||
}
|
||||
|
||||
handleNavigation(action: Object): boolean {
|
||||
const navState = this.props.reducer(this.state.navState, action);
|
||||
if (navState === this.state.navState) {
|
||||
return false;
|
||||
}
|
||||
this.setState({
|
||||
// $FlowFixMe - navState is missing properties :(
|
||||
navState,
|
||||
});
|
||||
|
||||
if (this.props.persistenceKey) {
|
||||
AsyncStorage.setItem(this.props.persistenceKey, JSON.stringify(navState));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
render(): ReactElement {
|
||||
const navigation = this.props.renderNavigation(
|
||||
this.state.navState,
|
||||
this.handleNavigation
|
||||
);
|
||||
return navigation;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = NavigationRootContainer;
|
@ -12,7 +12,6 @@
|
||||
'use strict';
|
||||
|
||||
const Animated = require('Animated');
|
||||
const NavigationContainer = require('NavigationContainer');
|
||||
const React = require('React');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const View = require('View');
|
||||
@ -179,4 +178,4 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = NavigationContainer.create(NavigationView);
|
||||
module.exports = NavigationView;
|
||||
|
@ -11,7 +11,7 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var NavigationStateUtils = require('NavigationStateUtils');
|
||||
const NavigationStateUtils = require('NavigationStateUtils');
|
||||
|
||||
import type {
|
||||
NavigationState,
|
||||
@ -19,14 +19,6 @@ import type {
|
||||
NavigationReducer,
|
||||
} from 'NavigationTypeDefinition';
|
||||
|
||||
import type {
|
||||
BackAction,
|
||||
} from 'NavigationRootContainer';
|
||||
|
||||
export type NavigationStackReducerAction = BackAction | {
|
||||
type: string,
|
||||
};
|
||||
|
||||
export type ReducerForStateHandler = (state: NavigationState) => NavigationReducer;
|
||||
|
||||
export type PushedReducerForActionHandler = (action: any, lastState: NavigationParentState) => ?NavigationReducer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user