diff --git a/src/components/PressableWithSecondaryInteraction/index.js b/src/components/PressableWithSecondaryInteraction/index.js index 78434ae65476..b29216f34c45 100644 --- a/src/components/PressableWithSecondaryInteraction/index.js +++ b/src/components/PressableWithSecondaryInteraction/index.js @@ -1,6 +1,7 @@ import _ from 'underscore'; import React, {Component} from 'react'; import {Pressable} from 'react-native'; +import {LongPressGestureHandler, State} from 'react-native-gesture-handler'; import SelectionScraper from '../../libs/SelectionScraper'; import * as pressableWithSecondaryInteractionPropTypes from './pressableWithSecondaryInteractionPropTypes'; import styles from '../../styles/styles'; @@ -11,7 +12,7 @@ import styles from '../../styles/styles'; class PressableWithSecondaryInteraction extends Component { constructor(props) { super(props); - + this.callSecondaryInteractionWithMappedEvent = this.callSecondaryInteractionWithMappedEvent.bind(this); this.executeSecondaryInteractionOnContextMenu = this.executeSecondaryInteractionOnContextMenu.bind(this); } @@ -26,6 +27,27 @@ class PressableWithSecondaryInteraction extends Component { this.pressableRef.removeEventListener('contextmenu', this.executeSecondaryInteractionOnContextMenu); } + /** + * @param {Object} e + */ + callSecondaryInteractionWithMappedEvent(e) { + if (e.nativeEvent.state !== State.ACTIVE) { + return; + } + + // Map gesture event to normal Responder event + const { + absoluteX, absoluteY, locationX, locationY, + } = e.nativeEvent; + const mapEvent = { + ...e, + nativeEvent: { + ...e.nativeEvent, pageX: absoluteX, pageY: absoluteY, x: locationX, y: locationY, + }, + }; + this.props.onSecondaryInteraction(mapEvent); + } + /** * @param {contextmenu} e - A right-click MouseEvent. * https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event @@ -44,18 +66,19 @@ class PressableWithSecondaryInteraction extends Component { // On Web, Text does not support LongPress events thus manage inline mode with styling instead of using Text. return ( - this.pressableRef = el} + + this.pressableRef = el} // eslint-disable-next-line react/jsx-props-no-spreading - {...defaultPressableProps} - > - {this.props.children} - + {...defaultPressableProps} + > + {this.props.children} + + ); } } diff --git a/src/components/PressableWithSecondaryInteraction/index.native.js b/src/components/PressableWithSecondaryInteraction/index.native.js index 650333e2c460..efb68e52eb79 100644 --- a/src/components/PressableWithSecondaryInteraction/index.native.js +++ b/src/components/PressableWithSecondaryInteraction/index.native.js @@ -1,6 +1,7 @@ import _ from 'underscore'; import React, {forwardRef} from 'react'; import {Pressable} from 'react-native'; +import {LongPressGestureHandler, State} from 'react-native-gesture-handler'; import * as pressableWithSecondaryInteractionPropTypes from './pressableWithSecondaryInteractionPropTypes'; import Text from '../Text'; import HapticFeedback from '../../libs/HapticFeedback'; @@ -15,21 +16,28 @@ const PressableWithSecondaryInteraction = (props) => { // Use Text node for inline mode to prevent content overflow. const Node = props.inline ? Text : Pressable; return ( - { + { + if (e.nativeEvent.state !== State.ACTIVE) { + return; + } e.preventDefault(); HapticFeedback.trigger(); props.onSecondaryInteraction(e); }} - onPressOut={props.onPressOut} - // eslint-disable-next-line react/jsx-props-no-spreading - {...(_.omit(props, 'onLongPress'))} > - {props.children} - + + {props.children} + + + ); }; diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js index 7d23894e613d..34ca78008e41 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.js +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js @@ -42,7 +42,9 @@ export default [ icon: Expensicons.Clipboard, successTextTranslateKey: 'reportActionContextMenu.copied', successIcon: Expensicons.Checkmark, - shouldShow: (type, reportAction) => (type === CONTEXT_MENU_TYPES.REPORT_ACTION && reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.IOU), + shouldShow: (type, reportAction) => (type === CONTEXT_MENU_TYPES.REPORT_ACTION + && reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.IOU + && !ReportUtils.isReportMessageAttachment(lodashGet(reportAction, ['message', 0, 'text'], ''))), // If return value is true, we switch the `text` and `icon` on // `ContextMenuItem` with `successText` and `successIcon` which will fallback to