From b2ca77a362301d6b437f8d307b00624aab4ffdfc Mon Sep 17 00:00:00 2001 From: Brad Bumbalough Date: Mon, 18 Oct 2021 16:56:43 -0500 Subject: [PATCH] fix: defer calling onSelect until after animation - Fixes #203 --- example/App.tsx | 43 ++++++++++++++++++++++++++++--- example/ShowActionSheetButton.tsx | 10 +++---- src/ActionSheet/index.tsx | 15 ++++++----- 3 files changed, 53 insertions(+), 15 deletions(-) diff --git a/example/App.tsx b/example/App.tsx index d96cc5c..9613aed 100644 --- a/example/App.tsx +++ b/example/App.tsx @@ -12,6 +12,7 @@ import { ScrollView, SafeAreaView, TouchableOpacity, + Share, } from 'react-native'; import ShowActionSheetButton from './ShowActionSheetButton'; @@ -19,7 +20,7 @@ import ShowActionSheetButton from './ShowActionSheetButton'; type Props = ActionSheetProps; interface State { - selectedIndex: number | null; + selectedIndex?: number | null; isModalOpen: boolean; } @@ -29,7 +30,7 @@ class App extends React.Component { isModalOpen: false, }; - _updateSelectionText = (selectedIndex: number) => { + _updateSelectionText = (selectedIndex?: number) => { this.setState({ selectedIndex, }); @@ -38,7 +39,9 @@ class App extends React.Component { _renderSelectionText = () => { const { selectedIndex } = this.state; const text = - selectedIndex === null ? 'No Option Selected' : `Option #${selectedIndex + 1} Selected`; + selectedIndex === null || selectedIndex === undefined + ? 'No Option Selected' + : `Option #${selectedIndex + 1} Selected`; return {text}; }; @@ -50,6 +53,23 @@ class App extends React.Component { this.setState((prevState) => ({ isModalOpen: !prevState.isModalOpen })); }; + async _onShare() { + try { + const result = await Share.share({ + message: 'React Native | A framework for building native apps using React', + }); + if (result.action === Share.sharedAction) { + if (result.activityType) { + // shared with activity type of result.activityType + } else { + // shared + } + } else if (result.action === Share.dismissedAction) { + // dismissed + } + } catch (error) {} + } + _renderButtons() { const { showActionSheetWithOptions } = this.props; return ( @@ -86,7 +106,7 @@ class App extends React.Component { { - if (index < 3) { + if (!index || index < 3) { showActionSheetWithOptions( { title: 'Sub Action Sheet', @@ -99,6 +119,21 @@ class App extends React.Component { }} showActionSheetWithOptions={showActionSheetWithOptions} /> + + showActionSheetWithOptions( + { + title: 'Share Menu', + options: ['Share', 'Cancel'], + cancelButtonIndex: 1, + }, + (i) => { + i === 0 && this._onShare(); + } + ) + } + /> {this._renderSectionHeader('Android-Only Options')} void + callback: (buttonIndex?: number) => void ) => void; - onSelection: (index: number) => void; + onSelection: (index?: number) => void; withTitle?: boolean; withMessage?: boolean; withIcons?: boolean; @@ -52,7 +52,7 @@ export default class ShowActionSheetButton extends React.PureComponent { } = this.props; // Same interface as https://facebook.github.io/react-native/docs/actionsheetios.html - const options = ['Delete', 'Disabled', 'Save', 'Share', 'Cancel']; + const options = ['Delete', 'Disabled', 'Save', 'Cancel']; const icons = withIcons ? [icon('delete'), icon('save'), icon('share'), icon('cancel')] : undefined; @@ -62,7 +62,7 @@ export default class ShowActionSheetButton extends React.PureComponent { : undefined; const destructiveButtonIndex = 0; const disabledButtonIndices = [1]; - const cancelButtonIndex = 4; + const cancelButtonIndex = 3; const textStyle: TextStyle | undefined = withCustomStyles ? { fontSize: 20, @@ -120,7 +120,7 @@ export default class ShowActionSheetButton extends React.PureComponent { // Android only, useModal, }, - (buttonIndex: number) => { + (buttonIndex?: number) => { // Do something here depending on the button index selected onSelection(buttonIndex); } diff --git a/src/ActionSheet/index.tsx b/src/ActionSheet/index.tsx index 72fae8b..72ea5d7 100644 --- a/src/ActionSheet/index.tsx +++ b/src/ActionSheet/index.tsx @@ -49,7 +49,7 @@ export default class ActionSheet extends React.Component { sheetOpacity: new Animated.Value(0), }; - _deferNextShow?: () => void = undefined; + _deferAfterAnimation?: () => void = undefined; _setActionSheetHeight = ({ nativeEvent }: any) => (this._actionSheetHeight = nativeEvent.layout.height); @@ -171,7 +171,7 @@ export default class ActionSheet extends React.Component { const { isVisible, overlayOpacity, sheetOpacity } = this.state; if (isVisible) { - this._deferNextShow = this.showActionSheetWithOptions.bind(this, options, onSelect); + this._deferAfterAnimation = this.showActionSheetWithOptions.bind(this, options, onSelect); return; } @@ -201,7 +201,7 @@ export default class ActionSheet extends React.Component { this.setState({ isAnimating: false, }); - this._deferNextShow = undefined; + this._deferAfterAnimation = undefined; } }); // @ts-ignore: Argument of type '"actionSheetHardwareBackPress"' is not assignable to parameter of type '"hardwareBackPress"' @@ -231,7 +231,10 @@ export default class ActionSheet extends React.Component { return false; } - onSelect && onSelect(index); + if (onSelect) { + this._deferAfterAnimation = onSelect.bind(this, index); + } + return this._animateOut(); }; @@ -267,8 +270,8 @@ export default class ActionSheet extends React.Component { isAnimating: false, }); - if (this._deferNextShow) { - this._deferNextShow(); + if (this._deferAfterAnimation) { + this._deferAfterAnimation(); } } });