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 {