[ReactNative] Add prompt to AlertIOS

Summary:
Add `AlertIOS.prompt`

It's compatible with the js spec, with the exception that I had to add
a callback param since it's async. Also supports the same button configuration
as `AlertIOS.alert`.

@public

Test Plan:
I've updated the `AlertIOS` example on UIExplorer with every
valid combination of
parameters, so just going through it should be fine.
This commit is contained in:
Tadeu Zagallo 2015-05-11 16:40:04 -07:00 committed by Christopher Chedeau
parent cfeae15c1f
commit ef339250b5
3 changed files with 154 additions and 7 deletions

View File

@ -95,9 +95,98 @@ exports.examples = [{
</TouchableHighlight>
</View>
);
},
}
},
{
title: 'Prompt',
render(): React.Component {
return <PromptExample />
}
}];
class PromptExample extends React.Component {
constructor(props) {
super(props);
this.promptResponse = this.promptResponse.bind(this);
this.state = {
promptValue: undefined,
};
this.title = 'Type a value';
this.defaultValue = 'Default value';
this.buttons = [{
text: 'Custom cancel',
}, {
text: 'Custom OK',
onPress: this.promptResponse
}];
}
render() {
return (
<View>
<Text style={{marginBottom: 10}}>
<Text style={{fontWeight: 'bold'}}>Prompt value:</Text> {this.state.promptValue}
</Text>
<TouchableHighlight
style={styles.wrapper}
onPress={this.prompt.bind(this, this.title, this.promptResponse)}>
<View style={styles.button}>
<Text>
prompt with title & callback
</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
style={styles.wrapper}
onPress={this.prompt.bind(this, this.title, this.buttons)}>
<View style={styles.button}>
<Text>
prompt with title & custom buttons
</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
style={styles.wrapper}
onPress={this.prompt.bind(this, this.title, this.defaultValue, this.promptResponse)}>
<View style={styles.button}>
<Text>
prompt with title, default value & callback
</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
style={styles.wrapper}
onPress={this.prompt.bind(this, this.title, this.defaultValue, this.buttons)}>
<View style={styles.button}>
<Text>
prompt with title, default value & custom buttons
</Text>
</View>
</TouchableHighlight>
</View>
);
}
prompt() {
// Flow's apply support is broken: #7035621
((AlertIOS.prompt: any).apply: any)(AlertIOS, arguments);
}
promptResponse(promptValue) {
this.setState({ promptValue });
}
}
var styles = StyleSheet.create({
wrapper: {
borderRadius: 5,

View File

@ -12,6 +12,7 @@
'use strict';
var RCTAlertManager = require('NativeModules').AlertManager;
var invariant = require('invariant');
var DEFAULT_BUTTON_TEXT = 'OK';
var DEFAULT_BUTTON = {
@ -47,14 +48,17 @@ class AlertIOS {
message?: ?string,
buttons?: Array<{
text: ?string;
onPress: ?Function;
}>
onPress?: ?Function;
}>,
type?: ?string
): void {
var callbacks = [];
var buttonsSpec = [];
title = title || '';
message = message || '';
buttons = buttons || [DEFAULT_BUTTON];
type = type || '';
buttons.forEach((btn, index) => {
callbacks[index] = btn.onPress;
var btnDef = {};
@ -65,12 +69,50 @@ class AlertIOS {
title,
message,
buttons: buttonsSpec,
}, (id) => {
type,
}, (id, value) => {
var cb = callbacks[id];
cb && cb();
cb && cb(value);
});
}
static prompt(
title: string,
value?: string,
buttons?: Array<{
text: ?string;
onPress?: ?Function;
}>,
callback?: ?Function
): void {
if (arguments.length === 2) {
if (typeof value === 'object') {
buttons = value;
value = undefined;
} else if (typeof value === 'function') {
callback = value;
value = undefined;
}
} else if (arguments.length === 3 && typeof buttons === 'function') {
callback = buttons;
buttons = undefined;
}
invariant(
!(callback && buttons) && (callback || buttons),
'Must provide either a button list or a callback, but not both'
);
if (!buttons) {
buttons = [{
text: 'Cancel',
}, {
text: 'OK',
onPress: callback
}];
}
this.alert(title, value, buttons, 'plain-text');
}
}
module.exports = AlertIOS;

View File

@ -59,6 +59,7 @@ RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args
{
NSString *title = args[@"title"];
NSString *message = args[@"message"];
NSString *type = args[@"type"];
NSArray *buttons = args[@"buttons"];
if (!title && !message) {
@ -70,13 +71,20 @@ RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args
}
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
message:message
message:nil
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
NSMutableArray *buttonKeys = [[NSMutableArray alloc] initWithCapacity:buttons.count];
if ([type isEqualToString:@"plain-text"]) {
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
[alertView textFieldAtIndex:0].text = message;
} else {
alertView.message = message;
}
NSInteger index = 0;
for (NSDictionary *button in buttons) {
if (button.count != 1) {
@ -108,7 +116,15 @@ RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args
RCTResponseSenderBlock callback = _alertCallbacks[index];
NSArray *buttonKeys = _alertButtonKeys[index];
callback(@[buttonKeys[buttonIndex]]);
NSArray *args;
if (alertView.alertViewStyle == UIAlertViewStylePlainTextInput) {
args = @[buttonKeys[buttonIndex], [alertView textFieldAtIndex:0].text];
} else {
args = @[buttonKeys[buttonIndex]];
}
callback(args);
[_alerts removeObjectAtIndex:index];
[_alertCallbacks removeObjectAtIndex:index];