From c6d8f6048ad850c8564b74062d886e4e59048cf9 Mon Sep 17 00:00:00 2001 From: Christoph Nakazawa Date: Wed, 13 Feb 2019 04:18:19 -0800 Subject: [PATCH] Properly gate platform specific code in Alert Summary: In the past, Alert and AlertIOS were separate modules and both were shipped on Android even though only Alert can be used there. We unified the two modules but it meant that the code for both was still shipped on both platforms. This diff changes it so that platform specific code is gated in a `Platform.OS` block, which means that the unnecessary code per platform is being stripped out. I'm not looking to win a beauty contest with the code in this module - we have barely touched it in years and I don't think we will touch it anytime soon, so I just merged the sub-classes (which only had static methods anyway) directly into the main class. I'm aware I could make two separate files with platform extensions but that ends up being more code here and it seems straightforward enough to me. Reviewed By: TheSavior Differential Revision: D14057404 fbshipit-source-id: 1ae1d227a39d76de9779b3db62960cca46e9b75c --- Libraries/Alert/Alert.js | 241 ++++++++++++++++----------------------- 1 file changed, 99 insertions(+), 142 deletions(-) diff --git a/Libraries/Alert/Alert.js b/Libraries/Alert/Alert.js index c47a1a796e8..ddc126516cb 100644 --- a/Libraries/Alert/Alert.js +++ b/Libraries/Alert/Alert.js @@ -51,9 +51,56 @@ class Alert { options?: Options, ): void { if (Platform.OS === 'ios') { - AlertIOS.alert(title, message, buttons); + Alert.prompt(title, message, buttons, 'default'); } else if (Platform.OS === 'android') { - AlertAndroid.alert(title, message, buttons, options); + let config = { + title: title || '', + message: message || '', + }; + + if (options) { + config = {...config, cancelable: options.cancelable}; + } + // At most three buttons (neutral, negative, positive). Ignore rest. + // The text 'OK' should be probably localized. iOS Alert does that in native. + const validButtons: Buttons = buttons + ? buttons.slice(0, 3) + : [{text: 'OK'}]; + const buttonPositive = validButtons.pop(); + const buttonNegative = validButtons.pop(); + const buttonNeutral = validButtons.pop(); + if (buttonNeutral) { + config = {...config, buttonNeutral: buttonNeutral.text || ''}; + } + if (buttonNegative) { + config = {...config, buttonNegative: buttonNegative.text || ''}; + } + if (buttonPositive) { + config = {...config, buttonPositive: buttonPositive.text || ''}; + } + NativeModules.DialogManagerAndroid.showAlert( + config, + errorMessage => console.warn(errorMessage), + (action, buttonKey) => { + if (action === NativeModules.DialogManagerAndroid.buttonClicked) { + if ( + buttonKey === NativeModules.DialogManagerAndroid.buttonNeutral + ) { + buttonNeutral.onPress && buttonNeutral.onPress(); + } else if ( + buttonKey === NativeModules.DialogManagerAndroid.buttonNegative + ) { + buttonNegative.onPress && buttonNegative.onPress(); + } else if ( + buttonKey === NativeModules.DialogManagerAndroid.buttonPositive + ) { + buttonPositive.onPress && buttonPositive.onPress(); + } + } else if (action === NativeModules.DialogManagerAndroid.dismissed) { + options && options.onDismiss && options.onDismiss(); + } + }, + ); } } @@ -66,157 +113,67 @@ class Alert { keyboardType?: string, ): void { if (Platform.OS === 'ios') { - AlertIOS.prompt( - title, - message, - callbackOrButtons, - type, - defaultValue, - keyboardType, - ); - } - } -} + 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.', + ); -/** - * Wrapper around the iOS native module. - */ -class AlertIOS { - static alert( - title: ?string, - message?: ?string, - callbackOrButtons?: ?((() => void) | Buttons), - ): void { - this.prompt(title, message, callbackOrButtons, 'default'); - } + const callback = type; + RCTAlertManager.alertWithArgs( + { + title: title || '', + type: 'plain-text', + defaultValue: message, + }, + (id, value) => { + callback(value); + }, + ); + return; + } - 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.', - ); + 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); + } + }); + } - const callback = type; RCTAlertManager.alertWithArgs( { title: title || '', - type: 'plain-text', - defaultValue: message, + message: message || undefined, + buttons, + type: type || undefined, + defaultValue, + cancelButtonKey, + destructiveButtonKey, + keyboardType, }, (id, value) => { - callback(value); + const cb = callbacks[id]; + cb && cb(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); - }, - ); - } -} - -/** - * Wrapper around the Android native module. - */ -class AlertAndroid { - static alert( - title: ?string, - message?: ?string, - buttons?: Buttons, - options?: Options, - ): void { - let config = { - title: title || '', - message: message || '', - }; - - if (options) { - config = {...config, cancelable: options.cancelable}; - } - // At most three buttons (neutral, negative, positive). Ignore rest. - // The text 'OK' should be probably localized. iOS Alert does that in native. - const validButtons: Buttons = buttons - ? buttons.slice(0, 3) - : [{text: 'OK'}]; - const buttonPositive = validButtons.pop(); - const buttonNegative = validButtons.pop(); - const buttonNeutral = validButtons.pop(); - if (buttonNeutral) { - config = {...config, buttonNeutral: buttonNeutral.text || ''}; - } - if (buttonNegative) { - config = {...config, buttonNegative: buttonNegative.text || ''}; - } - if (buttonPositive) { - config = {...config, buttonPositive: buttonPositive.text || ''}; - } - NativeModules.DialogManagerAndroid.showAlert( - config, - errorMessage => console.warn(errorMessage), - (action, buttonKey) => { - if (action === NativeModules.DialogManagerAndroid.buttonClicked) { - if (buttonKey === NativeModules.DialogManagerAndroid.buttonNeutral) { - buttonNeutral.onPress && buttonNeutral.onPress(); - } else if ( - buttonKey === NativeModules.DialogManagerAndroid.buttonNegative - ) { - buttonNegative.onPress && buttonNegative.onPress(); - } else if ( - buttonKey === NativeModules.DialogManagerAndroid.buttonPositive - ) { - buttonPositive.onPress && buttonPositive.onPress(); - } - } else if (action === NativeModules.DialogManagerAndroid.dismissed) { - options && options.onDismiss && options.onDismiss(); - } - }, - ); } }