From 77e670f5890bcfc58da5fbce079c16ff7289816e Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Sun, 2 Jan 2022 22:41:45 +0530 Subject: [PATCH 01/27] feat: Moved EmojiPicker into a fresh component --- .../EmojiPickerMenu/EmojiPicker}/index.js | 0 .../EmojiPicker}/index.native.js | 0 .../EmojiPickerMenu}/EmojiPickerMenuItem.js | 10 +- .../EmojiPickerMenu}/EmojiSkinToneList.js | 14 +- src/components/EmojiPickerMenu/index.js | 207 ++++++++++++++++++ .../getSkinToneEmojiFromIndex.js | 13 -- src/pages/home/report/ReportActionCompose.js | 152 +------------ 7 files changed, 221 insertions(+), 175 deletions(-) rename src/{pages/home/report/EmojiPickerMenu => components/EmojiPickerMenu/EmojiPicker}/index.js (100%) rename src/{pages/home/report/EmojiPickerMenu => components/EmojiPickerMenu/EmojiPicker}/index.native.js (100%) rename src/{pages/home/report => components/EmojiPickerMenu}/EmojiPickerMenuItem.js (86%) rename src/{pages/home/report => components/EmojiPickerMenu}/EmojiSkinToneList.js (88%) create mode 100644 src/components/EmojiPickerMenu/index.js delete mode 100644 src/pages/home/report/EmojiPickerMenu/getSkinToneEmojiFromIndex.js diff --git a/src/pages/home/report/EmojiPickerMenu/index.js b/src/components/EmojiPickerMenu/EmojiPicker/index.js similarity index 100% rename from src/pages/home/report/EmojiPickerMenu/index.js rename to src/components/EmojiPickerMenu/EmojiPicker/index.js diff --git a/src/pages/home/report/EmojiPickerMenu/index.native.js b/src/components/EmojiPickerMenu/EmojiPicker/index.native.js similarity index 100% rename from src/pages/home/report/EmojiPickerMenu/index.native.js rename to src/components/EmojiPickerMenu/EmojiPicker/index.native.js diff --git a/src/pages/home/report/EmojiPickerMenuItem.js b/src/components/EmojiPickerMenu/EmojiPickerMenuItem.js similarity index 86% rename from src/pages/home/report/EmojiPickerMenuItem.js rename to src/components/EmojiPickerMenu/EmojiPickerMenuItem.js index d2bb719943db..ee24d689f87d 100644 --- a/src/pages/home/report/EmojiPickerMenuItem.js +++ b/src/components/EmojiPickerMenu/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/EmojiPickerMenu/EmojiSkinToneList.js similarity index 88% rename from src/pages/home/report/EmojiSkinToneList.js rename to src/components/EmojiPickerMenu/EmojiSkinToneList.js index c04d3c49c622..1da050049011 100644 --- a/src/pages/home/report/EmojiSkinToneList.js +++ b/src/components/EmojiPickerMenu/EmojiSkinToneList.js @@ -2,11 +2,11 @@ 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 * as EmojiUtils from './../../libs/EmojiUtils'; import EmojiPickerMenuItem from './EmojiPickerMenuItem'; @@ -36,7 +36,7 @@ class EmojiSkinToneList extends Component { componentDidMount() { // Get the selected skinToneEmoji based on the index - const selectedEmoji = getSkinToneEmojiFromIndex(this.props.preferredSkinTone); + const selectedEmoji = EmojiUtils.getSkinToneEmojiFromIndex(this.props.preferredSkinTone); this.setState({highlightedIndex: selectedEmoji.skinTone}); } @@ -50,7 +50,7 @@ class EmojiSkinToneList extends Component { } render() { - const selectedEmoji = getSkinToneEmojiFromIndex(this.props.preferredSkinTone); + const selectedEmoji = EmojiUtils.getSkinToneEmojiFromIndex(this.props.preferredSkinTone); return ( { diff --git a/src/components/EmojiPickerMenu/index.js b/src/components/EmojiPickerMenu/index.js new file mode 100644 index 000000000000..938c0fa1132b --- /dev/null +++ b/src/components/EmojiPickerMenu/index.js @@ -0,0 +1,207 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import {Pressable, Dimensions} from 'react-native'; +import {withOnyx} from 'react-native-onyx'; +import compose from '../../libs/compose'; +import Popover from '../Popover'; +import Tooltip from '../Tooltip'; +import Icon from '../Icon'; +import ONYXKEYS from '../../ONYXKEYS'; +import * as StyleUtils from '../../styles/StyleUtils'; +import * as Expensicons from '../Icon/Expensicons'; +import * as User from '../../libs/actions/User'; +import * as EmojiUtils from '../../libs/EmojiUtils'; +import getButtonState from '../../libs/getButtonState'; +import styles from '../../styles/styles'; +import CONST from '../../CONST'; +import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions'; +import withLocalize, {withLocalizePropTypes} from '../withLocalize'; + +const propTypes = { + /** flag to disable the emoji picker button */ + isDisabled: PropTypes.bool, + + /** callback on emoji popover hide */ + onModalHide: PropTypes.func.isRequired, + ...windowDimensionsPropTypes, + ...withLocalizePropTypes, +}; + +const defaultProps = { + isDisabled: false, +}; + +class EmojiPickerMenu extends React.Component { + constructor(props) { + super(props); + + this.emojiPopoverAnchor = null; + this.emojiPopoverDimensionListener = null; + this.hideEmojiPicker = this.hideEmojiPicker.bind(this); + this.showEmojiPicker = this.showEmojiPicker.bind(this); + this.addEmojiToTextBox = this.addEmojiToTextBox.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 + */ + 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); + } + + + hideEmojiPicker() { + this.setState({isEmojiPickerVisible: false}); + } + + 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}, + })); + } + + /** + * Focus the search input in the emoji picker. + */ + focusEmojiSearchInput() { + if (!this.emojiSearchInput) { + return; + } + this.emojiSearchInput.focus(); + } + + + render() { + console.log('Props', this.props); + 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}) => ( + + + + )} + + + ); + } +} + +EmojiPickerMenu.propTypes = propTypes; +EmojiPickerMenu.defaultProps = defaultProps; + +export default compose( + withWindowDimensions, + withLocalize, + withOnyx({ + preferredSkinTone: { + key: ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE, + }, + frequentlyUsedEmojis: { + key: ONYXKEYS.FREQUENTLY_USED_EMOJIS, + }, + }), +)(EmojiPickerMenu); diff --git a/src/pages/home/report/EmojiPickerMenu/getSkinToneEmojiFromIndex.js b/src/pages/home/report/EmojiPickerMenu/getSkinToneEmojiFromIndex.js deleted file mode 100644 index abd173b073bd..000000000000 --- a/src/pages/home/report/EmojiPickerMenu/getSkinToneEmojiFromIndex.js +++ /dev/null @@ -1,13 +0,0 @@ -import _ from 'underscore'; -import * as Emojis from '../../../../../assets/emojis'; - -/** - * Fetch the emoji code of selected skinTone - * @param {Number} skinToneIndex - * @returns {String} - */ -function getSkinToneEmojiFromIndex(skinToneIndex) { - return _.find(Emojis.skinTones, emoji => emoji.skinTone === skinToneIndex) || Emojis.skinTones[0]; -} - -export default getSkinToneEmojiFromIndex; diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 76ff0f2df1a2..a35bad816506 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'; @@ -48,7 +42,7 @@ import ParticipantLocalTime from './ParticipantLocalTime'; import {withNetwork, withPersonalDetails} from '../../../components/OnyxProvider'; import DateUtils from '../../../libs/DateUtils'; import Tooltip from '../../../components/Tooltip'; -import * as EmojiUtils from '../../../libs/EmojiUtils'; +import EmojiPickerMenu from '../../../components/EmojiPickerMenu'; const propTypes = { /** Beta features list */ @@ -130,33 +124,18 @@ class ReportActionCompose extends React.Component { 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.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, @@ -172,7 +151,6 @@ class ReportActionCompose extends React.Component { this.focus(false); }); - Dimensions.addEventListener('change', this.measureEmojiPopoverAnchorPosition); } componentDidUpdate(prevProps) { @@ -195,24 +173,12 @@ class ReportActionCompose extends React.Component { componentWillUnmount() { ReportActionComposeFocusManager.clear(); - Dimensions.removeEventListener('change', this.measureEmojiPopoverAnchorPosition); } 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 @@ -379,70 +345,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 * @@ -649,51 +551,7 @@ 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}) => ( - - - - )} - + this.focus(true)} /> Date: Sun, 2 Jan 2022 22:41:57 +0530 Subject: [PATCH 02/27] fix: Temp removed EmojiUtils ref --- src/libs/actions/User.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js index c87c0849b632..5535211044e9 100644 --- a/src/libs/actions/User.js +++ b/src/libs/actions/User.js @@ -13,7 +13,6 @@ import * as Pusher from '../Pusher/pusher'; import Log from '../Log'; import NetworkConnection from '../NetworkConnection'; import NameValuePair from './NameValuePair'; -import getSkinToneEmojiFromIndex from '../../pages/home/report/EmojiPickerMenu/getSkinToneEmojiFromIndex'; import * as Link from './Link'; let sessionAuthToken = ''; @@ -96,9 +95,9 @@ function getUserDetails() { const blockedFromConcierge = lodashGet(response, `nameValuePairs.${CONST.NVP.BLOCKED_FROM_CONCIERGE}`, {}); Onyx.merge(ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE, blockedFromConcierge); - const preferredSkinTone = lodashGet(response, `nameValuePairs.${CONST.NVP.PREFERRED_EMOJI_SKIN_TONE}`, {}); - Onyx.merge(ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE, - getSkinToneEmojiFromIndex(preferredSkinTone).skinTone); + // const preferredSkinTone = lodashGet(response, `nameValuePairs.${CONST.NVP.PREFERRED_EMOJI_SKIN_TONE}`, {}); + // Onyx.merge(ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE, + // EmojiUtils.getSkinToneEmojiFromIndex(preferredSkinTone).skinTone); const frequentlyUsedEmojis = lodashGet(response, `nameValuePairs.${CONST.NVP.FREQUENTLY_USED_EMOJIS}`, []); Onyx.set(ONYXKEYS.FREQUENTLY_USED_EMOJIS, frequentlyUsedEmojis); From 9caf3471a09f7954e82a5f5ad2fbcd848c7c2c84 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Sun, 2 Jan 2022 22:42:22 +0530 Subject: [PATCH 03/27] fix: Added getSkinToneEmoji to utils --- src/libs/EmojiUtils.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libs/EmojiUtils.js b/src/libs/EmojiUtils.js index e5b8aa812313..4bb24ac183ce 100644 --- a/src/libs/EmojiUtils.js +++ b/src/libs/EmojiUtils.js @@ -3,6 +3,7 @@ import lodashOrderBy from 'lodash/orderBy'; import moment from 'moment'; import CONST from '../CONST'; import * as User from './actions/User'; +import * as Emojis from '../../assets/emojis'; /** * Get the unicode code of an emoji in base 16. @@ -154,6 +155,15 @@ function addToFrequentlyUsedEmojis(frequentlyUsedEmojis, newEmoji) { User.setFrequentlyUsedEmojis(frequentEmojiList); } +/** + * Fetch the emoji code of selected skinTone + * @param {Number} skinToneIndex + * @returns {String} + */ +function getSkinToneEmojiFromIndex(skinToneIndex) { + return _.find(Emojis.skinTones, emoji => emoji.skinTone === skinToneIndex) || Emojis.skinTones[0]; +} + export { getEmojiUnicode, @@ -163,4 +173,5 @@ export { getDynamicSpacing, mergeEmojisWithFrequentlyUsedEmojis, addToFrequentlyUsedEmojis, + getSkinToneEmojiFromIndex, }; From 4484bb2bc2cfa6e6ee33f1fb09ac2b2fcef7799b Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Sun, 2 Jan 2022 22:48:36 +0530 Subject: [PATCH 04/27] fix: Added getSkinToneEmojiFromIndex as a separate lib --- src/components/EmojiPickerMenu/EmojiSkinToneList.js | 6 +++--- .../EmojiPickerMenu/getSkinToneEmojiFromIndex.js | 13 +++++++++++++ src/libs/EmojiUtils.js | 12 ------------ src/libs/actions/User.js | 7 ++++--- 4 files changed, 20 insertions(+), 18 deletions(-) create mode 100644 src/components/EmojiPickerMenu/getSkinToneEmojiFromIndex.js diff --git a/src/components/EmojiPickerMenu/EmojiSkinToneList.js b/src/components/EmojiPickerMenu/EmojiSkinToneList.js index 1da050049011..20d29486b6e7 100644 --- a/src/components/EmojiPickerMenu/EmojiSkinToneList.js +++ b/src/components/EmojiPickerMenu/EmojiSkinToneList.js @@ -6,8 +6,8 @@ import styles from '../../styles/styles'; import * as Emojis from '../../../assets/emojis'; import withLocalize, {withLocalizePropTypes} from '../withLocalize'; import Text from '../Text'; -import * as EmojiUtils from './../../libs/EmojiUtils'; import EmojiPickerMenuItem from './EmojiPickerMenuItem'; +import getSkinToneEmojiFromIndex from './getSkinToneEmojiFromIndex'; const propTypes = { @@ -36,7 +36,7 @@ class EmojiSkinToneList extends Component { componentDidMount() { // Get the selected skinToneEmoji based on the index - const selectedEmoji = EmojiUtils.getSkinToneEmojiFromIndex(this.props.preferredSkinTone); + const selectedEmoji = getSkinToneEmojiFromIndex(this.props.preferredSkinTone); this.setState({highlightedIndex: selectedEmoji.skinTone}); } @@ -50,7 +50,7 @@ class EmojiSkinToneList extends Component { } render() { - const selectedEmoji = EmojiUtils.getSkinToneEmojiFromIndex(this.props.preferredSkinTone); + const selectedEmoji = getSkinToneEmojiFromIndex(this.props.preferredSkinTone); return ( { diff --git a/src/components/EmojiPickerMenu/getSkinToneEmojiFromIndex.js b/src/components/EmojiPickerMenu/getSkinToneEmojiFromIndex.js new file mode 100644 index 000000000000..ffb290ffce41 --- /dev/null +++ b/src/components/EmojiPickerMenu/getSkinToneEmojiFromIndex.js @@ -0,0 +1,13 @@ +import _ from 'underscore'; +import * as Emojis from '../../../assets/emojis'; + +/** + * Fetch the emoji code of selected skinTone + * @param {Number} skinToneIndex + * @returns {String} + */ +function getSkinToneEmojiFromIndex(skinToneIndex) { + return _.find(Emojis.skinTones, emoji => emoji.skinTone === skinToneIndex) || Emojis.skinTones[0]; +} + +export default getSkinToneEmojiFromIndex; diff --git a/src/libs/EmojiUtils.js b/src/libs/EmojiUtils.js index 4bb24ac183ce..fd46c5938924 100644 --- a/src/libs/EmojiUtils.js +++ b/src/libs/EmojiUtils.js @@ -3,7 +3,6 @@ import lodashOrderBy from 'lodash/orderBy'; import moment from 'moment'; import CONST from '../CONST'; import * as User from './actions/User'; -import * as Emojis from '../../assets/emojis'; /** * Get the unicode code of an emoji in base 16. @@ -155,16 +154,6 @@ function addToFrequentlyUsedEmojis(frequentlyUsedEmojis, newEmoji) { User.setFrequentlyUsedEmojis(frequentEmojiList); } -/** - * Fetch the emoji code of selected skinTone - * @param {Number} skinToneIndex - * @returns {String} - */ -function getSkinToneEmojiFromIndex(skinToneIndex) { - return _.find(Emojis.skinTones, emoji => emoji.skinTone === skinToneIndex) || Emojis.skinTones[0]; -} - - export { getEmojiUnicode, trimEmojiUnicode, @@ -173,5 +162,4 @@ export { getDynamicSpacing, mergeEmojisWithFrequentlyUsedEmojis, addToFrequentlyUsedEmojis, - getSkinToneEmojiFromIndex, }; diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js index 5535211044e9..ae1f05cfc19c 100644 --- a/src/libs/actions/User.js +++ b/src/libs/actions/User.js @@ -14,6 +14,7 @@ import Log from '../Log'; import NetworkConnection from '../NetworkConnection'; import NameValuePair from './NameValuePair'; import * as Link from './Link'; +import getSkinToneEmojiFromIndex from '../../components/EmojiPickerMenu/getSkinToneEmojiFromIndex'; let sessionAuthToken = ''; let sessionEmail = ''; @@ -95,9 +96,9 @@ function getUserDetails() { const blockedFromConcierge = lodashGet(response, `nameValuePairs.${CONST.NVP.BLOCKED_FROM_CONCIERGE}`, {}); Onyx.merge(ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE, blockedFromConcierge); - // const preferredSkinTone = lodashGet(response, `nameValuePairs.${CONST.NVP.PREFERRED_EMOJI_SKIN_TONE}`, {}); - // Onyx.merge(ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE, - // EmojiUtils.getSkinToneEmojiFromIndex(preferredSkinTone).skinTone); + const preferredSkinTone = lodashGet(response, `nameValuePairs.${CONST.NVP.PREFERRED_EMOJI_SKIN_TONE}`, {}); + Onyx.merge(ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE, + getSkinToneEmojiFromIndex(preferredSkinTone).skinTone); const frequentlyUsedEmojis = lodashGet(response, `nameValuePairs.${CONST.NVP.FREQUENTLY_USED_EMOJIS}`, []); Onyx.set(ONYXKEYS.FREQUENTLY_USED_EMOJIS, frequentlyUsedEmojis); From 3be92ed0bd1317180a61f72d747f90234e5d3ad9 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Sun, 2 Jan 2022 22:57:23 +0530 Subject: [PATCH 05/27] fix: Renamed components and updated refs --- .../EmojiPickerMenu}/index.js | 0 .../EmojiPickerMenu}/index.native.js | 0 .../EmojiPickerMenuItem.js | 0 .../EmojiSkinToneList.js | 0 .../getSkinToneEmojiFromIndex.js | 0 .../{EmojiPickerMenu => EmojiPicker}/index.js | 11 ++++++----- src/pages/home/report/ReportActionCompose.js | 4 ++-- 7 files changed, 8 insertions(+), 7 deletions(-) rename src/components/{EmojiPickerMenu/EmojiPicker => EmojiPicker/EmojiPickerMenu}/index.js (100%) rename src/components/{EmojiPickerMenu/EmojiPicker => EmojiPicker/EmojiPickerMenu}/index.native.js (100%) rename src/components/{EmojiPickerMenu => EmojiPicker}/EmojiPickerMenuItem.js (100%) rename src/components/{EmojiPickerMenu => EmojiPicker}/EmojiSkinToneList.js (100%) rename src/components/{EmojiPickerMenu => EmojiPicker}/getSkinToneEmojiFromIndex.js (100%) rename src/components/{EmojiPickerMenu => EmojiPicker}/index.js (95%) diff --git a/src/components/EmojiPickerMenu/EmojiPicker/index.js b/src/components/EmojiPicker/EmojiPickerMenu/index.js similarity index 100% rename from src/components/EmojiPickerMenu/EmojiPicker/index.js rename to src/components/EmojiPicker/EmojiPickerMenu/index.js diff --git a/src/components/EmojiPickerMenu/EmojiPicker/index.native.js b/src/components/EmojiPicker/EmojiPickerMenu/index.native.js similarity index 100% rename from src/components/EmojiPickerMenu/EmojiPicker/index.native.js rename to src/components/EmojiPicker/EmojiPickerMenu/index.native.js diff --git a/src/components/EmojiPickerMenu/EmojiPickerMenuItem.js b/src/components/EmojiPicker/EmojiPickerMenuItem.js similarity index 100% rename from src/components/EmojiPickerMenu/EmojiPickerMenuItem.js rename to src/components/EmojiPicker/EmojiPickerMenuItem.js diff --git a/src/components/EmojiPickerMenu/EmojiSkinToneList.js b/src/components/EmojiPicker/EmojiSkinToneList.js similarity index 100% rename from src/components/EmojiPickerMenu/EmojiSkinToneList.js rename to src/components/EmojiPicker/EmojiSkinToneList.js diff --git a/src/components/EmojiPickerMenu/getSkinToneEmojiFromIndex.js b/src/components/EmojiPicker/getSkinToneEmojiFromIndex.js similarity index 100% rename from src/components/EmojiPickerMenu/getSkinToneEmojiFromIndex.js rename to src/components/EmojiPicker/getSkinToneEmojiFromIndex.js diff --git a/src/components/EmojiPickerMenu/index.js b/src/components/EmojiPicker/index.js similarity index 95% rename from src/components/EmojiPickerMenu/index.js rename to src/components/EmojiPicker/index.js index 938c0fa1132b..d3884fbefadb 100644 --- a/src/components/EmojiPickerMenu/index.js +++ b/src/components/EmojiPicker/index.js @@ -7,6 +7,7 @@ import Popover from '../Popover'; import Tooltip from '../Tooltip'; import Icon from '../Icon'; import ONYXKEYS from '../../ONYXKEYS'; +import EmojiPickerMenu from './EmojiPickerMenu'; import * as StyleUtils from '../../styles/StyleUtils'; import * as Expensicons from '../Icon/Expensicons'; import * as User from '../../libs/actions/User'; @@ -31,7 +32,7 @@ const defaultProps = { isDisabled: false, }; -class EmojiPickerMenu extends React.Component { +class EmojiPicker extends React.Component { constructor(props) { super(props); @@ -56,7 +57,7 @@ class EmojiPickerMenu extends React.Component { } componentDidMount() { - // this.emojiPopoverDimensionListener = Dimensions.addEventListener('change', this.measureEmojiPopoverAnchorPosition); + this.emojiPopoverDimensionListener = Dimensions.addEventListener('change', this.measureEmojiPopoverAnchorPosition); } componentWillUnmount() { @@ -190,8 +191,8 @@ class EmojiPickerMenu extends React.Component { } } -EmojiPickerMenu.propTypes = propTypes; -EmojiPickerMenu.defaultProps = defaultProps; +EmojiPicker.propTypes = propTypes; +EmojiPicker.defaultProps = defaultProps; export default compose( withWindowDimensions, @@ -204,4 +205,4 @@ export default compose( key: ONYXKEYS.FREQUENTLY_USED_EMOJIS, }, }), -)(EmojiPickerMenu); +)(EmojiPicker); diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index a35bad816506..ff8987af2d0b 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -42,7 +42,7 @@ import ParticipantLocalTime from './ParticipantLocalTime'; import {withNetwork, withPersonalDetails} from '../../../components/OnyxProvider'; import DateUtils from '../../../libs/DateUtils'; import Tooltip from '../../../components/Tooltip'; -import EmojiPickerMenu from '../../../components/EmojiPickerMenu'; +import EmojiPicker from '../../../components/EmojiPicker'; const propTypes = { /** Beta features list */ @@ -551,7 +551,7 @@ class ReportActionCompose extends React.Component { )} - this.focus(true)} /> + this.focus(true)} /> Date: Sun, 2 Jan 2022 23:00:06 +0530 Subject: [PATCH 06/27] fix: Updated refs for picker --- .../EmojiPicker/EmojiPickerMenu/index.js | 24 +++++++++---------- .../EmojiPickerMenu/index.native.js | 16 ++++++------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/components/EmojiPicker/EmojiPickerMenu/index.js b/src/components/EmojiPicker/EmojiPickerMenu/index.js index 019f14ba3b1a..a45f3a9d9a1b 100755 --- a/src/components/EmojiPicker/EmojiPickerMenu/index.js +++ b/src/components/EmojiPicker/EmojiPickerMenu/index.js @@ -2,20 +2,20 @@ import React, {Component} from 'react'; import {View, FlatList} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; -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/components/EmojiPicker/EmojiPickerMenu/index.native.js b/src/components/EmojiPicker/EmojiPickerMenu/index.native.js index 59f49542336c..1f78f0e6067c 100644 --- a/src/components/EmojiPicker/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 '../../../components/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 '../../../components/Text'; +import withLocalize, {withLocalizePropTypes} from '../../../components/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 */ From a445cc7626df9e8b312c92a29bddebd19f64e2d4 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Sun, 2 Jan 2022 23:05:29 +0530 Subject: [PATCH 07/27] fix: Added emoji selection function --- src/components/EmojiPicker/index.js | 23 ++++++----------- src/pages/home/report/ReportActionCompose.js | 26 +++++++++++++++++++- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/components/EmojiPicker/index.js b/src/components/EmojiPicker/index.js index d3884fbefadb..b2b9309721df 100644 --- a/src/components/EmojiPicker/index.js +++ b/src/components/EmojiPicker/index.js @@ -24,6 +24,9 @@ const propTypes = { /** callback on emoji popover hide */ onModalHide: PropTypes.func.isRequired, + + /** callback on emoji selection */ + onEmojiSelected: PropTypes.func.isRequired, ...windowDimensionsPropTypes, ...withLocalizePropTypes, }; @@ -40,7 +43,7 @@ class EmojiPicker extends React.Component { this.emojiPopoverDimensionListener = null; this.hideEmojiPicker = this.hideEmojiPicker.bind(this); this.showEmojiPicker = this.showEmojiPicker.bind(this); - this.addEmojiToTextBox = this.addEmojiToTextBox.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); @@ -79,28 +82,16 @@ class EmojiPicker extends React.Component { User.setPreferredSkinTone(skinTone); } - /** * Callback for the emoji picker to add whatever emoji is chosen into the main input * * @param {String} emoji * @param {Object} emojiObject */ - addEmojiToTextBox(emoji, emojiObject) { + selectEmoji(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); + this.props.onEmojiSelected(emoji); } @@ -160,7 +151,7 @@ class EmojiPicker extends React.Component { }} > this.emojiSearchInput = el} preferredSkinTone={this.props.preferredSkinTone} updatePreferredSkinTone={this.setPreferredSkinTone} diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index ff8987af2d0b..5a0d0cff2e8f 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -125,6 +125,7 @@ class ReportActionCompose extends React.Component { this.submitForm = this.submitForm.bind(this); this.setIsFocused = this.setIsFocused.bind(this); this.focus = this.focus.bind(this); + this.addEmojiToTextBox = this.addEmojiToTextBox.bind(this); this.comment = props.comment; this.shouldFocusInputOnScreenFocus = canFocusInputOnScreenFocus(); this.onSelectionChange = this.onSelectionChange.bind(this); @@ -179,6 +180,26 @@ class ReportActionCompose extends React.Component { this.setState({selection: e.nativeEvent.selection}); } + /** + * 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); + } + /** * Updates the Highlight state of the composer @@ -551,7 +572,10 @@ class ReportActionCompose extends React.Component { )} - this.focus(true)} /> + this.focus(true)} + onEmojiSelected={this.addEmojiToTextBox} /> Date: Sun, 2 Jan 2022 23:07:50 +0530 Subject: [PATCH 08/27] chore: Code cleanup --- src/components/EmojiPicker/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/EmojiPicker/index.js b/src/components/EmojiPicker/index.js index b2b9309721df..f25ce9eb9584 100644 --- a/src/components/EmojiPicker/index.js +++ b/src/components/EmojiPicker/index.js @@ -127,9 +127,7 @@ class EmojiPicker extends React.Component { this.emojiSearchInput.focus(); } - render() { - console.log('Props', this.props); return ( <> { From 3b5f41032b56d2f86831f2d17e10ee0b28936c3c Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Sun, 2 Jan 2022 23:27:50 +0530 Subject: [PATCH 09/27] fix: Reordered function and fixed import typo --- src/libs/actions/User.js | 2 +- src/pages/home/report/ReportActionCompose.js | 49 ++++++++++---------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js index ae1f05cfc19c..27f3003aa7c8 100644 --- a/src/libs/actions/User.js +++ b/src/libs/actions/User.js @@ -14,7 +14,7 @@ import Log from '../Log'; import NetworkConnection from '../NetworkConnection'; import NameValuePair from './NameValuePair'; import * as Link from './Link'; -import getSkinToneEmojiFromIndex from '../../components/EmojiPickerMenu/getSkinToneEmojiFromIndex'; +import getSkinToneEmojiFromIndex from '../../components/EmojiPicker/getSkinToneEmojiFromIndex'; let sessionAuthToken = ''; let sessionEmail = ''; diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 5a0d0cff2e8f..b34a917cf1a6 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -180,27 +180,6 @@ class ReportActionCompose extends React.Component { this.setState({selection: e.nativeEvent.selection}); } - /** - * 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); - } - - /** * Updates the Highlight state of the composer * @@ -263,6 +242,27 @@ 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 @@ -573,9 +573,10 @@ class ReportActionCompose extends React.Component { )} this.focus(true)} - onEmojiSelected={this.addEmojiToTextBox} /> + isDisabled={isBlockedFromConcierge || isArchivedChatRoom} + onModalHide={() => this.focus(true)} + onEmojiSelected={this.addEmojiToTextBox} + /> Date: Sun, 2 Jan 2022 23:28:03 +0530 Subject: [PATCH 10/27] fix: Changed prop to optional --- src/components/EmojiPicker/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/EmojiPicker/index.js b/src/components/EmojiPicker/index.js index f25ce9eb9584..7e5dc3008c94 100644 --- a/src/components/EmojiPicker/index.js +++ b/src/components/EmojiPicker/index.js @@ -23,7 +23,7 @@ const propTypes = { isDisabled: PropTypes.bool, /** callback on emoji popover hide */ - onModalHide: PropTypes.func.isRequired, + onModalHide: PropTypes.func, /** callback on emoji selection */ onEmojiSelected: PropTypes.func.isRequired, @@ -33,6 +33,7 @@ const propTypes = { const defaultProps = { isDisabled: false, + onModalHide: () => {}, }; class EmojiPicker extends React.Component { From 2c411acb865702c96017c2570c784b2c65abaa75 Mon Sep 17 00:00:00 2001 From: Manan Jadhav Date: Mon, 3 Jan 2022 00:45:31 +0530 Subject: [PATCH 11/27] fix: Added EmojiPicker to the edit comment --- .../report/ReportActionItemMessageEdit.js | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/pages/home/report/ReportActionItemMessageEdit.js b/src/pages/home/report/ReportActionItemMessageEdit.js index dd18d89fccc0..3e68e1548b8f 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.js +++ b/src/pages/home/report/ReportActionItemMessageEdit.js @@ -12,8 +12,12 @@ import toggleReportActionComposeView from '../../../libs/toggleReportActionCompo import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; import Button from '../../../components/Button'; +import EmojiPicker from '../../../components/EmojiPicker'; import ReportActionComposeFocusManager from '../../../libs/ReportActionComposeFocusManager'; import compose from '../../../libs/compose'; +import * as User from '../../../libs/actions/User'; +import * as ReportUtils from '../../../libs/reportUtils'; +import CONST from '../../../CONST'; const propTypes = { /** All the data of the action */ @@ -31,6 +35,19 @@ const propTypes = { /** A ref to forward to the text input */ forwardedRef: PropTypes.func, + /** The report currently being looked at */ + report: PropTypes.shape({ + + /** participants associated with current report */ + participants: PropTypes.arrayOf(PropTypes.string), + }), + + // The NVP describing a user's block status + blockedFromConcierge: PropTypes.shape({ + // The date that the user will be unblocked + expiresAt: PropTypes.string, + }), + /** Window Dimensions Props */ ...windowDimensionsPropTypes, @@ -40,6 +57,8 @@ const propTypes = { const defaultProps = { forwardedRef: () => {}, + report: {}, + blockedFromConcierge: {}, }; class ReportActionItemMessageEdit extends React.Component { @@ -48,6 +67,7 @@ class ReportActionItemMessageEdit extends React.Component { this.updateDraft = this.updateDraft.bind(this); this.deleteDraft = this.deleteDraft.bind(this); this.debouncedSaveDraft = _.debounce(this.debouncedSaveDraft.bind(this), 1000); + this.addEmojiToTextBox = this.addEmojiToTextBox.bind(this); this.publishDraft = this.publishDraft.bind(this); this.triggerSaveOrCancel = this.triggerSaveOrCancel.bind(this); this.onSelectionChange = this.onSelectionChange.bind(this); @@ -73,6 +93,24 @@ class ReportActionItemMessageEdit extends React.Component { this.setState({selection: e.nativeEvent.selection}); } + /** + * Callback for the emoji picker to add whatever emoji is chosen into the main input + * + * @param {String} emoji + */ + addEmojiToTextBox(emoji) { + const newComment = this.state.draft.slice(0, this.state.selection.start) + + emoji + this.state.draft.slice(this.state.selection.end, this.state.draft.length); + this.setState(prevState => ({ + selection: { + start: prevState.selection.start + emoji.length, + end: prevState.selection.start + emoji.length, + }, + })); + this.updateDraft(newComment); + } + + /** * Update the value of the draft in Onyx * @@ -140,6 +178,16 @@ class ReportActionItemMessageEdit extends React.Component { } render() { + 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 isArchivedChatRoom = ReportUtils.isArchivedRoom(this.props.report); + return ( @@ -161,6 +209,10 @@ class ReportActionItemMessageEdit extends React.Component { selection={this.state.selection} onSelectionChange={this.onSelectionChange} /> +