diff --git a/src/CONST.js b/src/CONST.js index 4e21d5b5dcb7..d3fcdfeab284 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -187,6 +187,7 @@ const CONST = { }, }, NVP: { + BLOCKED_FROM_CONCIERGE: 'private_blockedFromConcierge', PAYPAL_ME_ADDRESS: 'expensify_payPalMeAddress', PRIORITY_MODE: 'priorityMode', TIMEZONE: 'timeZone', diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index e48c06e71938..5535e4b7c838 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -70,6 +70,9 @@ export default { // Contains the user preference for the LHN priority mode NVP_PRIORITY_MODE: 'nvp_priorityMode', + // Contains the users's block expiration (if they have one) + NVP_BLOCKED_FROM_CONCIERGE: 'private_blockedFromConcierge', + // SDK token used to communicate with Plaid API PLAID_LINK_TOKEN: 'plaidLinkToken', diff --git a/src/languages/en.js b/src/languages/en.js index 32c47d860c88..ecaa9bdbe38b 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -96,6 +96,7 @@ export default { sendAttachment: 'Send Attachment', addAttachment: 'Add Attachment', writeSomething: 'Write something...', + blockedFromConcierge: 'Communication is barred', youAppearToBeOffline: 'You appear to be offline.', fileUploadFailed: 'Upload Failed. File is not supported.', }, diff --git a/src/languages/es.js b/src/languages/es.js index 34a573d43937..4eb4c2119873 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -92,6 +92,7 @@ export default { sendAttachment: 'Enviar adjunto', addAttachment: 'Agregar Archivo Adjunto', writeSomething: 'Escribe algo...', + blockedFromConcierge: 'Comunicación no permitida', youAppearToBeOffline: 'Parece que estás desconectado.', }, reportActionContextMenu: { diff --git a/src/libs/actions/User.js b/src/libs/actions/User.js index afba94f91361..be8669e860f5 100644 --- a/src/libs/actions/User.js +++ b/src/libs/actions/User.js @@ -3,6 +3,7 @@ import lodashGet from 'lodash/get'; import Onyx from 'react-native-onyx'; import Str from 'expensify-common/lib/str'; import {PUBLIC_DOMAINS as COMMON_PUBLIC_DOMAINS} from 'expensify-common/lib/CONST'; +import moment from 'moment'; import ONYXKEYS from '../../ONYXKEYS'; import * as API from '../API'; import CONST from '../../CONST'; @@ -63,7 +64,7 @@ function getBetas() { function getUserDetails() { API.Get({ returnValueList: 'account, loginList, nameValuePairs', - name: CONST.NVP.PAYPAL_ME_ADDRESS, + nvpNames: `${CONST.NVP.BLOCKED_FROM_CONCIERGE}, ${CONST.NVP.PAYPAL_ME_ADDRESS}`, }) .then((response) => { // Update the User onyx key @@ -74,6 +75,10 @@ function getUserDetails() { // Update the nvp_payPalMeAddress NVP const payPalMeAddress = lodashGet(response, `nameValuePairs.${CONST.NVP.PAYPAL_ME_ADDRESS}`, ''); Onyx.merge(ONYXKEYS.NVP_PAYPAL_ME_ADDRESS, payPalMeAddress); + + // Update the blockedFromConcierge NVP + const blockedFromConcierge = lodashGet(response, `nameValuePairs.${CONST.NVP.BLOCKED_FROM_CONCIERGE}`, ''); + Onyx.merge(ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE, blockedFromConcierge); }); } @@ -174,6 +179,20 @@ function validateLogin(accountID, validateCode) { }); } +/** + * Checks if the expiresAt date of a user's ban is before right now + * + * @param {String} expiresAt + * @returns {boolean} + */ +function isBlockedFromConcierge(expiresAt) { + if (!expiresAt) { + return false; + } + + return moment().isBefore(moment(expiresAt), 'day'); +} + /** * Fetch the public domain info for the current user. * @@ -225,5 +244,6 @@ export { setExpensifyNewsStatus, setSecondaryLogin, validateLogin, + isBlockedFromConcierge, getDomainInfo, }; diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index a495f0268678..8cc69473fc06 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -49,6 +49,7 @@ 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 {canEditReportAction} from '../../../libs/reportUtils'; import ReportActionComposeFocusManager from '../../../libs/ReportActionComposeFocusManager'; @@ -97,6 +98,11 @@ const propTypes = { isOffline: PropTypes.bool, }), + // The NVP describing a user's block status + blockedFromConcierge: PropTypes.shape({ + // The date that the user will be unblocked + expiresAt: PropTypes.string, + }), ...windowDimensionsPropTypes, ...withLocalizePropTypes, }; @@ -107,6 +113,7 @@ const defaultProps = { report: {}, reportActions: {}, network: {isOffline: false}, + blockedFromConcierge: {}, }; class ReportActionCompose extends React.Component { @@ -390,6 +397,17 @@ 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 + && this.props.report.participants.includes(CONST.EMAIL.CONCIERGE); + let isBlockedFromConcierge = false; + if (isConciergeChat && this.props.blockedFromConcierge) { + isBlockedFromConcierge = User.isBlockedFromConcierge(this.props.blockedFromConcierge.expiresAt); + } + + const inputPlaceholder = isBlockedFromConcierge + ? this.props.translate('reportActionCompose.blockedFromConcierge') + : this.props.translate('reportActionCompose.writeSomething'); + return ( @@ -478,7 +497,7 @@ class ReportActionCompose extends React.Component { multiline ref={this.setTextInputRef} textAlignVertical="top" - placeholder={this.props.translate('reportActionCompose.writeSomething')} + placeholder={inputPlaceholder} placeholderTextColor={themeColors.placeholderText} onChangeText={this.updateComment} onKeyPress={this.triggerHotkeyActions} @@ -503,7 +522,7 @@ class ReportActionCompose extends React.Component { onPasteFile={file => displayFileInModal({file})} shouldClear={this.state.textInputShouldClear} onClear={() => this.setTextInputShouldClear(false)} - isDisabled={isComposeDisabled} + isDisabled={isComposeDisabled || isBlockedFromConcierge} selection={this.state.selection} onSelectionChange={this.onSelectionChange} /> @@ -542,6 +561,7 @@ class ReportActionCompose extends React.Component { ref={el => this.emojiPopoverAnchor = el} onLayout={this.measureEmojiPopoverAnchorPosition} onPress={this.showEmojiPicker} + disabled={isBlockedFromConcierge} > {({hovered, pressed}) => ( @@ -612,5 +632,8 @@ export default compose( report: { key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, }, + blockedFromConcierge: { + key: ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE, + }, }), )(ReportActionCompose);