mirror of
https://github.com/status-im/react-native.git
synced 2025-01-24 16:29:01 +00:00
ca8531105e
Summary: NavigationCardStack is a custom component, and its API should be explicit, not too generic.. In NavigationCardStack, the prop `renderOverlay` is actually used to render the NavigationHeader, and we uses absolute position to build the layout for the header and the body. One of the problem with using absolute postion and fixed height to build the layout that contains the header is that the header can't have variant height easily. Ideally, if the layout for the header used flex-box, we'd ve able to be more adaptive to deal with the header that has variant height. That said, let's rename `renderOverlay` to `renderHeader`, then build the proper layout that explicitly works better with the header. If we to need to support overlay in navigation, we may consider add `renderOverlay` later, if it's really necessary. Reviewed By: ericvicenti Differential Revision: D3670224 fbshipit-source-id: ff04acfe9dc995cb57117b3fd9b07d5f97b9c6ee
225 lines
6.5 KiB
JavaScript
225 lines
6.5 KiB
JavaScript
/**
|
|
* 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.
|
|
*
|
|
* @providesModule UIExplorerApp
|
|
* @flow
|
|
*/
|
|
'use strict';
|
|
|
|
const AsyncStorage = require('AsyncStorage');
|
|
const Linking = require('Linking');
|
|
const React = require('react');
|
|
const ReactNative = require('react-native');
|
|
const UIExplorerList = require('./UIExplorerList.ios');
|
|
const UIExplorerExampleList = require('./UIExplorerExampleList');
|
|
const UIExplorerNavigationReducer = require('./UIExplorerNavigationReducer');
|
|
const UIExplorerStateTitleMap = require('./UIExplorerStateTitleMap');
|
|
const URIActionMap = require('./URIActionMap');
|
|
|
|
const {
|
|
AppRegistry,
|
|
NavigationExperimental,
|
|
SnapshotViewIOS,
|
|
StyleSheet,
|
|
View,
|
|
} = ReactNative;
|
|
|
|
const {
|
|
CardStack: NavigationCardStack,
|
|
Header: NavigationHeader,
|
|
} = NavigationExperimental;
|
|
|
|
import type { NavigationSceneRendererProps } from 'NavigationTypeDefinition';
|
|
|
|
import type { UIExplorerNavigationState } from './UIExplorerNavigationReducer';
|
|
|
|
import type { UIExplorerExample } from './UIExplorerList.ios';
|
|
|
|
type Props = {
|
|
exampleFromAppetizeParams: string,
|
|
};
|
|
|
|
type State = UIExplorerNavigationState & {
|
|
externalExample?: string,
|
|
};
|
|
|
|
const APP_STATE_KEY = 'UIExplorerAppState.v1';
|
|
|
|
class UIExplorerApp extends React.Component {
|
|
_handleBack: Function;
|
|
_handleAction: Function;
|
|
_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() {
|
|
Linking.getInitialURL().then((url) => {
|
|
AsyncStorage.getItem(APP_STATE_KEY, (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));
|
|
});
|
|
}
|
|
|
|
_handleAction(action: Object) {
|
|
if (!action) {
|
|
return;
|
|
}
|
|
const newState = UIExplorerNavigationReducer(this.state, action);
|
|
if (this.state !== newState) {
|
|
this.setState(newState);
|
|
AsyncStorage.setItem(APP_STATE_KEY, JSON.stringify(this.state));
|
|
}
|
|
}
|
|
|
|
render() {
|
|
if (!this.state) {
|
|
return null;
|
|
}
|
|
if (this.state.externalExample) {
|
|
const Component = UIExplorerList.Modules[this.state.externalExample];
|
|
return (
|
|
<Component
|
|
onExampleExit={() => {
|
|
this._handleAction({ type: 'BackAction' });
|
|
}}
|
|
/>
|
|
);
|
|
}
|
|
return (
|
|
<NavigationCardStack
|
|
navigationState={this.state.stack}
|
|
style={styles.container}
|
|
renderHeader={this._renderHeader}
|
|
renderScene={this._renderScene}
|
|
|
|
/>
|
|
);
|
|
}
|
|
|
|
_renderHeader(props: NavigationSceneRendererProps): ReactElement<any> {
|
|
return (
|
|
<NavigationHeader
|
|
{...props}
|
|
onNavigateBack={this._handleBack}
|
|
renderTitleComponent={this._renderTitleComponent}
|
|
/>
|
|
);
|
|
}
|
|
|
|
_renderTitleComponent(props: NavigationSceneRendererProps): ReactElement<any> {
|
|
return (
|
|
<NavigationHeader.Title>
|
|
{UIExplorerStateTitleMap(props.scene.route)}
|
|
</NavigationHeader.Title>
|
|
);
|
|
}
|
|
|
|
_renderScene(props: NavigationSceneRendererProps): ?ReactElement<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) {
|
|
const Component = UIExplorerExampleList.makeRenderable(Example);
|
|
return (
|
|
<View style={styles.exampleContainer}>
|
|
<Component />
|
|
</View>
|
|
);
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
},
|
|
exampleContainer: {
|
|
flex: 1,
|
|
paddingTop: NavigationHeader.HEIGHT,
|
|
},
|
|
});
|
|
|
|
AppRegistry.registerComponent('SetPropertiesExampleApp', () => require('./SetPropertiesExampleApp'));
|
|
AppRegistry.registerComponent('RootViewSizeFlexibilityExampleApp', () => require('./RootViewSizeFlexibilityExampleApp'));
|
|
AppRegistry.registerComponent('UIExplorerApp', () => UIExplorerApp);
|
|
|
|
// Register suitable examples for snapshot tests
|
|
UIExplorerList.ComponentExamples.concat(UIExplorerList.APIExamples).forEach((Example: UIExplorerExample) => {
|
|
const ExampleModule = Example.module;
|
|
if (ExampleModule.displayName) {
|
|
class Snapshotter extends React.Component {
|
|
render() {
|
|
const Renderable = UIExplorerExampleList.makeRenderable(ExampleModule);
|
|
return (
|
|
<SnapshotViewIOS>
|
|
<Renderable />
|
|
</SnapshotViewIOS>
|
|
);
|
|
}
|
|
}
|
|
|
|
AppRegistry.registerComponent(ExampleModule.displayName, () => Snapshotter);
|
|
}
|
|
});
|
|
|
|
module.exports = UIExplorerApp;
|