From a7c1c5aff24671bba609caeb82092a8de3d3b232 Mon Sep 17 00:00:00 2001 From: Luke Walczak Date: Wed, 18 Nov 2020 21:09:39 -0800 Subject: [PATCH] Add possibility to disable buttons in action sheet ios (#28979) Summary: _**Fixed**_ version of [the previous PR](https://github.com/facebook/react-native/pull/28792) after reverting [changes](https://github.com/facebook/react-native/commit/c8d678abcf93fd3f6daf4bebfdf25937995c1fdf#commitcomment-39299254) ---- I've noticed that currently there is no option to disable button within the `ActionSheetIOS`. It can be really useful and decided to extend the API to support that functionality. I added a new option called `disabledButtonsIndices` to `ActionSheetIOS` which is an array of button indices which should be disabled. `ActionSheetIOS` documentation - PR https://github.com/facebook/react-native-website/pull/1898 ## Changelog [iOS] [Added] - Add disableButtonsIndices option to ActionSheetIOS component Pull Request resolved: https://github.com/facebook/react-native/pull/28979 Test Plan: 1. Run the `RNTester` 2. Choose `ActionSheetIOS` 3. Check the fourth example `Show Action Sheet with disabled buttons` 4. `Option 1` and `Option 2` should be disabled screenshot | gif --- | --- Screenshot 2020-04-30 at 15 16 22 | Reviewed By: sammy-SC Differential Revision: D21727497 Pulled By: PeteTheHeat fbshipit-source-id: 749b6c623eb8a44fe2bd96829ce89be5310e2368 --- Libraries/ActionSheetIOS/ActionSheetIOS.js | 2 + .../NativeActionSheetManager.js | 1 + React/CoreModules/RCTActionSheetManager.mm | 18 +++++++++ .../ActionSheetIOS/ActionSheetIOSExample.js | 38 +++++++++++++++++++ 4 files changed, 59 insertions(+) diff --git a/Libraries/ActionSheetIOS/ActionSheetIOS.js b/Libraries/ActionSheetIOS/ActionSheetIOS.js index bc3a935dee298b..1fc86a0fd8872c 100644 --- a/Libraries/ActionSheetIOS/ActionSheetIOS.js +++ b/Libraries/ActionSheetIOS/ActionSheetIOS.js @@ -33,6 +33,7 @@ const ActionSheetIOS = { * - `destructiveButtonIndex` (int or array of ints) - index or indices of destructive buttons in `options` * - `title` (string) - a title to show above the action sheet * - `message` (string) - a message to show below the title + * - `disabledButtonIndices` (array of numbers) - a list of button indices which should be disabled * * The 'callback' function takes one parameter, the zero-based index * of the selected item. @@ -49,6 +50,7 @@ const ActionSheetIOS = { +anchor?: ?number, +tintColor?: ColorValue | ProcessedColorValue, +userInterfaceStyle?: string, + +disabledButtonIndices?: Array, |}, callback: (buttonIndex: number) => void, ) { diff --git a/Libraries/ActionSheetIOS/NativeActionSheetManager.js b/Libraries/ActionSheetIOS/NativeActionSheetManager.js index 063d9147e1d69b..6d86200d9accd6 100644 --- a/Libraries/ActionSheetIOS/NativeActionSheetManager.js +++ b/Libraries/ActionSheetIOS/NativeActionSheetManager.js @@ -25,6 +25,7 @@ export interface Spec extends TurboModule { +anchor?: ?number, +tintColor?: ?number, +userInterfaceStyle?: ?string, + +disabledButtonIndices?: Array, |}, callback: (buttonIndex: number) => void, ) => void; diff --git a/React/CoreModules/RCTActionSheetManager.mm b/React/CoreModules/RCTActionSheetManager.mm index 754e461157349d..c2eae7c9fe8808 100644 --- a/React/CoreModules/RCTActionSheetManager.mm +++ b/React/CoreModules/RCTActionSheetManager.mm @@ -73,9 +73,15 @@ - (void)presentViewController:(UIViewController *)alertController NSArray *buttons = RCTConvertOptionalVecToArray(options.options(), ^id(NSString *element) { return element; }); + NSArray *disabledButtonIndices; NSInteger cancelButtonIndex = options.cancelButtonIndex() ? [RCTConvert NSInteger:@(*options.cancelButtonIndex())] : -1; NSArray *destructiveButtonIndices; + if (options.disabledButtonIndices()) { + disabledButtonIndices = RCTConvertVecToArray(*options.disabledButtonIndices(), ^id(double element) { + return @(element); + }); + } if (options.destructiveButtonIndices()) { destructiveButtonIndices = RCTConvertVecToArray(*options.destructiveButtonIndices(), ^id(double element) { return @(element); @@ -98,6 +104,7 @@ - (void)presentViewController:(UIViewController *)alertController @"destructiveButtonIndices" : destructiveButtonIndices, @"anchor" : anchor, @"tintColor" : tintColor, + @"disabledButtonIndices" : disabledButtonIndices, }); return; } @@ -132,6 +139,17 @@ - (void)presentViewController:(UIViewController *)alertController index++; } + if (disabledButtonIndices) { + for (NSNumber *disabledButtonIndex in disabledButtonIndices) { + if ([disabledButtonIndex integerValue] < buttons.count) { + [alertController.actions[[disabledButtonIndex integerValue]] setEnabled:false]; + } else { + RCTLogError(@"Index %@ from `disabledButtonIndices` is out of bounds. Maximum index value is %@.", @([disabledButtonIndex integerValue]), @(buttons.count - 1)); + return; + } + } + } + alertController.view.tintColor = tintColor; #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \ __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 diff --git a/packages/rn-tester/js/examples/ActionSheetIOS/ActionSheetIOSExample.js b/packages/rn-tester/js/examples/ActionSheetIOS/ActionSheetIOSExample.js index 786811a725d53f..917cba05c0ce09 100644 --- a/packages/rn-tester/js/examples/ActionSheetIOS/ActionSheetIOSExample.js +++ b/packages/rn-tester/js/examples/ActionSheetIOS/ActionSheetIOSExample.js @@ -25,6 +25,7 @@ const ScreenshotManager = NativeModules.ScreenshotManager; const BUTTONS = ['Option 0', 'Option 1', 'Option 2', 'Delete', 'Cancel']; const DESTRUCTIVE_INDEX = 3; const CANCEL_INDEX = 4; +const DISABLED_BUTTON_INDICES = [1, 2]; type Props = $ReadOnly<{||}>; type State = {|clicked: string|}; @@ -138,6 +139,37 @@ class ActionSheetAnchorExample extends React.Component< }; } +class ActionSheetDisabledExample extends React.Component { + state = { + clicked: 'none', + }; + + render() { + return ( + + + Click to show the ActionSheet + + Clicked button: {this.state.clicked} + + ); + } + + showActionSheet = () => { + ActionSheetIOS.showActionSheetWithOptions( + { + options: BUTTONS, + cancelButtonIndex: CANCEL_INDEX, + destructiveButtonIndex: DESTRUCTIVE_INDEX, + disabledButtonIndices: DISABLED_BUTTON_INDICES, + }, + buttonIndex => { + this.setState({clicked: BUTTONS[buttonIndex]}); + }, + ); + }; +} + class ShareActionSheetExample extends React.Component< $FlowFixMeProps, $FlowFixMeState, @@ -316,6 +348,12 @@ exports.examples = [ return ; }, }, + { + title: 'Show Action Sheet with disabled buttons', + render(): React.Element { + return ; + }, + }, { title: 'Show Share Action Sheet', render(): React.Element {