diff --git a/Libraries/Alert/Alert.js b/Libraries/Alert/Alert.js index ceab6763680b8e..c47a1a796e8b73 100644 --- a/Libraries/Alert/Alert.js +++ b/Libraries/Alert/Alert.js @@ -10,12 +10,10 @@ 'use strict'; -const AlertIOS = require('AlertIOS'); const NativeModules = require('NativeModules'); +const RCTAlertManager = NativeModules.AlertManager; const Platform = require('Platform'); -import type {AlertType, AlertButtonStyle} from 'AlertIOS'; - export type Buttons = Array<{ text?: string, onPress?: ?Function, @@ -27,37 +25,140 @@ type Options = { onDismiss?: ?Function, }; +type AlertType = $Enum<{ + default: string, + 'plain-text': string, + 'secure-text': string, + 'login-password': string, +}>; + +export type AlertButtonStyle = $Enum<{ + default: string, + cancel: string, + destructive: string, +}>; + /** * Launches an alert dialog with the specified title and message. * * See http://facebook.github.io/react-native/docs/alert.html */ class Alert { - /** - * Launches an alert dialog with the specified title and message. - * - * See http://facebook.github.io/react-native/docs/alert.html#alert - */ static alert( title: ?string, message?: ?string, buttons?: Buttons, options?: Options, - type?: AlertType, ): void { if (Platform.OS === 'ios') { - if (typeof type !== 'undefined') { - console.warn( - 'Alert.alert() with a 5th "type" parameter is deprecated and will be removed. Use AlertIOS.prompt() instead.', - ); - AlertIOS.alert(title, message, buttons, type); - return; - } AlertIOS.alert(title, message, buttons); } else if (Platform.OS === 'android') { AlertAndroid.alert(title, message, buttons, options); } } + + static prompt( + title: ?string, + message?: ?string, + callbackOrButtons?: ?(((text: string) => void) | Buttons), + type?: ?AlertType = 'plain-text', + defaultValue?: string, + keyboardType?: string, + ): void { + if (Platform.OS === 'ios') { + AlertIOS.prompt( + title, + message, + callbackOrButtons, + type, + defaultValue, + keyboardType, + ); + } + } +} + +/** + * Wrapper around the iOS native module. + */ +class AlertIOS { + static alert( + title: ?string, + message?: ?string, + callbackOrButtons?: ?((() => void) | Buttons), + ): void { + this.prompt(title, message, callbackOrButtons, 'default'); + } + + static prompt( + title: ?string, + message?: ?string, + callbackOrButtons?: ?(((text: string) => void) | Buttons), + type?: ?AlertType = 'plain-text', + defaultValue?: string, + keyboardType?: string, + ): void { + if (typeof type === 'function') { + console.warn( + 'You passed a callback function as the "type" argument to Alert.prompt(). React Native is ' + + 'assuming you want to use the deprecated Alert.prompt(title, defaultValue, buttons, callback) ' + + 'signature. The current signature is Alert.prompt(title, message, callbackOrButtons, type, defaultValue, ' + + 'keyboardType) and the old syntax will be removed in a future version.', + ); + + const callback = type; + RCTAlertManager.alertWithArgs( + { + title: title || '', + type: 'plain-text', + defaultValue: message, + }, + (id, value) => { + callback(value); + }, + ); + return; + } + + let callbacks = []; + const buttons = []; + let cancelButtonKey; + let destructiveButtonKey; + if (typeof callbackOrButtons === 'function') { + callbacks = [callbackOrButtons]; + } else if (Array.isArray(callbackOrButtons)) { + callbackOrButtons.forEach((btn, index) => { + callbacks[index] = btn.onPress; + if (btn.style === 'cancel') { + cancelButtonKey = String(index); + } else if (btn.style === 'destructive') { + destructiveButtonKey = String(index); + } + if (btn.text || index < (callbackOrButtons || []).length - 1) { + const btnDef = {}; + btnDef[index] = btn.text || ''; + buttons.push(btnDef); + } + }); + } + + RCTAlertManager.alertWithArgs( + { + title: title || '', + message: message || undefined, + buttons, + type: type || undefined, + defaultValue, + cancelButtonKey, + destructiveButtonKey, + keyboardType, + }, + (id, value) => { + const cb = callbacks[id]; + cb && cb(value); + }, + ); + } } /** diff --git a/Libraries/Alert/AlertIOS.js b/Libraries/Alert/AlertIOS.js deleted file mode 100644 index b7e1a0d73b7b59..00000000000000 --- a/Libraries/Alert/AlertIOS.js +++ /dev/null @@ -1,181 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow - * @jsdoc - */ - -'use strict'; - -const RCTAlertManager = require('NativeModules').AlertManager; - -/** - * An Alert button type - */ -export type AlertType = $Enum<{ - /** - * Default alert with no inputs - */ - default: string, - /** - * Plain text input alert - */ - 'plain-text': string, - /** - * Secure text input alert - */ - 'secure-text': string, - /** - * Login and password alert - */ - 'login-password': string, -}>; - -/** - * An Alert button style - */ -export type AlertButtonStyle = $Enum<{ - /** - * Default button style - */ - default: string, - /** - * Cancel button style - */ - cancel: string, - /** - * Destructive button style - */ - destructive: string, -}>; - -/** - * Array or buttons - * @typedef {Array} ButtonsArray - * @property {string=} text Button label - * @property {Function=} onPress Callback function when button pressed - * @property {AlertButtonStyle=} style Button style - */ -export type ButtonsArray = Array<{ - /** - * Button label - */ - text?: string, - /** - * Callback function when button pressed - */ - onPress?: ?Function, - /** - * Button style - */ - style?: AlertButtonStyle, -}>; - -/** - * Use `AlertIOS` to display an alert dialog with a message or to create a prompt for user input on iOS. If you don't need to prompt for user input, we recommend using `Alert.alert() for cross-platform support. - * - * See http://facebook.github.io/react-native/docs/alertios.html - */ -class AlertIOS { - /** - * Create and display a popup alert. - * - * See http://facebook.github.io/react-native/docs/alertios.html#alert - */ - static alert( - title: ?string, - message?: ?string, - callbackOrButtons?: ?((() => void) | ButtonsArray), - type?: AlertType, - ): void { - if (typeof type !== 'undefined') { - console.warn( - 'AlertIOS.alert() with a 4th "type" parameter is deprecated and will be removed. Use AlertIOS.prompt() instead.', - ); - this.prompt(title, message, callbackOrButtons, type); - return; - } - this.prompt(title, message, callbackOrButtons, 'default'); - } - - /** - * Create and display a prompt to enter some text. - * - * See http://facebook.github.io/react-native/docs/alertios.html#prompt - */ - static prompt( - title: ?string, - message?: ?string, - callbackOrButtons?: ?(((text: string) => void) | ButtonsArray), - type?: ?AlertType = 'plain-text', - defaultValue?: string, - keyboardType?: string, - ): void { - if (typeof type === 'function') { - console.warn( - 'You passed a callback function as the "type" argument to AlertIOS.prompt(). React Native is ' + - 'assuming you want to use the deprecated AlertIOS.prompt(title, defaultValue, buttons, callback) ' + - 'signature. The current signature is AlertIOS.prompt(title, message, callbackOrButtons, type, defaultValue, ' + - 'keyboardType) and the old syntax will be removed in a future version.', - ); - - const callback = type; - RCTAlertManager.alertWithArgs( - { - title: title || '', - type: 'plain-text', - defaultValue: message, - }, - (id, value) => { - callback(value); - }, - ); - return; - } - - let callbacks = []; - const buttons = []; - let cancelButtonKey; - let destructiveButtonKey; - if (typeof callbackOrButtons === 'function') { - callbacks = [callbackOrButtons]; - } else if (callbackOrButtons instanceof Array) { - callbackOrButtons.forEach((btn, index) => { - callbacks[index] = btn.onPress; - if (btn.style === 'cancel') { - cancelButtonKey = String(index); - } else if (btn.style === 'destructive') { - destructiveButtonKey = String(index); - } - if (btn.text || index < (callbackOrButtons || []).length - 1) { - const btnDef = {}; - btnDef[index] = btn.text || ''; - buttons.push(btnDef); - } - }); - } - - RCTAlertManager.alertWithArgs( - { - title: title || '', - message: message || undefined, - buttons, - type: type || undefined, - defaultValue, - cancelButtonKey, - destructiveButtonKey, - keyboardType, - }, - (id, value) => { - const cb = callbacks[id]; - cb && cb(value); - }, - ); - } -} - -module.exports = AlertIOS; diff --git a/Libraries/react-native/react-native-implementation.js b/Libraries/react-native/react-native-implementation.js index 1609858b8e35de..b7dc52b10a0533 100644 --- a/Libraries/react-native/react-native-implementation.js +++ b/Libraries/react-native/react-native-implementation.js @@ -198,7 +198,11 @@ module.exports = { return require('Alert'); }, get AlertIOS() { - return require('AlertIOS'); + warnOnce( + 'alert-ios', + 'AlertIOS is deprecated. Use the `Alert` module directly instead.', + ); + return require('Alert'); }, get Animated() { return require('Animated'); diff --git a/RNTester/js/AlertIOSExample.js b/RNTester/js/AlertIOSExample.js index b1e9f352eafed0..390ebf431cd5ed 100644 --- a/RNTester/js/AlertIOSExample.js +++ b/RNTester/js/AlertIOSExample.js @@ -12,7 +12,7 @@ const React = require('react'); const ReactNative = require('react-native'); -const {StyleSheet, View, Text, TouchableHighlight, AlertIOS} = ReactNative; +const {StyleSheet, View, Text, TouchableHighlight, Alert} = ReactNative; const {SimpleAlertExampleBlock} = require('./AlertExample'); @@ -54,9 +54,7 @@ class PromptOptions extends React.Component { - AlertIOS.prompt('Type a value', null, this.saveResponse) - }> + onPress={() => Alert.prompt('Type a value', null, this.saveResponse)}> prompt with title & callback @@ -65,7 +63,7 @@ class PromptOptions extends React.Component { - AlertIOS.prompt('Type a value', null, this.customButtons) + Alert.prompt('Type a value', null, this.customButtons) }> prompt with title & custom buttons @@ -75,7 +73,7 @@ class PromptOptions extends React.Component { - AlertIOS.prompt( + Alert.prompt( 'Type a phone number', null, null, @@ -92,7 +90,7 @@ class PromptOptions extends React.Component { - AlertIOS.prompt( + Alert.prompt( 'Type a value', null, this.saveResponse, @@ -108,7 +106,7 @@ class PromptOptions extends React.Component { - AlertIOS.prompt( + Alert.prompt( 'Type a value', null, this.customButtons, @@ -149,7 +147,7 @@ const styles = StyleSheet.create({ }); exports.framework = 'React'; -exports.title = 'AlertIOS'; +exports.title = 'Alert'; exports.description = 'iOS alerts and action sheets'; exports.examples = [ { @@ -171,7 +169,7 @@ exports.examples = [ AlertIOS.prompt('Plain Text Entry')}> + onPress={() => Alert.prompt('Plain Text Entry')}> plain-text @@ -179,7 +177,7 @@ exports.examples = [ - AlertIOS.prompt('Secure Text', null, null, 'secure-text') + Alert.prompt('Secure Text', null, null, 'secure-text') }> secure-text @@ -188,7 +186,7 @@ exports.examples = [ - AlertIOS.prompt('Login & Password', null, null, 'login-password') + Alert.prompt('Login & Password', null, null, 'login-password') }> login-password diff --git a/RNTester/js/PushNotificationIOSExample.js b/RNTester/js/PushNotificationIOSExample.js index a841f126e7de95..62066f1f09a11c 100644 --- a/RNTester/js/PushNotificationIOSExample.js +++ b/RNTester/js/PushNotificationIOSExample.js @@ -13,7 +13,7 @@ const React = require('react'); const ReactNative = require('react-native'); const { - AlertIOS, + Alert, PushNotificationIOS, StyleSheet, Text, @@ -110,20 +110,16 @@ class NotificationExample extends React.Component<{}> { } _onRegistered(deviceToken) { - AlertIOS.alert( - 'Registered For Remote Push', - `Device Token: ${deviceToken}`, - [ - { - text: 'Dismiss', - onPress: null, - }, - ], - ); + Alert.alert('Registered For Remote Push', `Device Token: ${deviceToken}`, [ + { + text: 'Dismiss', + onPress: null, + }, + ]); } _onRegistrationError(error) { - AlertIOS.alert( + Alert.alert( 'Failed To Register For Remote Push', `Error (${error.code}): ${error.message}`, [ @@ -142,7 +138,7 @@ class NotificationExample extends React.Component<{}> { category: ${notification.getCategory()};\n content-available: ${notification.getContentAvailable()}.`; - AlertIOS.alert('Push Notification Received', result, [ + Alert.alert('Push Notification Received', result, [ { text: 'Dismiss', onPress: null, @@ -151,7 +147,7 @@ class NotificationExample extends React.Component<{}> { } _onLocalNotification(notification) { - AlertIOS.alert( + Alert.alert( 'Local Notification Received', 'Alert message: ' + notification.getMessage(), [ diff --git a/RNTester/js/TimerExample.js b/RNTester/js/TimerExample.js index f1be0ece82b460..aaa5268afc3a9c 100644 --- a/RNTester/js/TimerExample.js +++ b/RNTester/js/TimerExample.js @@ -12,7 +12,7 @@ const React = require('react'); const ReactNative = require('react-native'); -const {AlertIOS, Platform, ToastAndroid, Text, View} = ReactNative; +const {Alert, Platform, ToastAndroid, Text, View} = ReactNative; const RNTesterButton = require('./RNTesterButton'); const performanceNow = require('fbjs/lib/performanceNow'); @@ -230,7 +230,7 @@ class TimerTester extends React.Component { ' ms / iter'; console.log(msg); if (Platform.OS === 'ios') { - AlertIOS.alert(msg); + Alert.alert(msg); } else if (Platform.OS === 'android') { ToastAndroid.show(msg, ToastAndroid.SHORT); }