diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index 42a4a2d651be..9db87bcba6db 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -105,6 +105,7 @@ export default { REPORT: 'report_', REPORT_ACTIONS: 'reportActions_', REPORT_DRAFT_COMMENT: 'reportDraftComment_', + REPORT_DRAFT_COMMENT_NUMBER_OF_LINES: 'reportDraftCommentNumberOfLines_', REPORT_ACTIONS_DRAFTS: 'reportActionsDrafts_', REPORT_USER_IS_TYPING: 'reportUserIsTyping_', POLICY: 'policy_', diff --git a/src/components/Composer/index.js b/src/components/Composer/index.js index 6eeef6d3fa1b..391dc68cdc04 100755 --- a/src/components/Composer/index.js +++ b/src/components/Composer/index.js @@ -26,6 +26,12 @@ const propTypes = { /** The value of the comment box */ value: PropTypes.string, + /** Number of lines for the comment */ + numberOfLines: PropTypes.number, + + /** Callback method to update number of lines for the comment */ + onNumberOfLinesChange: PropTypes.func, + /** Callback method to handle pasting a file */ onPasteFile: PropTypes.func, @@ -75,6 +81,8 @@ const propTypes = { const defaultProps = { defaultValue: undefined, value: undefined, + numberOfLines: 1, + onNumberOfLinesChange: () => {}, maxLines: -1, onPasteFile: () => {}, shouldClear: false, @@ -116,7 +124,7 @@ class Composer extends React.Component { : `${props.value || ''}`; this.state = { - numberOfLines: 1, + numberOfLines: props.numberOfLines, selection: { start: initialValue.length, end: initialValue.length, @@ -162,7 +170,8 @@ class Composer extends React.Component { if (prevProps.value !== this.props.value || prevProps.defaultValue !== this.props.defaultValue || prevProps.isComposerFullSize !== this.props.isComposerFullSize - || prevProps.windowWidth !== this.props.windowWidth) { + || prevProps.windowWidth !== this.props.windowWidth + || prevProps.numberOfLines !== this.props.numberOfLines) { this.updateNumberOfLines(); } @@ -334,11 +343,13 @@ class Composer extends React.Component { const lineHeight = parseInt(computedStyle.lineHeight, 10) || 20; const paddingTopAndBottom = parseInt(computedStyle.paddingBottom, 10) + parseInt(computedStyle.paddingTop, 10); - const numberOfLines = getNumberOfLines(this.props.maxLines, lineHeight, paddingTopAndBottom, this.textInput.scrollHeight); + const computedNumberOfLines = getNumberOfLines(this.props.maxLines, lineHeight, paddingTopAndBottom, this.textInput.scrollHeight); + const numberOfLines = computedNumberOfLines === 0 ? this.props.numberOfLines : computedNumberOfLines; updateIsFullComposerAvailable(this.props, numberOfLines); this.setState({ numberOfLines, }); + this.props.onNumberOfLinesChange(numberOfLines); }); } @@ -357,7 +368,6 @@ class Composer extends React.Component { selection={this.state.selection} onChange={this.shouldCallUpdateNumberOfLines} onSelectionChange={this.onSelectionChange} - numberOfLines={this.state.numberOfLines} style={[ propStyles, @@ -367,6 +377,7 @@ class Composer extends React.Component { ]} /* eslint-disable-next-line react/jsx-props-no-spreading */ {...propsWithoutStyles} + numberOfLines={this.state.numberOfLines} disabled={this.props.isDisabled} /> ); diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 5db7bd5b48bd..56e2f246def1 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -631,6 +631,15 @@ function saveReportComment(reportID, comment) { Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`, comment); } +/** + * Saves the number of lines for the comment + * @param {String} reportID + * @param {Number} numberOfLines + */ +function saveReportCommentNumberOfLines(reportID, numberOfLines) { + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT_NUMBER_OF_LINES}${reportID}`, numberOfLines); +} + /** * Immediate indication whether the report has a draft comment. * @@ -936,6 +945,16 @@ function saveReportActionDraft(reportID, reportActionID, draftMessage) { Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${reportID}_${reportActionID}`, draftMessage); } +/** + * Saves the number of lines for the report action draft + * @param {String} reportID + * @param {Number} reportActionID + * @param {Number} numberOfLines + */ +function saveReportActionDraftNumberOfLines(reportID, reportActionID, numberOfLines) { + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT_NUMBER_OF_LINES}${reportID}_${reportActionID}`, numberOfLines); +} + /** * @param {String} reportID * @param {String} previousValue @@ -1398,11 +1417,13 @@ export { subscribeToReportCommentPushNotifications, unsubscribeFromReportChannel, saveReportComment, + saveReportCommentNumberOfLines, broadcastUserIsTyping, togglePinnedState, editReportComment, handleUserDeletedLinks, saveReportActionDraft, + saveReportActionDraftNumberOfLines, deleteReportComment, navigateToConciergeChat, setReportWithDraft, diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 31876d1d6c68..4e57dba3b159 100644 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -62,6 +62,9 @@ const propTypes = { /** The comment left by the user */ comment: PropTypes.string, + /** Number of lines for the comment */ + numberOfLines: PropTypes.number, + /** The ID of the report actions will be created for */ reportID: PropTypes.string.isRequired, @@ -116,6 +119,7 @@ const propTypes = { const defaultProps = { betas: [], comment: '', + numberOfLines: 1, modal: {}, report: {}, reportActions: [], @@ -163,6 +167,7 @@ class ReportActionCompose extends React.Component { this.addAttachment = this.addAttachment.bind(this); this.insertSelectedEmoji = this.insertSelectedEmoji.bind(this); this.setExceededMaxCommentLength = this.setExceededMaxCommentLength.bind(this); + this.updateNumberOfLines = this.updateNumberOfLines.bind(this); this.comment = props.comment; // React Native will retain focus on an input for native devices but web/mWeb behave differently so we have some focus management @@ -561,6 +566,14 @@ class ReportActionCompose extends React.Component { } } + /** + * Update the number of lines for a comment in Onyx + * @param {Number} numberOfLines + */ + updateNumberOfLines(numberOfLines) { + Report.saveReportCommentNumberOfLines(this.props.reportID, numberOfLines); + } + /** * Listens for keyboard shortcuts and applies the action * @@ -829,6 +842,8 @@ class ReportActionCompose extends React.Component { setIsFullComposerAvailable={this.setIsFullComposerAvailable} isComposerFullSize={this.props.isComposerFullSize} value={this.state.value} + numberOfLines={this.props.numberOfLines} + onNumberOfLinesChange={this.updateNumberOfLines} onLayout={(e) => { const composerHeight = e.nativeEvent.layout.height; if (this.state.composerHeight === composerHeight) { @@ -931,6 +946,9 @@ export default compose( comment: { key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`, }, + numberOfLines: { + key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT_NUMBER_OF_LINES}${reportID}`, + }, modal: { key: ONYXKEYS.MODAL, }, diff --git a/src/pages/home/report/ReportActionItemMessageEdit.js b/src/pages/home/report/ReportActionItemMessageEdit.js index bc0c97534019..eb84a6837236 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.js +++ b/src/pages/home/report/ReportActionItemMessageEdit.js @@ -4,6 +4,7 @@ import {InteractionManager, Keyboard, View} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; import ExpensiMark from 'expensify-common/lib/ExpensiMark'; +import {withOnyx} from 'react-native-onyx'; import reportActionPropTypes from './reportActionPropTypes'; import styles from '../../../styles/styles'; import Composer from '../../../components/Composer'; @@ -24,6 +25,7 @@ import CONST from '../../../CONST'; import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; import withKeyboardState, {keyboardStatePropTypes} from '../../../components/withKeyboardState'; +import ONYXKEYS from '../../../ONYXKEYS'; const propTypes = { /** All the data of the action */ @@ -32,6 +34,9 @@ const propTypes = { /** Draft message */ draftMessage: PropTypes.string.isRequired, + /** Number of lines for the draft message */ + numberOfLines: PropTypes.number, + /** ReportID that holds the comment we're editing */ reportID: PropTypes.string.isRequired, @@ -57,6 +62,7 @@ const defaultProps = { forwardedRef: () => {}, report: {}, shouldDisableEmojiPicker: false, + numberOfLines: 1, }; class ReportActionItemMessageEdit extends React.Component { @@ -70,6 +76,7 @@ class ReportActionItemMessageEdit extends React.Component { this.onSelectionChange = this.onSelectionChange.bind(this); this.addEmojiToTextBox = this.addEmojiToTextBox.bind(this); this.setExceededMaxCommentLength = this.setExceededMaxCommentLength.bind(this); + this.updateNumberOfLines = this.updateNumberOfLines.bind(this); this.saveButtonID = 'saveButton'; this.cancelButtonID = 'cancelButton'; this.emojiButtonID = 'emojiButton'; @@ -136,6 +143,14 @@ class ReportActionItemMessageEdit extends React.Component { } } + /** + * Update the number of lines for a draft in Onyx + * @param {Number} numberOfLines + */ + updateNumberOfLines(numberOfLines) { + Report.saveReportActionDraftNumberOfLines(this.props.reportID, this.props.action.reportActionID, numberOfLines); + } + /** * Delete the draft of the comment being edited. This will take the comment out of "edit mode" with the old content. */ @@ -273,6 +288,8 @@ class ReportActionItemMessageEdit extends React.Component { }} selection={this.state.selection} onSelectionChange={this.onSelectionChange} + numberOfLines={this.props.numberOfLines} + onNumberOfLinesChange={this.updateNumberOfLines} /> `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT_NUMBER_OF_LINES}${reportID}_${action.reportActionID}`, + initWithStoredValues: false, + }, + }), )(React.forwardRef((props, ref) => ( /* eslint-disable-next-line react/jsx-props-no-spreading */