diff --git a/src/components/Reactions/AddReactionBubble.js b/src/components/Reactions/AddReactionBubble.js
index b22c69cf1ad6..69595517c606 100644
--- a/src/components/Reactions/AddReactionBubble.js
+++ b/src/components/Reactions/AddReactionBubble.js
@@ -11,39 +11,64 @@ import Text from '../Text';
import getButtonState from '../../libs/getButtonState';
import * as EmojiPickerAction from '../../libs/actions/EmojiPickerAction';
import emojis from '../../../assets/emojis';
+import ReportActionComposeFocusManager from '../../libs/ReportActionComposeFocusManager';
const propTypes = {
sizeScale: PropTypes.number,
iconSizeScale: PropTypes.number,
+
+ /**
+ * Called when the user presses on the icon button.
+ * Will have a function as parameter which you can call
+ * to open the picker.
+ */
onPressOpenPicker: PropTypes.func,
+
+ /**
+ * Will get called the moment before the picker opens.
+ */
+ onWillShowPicker: PropTypes.func,
+
+ /**
+ * Called when the user selects an emoji.
+ */
onSelectEmoji: PropTypes.func.isRequired,
};
const defaultProps = {
sizeScale: 1,
iconSizeScale: 1,
- onPressOpenPicker: () => {
-
- },
+ onWillShowPicker: () => {},
+ onPressOpenPicker: undefined,
};
const AddReactionBubble = (props) => {
const ref = React.createRef();
const onPress = () => {
- EmojiPickerAction.showEmojiPicker(
- () => {},
- (emojiCode) => {
- const emoji = _.find(emojis, e => e.code === emojiCode);
- if (emoji != null) {
- props.onSelectEmoji(emoji);
- }
- },
- ref.current,
- () => {
- props.onPressOpenPicker();
- },
- );
+ const openPicker = () => {
+ EmojiPickerAction.showEmojiPicker(
+ () => {},
+ (emojiCode) => {
+ const emoji = _.find(emojis, e => e.code === emojiCode);
+ if (emoji != null) {
+ props.onSelectEmoji(emoji);
+ }
+ },
+
+ // The ref can become null, if e.g. the AddReactionBubble component
+ // gets removed before showing the picker. In this case we want to
+ // default fallback to anchor to the composer.
+ ref.current || ReportActionComposeFocusManager.composerRef.current,
+ props.onWillShowPicker,
+ );
+ };
+
+ if (props.onPressOpenPicker) {
+ props.onPressOpenPicker(openPicker);
+ } else {
+ openPicker();
+ }
};
return (
diff --git a/src/components/Reactions/MiniQuickEmojiReactions.js b/src/components/Reactions/MiniQuickEmojiReactions.js
index bfb2046d152b..43fe5861f420 100644
--- a/src/components/Reactions/MiniQuickEmojiReactions.js
+++ b/src/components/Reactions/MiniQuickEmojiReactions.js
@@ -16,11 +16,9 @@ import emojis from '../../../assets/emojis';
const propTypes = {
onEmojiSelected: PropTypes.func.isRequired,
onPressOpenPicker: PropTypes.func,
- onEmojiPickerWillShow: PropTypes.func,
};
const defaultProps = {
- onEmojiPickerWillShow: () => {},
onPressOpenPicker: () => {},
};
@@ -39,7 +37,6 @@ const MiniQuickEmojiReactions = (props) => {
}
},
ref.current,
- props.onEmojiPickerWillShow,
);
};
diff --git a/src/components/Reactions/QuickEmojiReactions.js b/src/components/Reactions/QuickEmojiReactions/BaseQuickEmojiReactions.js
similarity index 56%
rename from src/components/Reactions/QuickEmojiReactions.js
rename to src/components/Reactions/QuickEmojiReactions/BaseQuickEmojiReactions.js
index 112af9bf0b61..b8e415b5adb4 100644
--- a/src/components/Reactions/QuickEmojiReactions.js
+++ b/src/components/Reactions/QuickEmojiReactions/BaseQuickEmojiReactions.js
@@ -2,22 +2,26 @@ import React from 'react';
import {View} from 'react-native';
import _ from 'underscore';
import PropTypes from 'prop-types';
-import EmojiReactionBubble from './EmojiReactionBubble';
-import AddReactionBubble from './AddReactionBubble';
-import CONST from '../../CONST';
+import EmojiReactionBubble from '../EmojiReactionBubble';
+import AddReactionBubble from '../AddReactionBubble';
+import CONST from '../../../CONST';
const EMOJI_BUBBLE_SCALE = 1.5;
-const propTypes = {
+const baseQuickEmojiReactionsPropTypes = {
onEmojiSelected: PropTypes.func.isRequired,
+ onWillShowPicker: PropTypes.func,
onPressOpenPicker: PropTypes.func,
};
-const defaultProps = {
- onPressOpenPicker: () => {},
+const baseQuickEmojiReactionsDefaultProps = {
+ onWillShowPicker: undefined,
+ onPressOpenPicker: undefined,
};
-const QuickEmojiReactions = props => (
+const BaseQuickEmojiReactions = props => (
+
+ // TODO: move this to styles file
(
);
-QuickEmojiReactions.displayName = 'QuickEmojiReactions';
-QuickEmojiReactions.propTypes = propTypes;
-QuickEmojiReactions.defaultProps = defaultProps;
-export default QuickEmojiReactions;
+BaseQuickEmojiReactions.displayName = 'BaseQuickEmojiReactions';
+BaseQuickEmojiReactions.propTypes = baseQuickEmojiReactionsPropTypes;
+BaseQuickEmojiReactions.defaultProps = baseQuickEmojiReactionsDefaultProps;
+export default BaseQuickEmojiReactions;
+
+export {
+ baseQuickEmojiReactionsPropTypes,
+ baseQuickEmojiReactionsDefaultProps,
+};
diff --git a/src/components/Reactions/QuickEmojiReactions/index.js b/src/components/Reactions/QuickEmojiReactions/index.js
new file mode 100644
index 000000000000..5ba1dee5f171
--- /dev/null
+++ b/src/components/Reactions/QuickEmojiReactions/index.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import BaseQuickEmojiReactions, {baseQuickEmojiReactionsDefaultProps, baseQuickEmojiReactionsPropTypes} from './BaseQuickEmojiReactions';
+
+const propTypes = {
+ ...baseQuickEmojiReactionsPropTypes,
+ closeContextMenu: PropTypes.func.isRequired,
+};
+
+const QuickEmojiReactions = (props) => {
+ const onPressOpenPicker = (openPicker) => {
+ openPicker();
+ };
+
+ return (
+
+ );
+};
+
+QuickEmojiReactions.displayName = 'QuickEmojiReactions';
+QuickEmojiReactions.propTypes = propTypes;
+QuickEmojiReactions.defaultProps = baseQuickEmojiReactionsDefaultProps;
+export default QuickEmojiReactions;
diff --git a/src/components/Reactions/QuickEmojiReactions/index.native.js b/src/components/Reactions/QuickEmojiReactions/index.native.js
new file mode 100644
index 000000000000..b3c3bed6800f
--- /dev/null
+++ b/src/components/Reactions/QuickEmojiReactions/index.native.js
@@ -0,0 +1,29 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import BaseQuickEmojiReactions, {baseQuickEmojiReactionsDefaultProps, baseQuickEmojiReactionsPropTypes} from './BaseQuickEmojiReactions';
+
+const propTypes = {
+ ...baseQuickEmojiReactionsPropTypes,
+ closeContextMenu: PropTypes.func.isRequired,
+};
+
+const QuickEmojiReactions = (props) => {
+ const onPressOpenPicker = (openPicker) => {
+ // We first need to close the menu as it's a popover.
+ // The picker is a popover as well and on mobile there can only
+ // be one active popover at a time.
+ props.closeContextMenu(() => {
+ requestAnimationFrame(openPicker);
+ });
+ };
+
+ return (
+ // eslint-disable-next-line react/jsx-props-no-spreading
+
+ );
+};
+
+QuickEmojiReactions.displayName = 'QuickEmojiReactions';
+QuickEmojiReactions.propTypes = propTypes;
+QuickEmojiReactions.defaultProps = baseQuickEmojiReactionsDefaultProps;
+export default QuickEmojiReactions;
diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js
index 2aa3dc058f5a..e32e017c899a 100644
--- a/src/pages/home/report/ContextMenu/ContextMenuActions.js
+++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js
@@ -44,22 +44,25 @@ export default [
renderContent: (closePopover, {
reportID, reportAction, close: closeManually, keepOpen,
}) => {
- const close = () => {
- if (!closePopover) {
+ const isMini = !closePopover;
+
+ const closeContextMenu = (onHideCallback) => {
+ if (isMini) {
closeManually();
- return;
+ if (onHideCallback) {
+ onHideCallback();
+ }
+ } else {
+ hideContextMenu(false, onHideCallback);
}
- hideContextMenu(false);
};
const onEmojiSelected = (emoji) => {
// TODO: we need to add the preferred skin tone here as well somehow
Report.toggleReaction(reportID, reportAction, emoji);
- close();
+ closeContextMenu();
};
- const isMini = !closePopover;
-
if (isMini) {
return (
);