diff --git a/src/pages/home/report/EmojiPickerMenu/index.js b/src/components/EmojiPicker/EmojiPickerMenu/index.js similarity index 96% rename from src/pages/home/report/EmojiPickerMenu/index.js rename to src/components/EmojiPicker/EmojiPickerMenu/index.js index b329fd31b92d..b03ddc38bd7a 100755 --- a/src/pages/home/report/EmojiPickerMenu/index.js +++ b/src/components/EmojiPicker/EmojiPickerMenu/index.js @@ -3,20 +3,20 @@ import {View, FlatList} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; import lodashGet from 'lodash/get'; -import CONST from '../../../../CONST'; -import styles from '../../../../styles/styles'; -import * as StyleUtils from '../../../../styles/StyleUtils'; -import themeColors from '../../../../styles/themes/default'; -import emojis from '../../../../../assets/emojis'; +import CONST from '../../../CONST'; +import styles from '../../../styles/styles'; +import * as StyleUtils from '../../../styles/StyleUtils'; +import themeColors from '../../../styles/themes/default'; +import emojis from '../../../../assets/emojis'; import EmojiPickerMenuItem from '../EmojiPickerMenuItem'; -import Text from '../../../../components/Text'; -import TextInputFocusable from '../../../../components/TextInputFocusable'; -import withWindowDimensions, {windowDimensionsPropTypes} from '../../../../components/withWindowDimensions'; -import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize'; -import compose from '../../../../libs/compose'; -import getOperatingSystem from '../../../../libs/getOperatingSystem'; +import Text from '../../Text'; +import TextInputFocusable from '../../TextInputFocusable'; +import withWindowDimensions, {windowDimensionsPropTypes} from '../../withWindowDimensions'; +import withLocalize, {withLocalizePropTypes} from '../../withLocalize'; +import compose from '../../../libs/compose'; +import getOperatingSystem from '../../../libs/getOperatingSystem'; import EmojiSkinToneList from '../EmojiSkinToneList'; -import * as EmojiUtils from '../../../../libs/EmojiUtils'; +import * as EmojiUtils from '../../../libs/EmojiUtils'; const propTypes = { /** Function to add the selected emoji to the main compose text input */ diff --git a/src/pages/home/report/EmojiPickerMenu/index.native.js b/src/components/EmojiPicker/EmojiPickerMenu/index.native.js similarity index 91% rename from src/pages/home/report/EmojiPickerMenu/index.native.js rename to src/components/EmojiPicker/EmojiPickerMenu/index.native.js index 69320bd4baf5..1a8d1017af8d 100644 --- a/src/pages/home/report/EmojiPickerMenu/index.native.js +++ b/src/components/EmojiPicker/EmojiPickerMenu/index.native.js @@ -1,16 +1,16 @@ import React, {Component} from 'react'; import {View, FlatList} from 'react-native'; import PropTypes from 'prop-types'; -import compose from '../../../../libs/compose'; -import withWindowDimensions, {windowDimensionsPropTypes} from '../../../../components/withWindowDimensions'; -import CONST from '../../../../CONST'; -import styles from '../../../../styles/styles'; -import emojis from '../../../../../assets/emojis'; +import compose from '../../../libs/compose'; +import withWindowDimensions, {windowDimensionsPropTypes} from '../../withWindowDimensions'; +import CONST from '../../../CONST'; +import styles from '../../../styles/styles'; +import emojis from '../../../../assets/emojis'; import EmojiPickerMenuItem from '../EmojiPickerMenuItem'; -import Text from '../../../../components/Text'; -import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize'; +import Text from '../../Text'; +import withLocalize, {withLocalizePropTypes} from '../../withLocalize'; import EmojiSkinToneList from '../EmojiSkinToneList'; -import * as EmojiUtils from '../../../../libs/EmojiUtils'; +import * as EmojiUtils from '../../../libs/EmojiUtils'; const propTypes = { /** Function to add the selected emoji to the main compose text input */ diff --git a/src/pages/home/report/EmojiPickerMenuItem.js b/src/components/EmojiPicker/EmojiPickerMenuItem.js similarity index 86% rename from src/pages/home/report/EmojiPickerMenuItem.js rename to src/components/EmojiPicker/EmojiPickerMenuItem.js index d2bb719943db..ee24d689f87d 100644 --- a/src/pages/home/report/EmojiPickerMenuItem.js +++ b/src/components/EmojiPicker/EmojiPickerMenuItem.js @@ -1,11 +1,11 @@ import React from 'react'; import PropTypes from 'prop-types'; import {Pressable} from 'react-native'; -import styles from '../../../styles/styles'; -import * as StyleUtils from '../../../styles/StyleUtils'; -import getButtonState from '../../../libs/getButtonState'; -import Hoverable from '../../../components/Hoverable'; -import Text from '../../../components/Text'; +import styles from '../../styles/styles'; +import * as StyleUtils from '../../styles/StyleUtils'; +import getButtonState from '../../libs/getButtonState'; +import Hoverable from '../Hoverable'; +import Text from '../Text'; const propTypes = { /** The unicode that is used to display the emoji */ diff --git a/src/pages/home/report/EmojiSkinToneList.js b/src/components/EmojiPicker/EmojiSkinToneList.js similarity index 90% rename from src/pages/home/report/EmojiSkinToneList.js rename to src/components/EmojiPicker/EmojiSkinToneList.js index c04d3c49c622..f8e2595368c5 100644 --- a/src/pages/home/report/EmojiSkinToneList.js +++ b/src/components/EmojiPicker/EmojiSkinToneList.js @@ -2,13 +2,12 @@ import _ from 'underscore'; import React, {Component} from 'react'; import {View, Pressable} from 'react-native'; import PropTypes from 'prop-types'; -import styles from '../../../styles/styles'; -import * as Emojis from '../../../../assets/emojis'; -import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; -import Text from '../../../components/Text'; -import getSkinToneEmojiFromIndex from './EmojiPickerMenu/getSkinToneEmojiFromIndex'; +import styles from '../../styles/styles'; +import * as Emojis from '../../../assets/emojis'; +import withLocalize, {withLocalizePropTypes} from '../withLocalize'; +import Text from '../Text'; import EmojiPickerMenuItem from './EmojiPickerMenuItem'; - +import getSkinToneEmojiFromIndex from './getSkinToneEmojiFromIndex'; const propTypes = { @@ -52,7 +51,7 @@ class EmojiSkinToneList extends Component { render() { const selectedEmoji = getSkinToneEmojiFromIndex(this.props.preferredSkinTone); return ( - + { !this.state.isSkinToneListVisible && ( {}, + onBeforeShowEmojiPicker: () => {}, +}; + +class EmojiPicker extends React.Component { + constructor(props) { + super(props); + + this.hideEmojiPicker = this.hideEmojiPicker.bind(this); + this.showEmojiPicker = this.showEmojiPicker.bind(this); + this.selectEmoji = this.selectEmoji.bind(this); + this.measureEmojiPopoverAnchorPosition = this.measureEmojiPopoverAnchorPosition.bind(this); + this.setPreferredSkinTone = this.setPreferredSkinTone.bind(this); + this.focusEmojiSearchInput = this.focusEmojiSearchInput.bind(this); + + this.state = { + isEmojiPickerVisible: false, + + // The horizontal and vertical position (relative to the window) where the emoji popover will display. + emojiPopoverAnchorPosition: { + horizontal: 0, + vertical: 0, + }, + }; + } + + componentDidMount() { + this.emojiPopoverDimensionListener = Dimensions.addEventListener('change', this.measureEmojiPopoverAnchorPosition); + } + + componentWillUnmount() { + if (!this.emojiPopoverDimensionListener) { + return; + } + this.emojiPopoverDimensionListener.remove(); + } + + /** + * Update preferredSkinTone and sync with Onyx, NVP. + * @param {Number|String} skinTone + */ + setPreferredSkinTone(skinTone) { + if (skinTone === this.props.preferredSkinTone) { + return; + } + + User.setPreferredSkinTone(skinTone); + } + + /** + * Callback for the emoji picker to add whatever emoji is chosen into the main input + * + * @param {String} emoji + * @param {Object} emojiObject + */ + selectEmoji(emoji, emojiObject) { + EmojiUtils.addToFrequentlyUsedEmojis(this.props.frequentlyUsedEmojis, emojiObject); + this.hideEmojiPicker(); + this.props.onEmojiSelected(emoji); + } + + hideEmojiPicker() { + this.setState({isEmojiPickerVisible: false}); + } + + showEmojiPicker() { + if (_.isFunction(this.props.onBeforeShowEmojiPicker)) { + this.props.onBeforeShowEmojiPicker(); + } + this.setState({isEmojiPickerVisible: true}); + } + + measureEmojiPopoverAnchorPosition() { + if (!this.emojiPopoverAnchor) { + return; + } + + this.emojiPopoverAnchor.measureInWindow((x, y, width) => this.setState({ + emojiPopoverAnchorPosition: {horizontal: x + width, vertical: y}, + })); + } + + /** + * Focus the search input in the emoji picker. + */ + focusEmojiSearchInput() { + if (!this.emojiSearchInput) { + return; + } + this.emojiSearchInput.focus(); + } + + render() { + return ( + <> + { + + // There is no way to disable animations and they are really laggy, because there are so many + // emojis. The best alternative is to set it to 1ms so it just "pops" in and out + } + + this.emojiSearchInput = el} + preferredSkinTone={this.props.preferredSkinTone} + updatePreferredSkinTone={this.setPreferredSkinTone} + frequentlyUsedEmojis={this.props.frequentlyUsedEmojis} + /> + + ([ + styles.chatItemEmojiButton, + StyleUtils.getButtonBackgroundColorStyle(getButtonState(hovered, pressed)), + ])} + ref={el => this.emojiPopoverAnchor = el} + onLayout={this.measureEmojiPopoverAnchorPosition} + onPress={this.showEmojiPicker} + disabled={this.props.isDisabled} + > + {({hovered, pressed}) => ( + + + + )} + + + ); + } +} + +EmojiPicker.propTypes = propTypes; +EmojiPicker.defaultProps = defaultProps; + +export default compose( + withWindowDimensions, + withLocalize, + withOnyx({ + preferredSkinTone: { + key: ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE, + }, + frequentlyUsedEmojis: { + key: ONYXKEYS.FREQUENTLY_USED_EMOJIS, + }, + }), +)(EmojiPicker); diff --git a/src/libs/EmojiUtils.js b/src/libs/EmojiUtils.js index be23ae476e22..15199651661b 100644 --- a/src/libs/EmojiUtils.js +++ b/src/libs/EmojiUtils.js @@ -172,7 +172,6 @@ function addToFrequentlyUsedEmojis(frequentlyUsedEmojis, newEmoji) { User.setFrequentlyUsedEmojis(frequentEmojiList); } - export { isSingleEmoji, getDynamicHeaderIndices, diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js index b3ec5411b526..bae0d77af0df 100644 --- a/src/libs/actions/User.js +++ b/src/libs/actions/User.js @@ -16,9 +16,9 @@ import redirectToSignIn from './SignInRedirect'; import NameValuePair from './NameValuePair'; import Growl from '../Growl'; import * as Localize from '../Localize'; -import getSkinToneEmojiFromIndex from '../../pages/home/report/EmojiPickerMenu/getSkinToneEmojiFromIndex'; import * as CloseAccountActions from './CloseAccount'; import * as Link from './Link'; +import getSkinToneEmojiFromIndex from '../../components/EmojiPicker/getSkinToneEmojiFromIndex'; let sessionAuthToken = ''; let sessionEmail = ''; @@ -230,17 +230,22 @@ function validateLogin(accountID, validateCode) { } /** - * Checks if the expiresAt date of a user's ban is before right now + * Checks the blockedFromConcierge object to see if it has an expiresAt key, + * and if so whether the expiresAt date of a user's ban is before right now * - * @param {String} expiresAt - * @returns {boolean} + * @param {Object} blockedFromConcierge + * @returns {Boolean} */ -function isBlockedFromConcierge(expiresAt) { - if (!expiresAt) { +function isBlockedFromConcierge(blockedFromConcierge) { + if (_.isEmpty(blockedFromConcierge)) { return false; } - return moment().isBefore(moment(expiresAt), 'day'); + if (!blockedFromConcierge.expiresAt) { + return false; + } + + return moment().isBefore(moment(blockedFromConcierge.expiresAt), 'day'); } /** diff --git a/src/libs/reportUtils.js b/src/libs/reportUtils.js index a6164960ae6d..0180b260b16b 100644 --- a/src/libs/reportUtils.js +++ b/src/libs/reportUtils.js @@ -179,6 +179,16 @@ function isConciergeChatReport(report) { && report.participants[0] === CONST.EMAIL.CONCIERGE; } +/** + * Returns true if Concierge is one of the chat participants (1:1 as well as group chats) + * @param {Object} report + * @returns {Boolean} + */ +function chatIncludesConcierge(report) { + return report.participants + && _.contains(report.participants, CONST.EMAIL.CONCIERGE); +} + /** * Returns true if there is any automated expensify account in emails * @param {Array} emails @@ -246,4 +256,5 @@ export { hasExpensifyEmails, canShowReportRecipientLocalTime, formatReportLastMessageText, + chatIncludesConcierge, }; diff --git a/src/pages/RequestCallPage.js b/src/pages/RequestCallPage.js index 63e2a79aa69e..3606bd7a77db 100644 --- a/src/pages/RequestCallPage.js +++ b/src/pages/RequestCallPage.js @@ -285,7 +285,7 @@ class RequestCallPage extends Component { } render() { - const isBlockedFromConcierge = !_.isEmpty(this.props.blockedFromConcierge) && User.isBlockedFromConcierge(this.props.blockedFromConcierge.expiresAt); + const isBlockedFromConcierge = User.isBlockedFromConcierge(this.props.blockedFromConcierge); return ( diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index aabc286d5a07..c25817ed821a 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -3,9 +3,7 @@ import PropTypes from 'prop-types'; import { View, TouchableOpacity, - Pressable, InteractionManager, - Dimensions, } from 'react-native'; import {withNavigationFocus} from '@react-navigation/compat'; import _ from 'underscore'; @@ -13,7 +11,6 @@ import lodashGet from 'lodash/get'; import {withOnyx} from 'react-native-onyx'; import lodashIntersection from 'lodash/intersection'; import styles from '../../../styles/styles'; -import * as StyleUtils from '../../../styles/StyleUtils'; import themeColors from '../../../styles/themes/default'; import TextInputFocusable from '../../../components/TextInputFocusable'; import ONYXKEYS from '../../../ONYXKEYS'; @@ -25,11 +22,8 @@ import ReportTypingIndicator from './ReportTypingIndicator'; import AttachmentModal from '../../../components/AttachmentModal'; import compose from '../../../libs/compose'; import PopoverMenu from '../../../components/PopoverMenu'; -import Popover from '../../../components/Popover'; -import EmojiPickerMenu from './EmojiPickerMenu'; import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions'; import withDrawerState from '../../../components/withDrawerState'; -import getButtonState from '../../../libs/getButtonState'; import CONST from '../../../CONST'; import canFocusInputOnScreenFocus from '../../../libs/canFocusInputOnScreenFocus'; import variables from '../../../styles/variables'; @@ -37,7 +31,6 @@ import withLocalize, {withLocalizePropTypes} from '../../../components/withLocal import Permissions from '../../../libs/Permissions'; import Navigation from '../../../libs/Navigation/Navigation'; import ROUTES from '../../../ROUTES'; -import * as User from '../../../libs/actions/User'; import reportActionPropTypes from './reportActionPropTypes'; import * as ReportUtils from '../../../libs/reportUtils'; import ReportActionComposeFocusManager from '../../../libs/ReportActionComposeFocusManager'; @@ -47,10 +40,12 @@ import currentUserPersonalDetailsPropsTypes from '../../settings/Profile/current import ParticipantLocalTime from './ParticipantLocalTime'; import {withNetwork, withPersonalDetails} from '../../../components/OnyxProvider'; import DateUtils from '../../../libs/DateUtils'; +import * as User from '../../../libs/actions/User'; import Tooltip from '../../../components/Tooltip'; -import * as EmojiUtils from '../../../libs/EmojiUtils'; +import EmojiPicker from '../../../components/EmojiPicker'; import VirtualKeyboard from '../../../libs/VirtualKeyboard'; + const propTypes = { /** Beta features list */ betas: PropTypes.arrayOf(PropTypes.string).isRequired, @@ -125,41 +120,25 @@ class ReportActionCompose extends React.Component { constructor(props) { super(props); - this.dimensionsEventListener = null; - this.updateComment = this.updateComment.bind(this); this.debouncedSaveReportComment = _.debounce(this.debouncedSaveReportComment.bind(this), 1000, false); this.debouncedBroadcastUserIsTyping = _.debounce(this.debouncedBroadcastUserIsTyping.bind(this), 100, true); this.triggerHotkeyActions = this.triggerHotkeyActions.bind(this); this.submitForm = this.submitForm.bind(this); this.setIsFocused = this.setIsFocused.bind(this); - this.showEmojiPicker = this.showEmojiPicker.bind(this); - this.hideEmojiPicker = this.hideEmojiPicker.bind(this); - this.addEmojiToTextBox = this.addEmojiToTextBox.bind(this); this.focus = this.focus.bind(this); + this.addEmojiToTextBox = this.addEmojiToTextBox.bind(this); this.comment = props.comment; this.shouldFocusInputOnScreenFocus = canFocusInputOnScreenFocus(); - this.focusEmojiSearchInput = this.focusEmojiSearchInput.bind(this); - this.measureEmojiPopoverAnchorPosition = this.measureEmojiPopoverAnchorPosition.bind(this); this.onSelectionChange = this.onSelectionChange.bind(this); - this.emojiPopoverAnchor = null; - this.emojiSearchInput = null; this.setTextInputRef = this.setTextInputRef.bind(this); this.getInputPlaceholder = this.getInputPlaceholder.bind(this); - this.setPreferredSkinTone = this.setPreferredSkinTone.bind(this); this.state = { isFocused: this.shouldFocusInputOnScreenFocus, textInputShouldClear: false, isCommentEmpty: props.comment.length === 0, - isEmojiPickerVisible: false, isMenuVisible: false, - - // The horizontal and vertical position (relative to the window) where the emoji popover will display. - emojiPopoverAnchorPosition: { - horizontal: 0, - vertical: 0, - }, selection: { start: props.comment.length, end: props.comment.length, @@ -175,7 +154,6 @@ class ReportActionCompose extends React.Component { this.focus(false); }); - this.dimensionsEventListener = Dimensions.addEventListener('change', this.measureEmojiPopoverAnchorPosition); } componentDidUpdate(prevProps) { @@ -198,29 +176,12 @@ class ReportActionCompose extends React.Component { componentWillUnmount() { ReportActionComposeFocusManager.clear(); - - if (!this.dimensionsEventListener) { - return; - } - this.dimensionsEventListener.remove(); } onSelectionChange(e) { this.setState({selection: e.nativeEvent.selection}); } - /** - * Update preferredSkinTone and sync with Onyx, NVP. - * @param {Number|String} skinTone - */ - setPreferredSkinTone(skinTone) { - if (skinTone === this.props.preferredSkinTone) { - return; - } - - User.setPreferredSkinTone(skinTone); - } - /** * Updates the Highlight state of the composer * @@ -269,10 +230,7 @@ class ReportActionCompose extends React.Component { return this.props.translate('reportActionCompose.roomIsArchived'); } - if (this.props.report.participants - && _.contains(this.props.report.participants, CONST.EMAIL.CONCIERGE) - && !_.isEmpty(this.props.blockedFromConcierge) - && User.isBlockedFromConcierge(this.props.blockedFromConcierge.expiresAt)) { + if (ReportUtils.chatIncludesConcierge(this.props.report) && User.isBlockedFromConcierge(this.props.blockedFromConcierge)) { return this.props.translate('reportActionCompose.blockedFromConcierge'); } @@ -283,6 +241,26 @@ class ReportActionCompose extends React.Component { return this.props.translate('reportActionCompose.writeSomething'); } + /** + * Callback for the emoji picker to add whatever emoji is chosen into the main input + * + * @param {String} emoji + */ + addEmojiToTextBox(emoji) { + const newComment = this.comment.slice(0, this.state.selection.start) + + emoji + this.comment.slice(this.state.selection.end, this.comment.length); + this.textInput.setNativeProps({ + text: newComment, + }); + this.setState(prevState => ({ + selection: { + start: prevState.selection.start + emoji.length, + end: prevState.selection.start + emoji.length, + }, + })); + this.updateComment(newComment); + } + /** * Focus the composer text input * @param {Boolean} [shouldelay=false] Impose delay before focusing the composer @@ -388,70 +366,6 @@ class ReportActionCompose extends React.Component { } } - /** - * Show the ReportActionContextMenu modal popover. - * - */ - showEmojiPicker() { - this.textInput.blur(); - this.setState({isEmojiPickerVisible: true}); - } - - /** - * This gets called onLayout to find the cooridnates of the Anchor for the Emoji Picker. - */ - measureEmojiPopoverAnchorPosition() { - if (!this.emojiPopoverAnchor) { - return; - } - - this.emojiPopoverAnchor.measureInWindow((x, y, width) => this.setState({ - emojiPopoverAnchorPosition: {horizontal: x + width, vertical: y}, - })); - } - - - /** - * Hide the ReportActionContextMenu modal popover. - */ - hideEmojiPicker() { - this.setState({isEmojiPickerVisible: false}); - } - - /** - * Callback for the emoji picker to add whatever emoji is chosen into the main input - * - * @param {String} emoji - * @param {Object} emojiObject - */ - addEmojiToTextBox(emoji, emojiObject) { - EmojiUtils.addToFrequentlyUsedEmojis(this.props.frequentlyUsedEmojis, emojiObject); - this.hideEmojiPicker(); - const newComment = this.comment.slice(0, this.state.selection.start) - + emoji + this.comment.slice(this.state.selection.end, this.comment.length); - this.textInput.setNativeProps({ - text: newComment, - }); - this.setState(prevState => ({ - selection: { - start: prevState.selection.start + emoji.length, - end: prevState.selection.start + emoji.length, - }, - })); - this.updateComment(newComment); - } - - /** - * Focus the search input in the emoji picker. - */ - focusEmojiSearchInput() { - if (!this.emojiSearchInput) { - return; - } - - this.emojiSearchInput.focus(); - } - /** * Add a new comment to this chat * @@ -490,12 +404,7 @@ class ReportActionCompose extends React.Component { // Prevents focusing and showing the keyboard while the drawer is covering the chat. const isComposeDisabled = this.props.isDrawerOpen && this.props.isSmallScreenWidth; - const isConciergeChat = this.props.report.participants - && _.contains(this.props.report.participants, CONST.EMAIL.CONCIERGE); - let isBlockedFromConcierge = false; - if (isConciergeChat && !_.isEmpty(this.props.blockedFromConcierge)) { - isBlockedFromConcierge = User.isBlockedFromConcierge(this.props.blockedFromConcierge.expiresAt); - } + const isBlockedFromConcierge = ReportUtils.chatIncludesConcierge(this.props.report) && User.isBlockedFromConcierge(this.props.blockedFromConcierge); const inputPlaceholder = this.getInputPlaceholder(); const isArchivedChatRoom = ReportUtils.isArchivedRoom(this.props.report); @@ -657,51 +566,12 @@ class ReportActionCompose extends React.Component { )} - { - - // There is no way to disable animations and they are really laggy, because there are so many - // emojis. The best alternative is to set it to 1ms so it just "pops" in and out - } - this.focus(true)} - hideModalContentWhileAnimating - animationInTiming={1} - animationOutTiming={1} - anchorPosition={{ - bottom: this.props.windowHeight - this.state.emojiPopoverAnchorPosition.vertical, - left: this.state.emojiPopoverAnchorPosition.horizontal - CONST.EMOJI_PICKER_SIZE, - }} - > - this.emojiSearchInput = el} - preferredSkinTone={this.props.preferredSkinTone} - updatePreferredSkinTone={this.setPreferredSkinTone} - frequentlyUsedEmojis={this.props.frequentlyUsedEmojis} - /> - - ([ - styles.chatItemEmojiButton, - StyleUtils.getButtonBackgroundColorStyle(getButtonState(hovered, pressed)), - ])} - ref={el => this.emojiPopoverAnchor = el} - onLayout={this.measureEmojiPopoverAnchorPosition} - onPress={this.showEmojiPicker} - disabled={isBlockedFromConcierge || isArchivedChatRoom} - > - {({hovered, pressed}) => ( - - - - )} - + onEmojiSelected={this.addEmojiToTextBox} + onBeforeShowEmojiPicker={() => this.textInput.blur()} + />