diff --git a/src/CONST.js b/src/CONST.js index c60a5d15b06e..40adea18c70c 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -677,6 +677,9 @@ const CONST = { this.EMAIL.ADMIN, ]; }, + + // There's a limit of 60k characters in Auth - https://github.com/Expensify/Auth/blob/198d59547f71fdee8121325e8bc9241fc9c3236a/auth/lib/Request.h#L28 + MAX_COMMENT_LENGTH: 60_000, }; export default CONST; diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 76358e699946..5d9807854324 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -1081,9 +1081,10 @@ function fetchAllReports( * @param {File} [file] */ function addAction(reportID, text, file) { - // Convert the comment from MD into HTML because that's how it is stored in the database + // For comments shorter than 10k chars, convert the comment from MD into HTML because that's how it is stored in the database + // For longer comments, skip parsing and display plaintext for performance reasons. It takes over 40s to parse a 100k long string!! const parser = new ExpensiMark(); - const commentText = parser.replace(text); + const commentText = text.length < 10000 ? parser.replace(text) : text; const isAttachment = _.isEmpty(text) && file !== undefined; const attachmentInfo = isAttachment ? file : {}; diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 6517fef5d24a..94baafa5bd59 100755 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -370,8 +370,8 @@ class ReportActionCompose extends React.Component { const trimmedComment = this.comment.trim(); - // Don't submit empty comments - if (!trimmedComment) { + // Don't submit empty comments or comments that exceed the character limit + if (!trimmedComment || trimmedComment.length > CONST.MAX_COMMENT_LENGTH) { return; } @@ -401,6 +401,8 @@ class ReportActionCompose extends React.Component { const isComposeDisabled = this.props.isDrawerOpen && this.props.isSmallScreenWidth; const isBlockedFromConcierge = ReportUtils.chatIncludesConcierge(this.props.report) && User.isBlockedFromConcierge(this.props.blockedFromConcierge); const inputPlaceholder = this.getInputPlaceholder(); + const hasExceededMaxCommentLength = this.comment.length > CONST.MAX_COMMENT_LENGTH; + return ( {shouldShowReportRecipientLocalTime @@ -411,6 +413,7 @@ class ReportActionCompose extends React.Component { : styles.chatItemComposeBoxColor, styles.chatItemComposeBox, styles.flexRow, + hasExceededMaxCommentLength && styles.borderColorDanger, ]} > e.preventDefault()} - disabled={this.state.isCommentEmpty || isBlockedFromConcierge} + disabled={this.state.isCommentEmpty || isBlockedFromConcierge || hasExceededMaxCommentLength} hitSlop={{ top: 3, right: 3, bottom: 3, left: 3, }} @@ -583,24 +586,31 @@ class ReportActionCompose extends React.Component { - {this.props.network.isOffline ? ( - - - - - {this.props.translate('reportActionCompose.youAppearToBeOffline')} - - + + + {this.props.network.isOffline ? ( + + + + {this.props.translate('reportActionCompose.youAppearToBeOffline')} + + + ) : } - ) : } + {hasExceededMaxCommentLength && ( + + {`${this.comment.length}/${CONST.MAX_COMMENT_LENGTH}`} + + )} + ); } diff --git a/src/pages/home/report/ReportTypingIndicator.js b/src/pages/home/report/ReportTypingIndicator.js index aea493cadeb3..ee43a3a004ff 100755 --- a/src/pages/home/report/ReportTypingIndicator.js +++ b/src/pages/home/report/ReportTypingIndicator.js @@ -1,5 +1,4 @@ import React from 'react'; -import {View} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; @@ -50,7 +49,7 @@ class ReportTypingIndicator extends React.Component { // Decide on the Text element that will hold the display based on the number of users that are typing. switch (numUsersTyping) { case 0: - return ; + return <>; case 1: return ( - - {this.props.translate('reportTypingIndicator.multipleUsers')} - {` ${this.props.translate('reportTypingIndicator.areTyping')}`} - - + + {this.props.translate('reportTypingIndicator.multipleUsers')} + {` ${this.props.translate('reportTypingIndicator.areTyping')}`} + ); } }