mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a769f91ccf | ||
|
|
b68bae447d | ||
|
|
52d2dbe8da | ||
|
|
8ed96be6b0 | ||
|
|
c4fbfa66c1 | ||
|
|
12d96eec91 | ||
|
|
d403c24493 | ||
|
|
9f07e1f306 | ||
|
|
ca47230955 | ||
|
|
0acba126f9 | ||
|
|
90dd33726c | ||
|
|
eb3df43818 | ||
|
|
f514409495 | ||
|
|
6f5acbd95a | ||
|
|
2f1ed20a6e |
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 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 AppStateExample
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
AppState,
|
||||
Text,
|
||||
View
|
||||
} = React;
|
||||
|
||||
var AppStateSubscription = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
appState: AppState.currentState,
|
||||
previousAppStates: [],
|
||||
};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
AppState.addEventListener('change', this._handleAppStateChange);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
AppState.removeEventListener('change', this._handleAppStateChange);
|
||||
},
|
||||
_handleAppStateChange: function(appState) {
|
||||
var previousAppStates = this.state.previousAppStates.slice();
|
||||
previousAppStates.push(this.state.appState);
|
||||
this.setState({
|
||||
appState,
|
||||
previousAppStates,
|
||||
});
|
||||
},
|
||||
render() {
|
||||
if (this.props.showCurrentOnly) {
|
||||
return (
|
||||
<View>
|
||||
<Text>{this.state.appState}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<View>
|
||||
<Text>{JSON.stringify(this.state.previousAppStates)}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
exports.title = 'AppState';
|
||||
exports.description = 'app background status';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'AppState.currentState',
|
||||
description: 'Can be null on app initialization',
|
||||
render() { return <Text>{AppState.currentState}</Text>; }
|
||||
},
|
||||
{
|
||||
title: 'Subscribed AppState:',
|
||||
description: 'This changes according to the current state, so you can only ever see it rendered as "active"',
|
||||
render(): ReactElement { return <AppStateSubscription showCurrentOnly={true} />; }
|
||||
},
|
||||
{
|
||||
title: 'Previous states:',
|
||||
render(): ReactElement { return <AppStateSubscription showCurrentOnly={false} />; }
|
||||
},
|
||||
];
|
||||
@@ -16,25 +16,31 @@
|
||||
'use strict';
|
||||
|
||||
const React = require('react-native');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const UIExplorerBlock = require('UIExplorerBlock');
|
||||
const UIExplorerPage = require('UIExplorerPage');
|
||||
|
||||
const {
|
||||
PickerAndroid,
|
||||
Picker,
|
||||
Text,
|
||||
TouchableWithoutFeedback,
|
||||
} = React;
|
||||
const Item = PickerAndroid.Item;
|
||||
const Item = Picker.Item;
|
||||
|
||||
const PickerExample = React.createClass({
|
||||
|
||||
statics: {
|
||||
title: '<Picker>',
|
||||
description: 'Provides multiple options to choose from, using either a dropdown menu or a dialog.',
|
||||
},
|
||||
|
||||
const PickerAndroidExample = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
selected1: 'key1',
|
||||
selected2: 'key1',
|
||||
selected3: 'key1',
|
||||
selected4: 'key1',
|
||||
color: 'red',
|
||||
mode: PickerAndroid.MODE_DIALOG,
|
||||
mode: Picker.MODE_DIALOG,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -42,101 +48,93 @@ const PickerAndroidExample = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerPage title="<PickerAndroid>">
|
||||
<UIExplorerPage title="<Picker>">
|
||||
<UIExplorerBlock title="Basic Picker">
|
||||
<PickerAndroid
|
||||
style={{width: 100, height: 56}}
|
||||
onSelect={this.onSelect.bind(this, 'selected1')}>
|
||||
<Item text="hello" value="key0" selected={this.state.selected1 === 'key0'} />
|
||||
<Item text="world" value="key1" selected={this.state.selected1 === 'key1'} />
|
||||
</PickerAndroid>
|
||||
<Picker
|
||||
style={styles.picker}
|
||||
selectedValue={this.state.selected1}
|
||||
onValueChange={this.onValueChange.bind(this, 'selected1')}>
|
||||
<Item label="hello" value="key0" />
|
||||
<Item label="world" value="key1" />
|
||||
</Picker>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Disabled picker">
|
||||
<PickerAndroid style={{width: 100, height: 56}} enabled={false}>
|
||||
<Item text="hello" value="key0" selected={this.state.selected1 === 'key0'} />
|
||||
<Item text="world" value="key1" selected={this.state.selected1 === 'key1'} />
|
||||
</PickerAndroid>
|
||||
<Picker style={styles.picker} enabled={false} selectedValue={this.state.selected1}>
|
||||
<Item label="hello" value="key0" />
|
||||
<Item label="world" value="key1" />
|
||||
</Picker>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Dropdown Picker">
|
||||
<PickerAndroid
|
||||
style={{width: 100, height: 56}}
|
||||
onSelect={this.onSelect.bind(this, 'selected2')}
|
||||
<Picker
|
||||
style={styles.picker}
|
||||
selectedValue={this.state.selected2}
|
||||
onValueChange={this.onValueChange.bind(this, 'selected2')}
|
||||
mode="dropdown">
|
||||
<Item text="hello" value="key0" selected={this.state.selected2 === 'key0'} />
|
||||
<Item text="world" value="key1" selected={this.state.selected2 === 'key1'} />
|
||||
</PickerAndroid>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Alternating Picker">
|
||||
<PickerAndroid
|
||||
style={{width: 100, height: 56}}
|
||||
onSelect={this.onSelect.bind(this, 'selected3')}
|
||||
mode={this.state.mode}>
|
||||
<Item text="hello" value="key0" selected={this.state.selected3 === 'key0'} />
|
||||
<Item text="world" value="key1" selected={this.state.selected3 === 'key1'} />
|
||||
</PickerAndroid>
|
||||
<TouchableWithoutFeedback onPress={this.changeMode}>
|
||||
<Text>Tap here to switch between dialog/dropdown.</Text>
|
||||
</TouchableWithoutFeedback>
|
||||
<Item label="hello" value="key0" />
|
||||
<Item label="world" value="key1" />
|
||||
</Picker>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Picker with prompt message">
|
||||
<PickerAndroid
|
||||
style={{width: 100, height: 56}}
|
||||
onSelect={this.onSelect.bind(this, 'selected4')}
|
||||
<Picker
|
||||
style={styles.picker}
|
||||
selectedValue={this.state.selected3}
|
||||
onValueChange={this.onValueChange.bind(this, 'selected3')}
|
||||
prompt="Pick one, just one">
|
||||
<Item text="hello" value="key0" selected={this.state.selected4 === 'key0'} />
|
||||
<Item text="world" value="key1" selected={this.state.selected4 === 'key1'} />
|
||||
</PickerAndroid>
|
||||
<Item label="hello" value="key0" />
|
||||
<Item label="world" value="key1" />
|
||||
</Picker>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Picker with no listener">
|
||||
<PickerAndroid style={{width: 100, height: 56}}>
|
||||
<Item text="hello" value="key0" />
|
||||
<Item text="world" value="key1" />
|
||||
</PickerAndroid>
|
||||
<Picker style={styles.picker}>
|
||||
<Item label="hello" value="key0" />
|
||||
<Item label="world" value="key1" />
|
||||
</Picker>
|
||||
<Text>
|
||||
You can not change the value of this picker because it doesn't set a selected prop on
|
||||
its items.
|
||||
Cannot change the value of this picker because it doesn't update selectedValue.
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Colorful pickers">
|
||||
<PickerAndroid style={{width: 100, height: 56, color: 'black'}}
|
||||
onSelect={this.onSelect.bind(this, 'color')}
|
||||
<Picker
|
||||
style={[styles.picker, {color: 'white', backgroundColor: '#333'}]}
|
||||
selectedValue={this.state.color}
|
||||
onValueChange={this.onValueChange.bind(this, 'color')}
|
||||
mode="dropdown">
|
||||
<Item text="red" color="red" value="red" selected={this.state.color === 'red'}/>
|
||||
<Item text="green" color="green" value="green" selected={this.state.color === 'green'}/>
|
||||
<Item text="blue" color="blue" value="blue" selected={this.state.color === 'blue'}/>
|
||||
</PickerAndroid>
|
||||
<PickerAndroid style={{width: 100, height: 56}}
|
||||
onSelect={this.onSelect.bind(this, 'color')}
|
||||
<Item label="red" color="red" value="red" />
|
||||
<Item label="green" color="green" value="green" />
|
||||
<Item label="blue" color="blue" value="blue" />
|
||||
</Picker>
|
||||
<Picker
|
||||
style={styles.picker}
|
||||
selectedValue={this.state.color}
|
||||
onValueChange={this.onValueChange.bind(this, 'color')}
|
||||
mode="dialog">
|
||||
<Item text="red" color="red" value="red" selected={this.state.color === 'red'}/>
|
||||
<Item text="green" color="green" value="green" selected={this.state.color === 'green'}/>
|
||||
<Item text="blue" color="blue" value="blue" selected={this.state.color === 'blue'} />
|
||||
</PickerAndroid>
|
||||
<Item label="red" color="red" value="red" />
|
||||
<Item label="green" color="green" value="green" />
|
||||
<Item label="blue" color="blue" value="blue" />
|
||||
</Picker>
|
||||
</UIExplorerBlock>
|
||||
</UIExplorerPage>
|
||||
);
|
||||
},
|
||||
|
||||
changeMode: function() {
|
||||
const newMode = this.state.mode === PickerAndroid.MODE_DIALOG
|
||||
? PickerAndroid.MODE_DROPDOWN
|
||||
: PickerAndroid.MODE_DIALOG;
|
||||
const newMode = this.state.mode === Picker.MODE_DIALOG
|
||||
? Picker.MODE_DROPDOWN
|
||||
: Picker.MODE_DIALOG;
|
||||
this.setState({mode: newMode});
|
||||
},
|
||||
|
||||
onSelect: function(key, value) {
|
||||
onValueChange: function(key: string, value: string) {
|
||||
const newState = {};
|
||||
newState[key] = value;
|
||||
this.setState(newState);
|
||||
},
|
||||
});
|
||||
|
||||
exports.title = '<PickerAndroid>';
|
||||
exports.displayName = 'PickerAndroidExample';
|
||||
exports.description = 'The Android Picker component provides multiple options to choose from';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'PickerAndroidExample',
|
||||
render(): ReactElement { return <PickerAndroidExample />; }
|
||||
var styles = StyleSheet.create({
|
||||
picker: {
|
||||
width: 100,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
module.exports = PickerExample;
|
||||
|
||||
@@ -348,25 +348,19 @@ exports.examples = [
|
||||
placeholder="multiline, aligned top-left"
|
||||
placeholderTextColor="red"
|
||||
multiline={true}
|
||||
textAlign="start"
|
||||
textAlignVertical="top"
|
||||
style={styles.multiline}
|
||||
style={[styles.multiline, {textAlign: "left", textAlignVertical: "top"}]}
|
||||
/>
|
||||
<TextInput
|
||||
autoCorrect={true}
|
||||
placeholder="multiline, aligned center"
|
||||
placeholderTextColor="green"
|
||||
multiline={true}
|
||||
textAlign="center"
|
||||
textAlignVertical="center"
|
||||
style={[styles.multiline]}
|
||||
style={[styles.multiline, {textAlign: "center", textAlignVertical: "center"}]}
|
||||
/>
|
||||
<TextInput
|
||||
autoCorrect={true}
|
||||
multiline={true}
|
||||
textAlign="end"
|
||||
textAlignVertical="bottom"
|
||||
style={[styles.multiline, {color: 'blue'}]}>
|
||||
style={[styles.multiline, {color: 'blue'}, {textAlign: "right", textAlignVertical: "bottom"}]}>
|
||||
<Text style={styles.multiline}>multiline with children, aligned bottom-right</Text>
|
||||
</TextInput>
|
||||
</View>
|
||||
|
||||
@@ -43,6 +43,7 @@ var COMPONENTS = [
|
||||
var APIS = [
|
||||
require('./AccessibilityAndroidExample.android'),
|
||||
require('./AlertExample').AlertExample,
|
||||
require('./AppStateExample'),
|
||||
require('./BorderExample'),
|
||||
require('./CameraRollExample'),
|
||||
require('./ClipboardExample'),
|
||||
|
||||
@@ -64,6 +64,7 @@ var APIS = [
|
||||
require('./AnimatedExample'),
|
||||
require('./AnimatedGratuitousApp/AnExApp'),
|
||||
require('./AppStateIOSExample'),
|
||||
require('./AppStateExample'),
|
||||
require('./AsyncStorageExample'),
|
||||
require('./BorderExample'),
|
||||
require('./BoxShadowExample'),
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* 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 AppState
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var Map = require('Map');
|
||||
var NativeModules = require('NativeModules');
|
||||
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||
var RCTAppState = NativeModules.AppState;
|
||||
|
||||
var logError = require('logError');
|
||||
var invariant = require('invariant');
|
||||
|
||||
var _eventHandlers = {
|
||||
change: new Map(),
|
||||
memoryWarning: new Map(),
|
||||
};
|
||||
|
||||
/**
|
||||
* `AppState` can tell you if the app is in the foreground or background,
|
||||
* and notify you when the state changes.
|
||||
*
|
||||
* AppState is frequently used to determine the intent and proper behavior when
|
||||
* handling push notifications.
|
||||
*
|
||||
* ### App States
|
||||
*
|
||||
* - `active` - The app is running in the foreground
|
||||
* - `background` - The app is running in the background. The user is either
|
||||
* in another app or on the home screen
|
||||
* - `inactive` - This is a transition state that currently never happens for
|
||||
* typical React Native apps.
|
||||
*
|
||||
* For more information, see
|
||||
* [Apple's documentation](https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html)
|
||||
*
|
||||
* ### Basic Usage
|
||||
*
|
||||
* To see the current state, you can check `AppState.currentState`, which
|
||||
* will be kept up-to-date. However, `currentState` will be null at launch
|
||||
* while `AppState` retrieves it over the bridge.
|
||||
*
|
||||
* ```
|
||||
* getInitialState: function() {
|
||||
* return {
|
||||
* currentAppState: AppState.currentState,
|
||||
* };
|
||||
* },
|
||||
* componentDidMount: function() {
|
||||
* AppState.addEventListener('change', this._handleAppStateChange);
|
||||
* },
|
||||
* componentWillUnmount: function() {
|
||||
* AppState.removeEventListener('change', this._handleAppStateChange);
|
||||
* },
|
||||
* _handleAppStateChange: function(currentAppState) {
|
||||
* this.setState({ currentAppState, });
|
||||
* },
|
||||
* render: function() {
|
||||
* return (
|
||||
* <Text>Current state is: {this.state.currentAppState}</Text>
|
||||
* );
|
||||
* },
|
||||
* ```
|
||||
*
|
||||
* This example will only ever appear to say "Current state is: active" because
|
||||
* the app is only visible to the user when in the `active` state, and the null
|
||||
* state will happen only momentarily.
|
||||
*/
|
||||
|
||||
var AppState = {
|
||||
|
||||
/**
|
||||
* Add a handler to AppState changes by listening to the `change` event type
|
||||
* and providing the handler
|
||||
*/
|
||||
addEventListener: function(
|
||||
type: string,
|
||||
handler: Function
|
||||
) {
|
||||
invariant(
|
||||
['change', 'memoryWarning'].indexOf(type) !== -1,
|
||||
'Trying to subscribe to unknown event: "%s"', type
|
||||
);
|
||||
if (type === 'change') {
|
||||
_eventHandlers[type].set(handler, RCTDeviceEventEmitter.addListener(
|
||||
'appStateDidChange',
|
||||
(appStateData) => {
|
||||
handler(appStateData.app_state);
|
||||
}
|
||||
));
|
||||
} else if (type === 'memoryWarning') {
|
||||
_eventHandlers[type].set(handler, RCTDeviceEventEmitter.addListener(
|
||||
'memoryWarning',
|
||||
handler
|
||||
));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a handler by passing the `change` event type and the handler
|
||||
*/
|
||||
removeEventListener: function(
|
||||
type: string,
|
||||
handler: Function
|
||||
) {
|
||||
invariant(
|
||||
['change', 'memoryWarning'].indexOf(type) !== -1,
|
||||
'Trying to remove listener for unknown event: "%s"', type
|
||||
);
|
||||
if (!_eventHandlers[type].has(handler)) {
|
||||
return;
|
||||
}
|
||||
_eventHandlers[type].get(handler).remove();
|
||||
_eventHandlers[type].delete(handler);
|
||||
},
|
||||
|
||||
// TODO: getCurrentAppState callback seems to be called at a really late stage
|
||||
// after app launch. Trying to get currentState when mounting App component
|
||||
// will likely to have the initial value here.
|
||||
// Initialize to 'active' instead of null.
|
||||
currentState: ('active' : ?string),
|
||||
|
||||
};
|
||||
|
||||
RCTDeviceEventEmitter.addListener(
|
||||
'appStateDidChange',
|
||||
(appStateData) => {
|
||||
AppState.currentState = appStateData.app_state;
|
||||
}
|
||||
);
|
||||
|
||||
RCTAppState.getCurrentAppState(
|
||||
(appStateData) => {
|
||||
AppState.currentState = appStateData.app_state;
|
||||
},
|
||||
logError
|
||||
);
|
||||
|
||||
module.exports = AppState;
|
||||
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* 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 Picker
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var ColorPropType = require('ColorPropType');
|
||||
var PickerIOS = require('PickerIOS');
|
||||
var PickerAndroid = require('PickerAndroid');
|
||||
var Platform = require('Platform');
|
||||
var React = require('React');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var StyleSheetPropType = require('StyleSheetPropType');
|
||||
var TextStylePropTypes = require('TextStylePropTypes');
|
||||
var UnimplementedView = require('UnimplementedView');
|
||||
var View = require('View');
|
||||
var ViewStylePropTypes = require('ViewStylePropTypes');
|
||||
|
||||
var itemStylePropType = StyleSheetPropType(TextStylePropTypes);
|
||||
|
||||
var pickerStyleType = StyleSheetPropType({
|
||||
...ViewStylePropTypes,
|
||||
color: ColorPropType,
|
||||
});
|
||||
|
||||
var MODE_DIALOG = 'dialog';
|
||||
var MODE_DROPDOWN = 'dropdown';
|
||||
|
||||
/**
|
||||
* Renders the native picker component on iOS and Android. Example:
|
||||
*
|
||||
* <Picker
|
||||
* selectedValue={this.state.language}
|
||||
* onValueChange={(lang) => this.setState({language: lang})}>
|
||||
* <Picker.Item label="Java" value="java" />
|
||||
* <Picker.Item label="JavaScript" value="js" />
|
||||
* </Picker>
|
||||
*
|
||||
* Note: The picker has a default fixed height which you can modify
|
||||
* using `style` if needed. To set the width, you can use `style`
|
||||
* as well, e.g. to set a fixed width or stretch the picker horizontally.
|
||||
*/
|
||||
var Picker = React.createClass({
|
||||
|
||||
statics: {
|
||||
/**
|
||||
* On Android, display the options in a dialog.
|
||||
*/
|
||||
MODE_DIALOG: MODE_DIALOG,
|
||||
/**
|
||||
* On Android, display the options in a dropdown (this is the default).
|
||||
*/
|
||||
MODE_DROPDOWN: MODE_DROPDOWN,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
mode: MODE_DIALOG,
|
||||
};
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
...View.propTypes,
|
||||
style: pickerStyleType,
|
||||
/**
|
||||
* Value matching value of one of the items. Can be a string or an integer.
|
||||
*/
|
||||
selectedValue: React.PropTypes.any,
|
||||
/**
|
||||
* Callback for when an item is selected. This is called with the following parameters:
|
||||
* - `itemValue`: the `value` prop of the item that was selected
|
||||
* - `itemPosition`: the index of the selected item in this picker
|
||||
*/
|
||||
onValueChange: React.PropTypes.func,
|
||||
/**
|
||||
* If set to false, the picker will be disabled, i.e. the user will not be able to make a
|
||||
* selection.
|
||||
* @platform android
|
||||
*/
|
||||
enabled: React.PropTypes.bool,
|
||||
/**
|
||||
* On Android, specifies how to display the selection items when the user taps on the picker:
|
||||
* - 'dialog': Show a modal dialog. This is the default.
|
||||
* - 'dropdown': Shows a dropdown anchored to the picker view
|
||||
*
|
||||
* @platform android
|
||||
*/
|
||||
mode: React.PropTypes.oneOf([MODE_DIALOG, MODE_DROPDOWN]),
|
||||
/**
|
||||
* Style to apply to each of the item labels.
|
||||
* @platform ios
|
||||
*/
|
||||
itemStyle: itemStylePropType,
|
||||
/**
|
||||
* Prompt string for this picker, used on Android in dialog mode as the title of the dialog.
|
||||
* @platform android
|
||||
*/
|
||||
prompt: React.PropTypes.string,
|
||||
/**
|
||||
* Used to locate this view in end-to-end tests.
|
||||
*/
|
||||
testID: React.PropTypes.string,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (Platform.OS === 'ios') {
|
||||
return <PickerIOS {...this.props}>{this.props.children}</PickerIOS>;
|
||||
} else if (Platform.OS === 'android') {
|
||||
return <PickerAndroid {...this.props}>{this.props.children}</PickerAndroid>;
|
||||
} else {
|
||||
return <UnimplementedView />;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Individual selectable item in a Picker.
|
||||
*/
|
||||
Picker.Item = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
/**
|
||||
* Text to display for this item.
|
||||
*/
|
||||
label: React.PropTypes.string.isRequired,
|
||||
/**
|
||||
* The value to be passed to picker's `onValueChange` callback when
|
||||
* this item is selected. Can be a string or an integer.
|
||||
*/
|
||||
value: React.PropTypes.any,
|
||||
/**
|
||||
* Color of this item's text.
|
||||
* @platform android
|
||||
*/
|
||||
color: ColorPropType,
|
||||
/**
|
||||
* Used to locate the item in end-to-end tests.
|
||||
*/
|
||||
testID: React.PropTypes.string,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// The items are not rendered directly
|
||||
throw null;
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = Picker;
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* 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 PickerAndroid
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var ColorPropType = require('ColorPropType');
|
||||
var React = require('React');
|
||||
var ReactChildren = require('ReactChildren');
|
||||
var ReactPropTypes = require('ReactPropTypes');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var StyleSheetPropType = require('StyleSheetPropType');
|
||||
var View = require('View');
|
||||
var ViewStylePropTypes = require('ViewStylePropTypes');
|
||||
|
||||
var processColor = require('processColor');
|
||||
var requireNativeComponent = require('requireNativeComponent');
|
||||
|
||||
var REF_PICKER = 'picker';
|
||||
var MODE_DIALOG = 'dialog';
|
||||
var MODE_DROPDOWN = 'dropdown';
|
||||
|
||||
var pickerStyleType = StyleSheetPropType({
|
||||
...ViewStylePropTypes,
|
||||
color: ColorPropType,
|
||||
});
|
||||
|
||||
type Event = Object;
|
||||
|
||||
/**
|
||||
* Not exposed as a public API - use <Picker> instead.
|
||||
*/
|
||||
var PickerAndroid = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
...View.propTypes,
|
||||
style: pickerStyleType,
|
||||
selectedValue: React.PropTypes.any,
|
||||
enabled: ReactPropTypes.bool,
|
||||
mode: ReactPropTypes.oneOf(['dialog', 'dropdown']),
|
||||
onValueChange: ReactPropTypes.func,
|
||||
prompt: ReactPropTypes.string,
|
||||
testID: ReactPropTypes.string,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this._stateFromProps(this.props);
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
this.setState(this._stateFromProps(nextProps));
|
||||
},
|
||||
|
||||
// Translate prop and children into stuff that the native picker understands.
|
||||
_stateFromProps: function(props) {
|
||||
var selectedIndex = 0;
|
||||
let items = ReactChildren.map(props.children, (child, index) => {
|
||||
if (child.props.value === props.selectedValue) {
|
||||
selectedIndex = index;
|
||||
}
|
||||
let childProps = {
|
||||
value: child.props.value,
|
||||
label: child.props.label,
|
||||
};
|
||||
if (child.props.color) {
|
||||
childProps.color = processColor(child.props.color);
|
||||
}
|
||||
return childProps;
|
||||
});
|
||||
return {selectedIndex, items};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var Picker = this.props.mode === MODE_DROPDOWN ? DropdownPicker : DialogPicker;
|
||||
|
||||
var nativeProps = {
|
||||
enabled: this.props.enabled,
|
||||
items: this.state.items,
|
||||
mode: this.props.mode,
|
||||
onSelect: this._onChange,
|
||||
prompt: this.props.prompt,
|
||||
selected: this.state.selectedIndex,
|
||||
testID: this.props.testID,
|
||||
style: [styles.pickerAndroid, this.props.style],
|
||||
};
|
||||
|
||||
return <Picker ref={REF_PICKER} {...nativeProps} />;
|
||||
},
|
||||
|
||||
_onChange: function(event: Event) {
|
||||
if (this.props.onValueChange) {
|
||||
var position = event.nativeEvent.position;
|
||||
if (position >= 0) {
|
||||
var value = this.props.children[position].props.value;
|
||||
this.props.onValueChange(value);
|
||||
} else {
|
||||
this.props.onValueChange(null);
|
||||
}
|
||||
}
|
||||
|
||||
// The picker is a controlled component. This means we expect the
|
||||
// on*Change handlers to be in charge of updating our
|
||||
// `selectedValue` prop. That way they can also
|
||||
// disallow/undo/mutate the selection of certain values. In other
|
||||
// words, the embedder of this component should be the source of
|
||||
// truth, not the native component.
|
||||
if (this.refs[REF_PICKER] && this.state.selectedIndex !== event.nativeEvent.position) {
|
||||
this.refs[REF_PICKER].setNativeProps({selected: this.state.selectedIndex});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
pickerAndroid: {
|
||||
// We have to set the picker's dimensions explicitly to ensure
|
||||
// it gets rendered.
|
||||
// TODO would be better to export a native constant for this,
|
||||
// like in iOS the RCTDatePickerManager.m
|
||||
width: 80,
|
||||
height: 50,
|
||||
},
|
||||
});
|
||||
|
||||
var cfg = {
|
||||
nativeOnly: {
|
||||
items: true,
|
||||
selected: true,
|
||||
}
|
||||
}
|
||||
var DropdownPicker = requireNativeComponent('AndroidDropdownPicker', PickerAndroid, cfg);
|
||||
var DialogPicker = requireNativeComponent('AndroidDialogPicker', PickerAndroid, cfg);
|
||||
|
||||
module.exports = PickerAndroid;
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* 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 PickerAndroid
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
module.exports = require('UnimplementedView');
|
||||
@@ -1,213 +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 PickerAndroid
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var ColorPropType = require('ColorPropType');
|
||||
var React = require('React');
|
||||
var ReactChildren = require('ReactChildren');
|
||||
var ReactPropTypes = require('ReactPropTypes');
|
||||
var StyleSheetPropType = require('StyleSheetPropType');
|
||||
var View = require('View');
|
||||
var ViewStylePropTypes = require('ViewStylePropTypes');
|
||||
|
||||
var processColor = require('processColor');
|
||||
var requireNativeComponent = require('requireNativeComponent');
|
||||
|
||||
var MODE_DIALOG = 'dialog';
|
||||
var MODE_DROPDOWN = 'dropdown';
|
||||
var REF_PICKER = 'picker';
|
||||
|
||||
var pickerStyleType = StyleSheetPropType({
|
||||
...ViewStylePropTypes,
|
||||
color: ColorPropType,
|
||||
});
|
||||
|
||||
type Items = {
|
||||
selected: number;
|
||||
items: any[];
|
||||
};
|
||||
|
||||
type Event = Object;
|
||||
|
||||
/**
|
||||
* Individual selectable item in a Picker.
|
||||
*/
|
||||
var Item = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
/**
|
||||
* Color of this item's text.
|
||||
*/
|
||||
color: ColorPropType,
|
||||
/**
|
||||
* Text to display for this item.
|
||||
*/
|
||||
text: ReactPropTypes.string.isRequired,
|
||||
/**
|
||||
* The value to be passed to picker's `onSelect` callback when this item is selected.
|
||||
*/
|
||||
value: ReactPropTypes.string,
|
||||
/**
|
||||
* If `true`, this item is selected and shown in the picker.
|
||||
* Usually this is set based on state.
|
||||
*/
|
||||
selected: ReactPropTypes.bool,
|
||||
/**
|
||||
* Used to locate this view in end-to-end tests.
|
||||
*/
|
||||
testID: ReactPropTypes.string,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
throw new Error('Picker items should never be rendered');
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* <PickerAndroid> - A React component that renders the native Picker widget on Android. The items
|
||||
* that can be selected are specified as children views of type Item. Example usage:
|
||||
*
|
||||
* <PickerAndroid>
|
||||
* <PickerAndroid.Item text="Java" value="js" />
|
||||
* <PickerAndroid.Item text="JavaScript" value="java" selected={true} />
|
||||
* </PickerAndroid>
|
||||
*/
|
||||
var PickerAndroid = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
...View.propTypes,
|
||||
style: pickerStyleType,
|
||||
/**
|
||||
* If set to false, the picker will be disabled, i.e. the user will not be able to make a
|
||||
* selection.
|
||||
*/
|
||||
enabled: ReactPropTypes.bool,
|
||||
/**
|
||||
* Specifies how to display the selection items when the user taps on the picker:
|
||||
*
|
||||
* - dialog: Show a modal dialog
|
||||
* - dropdown: Shows a dropdown anchored to the picker view
|
||||
*/
|
||||
mode: ReactPropTypes.oneOf([MODE_DIALOG, MODE_DROPDOWN]),
|
||||
/**
|
||||
* Callback for when an item is selected. This is called with the following parameters:
|
||||
*
|
||||
* - `itemValue`: the `value` prop of the item that was selected
|
||||
* - `itemPosition`: the index of the selected item in this picker
|
||||
*/
|
||||
onSelect: ReactPropTypes.func,
|
||||
/**
|
||||
* Prompt string for this picker, currently only used in `dialog` mode as the title of the
|
||||
* dialog.
|
||||
*/
|
||||
prompt: ReactPropTypes.string,
|
||||
/**
|
||||
* Used to locate this view in end-to-end tests.
|
||||
*/
|
||||
testID: ReactPropTypes.string,
|
||||
},
|
||||
|
||||
statics: {
|
||||
Item: Item,
|
||||
MODE_DIALOG: MODE_DIALOG,
|
||||
MODE_DROPDOWN: MODE_DROPDOWN,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
mode: MODE_DIALOG,
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var Picker = this.props.mode === MODE_DROPDOWN ? DropdownPicker : DialogPicker;
|
||||
|
||||
var { selected, items } = this._getItems();
|
||||
|
||||
var nativeProps = {
|
||||
enabled: this.props.enabled,
|
||||
items: items,
|
||||
mode: this.props.mode,
|
||||
onSelect: this._onSelect,
|
||||
prompt: this.props.prompt,
|
||||
selected: selected,
|
||||
style: this.props.style,
|
||||
testID: this.props.testID,
|
||||
};
|
||||
|
||||
return <Picker ref={REF_PICKER} {...nativeProps} />;
|
||||
},
|
||||
|
||||
/**
|
||||
* Transform this view's children into an array of items to be passed to the native component.
|
||||
* Since we're traversing the children, also determine the selected position.
|
||||
*
|
||||
* @returns an object with two keys:
|
||||
*
|
||||
* - `selected` (number) - the index of the selected item
|
||||
* - `items` (array) - the items of this picker, as an array of strings
|
||||
*/
|
||||
_getItems: function(): Items {
|
||||
var items = [];
|
||||
var selected = 0;
|
||||
ReactChildren.forEach(this.props.children, function(child, index) {
|
||||
var childProps = Object.assign({}, child.props);
|
||||
if (childProps.color) {
|
||||
childProps.color = processColor(childProps.color);
|
||||
}
|
||||
items.push(childProps);
|
||||
if (childProps.selected) {
|
||||
selected = index;
|
||||
}
|
||||
});
|
||||
return {
|
||||
selected: selected,
|
||||
items: items,
|
||||
};
|
||||
},
|
||||
|
||||
_onSelect: function(event: Event) {
|
||||
if (this.props.onSelect) {
|
||||
var position = event.nativeEvent.position;
|
||||
if (position >= 0) {
|
||||
var value = this.props.children[position].props.value;
|
||||
this.props.onSelect(value, position);
|
||||
} else {
|
||||
this.props.onSelect(null, position);
|
||||
}
|
||||
}
|
||||
|
||||
// The native Picker has changed, but the props haven't (yet). If
|
||||
// the handler decides to not accept the new value or do something
|
||||
// else with it we might end up in a bad state, so we reset the
|
||||
// selection on the native component.
|
||||
// tl;dr: PickerAndroid is a controlled component.
|
||||
var { selected } = this._getItems();
|
||||
if (this.refs[REF_PICKER]) {
|
||||
this.refs[REF_PICKER].setNativeProps({selected: selected});
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
var cfg = {
|
||||
nativeOnly: {
|
||||
items: true,
|
||||
selected: true,
|
||||
}
|
||||
}
|
||||
var DropdownPicker = requireNativeComponent('AndroidDropdownPicker', PickerAndroid, cfg);
|
||||
var DialogPicker = requireNativeComponent('AndroidDialogPicker', PickerAndroid, cfg);
|
||||
|
||||
module.exports = PickerAndroid;
|
||||
@@ -101,24 +101,6 @@ var TextInput = React.createClass({
|
||||
* The default value is false.
|
||||
*/
|
||||
autoFocus: PropTypes.bool,
|
||||
/**
|
||||
* Set the position of the cursor from where editing will begin.
|
||||
* @platform android
|
||||
*/
|
||||
textAlign: PropTypes.oneOf([
|
||||
'start',
|
||||
'center',
|
||||
'end',
|
||||
]),
|
||||
/**
|
||||
* Aligns text vertically within the TextInput.
|
||||
* @platform android
|
||||
*/
|
||||
textAlignVertical: PropTypes.oneOf([
|
||||
'top',
|
||||
'center',
|
||||
'bottom',
|
||||
]),
|
||||
/**
|
||||
* If false, text is not editable. The default value is true.
|
||||
*/
|
||||
@@ -491,10 +473,6 @@ var TextInput = React.createClass({
|
||||
|
||||
var autoCapitalize =
|
||||
UIManager.AndroidTextInput.Constants.AutoCapitalizationType[this.props.autoCapitalize];
|
||||
var textAlign = UIManager.AndroidTextInput.Constants.TextAlign[this.props.textAlign];
|
||||
var textAlignVertical =
|
||||
UIManager.AndroidTextInput.Constants.TextAlignVertical[this.props.textAlignVertical];
|
||||
|
||||
var children = this.props.children;
|
||||
var childCount = 0;
|
||||
ReactChildren.forEach(children, () => ++childCount);
|
||||
@@ -512,8 +490,6 @@ var TextInput = React.createClass({
|
||||
style={[this.props.style]}
|
||||
autoCapitalize={autoCapitalize}
|
||||
autoCorrect={this.props.autoCorrect}
|
||||
textAlign={textAlign}
|
||||
textAlignVertical={textAlignVertical}
|
||||
keyboardType={this.props.keyboardType}
|
||||
mostRecentEventCount={0}
|
||||
multiline={this.props.multiline}
|
||||
|
||||
@@ -46,6 +46,12 @@ var TextStylePropTypes = Object.assign(Object.create(ViewStylePropTypes), {
|
||||
textAlign: ReactPropTypes.oneOf(
|
||||
['auto' /*default*/, 'left', 'right', 'center', 'justify']
|
||||
),
|
||||
/**
|
||||
* @platform android
|
||||
*/
|
||||
textAlignVertical: ReactPropTypes.oneOf(
|
||||
['auto' /*default*/, 'top', 'bottom', 'center']
|
||||
),
|
||||
/**
|
||||
* @platform ios
|
||||
*/
|
||||
|
||||
+2
-1
@@ -25,7 +25,7 @@ var ReactNative = {
|
||||
get Modal() { return require('Modal'); },
|
||||
get Navigator() { return require('Navigator'); },
|
||||
get NavigatorIOS() { return require('NavigatorIOS'); },
|
||||
get PickerAndroid() { return require('PickerAndroid'); },
|
||||
get Picker() { return require('Picker'); },
|
||||
get PickerIOS() { return require('PickerIOS'); },
|
||||
get ProgressBarAndroid() { return require('ProgressBarAndroid'); },
|
||||
get ProgressViewIOS() { return require('ProgressViewIOS'); },
|
||||
@@ -60,6 +60,7 @@ var ReactNative = {
|
||||
get AlertIOS() { return require('AlertIOS'); },
|
||||
get Animated() { return require('Animated'); },
|
||||
get AppRegistry() { return require('AppRegistry'); },
|
||||
get AppState() { return require('AppState'); },
|
||||
get AppStateIOS() { return require('AppStateIOS'); },
|
||||
get AsyncStorage() { return require('AsyncStorage'); },
|
||||
get BackAndroid() { return require('BackAndroid'); },
|
||||
|
||||
@@ -37,7 +37,7 @@ var ReactNative = Object.assign(Object.create(require('React')), {
|
||||
Modal: require('Modal'),
|
||||
Navigator: require('Navigator'),
|
||||
NavigatorIOS: require('NavigatorIOS'),
|
||||
PickerAndroid: require('PickerAndroid'),
|
||||
Picker: require('Picker'),
|
||||
PickerIOS: require('PickerIOS'),
|
||||
ProgressBarAndroid: require('ProgressBarAndroid'),
|
||||
ProgressViewIOS: require('ProgressViewIOS'),
|
||||
@@ -72,6 +72,7 @@ var ReactNative = Object.assign(Object.create(require('React')), {
|
||||
AlertIOS: require('AlertIOS'),
|
||||
Animated: require('Animated'),
|
||||
AppRegistry: require('AppRegistry'),
|
||||
AppState: require('AppState'),
|
||||
AppStateIOS: require('AppStateIOS'),
|
||||
AsyncStorage: require('AsyncStorage'),
|
||||
BackAndroid: require('BackAndroid'),
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "React"
|
||||
s.version = "0.0.0-master"
|
||||
s.version = "0.19.0"
|
||||
s.summary = "Build high quality mobile apps using React."
|
||||
s.description = <<-DESC
|
||||
React Native apps are built using the React JS
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
VERSION_NAME=0.12.0-SNAPSHOT
|
||||
VERSION_NAME=0.19.1
|
||||
GROUP=com.facebook.react
|
||||
|
||||
POM_NAME=ReactNative
|
||||
|
||||
@@ -265,17 +265,6 @@ public class DevSupportManagerImpl implements DevSupportManager {
|
||||
handleReloadJS();
|
||||
}
|
||||
});
|
||||
options.put(
|
||||
mDevSettings.isHotModuleReplacementEnabled()
|
||||
? mApplicationContext.getString(R.string.catalyst_hot_module_replacement_off)
|
||||
: mApplicationContext.getString(R.string.catalyst_hot_module_replacement),
|
||||
new DevOptionHandler() {
|
||||
@Override
|
||||
public void onOptionSelected() {
|
||||
mDevSettings.setHotModuleReplacementEnabled(!mDevSettings.isHotModuleReplacementEnabled());
|
||||
handleReloadJS();
|
||||
}
|
||||
});
|
||||
options.put(
|
||||
mDevSettings.isReloadOnJSChangeEnabled()
|
||||
? mApplicationContext.getString(R.string.catalyst_live_reload_off)
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.facebook.react.modules.appstate;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.bridge.LifecycleEventListener;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter;
|
||||
|
||||
public class AppStateModule extends ReactContextBaseJavaModule
|
||||
implements LifecycleEventListener {
|
||||
|
||||
public static final String APP_STATE_ACTIVE = "active";
|
||||
public static final String APP_STATE_BACKGROUND = "background";
|
||||
|
||||
private String mAppState = "uninitialized";
|
||||
|
||||
public AppStateModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "AppState";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
getReactApplicationContext().addLifecycleEventListener(this);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getCurrentAppState(Callback success, Callback error) {
|
||||
success.invoke(createAppStateEventMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHostResume() {
|
||||
mAppState = APP_STATE_ACTIVE;
|
||||
sendAppStateChangeEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHostPause() {
|
||||
mAppState = APP_STATE_BACKGROUND;
|
||||
sendAppStateChangeEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHostDestroy() {
|
||||
// do not set state to destroyed, do not send an event. By the current implementation, the
|
||||
// catalyst instance is going to be immediately dropped, and all JS calls with it.
|
||||
}
|
||||
|
||||
private WritableMap createAppStateEventMap() {
|
||||
WritableMap appState = Arguments.createMap();
|
||||
appState.putString("app_state", mAppState);
|
||||
return appState;
|
||||
}
|
||||
|
||||
private void sendAppStateChangeEvent() {
|
||||
getReactApplicationContext().getJSModule(RCTDeviceEventEmitter.class)
|
||||
.emit("appStateDidChange", createAppStateEventMap());
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import com.facebook.react.modules.netinfo.NetInfoModule;
|
||||
import com.facebook.react.modules.network.NetworkingModule;
|
||||
import com.facebook.react.modules.storage.AsyncStorageModule;
|
||||
import com.facebook.react.modules.toast.ToastModule;
|
||||
import com.facebook.react.modules.appstate.AppStateModule;
|
||||
import com.facebook.react.modules.websocket.WebSocketModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import com.facebook.react.views.art.ARTRenderableViewManager;
|
||||
@@ -59,6 +60,7 @@ public class MainReactPackage implements ReactPackage {
|
||||
@Override
|
||||
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
||||
return Arrays.<NativeModule>asList(
|
||||
new AppStateModule(reactContext),
|
||||
new AsyncStorageModule(reactContext),
|
||||
new CameraRollManager(reactContext),
|
||||
new ClipboardModule(reactContext),
|
||||
@@ -68,8 +70,8 @@ public class MainReactPackage implements ReactPackage {
|
||||
new LocationModule(reactContext),
|
||||
new NetworkingModule(reactContext),
|
||||
new NetInfoModule(reactContext),
|
||||
new WebSocketModule(reactContext),
|
||||
new ToastModule(reactContext));
|
||||
new ToastModule(reactContext),
|
||||
new WebSocketModule(reactContext));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,17 +93,17 @@ public class MainReactPackage implements ReactPackage {
|
||||
new ReactImageManager(),
|
||||
new ReactProgressBarViewManager(),
|
||||
new ReactRawTextManager(),
|
||||
new RecyclerViewBackedScrollViewManager(),
|
||||
new ReactScrollViewManager(),
|
||||
new ReactSwitchManager(),
|
||||
new ReactTextInlineImageViewManager(),
|
||||
new ReactTextInputManager(),
|
||||
new ReactTextViewManager(),
|
||||
new ReactToolbarManager(),
|
||||
new ReactViewManager(),
|
||||
new ReactViewPagerManager(),
|
||||
new ReactTextInlineImageViewManager(),
|
||||
new ReactVirtualTextViewManager(),
|
||||
new SwipeRefreshLayoutManager(),
|
||||
new ReactWebViewManager());
|
||||
new ReactWebViewManager(),
|
||||
new RecyclerViewBackedScrollViewManager(),
|
||||
new SwipeRefreshLayoutManager());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ public class ViewProps {
|
||||
public static final String ON = "on";
|
||||
public static final String RESIZE_MODE = "resizeMode";
|
||||
public static final String TEXT_ALIGN = "textAlign";
|
||||
public static final String TEXT_ALIGN_VERTICAL = "textAlignVertical";
|
||||
|
||||
public static final String BORDER_WIDTH = "borderWidth";
|
||||
public static final String BORDER_LEFT_WIDTH = "borderLeftWidth";
|
||||
|
||||
@@ -352,11 +352,11 @@ public class ReactImageView extends GenericDraweeView {
|
||||
return resId > 0 ? context.getResources().getDrawable(resId) : null;
|
||||
}
|
||||
|
||||
private static @Nullable Uri getResourceDrawableUri(Context context, @Nullable String name) {
|
||||
private static Uri getResourceDrawableUri(Context context, @Nullable String name) {
|
||||
int resId = getResourceDrawableId(context, name);
|
||||
return resId > 0 ? new Uri.Builder()
|
||||
.scheme(UriUtil.LOCAL_RESOURCE_SCHEME)
|
||||
.path(String.valueOf(resId))
|
||||
.build() : null;
|
||||
.build() : Uri.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ public abstract class ReactPickerManager extends SimpleViewManager<ReactPicker>
|
||||
}
|
||||
|
||||
TextView textView = (TextView) convertView;
|
||||
textView.setText(item.getString("text"));
|
||||
textView.setText(item.getString("label"));
|
||||
if (!isDropdown && mPrimaryTextColor != null) {
|
||||
textView.setTextColor(mPrimaryTextColor);
|
||||
} else if (item.hasKey("color") && !item.isNull("color")) {
|
||||
|
||||
+28
-16
@@ -28,6 +28,8 @@ import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.JSApplicationCausedNativeException;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
@@ -202,14 +204,34 @@ public class ReactTextInputManager extends
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "textAlign")
|
||||
public void setTextAlign(ReactEditText view, int gravity) {
|
||||
view.setGravityHorizontal(gravity);
|
||||
@ReactProp(name = ViewProps.TEXT_ALIGN)
|
||||
public void setTextAlign(ReactEditText view, @Nullable String textAlign) {
|
||||
if (textAlign == null || "auto".equals(textAlign)) {
|
||||
view.setGravityHorizontal(Gravity.NO_GRAVITY);
|
||||
} else if ("left".equals(textAlign)) {
|
||||
view.setGravityHorizontal(Gravity.LEFT);
|
||||
} else if ("right".equals(textAlign)) {
|
||||
view.setGravityHorizontal(Gravity.RIGHT);
|
||||
} else if ("center".equals(textAlign)) {
|
||||
view.setGravityHorizontal(Gravity.CENTER_HORIZONTAL);
|
||||
} else {
|
||||
throw new JSApplicationIllegalArgumentException("Invalid textAlign: " + textAlign);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "textAlignVertical")
|
||||
public void setTextAlignVertical(ReactEditText view, int gravity) {
|
||||
view.setGravityVertical(gravity);
|
||||
@ReactProp(name = ViewProps.TEXT_ALIGN_VERTICAL)
|
||||
public void setTextAlignVertical(ReactEditText view, @Nullable String textAlignVertical) {
|
||||
if (textAlignVertical == null || "auto".equals(textAlignVertical)) {
|
||||
view.setGravityVertical(Gravity.NO_GRAVITY);
|
||||
} else if ("top".equals(textAlignVertical)) {
|
||||
view.setGravityVertical(Gravity.TOP);
|
||||
} else if ("bottom".equals(textAlignVertical)) {
|
||||
view.setGravityVertical(Gravity.BOTTOM);
|
||||
} else if ("center".equals(textAlignVertical)) {
|
||||
view.setGravityVertical(Gravity.CENTER_VERTICAL);
|
||||
} else {
|
||||
throw new JSApplicationIllegalArgumentException("Invalid textAlignVertical: " + textAlignVertical);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "editable", defaultBoolean = true)
|
||||
@@ -474,16 +496,6 @@ public class ReactTextInputManager extends
|
||||
@Override
|
||||
public @Nullable Map getExportedViewConstants() {
|
||||
return MapBuilder.of(
|
||||
"TextAlign",
|
||||
MapBuilder.of(
|
||||
"start", Gravity.START,
|
||||
"center", Gravity.CENTER_HORIZONTAL,
|
||||
"end", Gravity.END),
|
||||
"TextAlignVertical",
|
||||
MapBuilder.of(
|
||||
"top", Gravity.TOP,
|
||||
"center", Gravity.CENTER_VERTICAL,
|
||||
"bottom", Gravity.BOTTOM),
|
||||
"AutoCapitalizationType",
|
||||
MapBuilder.of(
|
||||
"none",
|
||||
|
||||
@@ -60,8 +60,7 @@ import com.android.build.OutputFile
|
||||
apply from: "react.gradle"
|
||||
|
||||
/**
|
||||
* Set this to true to create three separate APKs instead of one:
|
||||
* - A universal APK that works on all devices
|
||||
* Set this to true to create two separate APKs instead of one:
|
||||
* - An APK that only works on ARM devices
|
||||
* - An APK that only works on x86 devices
|
||||
* The advantage is the size of the APK is reduced by about 4MB.
|
||||
@@ -92,7 +91,7 @@ android {
|
||||
splits {
|
||||
abi {
|
||||
enable enableSeparateBuildPerCPUArchitecture
|
||||
universalApk true
|
||||
universalApk false // Also generate an universal APK
|
||||
reset()
|
||||
include "armeabi-v7a", "x86"
|
||||
}
|
||||
@@ -121,5 +120,5 @@ android {
|
||||
dependencies {
|
||||
compile fileTree(dir: "libs", include: ["*.jar"])
|
||||
compile "com.android.support:appcompat-v7:23.0.1"
|
||||
compile "com.facebook.react:react-native:0.13.0"
|
||||
compile "com.facebook.react:react-native:0.19.+"
|
||||
}
|
||||
|
||||
@@ -525,7 +525,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "../node_modules/react-native/packager/react-native-xcode.sh";
|
||||
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";
|
||||
showEnvVarsInLog = 1;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native",
|
||||
"version": "0.0.0-master",
|
||||
"version": "0.19.0",
|
||||
"description": "A framework for building native apps using React",
|
||||
"license": "BSD-3-Clause",
|
||||
"repository": {
|
||||
|
||||
@@ -10,6 +10,13 @@
|
||||
# This script is supposed to be invoked as part of Xcode build process
|
||||
# and relies on envoronment variables (including PWD) set by Xcode
|
||||
|
||||
# There is no point in creating an offline package for simulator builds
|
||||
# because the packager is supposed to be running during development anyways
|
||||
if [[ "$PLATFORM_NAME" = "iphonesimulator" ]]; then
|
||||
echo "Skipping bundling for Simulator platform"
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
case "$CONFIGURATION" in
|
||||
Debug)
|
||||
DEV=true
|
||||
@@ -23,12 +30,12 @@ case "$CONFIGURATION" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# Path to react-native folder inside node_modules
|
||||
REACT_NATIVE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
# Xcode project file for React Native apps is located in ios/ subfolder
|
||||
cd ..
|
||||
|
||||
set -x
|
||||
DEST=$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH
|
||||
|
||||
# Define NVM_DIR and source the nvm.sh setup script
|
||||
[ -z "$NVM_DIR" ] && export NVM_DIR="$HOME/.nvm"
|
||||
|
||||
@@ -43,10 +50,25 @@ if [[ -x "$HOME/.nodenv/bin/nodenv" ]]; then
|
||||
eval "$($HOME/.nodenv/bin/nodenv init -)"
|
||||
fi
|
||||
|
||||
# npm global install path may be a non-standard location
|
||||
PATH="$(npm prefix -g)/bin:$PATH"
|
||||
[ -z "$NODE_BINARY" ] && export NODE_BINARY="node"
|
||||
|
||||
react-native bundle \
|
||||
nodejs_not_found()
|
||||
{
|
||||
echo "error: Can't find '$NODE_BINARY' binary to build React Native bundle" >&2
|
||||
echo "If you have non-standard nodejs installation, select your project in Xcode," >&2
|
||||
echo "find 'Build Phases' - 'Bundle React Native code and images'" >&2
|
||||
echo "and change NODE_BINARY to absolute path to your node executable" >&2
|
||||
echo "(you can find it by invoking 'which node' in the terminal)" >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
type $NODE_BINARY >/dev/null 2>&1 || nodejs_not_found
|
||||
|
||||
# Print commands before executing them (useful for troubleshooting)
|
||||
set -x
|
||||
DEST=$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH
|
||||
|
||||
$NODE_BINARY $REACT_NATIVE_DIR/local-cli/cli.js bundle \
|
||||
--entry-file index.ios.js \
|
||||
--platform ios \
|
||||
--dev $DEV \
|
||||
|
||||
@@ -47,7 +47,6 @@ for i in "${artifacts_list[@]}"; do
|
||||
artifact_file="${artifacts_dir}/react-native-${RELEASE}.0${i}"
|
||||
|
||||
[ -e "${artifact_file}" ] || error "Couldn't find file: ${artifact_file}"
|
||||
[ -e "${artifact_file}.asc" ] || error "Couldn't find file: ${artifact_file}.asc"
|
||||
done
|
||||
|
||||
success "Generated artifacts for Maven"
|
||||
|
||||
@@ -225,6 +225,7 @@ var apis = [
|
||||
'../Libraries/Animated/src/AnimatedImplementation.js',
|
||||
'../Libraries/AppRegistry/AppRegistry.js',
|
||||
'../Libraries/AppStateIOS/AppStateIOS.ios.js',
|
||||
'../Libraries/AppState/AppState.js',
|
||||
'../Libraries/Storage/AsyncStorage.js',
|
||||
'../Libraries/Utilities/BackAndroid.android.js',
|
||||
'../Libraries/CameraRoll/CameraRoll.js',
|
||||
|
||||
Reference in New Issue
Block a user