[react_native] Refactor UIExplorerList to fix UIExplorerApp

This commit is contained in:
Andrei Coman 2015-07-23 06:43:35 -07:00
parent 19a8eff668
commit 9c8ba9502c
3 changed files with 372 additions and 1 deletions

View File

@ -17,7 +17,7 @@
'use strict';
var React = require('react-native');
var UIExplorerList = require('./UIExplorerList');
var UIExplorerList = require('./UIExplorerList.ios');
var {
AppRegistry,
NavigatorIOS,

View File

@ -0,0 +1,176 @@
/**
* 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
*/
'use strict';
var React = require('react-native');
var {
AppRegistry,
Settings,
StyleSheet,
} = React;
var { TestModule } = React.addons;
import type { NavigationContext } from 'NavigationContext';
var UIExplorerListBase = require('./UIExplorerListBase');
var COMPONENTS = [
require('./ActivityIndicatorIOSExample'),
require('./DatePickerIOSExample'),
require('./ImageExample'),
require('./LayoutEventsExample'),
require('./ListViewExample'),
require('./ListViewGridLayoutExample'),
require('./ListViewPagingExample'),
require('./MapViewExample'),
require('./Navigator/NavigatorExample'),
require('./NavigatorIOSColorsExample'),
require('./NavigatorIOSExample'),
require('./PickerIOSExample'),
require('./ProgressViewIOSExample'),
require('./ScrollViewExample'),
require('./SegmentedControlIOSExample'),
require('./SliderIOSExample'),
require('./SwitchIOSExample'),
require('./TabBarIOSExample'),
require('./TextExample.ios'),
require('./TextInputExample'),
require('./TouchableExample'),
require('./ViewExample'),
require('./WebViewExample'),
];
var APIS = [
require('./AccessibilityIOSExample'),
require('./ActionSheetIOSExample'),
require('./AdSupportIOSExample'),
require('./AlertIOSExample'),
require('./AnimationExample/AnExApp'),
require('./AppStateIOSExample'),
require('./AsyncStorageExample'),
require('./BorderExample'),
require('./CameraRollExample.ios'),
require('./GeolocationExample'),
require('./LayoutExample'),
require('./NetInfoExample'),
require('./PanResponderExample'),
require('./PointerEventsExample'),
require('./PushNotificationIOSExample'),
require('./StatusBarIOSExample'),
require('./TimerExample'),
require('./VibrationIOSExample'),
require('./XHRExample'),
];
// Register suitable examples for snapshot tests
COMPONENTS.concat(APIS).forEach((Example) => {
if (Example.displayName) {
var Snapshotter = React.createClass({
componentDidMount: function() {
// View is still blank after first RAF :\
global.requestAnimationFrame(() =>
global.requestAnimationFrame(() => TestModule.verifySnapshot(
TestModule.markTestPassed
)
));
},
render: function() {
var Renderable = UIExplorerListBase.makeRenderable(Example);
return <Renderable />;
},
});
AppRegistry.registerComponent(Example.displayName, () => Snapshotter);
}
});
type Props = {
navigator: {
navigationContext: NavigationContext,
push: (route: {title: string, component: ReactClass<any,any,any>}) => void,
},
onExternalExampleRequested: Function,
};
class UIExplorerList extends React.Component {
props: Props;
render() {
return (
<UIExplorerListBase
components={COMPONENTS}
apis={APIS}
searchText={Settings.get('searchText')}
renderAdditionalView={this.renderAdditionalView.bind(this)}
search={this.search.bind(this)}
onPressRow={this.onPressRow.bind(this)}
/>
);
}
componentWillMount() {
this.props.navigator.navigationContext.addListener('didfocus', function(event) {
if (event.data.route.title === 'UIExplorer') {
Settings.set({visibleExample: null});
}
});
}
componentDidMount() {
var visibleExampleTitle = Settings.get('visibleExample');
if (visibleExampleTitle) {
var predicate = (example) => example.title === visibleExampleTitle;
var foundExample = APIS.find(predicate) || COMPONENTS.find(predicate);
if (foundExample) {
setTimeout(() => this._openExample(foundExample), 100);
}
}
}
renderAdditionalView(renderRow: Function, renderTextInput: Function): React.Component {
return renderTextInput(styles.searchTextInput);
}
search(text: mixed) {
Settings.set({searchText: text});
}
_openExample(example: any) {
if (example.external) {
this.props.onExternalExampleRequested(example);
return;
}
var Component = UIExplorerListBase.makeRenderable(example);
this.props.navigator.push({
title: Component.title,
component: Component,
});
}
onPressRow(example: any) {
Settings.set({visibleExample: example.title});
this._openExample(example);
}
}
var styles = StyleSheet.create({
searchTextInput: {
height: 30,
},
});
module.exports = UIExplorerList;

View File

@ -0,0 +1,195 @@
/**
* 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
*/
'use strict';
var React = require('react-native');
var {
ListView,
PixelRatio,
StyleSheet,
Text,
TextInput,
TouchableHighlight,
View,
} = React;
var createExamplePage = require('./createExamplePage');
var ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
sectionHeaderHasChanged: (h1, h2) => h1 !== h2,
});
class UIExplorerListBase extends React.Component {
constructor(props: any) {
super(props);
this.state = {
dataSource: ds.cloneWithRowsAndSections({
components: [],
apis: [],
}),
searchText: this.props.searchText,
};
}
componentDidMount(): void {
this.search(this.state.searchText);
}
render() {
var topView = this.props.renderAdditionalView &&
this.props.renderAdditionalView(this.renderRow.bind(this), this.renderTextInput.bind(this));
return (
<View style={styles.listContainer}>
{topView}
<ListView
style={styles.list}
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
renderSectionHeader={this._renderSectionHeader}
keyboardShouldPersistTaps={true}
automaticallyAdjustContentInsets={false}
keyboardDismissMode="on-drag"
/>
</View>
);
}
renderTextInput(searchTextInputStyle: any) {
return (
<View style={styles.searchRow}>
<TextInput
autoCapitalize="none"
autoCorrect={false}
clearButtonMode="always"
onChangeText={this.search.bind(this)}
placeholder="Search..."
style={[styles.searchTextInput, searchTextInputStyle]}
testID="explorer_search"
value={this.state.searchText}
/>
</View>
);
}
_renderSectionHeader(data: any, section: string) {
return (
<View style={styles.sectionHeader}>
<Text style={styles.sectionHeaderTitle}>
{section.toUpperCase()}
</Text>
</View>
);
}
renderRow(example: any, i: number) {
return (
<View key={i}>
<TouchableHighlight onPress={() => this.onPressRow(example)}>
<View style={styles.row}>
<Text style={styles.rowTitleText}>
{example.title}
</Text>
<Text style={styles.rowDetailText}>
{example.description}
</Text>
</View>
</TouchableHighlight>
<View style={styles.separator} />
</View>
);
}
search(text: mixed): void {
this.props.search && this.props.search(text);
var regex = new RegExp(text, 'i');
var filter = (component) => regex.test(component.title);
this.setState({
dataSource: ds.cloneWithRowsAndSections({
components: this.props.components.filter(filter),
apis: this.props.apis.filter(filter),
}),
searchText: text,
});
}
onPressRow(example: any): void {
this.props.onPressRow && this.props.onPressRow(example);
}
static makeRenderable(example: any): ReactClass<any, any, any> {
return example.examples ?
createExamplePage(null, example) :
example;
}
}
var styles = StyleSheet.create({
listContainer: {
flex: 1,
},
list: {
backgroundColor: '#eeeeee',
},
sectionHeader: {
padding: 5,
},
group: {
backgroundColor: 'white',
},
sectionHeaderTitle: {
fontWeight: '500',
fontSize: 11,
},
row: {
backgroundColor: 'white',
justifyContent: 'center',
paddingHorizontal: 15,
paddingVertical: 8,
},
separator: {
height: 1 / PixelRatio.get(),
backgroundColor: '#bbbbbb',
marginLeft: 15,
},
rowTitleText: {
fontSize: 17,
fontWeight: '500',
},
rowDetailText: {
fontSize: 15,
color: '#888888',
lineHeight: 20,
},
searchRow: {
backgroundColor: '#eeeeee',
paddingTop: 75,
paddingLeft: 10,
paddingRight: 10,
paddingBottom: 10,
},
searchTextInput: {
backgroundColor: 'white',
borderColor: '#cccccc',
borderRadius: 3,
borderWidth: 1,
paddingLeft: 8,
},
});
module.exports = UIExplorerListBase;