Remove NavExperimental from UIExplorer
Summary: Simplify the UIExplorer setup, and remove dependency on NavigationExperimental, which is being phased out in favor of React Navigation. Reviewed By: mkonicek Differential Revision: D4627131 fbshipit-source-id: 6294623a885074a73c831b0d817770fbe8a90221
This commit is contained in:
parent
db8cec4331
commit
761d528153
|
@ -23,22 +23,35 @@
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
export type UIExplorerListWithFilterAction = {
|
export type UIExplorerBackAction = {
|
||||||
type: 'UIExplorerListWithFilterAction',
|
type: 'UIExplorerBackAction',
|
||||||
filter: ?string;
|
};
|
||||||
|
|
||||||
|
export type UIExplorerListAction = {
|
||||||
|
type: 'UIExplorerListAction',
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UIExplorerExampleAction = {
|
export type UIExplorerExampleAction = {
|
||||||
type: 'UIExplorerExampleAction',
|
type: 'UIExplorerExampleAction',
|
||||||
openExample: string;
|
openExample: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UIExplorerAction = UIExplorerListWithFilterAction | UIExplorerExampleAction;
|
export type UIExplorerAction = (
|
||||||
|
UIExplorerBackAction |
|
||||||
|
UIExplorerListAction |
|
||||||
|
UIExplorerExampleAction
|
||||||
|
);
|
||||||
|
|
||||||
function ExampleListWithFilter(filter: ?string): UIExplorerListWithFilterAction {
|
|
||||||
|
function Back(): UIExplorerBackAction {
|
||||||
return {
|
return {
|
||||||
type: 'UIExplorerListWithFilterAction',
|
type: 'UIExplorerBackAction',
|
||||||
filter,
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function ExampleList(): UIExplorerListAction {
|
||||||
|
return {
|
||||||
|
type: 'UIExplorerListAction',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +63,8 @@ function ExampleAction(openExample: string): UIExplorerExampleAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
const UIExplorerActions = {
|
const UIExplorerActions = {
|
||||||
ExampleListWithFilter,
|
Back,
|
||||||
|
ExampleList,
|
||||||
ExampleAction,
|
ExampleAction,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -33,18 +33,18 @@ const React = require('react');
|
||||||
const StatusBar = require('StatusBar');
|
const StatusBar = require('StatusBar');
|
||||||
const StyleSheet = require('StyleSheet');
|
const StyleSheet = require('StyleSheet');
|
||||||
const ToolbarAndroid = require('ToolbarAndroid');
|
const ToolbarAndroid = require('ToolbarAndroid');
|
||||||
|
const UIExplorerActions = require('./UIExplorerActions');
|
||||||
const UIExplorerExampleContainer = require('./UIExplorerExampleContainer');
|
const UIExplorerExampleContainer = require('./UIExplorerExampleContainer');
|
||||||
const UIExplorerExampleList = require('./UIExplorerExampleList');
|
const UIExplorerExampleList = require('./UIExplorerExampleList');
|
||||||
const UIExplorerList = require('./UIExplorerList');
|
const UIExplorerList = require('./UIExplorerList');
|
||||||
const UIExplorerNavigationReducer = require('./UIExplorerNavigationReducer');
|
const UIExplorerNavigationReducer = require('./UIExplorerNavigationReducer');
|
||||||
const UIExplorerStateTitleMap = require('./UIExplorerStateTitleMap');
|
|
||||||
const UIManager = require('UIManager');
|
const UIManager = require('UIManager');
|
||||||
const URIActionMap = require('./URIActionMap');
|
const URIActionMap = require('./URIActionMap');
|
||||||
const View = require('View');
|
const View = require('View');
|
||||||
|
|
||||||
const nativeImageSource = require('nativeImageSource');
|
const nativeImageSource = require('nativeImageSource');
|
||||||
|
|
||||||
import type {UIExplorerNavigationState} from './UIExplorerNavigationReducer';
|
import type { UIExplorerNavigationState } from './UIExplorerNavigationReducer';
|
||||||
|
|
||||||
UIManager.setLayoutAnimationEnabledExperimental(true);
|
UIManager.setLayoutAnimationEnabledExperimental(true);
|
||||||
|
|
||||||
|
@ -54,27 +54,31 @@ type Props = {
|
||||||
exampleFromAppetizeParams: string,
|
exampleFromAppetizeParams: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = UIExplorerNavigationState & {
|
const APP_STATE_KEY = 'UIExplorerAppState.v2';
|
||||||
externalExample: ?string,
|
|
||||||
};
|
const HEADER_LOGO_ICON = nativeImageSource({
|
||||||
|
android: 'launcher_icon',
|
||||||
|
width: 132,
|
||||||
|
height: 144
|
||||||
|
});
|
||||||
|
|
||||||
|
const HEADER_NAV_ICON = nativeImageSource({
|
||||||
|
android: 'ic_menu_black_24dp',
|
||||||
|
width: 48,
|
||||||
|
height: 48
|
||||||
|
});
|
||||||
|
|
||||||
class UIExplorerApp extends React.Component {
|
class UIExplorerApp extends React.Component {
|
||||||
_handleAction: Function;
|
props: Props;
|
||||||
_renderDrawerContent: Function;
|
state: UIExplorerNavigationState;
|
||||||
state: State;
|
|
||||||
constructor(props: Props) {
|
|
||||||
super(props);
|
|
||||||
this._handleAction = this._handleAction.bind(this);
|
|
||||||
this._renderDrawerContent = this._renderDrawerContent.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
BackAndroid.addEventListener('hardwareBackPress', this._handleBackButtonPress.bind(this));
|
BackAndroid.addEventListener('hardwareBackPress', this._handleBackButtonPress);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
Linking.getInitialURL().then((url) => {
|
Linking.getInitialURL().then((url) => {
|
||||||
AsyncStorage.getItem('UIExplorerAppState', (err, storedString) => {
|
AsyncStorage.getItem(APP_STATE_KEY, (err, storedString) => {
|
||||||
const exampleAction = URIActionMap(this.props.exampleFromAppetizeParams);
|
const exampleAction = URIActionMap(this.props.exampleFromAppetizeParams);
|
||||||
const urlAction = URIActionMap(url);
|
const urlAction = URIActionMap(url);
|
||||||
const launchAction = exampleAction || urlAction;
|
const launchAction = exampleAction || urlAction;
|
||||||
|
@ -116,7 +120,7 @@ class UIExplorerApp extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderDrawerContent() {
|
_renderDrawerContent = () => {
|
||||||
return (
|
return (
|
||||||
<View style={styles.drawerContentWrapper}>
|
<View style={styles.drawerContentWrapper}>
|
||||||
<UIExplorerExampleList
|
<UIExplorerExampleList
|
||||||
|
@ -127,47 +131,33 @@ class UIExplorerApp extends React.Component {
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
_renderApp() {
|
_renderApp() {
|
||||||
const {
|
const {
|
||||||
externalExample,
|
openExample,
|
||||||
stack,
|
|
||||||
} = this.state;
|
} = this.state;
|
||||||
if (externalExample) {
|
|
||||||
const Component = UIExplorerList.Modules[externalExample];
|
if (openExample) {
|
||||||
|
const ExampleModule = UIExplorerList.Modules[openExample];
|
||||||
|
if (ExampleModule.external) {
|
||||||
return (
|
return (
|
||||||
<Component
|
<ExampleModule
|
||||||
onExampleExit={() => {
|
onExampleExit={() => {
|
||||||
this._handleAction({ type: 'BackAction' });
|
this._handleAction(UIExplorerActions.Back());
|
||||||
}}
|
}}
|
||||||
ref={(example) => { this._exampleRef = example; }}
|
ref={(example) => { this._exampleRef = example; }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
} else if (ExampleModule) {
|
||||||
const title = UIExplorerStateTitleMap(stack.routes[stack.index]);
|
|
||||||
const index = stack.routes.length <= 1 ? 1 : stack.index;
|
|
||||||
|
|
||||||
if (stack && stack.routes[index]) {
|
|
||||||
const {key} = stack.routes[index];
|
|
||||||
const ExampleModule = UIExplorerList.Modules[key];
|
|
||||||
if (ExampleModule) {
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<ToolbarAndroid
|
<ToolbarAndroid
|
||||||
logo={nativeImageSource({
|
logo={HEADER_LOGO_ICON}
|
||||||
android: 'launcher_icon',
|
navIcon={HEADER_NAV_ICON}
|
||||||
width: 132,
|
|
||||||
height: 144
|
|
||||||
})}
|
|
||||||
navIcon={nativeImageSource({
|
|
||||||
android: 'ic_menu_black_24dp',
|
|
||||||
width: 48,
|
|
||||||
height: 48
|
|
||||||
})}
|
|
||||||
onIconClicked={() => this.drawer.openDrawer()}
|
onIconClicked={() => this.drawer.openDrawer()}
|
||||||
style={styles.toolbar}
|
style={styles.toolbar}
|
||||||
title={title}
|
title={ExampleModule.title}
|
||||||
/>
|
/>
|
||||||
<UIExplorerExampleContainer
|
<UIExplorerExampleContainer
|
||||||
module={ExampleModule}
|
module={ExampleModule}
|
||||||
|
@ -177,46 +167,38 @@ class UIExplorerApp extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<ToolbarAndroid
|
<ToolbarAndroid
|
||||||
logo={nativeImageSource({
|
logo={HEADER_LOGO_ICON}
|
||||||
android: 'launcher_icon',
|
navIcon={HEADER_NAV_ICON}
|
||||||
width: 132,
|
|
||||||
height: 144
|
|
||||||
})}
|
|
||||||
navIcon={nativeImageSource({
|
|
||||||
android: 'ic_menu_black_24dp',
|
|
||||||
width: 48,
|
|
||||||
height: 48
|
|
||||||
})}
|
|
||||||
onIconClicked={() => this.drawer.openDrawer()}
|
onIconClicked={() => this.drawer.openDrawer()}
|
||||||
style={styles.toolbar}
|
style={styles.toolbar}
|
||||||
title={title}
|
title="UIExplorer"
|
||||||
/>
|
/>
|
||||||
<UIExplorerExampleList
|
<UIExplorerExampleList
|
||||||
onNavigate={this._handleAction}
|
onNavigate={this._handleAction}
|
||||||
list={UIExplorerList}
|
list={UIExplorerList}
|
||||||
{...stack.routes[0]}
|
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleAction(action: Object): boolean {
|
_handleAction = (action: Object): boolean => {
|
||||||
this.drawer && this.drawer.closeDrawer();
|
this.drawer && this.drawer.closeDrawer();
|
||||||
const newState = UIExplorerNavigationReducer(this.state, action);
|
const newState = UIExplorerNavigationReducer(this.state, action);
|
||||||
if (this.state !== newState) {
|
if (this.state !== newState) {
|
||||||
this.setState(
|
this.setState(
|
||||||
newState,
|
newState,
|
||||||
() => AsyncStorage.setItem('UIExplorerAppState', JSON.stringify(this.state))
|
() => AsyncStorage.setItem(APP_STATE_KEY, JSON.stringify(this.state))
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
_handleBackButtonPress() {
|
_handleBackButtonPress = () => {
|
||||||
if (this._overrideBackPressForDrawerLayout) {
|
if (this._overrideBackPressForDrawerLayout) {
|
||||||
// This hack is necessary because drawer layout provides an imperative API
|
// This hack is necessary because drawer layout provides an imperative API
|
||||||
// with open and close methods. This code would be cleaner if the drawer
|
// with open and close methods. This code would be cleaner if the drawer
|
||||||
|
@ -231,8 +213,8 @@ class UIExplorerApp extends React.Component {
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return this._handleAction({ type: 'BackAction' });
|
return this._handleAction(UIExplorerActions.Back());
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
|
|
@ -27,62 +27,46 @@ const AsyncStorage = require('AsyncStorage');
|
||||||
const Linking = require('Linking');
|
const Linking = require('Linking');
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
const ReactNative = require('react-native');
|
const ReactNative = require('react-native');
|
||||||
|
const UIExplorerActions = require('./UIExplorerActions');
|
||||||
const UIExplorerExampleContainer = require('./UIExplorerExampleContainer');
|
const UIExplorerExampleContainer = require('./UIExplorerExampleContainer');
|
||||||
const UIExplorerExampleList = require('./UIExplorerExampleList');
|
const UIExplorerExampleList = require('./UIExplorerExampleList');
|
||||||
const UIExplorerList = require('./UIExplorerList.ios');
|
const UIExplorerList = require('./UIExplorerList.ios');
|
||||||
const UIExplorerNavigationReducer = require('./UIExplorerNavigationReducer');
|
const UIExplorerNavigationReducer = require('./UIExplorerNavigationReducer');
|
||||||
const UIExplorerStateTitleMap = require('./UIExplorerStateTitleMap');
|
|
||||||
const URIActionMap = require('./URIActionMap');
|
const URIActionMap = require('./URIActionMap');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
Button,
|
||||||
AppRegistry,
|
AppRegistry,
|
||||||
NavigationExperimental,
|
|
||||||
SnapshotViewIOS,
|
SnapshotViewIOS,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
|
Text,
|
||||||
View,
|
View,
|
||||||
} = ReactNative;
|
} = ReactNative;
|
||||||
|
|
||||||
const {
|
|
||||||
CardStack: NavigationCardStack,
|
|
||||||
Header: NavigationHeader,
|
|
||||||
} = NavigationExperimental;
|
|
||||||
|
|
||||||
import type { NavigationSceneRendererProps } from 'NavigationTypeDefinition';
|
|
||||||
|
|
||||||
import type { UIExplorerNavigationState } from './UIExplorerNavigationReducer';
|
|
||||||
|
|
||||||
import type { UIExplorerExample } from './UIExplorerList.ios';
|
import type { UIExplorerExample } from './UIExplorerList.ios';
|
||||||
|
import type { UIExplorerAction } from './UIExplorerActions';
|
||||||
|
import type { UIExplorerNavigationState } from './UIExplorerNavigationReducer';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
exampleFromAppetizeParams: string,
|
exampleFromAppetizeParams: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = UIExplorerNavigationState & {
|
const APP_STATE_KEY = 'UIExplorerAppState.v2';
|
||||||
externalExample?: string,
|
|
||||||
};
|
|
||||||
|
|
||||||
const APP_STATE_KEY = 'UIExplorerAppState.v1';
|
const Header = ({ onBack, title}) => (
|
||||||
|
<View style={styles.header}>
|
||||||
|
<View style={styles.headerCenter}>
|
||||||
|
<Text style={styles.title}>{title}</Text>
|
||||||
|
</View>
|
||||||
|
{onBack && <View style={styles.headerLeft}>
|
||||||
|
<Button title="Back" onPress={onBack} />
|
||||||
|
</View>}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
class UIExplorerApp extends React.Component {
|
class UIExplorerApp extends React.Component {
|
||||||
_handleBack: Function;
|
props: Props;
|
||||||
_handleAction: Function;
|
state: UIExplorerNavigationState;
|
||||||
_renderCard: Function;
|
|
||||||
_renderHeader: Function;
|
|
||||||
_renderScene: Function;
|
|
||||||
_renderTitleComponent: Function;
|
|
||||||
state: State;
|
|
||||||
|
|
||||||
constructor(props: Props) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
this._handleAction = this._handleAction.bind(this);
|
|
||||||
this._handleBack = this._handleAction.bind(this, {type: 'back'});
|
|
||||||
this._renderHeader = this._renderHeader.bind(this);
|
|
||||||
this._renderScene = this._renderScene.bind(this);
|
|
||||||
this._renderTitleComponent = this._renderTitleComponent.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
Linking.getInitialURL().then((url) => {
|
Linking.getInitialURL().then((url) => {
|
||||||
|
@ -92,7 +76,7 @@ class UIExplorerApp extends React.Component {
|
||||||
const launchAction = exampleAction || urlAction;
|
const launchAction = exampleAction || urlAction;
|
||||||
if (err || !storedString) {
|
if (err || !storedString) {
|
||||||
const initialAction = launchAction || {type: 'InitialAction'};
|
const initialAction = launchAction || {type: 'InitialAction'};
|
||||||
this.setState(UIExplorerNavigationReducer(null, initialAction));
|
this.setState(UIExplorerNavigationReducer(undefined, initialAction));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const storedState = JSON.parse(storedString);
|
const storedState = JSON.parse(storedString);
|
||||||
|
@ -109,7 +93,11 @@ class UIExplorerApp extends React.Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleAction(action: Object) {
|
_handleBack = () => {
|
||||||
|
this._handleAction(UIExplorerActions.Back());
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleAction = (action: ?UIExplorerAction) => {
|
||||||
if (!action) {
|
if (!action) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -126,73 +114,58 @@ class UIExplorerApp extends React.Component {
|
||||||
if (!this.state) {
|
if (!this.state) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (this.state.externalExample) {
|
if (this.state.openExample) {
|
||||||
const Component = UIExplorerList.Modules[this.state.externalExample];
|
const Component = UIExplorerList.Modules[this.state.openExample];
|
||||||
|
if (Component.external) {
|
||||||
return (
|
return (
|
||||||
<Component
|
<Component
|
||||||
onExampleExit={() => {
|
onExampleExit={this._handleBack}
|
||||||
this._handleAction({ type: 'BackAction' });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
} else {
|
||||||
return (
|
|
||||||
<NavigationCardStack
|
|
||||||
navigationState={this.state.stack}
|
|
||||||
style={styles.container}
|
|
||||||
renderHeader={this._renderHeader}
|
|
||||||
renderScene={this._renderScene}
|
|
||||||
onNavigateBack={this._handleBack}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_renderHeader(props: NavigationSceneRendererProps): React.Element<any> {
|
|
||||||
return (
|
|
||||||
<NavigationHeader
|
|
||||||
{...props}
|
|
||||||
onNavigateBack={this._handleBack}
|
|
||||||
renderTitleComponent={this._renderTitleComponent}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_renderTitleComponent(props: NavigationSceneRendererProps): React.Element<any> {
|
|
||||||
return (
|
|
||||||
<NavigationHeader.Title>
|
|
||||||
{UIExplorerStateTitleMap(props.scene.route)}
|
|
||||||
</NavigationHeader.Title>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_renderScene(props: NavigationSceneRendererProps): ?React.Element<any> {
|
|
||||||
const state = props.scene.route;
|
|
||||||
if (state.key === 'AppList') {
|
|
||||||
return (
|
|
||||||
<UIExplorerExampleList
|
|
||||||
onNavigate={this._handleAction}
|
|
||||||
list={UIExplorerList}
|
|
||||||
style={styles.exampleContainer}
|
|
||||||
{...state}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Example = UIExplorerList.Modules[state.key];
|
|
||||||
if (Example) {
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.exampleContainer}>
|
<View style={styles.exampleContainer}>
|
||||||
<UIExplorerExampleContainer module={Example} />
|
<Header onBack={this._handleBack} title={Component.title} />
|
||||||
|
<UIExplorerExampleContainer module={Component} />
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<View style={styles.exampleContainer}>
|
||||||
|
<Header title="UIExplorer" />
|
||||||
|
<UIExplorerExampleList
|
||||||
|
onNavigate={this._handleAction}
|
||||||
|
list={UIExplorerList}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
header: {
|
||||||
|
height: 60,
|
||||||
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||||
|
borderBottomColor: '#96969A',
|
||||||
|
backgroundColor: '#F5F5F6',
|
||||||
|
flexDirection: 'row',
|
||||||
|
paddingTop: 20,
|
||||||
|
},
|
||||||
|
headerLeft: {
|
||||||
|
},
|
||||||
|
headerCenter: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
position: 'absolute',
|
||||||
|
top: 27,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 19,
|
||||||
|
fontWeight: '600',
|
||||||
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
exampleContainer: {
|
exampleContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
|
|
@ -154,9 +154,7 @@ class UIExplorerExampleList extends React.Component {
|
||||||
}}}
|
}}}
|
||||||
onNavigate={this.props.onNavigate}
|
onNavigate={this.props.onNavigate}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
this.props.onNavigate(
|
this.props.onNavigate(UIExplorerActions.ExampleList());
|
||||||
UIExplorerActions.ExampleListWithFilter('')
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -23,151 +23,47 @@
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ReactNative = require('react-native');
|
|
||||||
// $FlowFixMe : This is a platform-forked component, and flow seems to only run on iOS?
|
// $FlowFixMe : This is a platform-forked component, and flow seems to only run on iOS?
|
||||||
const UIExplorerList = require('./UIExplorerList');
|
const UIExplorerList = require('./UIExplorerList');
|
||||||
|
|
||||||
const {
|
|
||||||
NavigationExperimental,
|
|
||||||
} = ReactNative;
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
StateUtils: NavigationStateUtils,
|
|
||||||
} = NavigationExperimental;
|
|
||||||
|
|
||||||
import type {NavigationState} from 'NavigationTypeDefinition';
|
|
||||||
|
|
||||||
export type UIExplorerNavigationState = {
|
export type UIExplorerNavigationState = {
|
||||||
externalExample: ?string;
|
openExample: ?string,
|
||||||
stack: NavigationState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultGetReducerForState = (initialState) => (state) => state || initialState;
|
function UIExplorerNavigationReducer(
|
||||||
|
state: ?UIExplorerNavigationState,
|
||||||
|
action: any
|
||||||
|
): UIExplorerNavigationState {
|
||||||
|
|
||||||
function getNavigationState(state: any): ?NavigationState {
|
|
||||||
if (
|
if (
|
||||||
(state instanceof Object) &&
|
// Default value is to see example list
|
||||||
(state.routes instanceof Array) &&
|
!state ||
|
||||||
(state.routes[0] !== undefined) &&
|
|
||||||
(typeof state.index === 'number') &&
|
// Handle the explicit list action
|
||||||
(state.routes[state.index] !== undefined)
|
action.type === 'UIExplorerListAction' ||
|
||||||
|
|
||||||
|
// Handle requests to go back to the list when an example is open
|
||||||
|
(state.openExample && action.type === 'UIExplorerBackAction')
|
||||||
) {
|
) {
|
||||||
return state;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function StackReducer({initialState, getReducerForState, getPushedReducerForAction}: any): Function {
|
|
||||||
const getReducerForStateWithDefault = getReducerForState || defaultGetReducerForState;
|
|
||||||
return function (lastState: ?NavigationState, action: any): NavigationState {
|
|
||||||
if (!lastState) {
|
|
||||||
return initialState;
|
|
||||||
}
|
|
||||||
const lastParentState = getNavigationState(lastState);
|
|
||||||
if (!lastParentState) {
|
|
||||||
return lastState;
|
|
||||||
}
|
|
||||||
|
|
||||||
const activeSubState = lastParentState.routes[lastParentState.index];
|
|
||||||
const activeSubReducer = getReducerForStateWithDefault(activeSubState);
|
|
||||||
const nextActiveState = activeSubReducer(activeSubState, action);
|
|
||||||
if (nextActiveState !== activeSubState) {
|
|
||||||
const nextChildren = [...lastParentState.routes];
|
|
||||||
nextChildren[lastParentState.index] = nextActiveState;
|
|
||||||
return {
|
return {
|
||||||
...lastParentState,
|
// A null openExample will cause the views to display the UIExplorer example list
|
||||||
routes: nextChildren,
|
openExample: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const subReducerToPush = getPushedReducerForAction(action, lastParentState);
|
|
||||||
if (subReducerToPush) {
|
|
||||||
return NavigationStateUtils.push(
|
|
||||||
lastParentState,
|
|
||||||
subReducerToPush(null, action)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (action.type) {
|
|
||||||
case 'back':
|
|
||||||
case 'BackAction':
|
|
||||||
if (lastParentState.index === 0 || lastParentState.routes.length === 1) {
|
|
||||||
return lastParentState;
|
|
||||||
}
|
|
||||||
return NavigationStateUtils.pop(lastParentState);
|
|
||||||
}
|
|
||||||
|
|
||||||
return lastParentState;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const UIExplorerStackReducer = StackReducer({
|
|
||||||
getPushedReducerForAction: (action, lastState) => {
|
|
||||||
if (action.type === 'UIExplorerExampleAction' && UIExplorerList.Modules[action.openExample]) {
|
|
||||||
if (lastState.routes.find(route => route.key === action.openExample)) {
|
|
||||||
// The example is already open, we should avoid pushing examples twice
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (state) => state || {key: action.openExample};
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
getReducerForState: (initialState) => (state) => state || initialState,
|
|
||||||
initialState: {
|
|
||||||
key: 'UIExplorerMainStack',
|
|
||||||
index: 0,
|
|
||||||
routes: [
|
|
||||||
{key: 'AppList'},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
function UIExplorerNavigationReducer(lastState: ?UIExplorerNavigationState, action: any): UIExplorerNavigationState {
|
|
||||||
if (!lastState) {
|
|
||||||
return {
|
|
||||||
externalExample: null,
|
|
||||||
stack: UIExplorerStackReducer(null, action),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (action.type === 'UIExplorerListWithFilterAction') {
|
|
||||||
return {
|
|
||||||
externalExample: null,
|
|
||||||
stack: {
|
|
||||||
key: 'UIExplorerMainStack',
|
|
||||||
index: 0,
|
|
||||||
routes: [
|
|
||||||
{
|
|
||||||
key: 'AppList',
|
|
||||||
filter: action.filter,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (action.type === 'BackAction' && lastState.externalExample) {
|
|
||||||
return {
|
|
||||||
...lastState,
|
|
||||||
externalExample: null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (action.type === 'UIExplorerExampleAction') {
|
if (action.type === 'UIExplorerExampleAction') {
|
||||||
|
|
||||||
|
// Make sure we see the module before returning the new state
|
||||||
const ExampleModule = UIExplorerList.Modules[action.openExample];
|
const ExampleModule = UIExplorerList.Modules[action.openExample];
|
||||||
if (ExampleModule && ExampleModule.external) {
|
|
||||||
|
if (ExampleModule) {
|
||||||
return {
|
return {
|
||||||
...lastState,
|
openExample: action.openExample,
|
||||||
externalExample: action.openExample,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const newStack = UIExplorerStackReducer(lastState.stack, action);
|
|
||||||
if (newStack !== lastState.stack) {
|
return state;
|
||||||
return {
|
|
||||||
externalExample: null,
|
|
||||||
stack: newStack,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return lastState;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = UIExplorerNavigationReducer;
|
module.exports = UIExplorerNavigationReducer;
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* Facebook reserves all rights not expressly granted.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* @flow
|
|
||||||
* @providesModule UIExplorerStateTitleMap
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// $FlowFixMe : This is a platform-forked component, and flow seems to only run on iOS?
|
|
||||||
const UIExplorerList = require('./UIExplorerList');
|
|
||||||
|
|
||||||
import type {NavigationRoute} from 'NavigationTypeDefinition';
|
|
||||||
|
|
||||||
function StateTitleMap(route: NavigationRoute): string {
|
|
||||||
if (UIExplorerList.Modules[route.key]) {
|
|
||||||
return UIExplorerList.Modules[route.key].title;
|
|
||||||
}
|
|
||||||
if (route.key === 'AppList') {
|
|
||||||
return 'UIExplorer';
|
|
||||||
}
|
|
||||||
return 'Unknown';
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = StateTitleMap;
|
|
|
@ -32,7 +32,9 @@ const {
|
||||||
Alert,
|
Alert,
|
||||||
} = ReactNative;
|
} = ReactNative;
|
||||||
|
|
||||||
function PathActionMap(path: string): ?Object {
|
import type { UIExplorerAction } from './UIExplorerActions';
|
||||||
|
|
||||||
|
function PathActionMap(path: string): ?UIExplorerAction {
|
||||||
// Warning! Hacky parsing for example code. Use a library for this!
|
// Warning! Hacky parsing for example code. Use a library for this!
|
||||||
const exampleParts = path.split('/example/');
|
const exampleParts = path.split('/example/');
|
||||||
const exampleKey = exampleParts[1];
|
const exampleKey = exampleParts[1];
|
||||||
|
@ -46,11 +48,11 @@ function PathActionMap(path: string): ?Object {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function URIActionMap(uri: ?string): ?Object {
|
function URIActionMap(uri: ?string): ?UIExplorerAction {
|
||||||
// Warning! Hacky parsing for example code. Use a library for this!
|
|
||||||
if (!uri) {
|
if (!uri) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
// Warning! Hacky parsing for example code. Use a library for this!
|
||||||
const parts = uri.split('rnuiexplorer:/');
|
const parts = uri.split('rnuiexplorer:/');
|
||||||
if (!parts[1]) {
|
if (!parts[1]) {
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Reference in New Issue