From b862234e5f8f97cdd8638acc7b1e88a3037bf6ba Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Mon, 31 Jul 2023 09:24:15 -0700 Subject: [PATCH 001/339] Add parent reportAction isDeletedParentAction --- src/components/ReportActionItem/TaskPreview.js | 7 +++++-- src/languages/en.js | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/ReportActionItem/TaskPreview.js b/src/components/ReportActionItem/TaskPreview.js index 740ab345fa74..b8b676a7e2b5 100644 --- a/src/components/ReportActionItem/TaskPreview.js +++ b/src/components/ReportActionItem/TaskPreview.js @@ -22,6 +22,7 @@ import * as ReportUtils from '../../libs/ReportUtils'; import RenderHTML from '../RenderHTML'; import PressableWithoutFeedback from '../Pressable/PressableWithoutFeedback'; import personalDetailsPropType from '../../pages/personalDetailsPropType'; +import * as ReportActionsUtils from '../../libs/ReportActionsUtils'; const propTypes = { /** All personal details asssociated with user */ @@ -71,8 +72,10 @@ function TaskPreview(props) { const assigneeDisplayName = lodashGet(props.personalDetailsList, [taskAssigneeAccountID, 'displayName'], ''); const taskAssignee = assigneeLogin || assigneeDisplayName; const htmlForTaskPreview = taskAssignee ? `@${taskAssignee} ${taskTitle}` : `${taskTitle}`; - - return ( + const isDeletedParentAction = ReportActionsUtils.isDeletedParentAction(props.action); + return isDeletedParentAction ? ( + ${props.translate('parentReportAction.deletedTask')}`} /> + ) : ( Navigation.navigate(ROUTES.getReportRoute(props.taskReportID))} diff --git a/src/languages/en.js b/src/languages/en.js index b7a130addf18..42e0de6eb037 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -1503,6 +1503,7 @@ export default { parentReportAction: { deletedMessage: '[Deleted message]', deletedRequest: '[Deleted request]', + deletedTask: '[Deleted task]', hiddenMessage: '[Hidden message]', }, threads: { From 69b67846de69452edd27e79d272f0126c6e54077 Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Tue, 1 Aug 2023 15:00:54 -0700 Subject: [PATCH 002/339] Add isDeletedParentAction check --- src/pages/home/report/ReportActionItem.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 8c6defcb2951..00467a50def0 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -449,8 +449,8 @@ function ReportActionItem(props) { }; if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) { - const parentReport = ReportActionsUtils.getParentReportAction(props.report); - if (ReportActionsUtils.isTransactionThread(parentReport)) { + const parentReportAction = ReportActionsUtils.getParentReportAction(props.report); + if (ReportActionsUtils.isTransactionThread(parentReportAction)) { return ( ); } - if (ReportUtils.isTaskReport(props.report)) { + if (ReportUtils.isTaskReport(props.report) && !ReportActionsUtils.isDeletedParentAction(parentReportAction)) { return ( Date: Tue, 1 Aug 2023 15:21:07 -0700 Subject: [PATCH 003/339] Update header view on cancelled task --- src/pages/home/HeaderView.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 7622a0e73f18..1be79bb6fa92 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -31,6 +31,7 @@ import PinButton from '../../components/PinButton'; import Navigation from '../../libs/Navigation/Navigation'; import ROUTES from '../../ROUTES'; import TaskHeaderActionButton from '../../components/TaskHeaderActionButton'; +import * as ReportActionsUtils from '../../libs/ReportActionsUtils'; const propTypes = { /** Toggles the navigationMenu open and closed */ @@ -94,12 +95,14 @@ function HeaderView(props) { const isConcierge = ReportUtils.hasSingleParticipant(props.report) && _.contains(participants, CONST.ACCOUNT_ID.CONCIERGE); const isAutomatedExpensifyAccount = ReportUtils.hasSingleParticipant(props.report) && ReportUtils.hasAutomatedExpensifyAccountIDs(participants); const guideCalendarLink = lodashGet(props.account, 'guideCalendarLink'); + const parentReportAction = ReportActionsUtils.getParentReportAction(props.report); + const isDeletedParentAction = ReportActionsUtils.isDeletedParentAction(parentReportAction); // We hide the button when we are chatting with an automated Expensify account since it's not possible to contact // these users via alternative means. It is possible to request a call with Concierge so we leave the option for them. const shouldShowCallButton = (isConcierge && guideCalendarLink) || (!isAutomatedExpensifyAccount && !isTaskReport); const threeDotMenuItems = []; - if (isTaskReport) { + if (isTaskReport && !isDeletedParentAction) { const isTaskAssigneeOrTaskOwner = Task.isTaskAssigneeOrTaskOwner(props.report, props.session.accountID); if (ReportUtils.isOpenTaskReport(props.report) && isTaskAssigneeOrTaskOwner) { threeDotMenuItems.push({ @@ -133,7 +136,7 @@ function HeaderView(props) { const defaultSubscriptSize = ReportUtils.isExpenseRequest(props.report) ? CONST.AVATAR_SIZE.SMALL_NORMAL : CONST.AVATAR_SIZE.DEFAULT; const icons = ReportUtils.getIcons(reportHeaderData, props.personalDetails); const brickRoadIndicator = ReportUtils.hasReportNameError(props.report) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''; - const shouldShowBorderBottom = !isTaskReport || !props.isSmallScreenWidth; + const shouldShowBorderBottom = !props.isSmallScreenWidth; return ( Date: Tue, 1 Aug 2023 15:31:47 -0700 Subject: [PATCH 004/339] update the header --- src/libs/ReportUtils.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index f5d417fb0a79..4e400345a544 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1244,8 +1244,8 @@ function getReportPreviewMessage(report, reportAction = {}) { */ function getReportName(report, policy = undefined) { let formattedName; + const parentReportAction = ReportActionsUtils.getParentReportAction(report); if (isChatThread(report)) { - const parentReportAction = ReportActionsUtils.getParentReportAction(report); if (ReportActionsUtils.isTransactionThread(parentReportAction)) { return getTransactionReportName(parentReportAction); } @@ -1263,6 +1263,11 @@ function getReportName(report, policy = undefined) { } return parentReportActionMessage || Localize.translateLocal('parentReportAction.deletedMessage'); } + + if (isTaskReport(report) && ReportActionsUtils.isDeletedParentAction(parentReportAction)) { + return Localize.translateLocal('parentReportAction.deletedTask'); + } + if (isChatRoom(report) || isTaskReport(report)) { formattedName = report.reportName; } From 1c887daf3d549624ad5730c4df44281df68d955a Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Tue, 1 Aug 2023 17:36:03 -0700 Subject: [PATCH 005/339] add method to get all reportActions --- src/libs/ReportActionsUtils.js | 22 ++++++++++++++++++++++ src/libs/actions/Task.js | 1 + 2 files changed, 23 insertions(+) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 3cd5621e5e32..d6a59921dc0b 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -561,6 +561,27 @@ function isMessageDeleted(reportAction) { return lodashGet(reportAction, ['message', 0, 'isDeletedParentAction'], false); } +/** + * When you change assignees, a task created reportAction is added to that specific assignee's report. + * You can do this multiple times, so when we perform an action that modifies the parent report, we need to update all the parent report actions + * @param {*} taskReportID + * @returns {Array} taskCreatedReportActions + */ +function getTaskCreatedReportActions(taskReportID) { + const taskCreatedReportActions = []; + _.each(allReports, (report) => { + _.each(report.reportActions, (reportAction) => { + if (reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT || reportAction.originalMessage.taskReportID !== taskReportID) + { + return; + } + + taskCreatedReportActions.push(reportAction); + }); + }); + return taskCreatedReportActions; +} + export { getSortedReportActions, getLastVisibleAction, @@ -593,4 +614,5 @@ export { isWhisperAction, isPendingRemove, getReportAction, + getTaskCreatedReportActions, }; diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.js index 3c6ddefbc32d..6bba6a052e75 100644 --- a/src/libs/actions/Task.js +++ b/src/libs/actions/Task.js @@ -621,6 +621,7 @@ function cancelTask(taskReportID, taskTitle, originalStateNum, originalStatusNum const message = `canceled task: ${taskTitle}`; const optimisticCancelReportAction = ReportUtils.buildOptimisticTaskReportAction(taskReportID, CONST.REPORT.ACTIONS.TYPE.TASKCANCELLED, message); const optimisticReportActionID = optimisticCancelReportAction.reportActionID; + const parentReportAction = ReportActionsUtils.getParentReportAction(taskReportID); const optimisticData = [ { From c9df9ce550c7415b34205b4b95fd3b66cad32334 Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Wed, 2 Aug 2023 16:19:48 -0700 Subject: [PATCH 006/339] update cancelTask method --- src/languages/en.js | 2 +- src/libs/actions/Task.js | 35 +++++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index b6f947a7b0c1..507bd150b3ff 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -1332,7 +1332,7 @@ export default { completed: 'Completed', messages: { completed: 'completed task', - canceled: 'canceled task', + canceled: 'deleted task', reopened: 'reopened task', error: 'You do not have the permission to do the requested action.', }, diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.js index 433f555168a9..5dc86635e5c4 100644 --- a/src/libs/actions/Task.js +++ b/src/libs/actions/Task.js @@ -618,20 +618,14 @@ function getShareDestination(reportID, reports, personalDetails) { * @param {number} originalStatusNum */ function cancelTask(taskReportID, taskTitle, originalStateNum, originalStatusNum) { - const message = `canceled task: ${taskTitle}`; + const message = `deleted task: ${taskTitle}`; const optimisticCancelReportAction = ReportUtils.buildOptimisticTaskReportAction(taskReportID, CONST.REPORT.ACTIONS.TYPE.TASKCANCELLED, message); const optimisticReportActionID = optimisticCancelReportAction.reportActionID; - const parentReportAction = ReportActionsUtils.getParentReportAction(taskReportID); + const taskReport = ReportUtils.getReport(taskReportID); + const parentReportAction = ReportActionsUtils.getParentReportAction(taskReport); + const parentReport = ReportUtils.getParentReport(taskReport); const optimisticData = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`, - value: { - stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, - statusNum: CONST.REPORT.STATUS.CLOSED, - }, - }, { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`, @@ -648,6 +642,27 @@ function cancelTask(taskReportID, taskTitle, originalStateNum, originalStatusNum [optimisticReportActionID]: optimisticCancelReportAction, }, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReport.reportID}`, + value: { + [parentReportAction.reportActionID]: { + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + previousMessage: parentReportAction.message, + message: { + translationKey: '', + type: 'COMMENT', + html: '', + text: '', + isEdited: true, + isDeletedParentAction: true, + }, + errors: null, + linkMetaData: [], + }, + }, + } + ]; const successData = [ From f640ac2bbd8010b262f48d147d24a198ea92d0bf Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Wed, 2 Aug 2023 17:14:38 -0700 Subject: [PATCH 007/339] fix message not showing up --- src/libs/actions/Task.js | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.js index 5dc86635e5c4..8c94e1f73c31 100644 --- a/src/libs/actions/Task.js +++ b/src/libs/actions/Task.js @@ -625,6 +625,25 @@ function cancelTask(taskReportID, taskTitle, originalStateNum, originalStatusNum const parentReportAction = ReportActionsUtils.getParentReportAction(taskReport); const parentReport = ReportUtils.getParentReport(taskReport); + const optimisticReportActions = { + [parentReportAction.reportActionID]: { + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + previousMessage: parentReportAction.message, + message: [{ + translationKey: '', + type: 'COMMENT', + html: '', + text: '', + isEdited: true, + isDeletedParentAction: true, + }], + errors: null, + linkMetaData: [], + }, + }; + + // TODO: Figure out some way to get the previous message to show in the LHN for the parent report + const optimisticData = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -633,6 +652,7 @@ function cancelTask(taskReportID, taskTitle, originalStateNum, originalStatusNum lastVisibleActionCreated: optimisticCancelReportAction.created, lastMessageText: message, lastActorAccountID: optimisticCancelReportAction.actorAccountID, + updateReportInLHN: true, }, }, { @@ -645,24 +665,8 @@ function cancelTask(taskReportID, taskTitle, originalStateNum, originalStatusNum { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReport.reportID}`, - value: { - [parentReportAction.reportActionID]: { - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, - previousMessage: parentReportAction.message, - message: { - translationKey: '', - type: 'COMMENT', - html: '', - text: '', - isEdited: true, - isDeletedParentAction: true, - }, - errors: null, - linkMetaData: [], - }, - }, - } - + value: optimisticReportActions, + }, ]; const successData = [ From 24fc6c8f2356ee8691313f048de644bfcd892b77 Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Wed, 2 Aug 2023 17:40:55 -0700 Subject: [PATCH 008/339] show the parent --- src/components/ReportActionItem/TaskPreview.js | 12 ++++++++---- src/pages/home/report/ReportActionItem.js | 13 ++++++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/components/ReportActionItem/TaskPreview.js b/src/components/ReportActionItem/TaskPreview.js index b8b676a7e2b5..d8298312df0d 100644 --- a/src/components/ReportActionItem/TaskPreview.js +++ b/src/components/ReportActionItem/TaskPreview.js @@ -73,9 +73,7 @@ function TaskPreview(props) { const taskAssignee = assigneeLogin || assigneeDisplayName; const htmlForTaskPreview = taskAssignee ? `@${taskAssignee} ${taskTitle}` : `${taskTitle}`; const isDeletedParentAction = ReportActionsUtils.isDeletedParentAction(props.action); - return isDeletedParentAction ? ( - ${props.translate('parentReportAction.deletedTask')}`} /> - ) : ( + return ( Navigation.navigate(ROUTES.getReportRoute(props.taskReportID))} @@ -83,7 +81,11 @@ function TaskPreview(props) { accessibilityRole={CONST.ACCESSIBILITY_ROLE.BUTTON} accessibilityLabel={props.translate('task.task')} > - + { + isDeletedParentAction ? ( + ${props.translate('parentReportAction.deletedTask')}`} /> + ) : ( + + ) + } ); } - if (ReportUtils.isTaskReport(props.report) && !ReportActionsUtils.isDeletedParentAction(parentReportAction)) { + if (ReportUtils.isTaskReport(props.report)) { + if (ReportActionsUtils.isDeletedParentAction(parentReportAction)) { + return ( + + ) + } + return ( Date: Thu, 3 Aug 2023 15:32:20 -0700 Subject: [PATCH 009/339] Remove the link in Preview isDeletedParentAction --- src/components/ReportActionItem/TaskPreview.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/ReportActionItem/TaskPreview.js b/src/components/ReportActionItem/TaskPreview.js index d8298312df0d..9179858163d8 100644 --- a/src/components/ReportActionItem/TaskPreview.js +++ b/src/components/ReportActionItem/TaskPreview.js @@ -73,6 +73,11 @@ function TaskPreview(props) { const taskAssignee = assigneeLogin || assigneeDisplayName; const htmlForTaskPreview = taskAssignee ? `@${taskAssignee} ${taskTitle}` : `${taskTitle}`; const isDeletedParentAction = ReportActionsUtils.isDeletedParentAction(props.action); + + if (isDeletedParentAction) { + return ${props.translate('parentReportAction.deletedTask')}`} />; + } + return ( - { - isDeletedParentAction ? ( - ${props.translate('parentReportAction.deletedTask')}`} /> - ) : ( - + - ) - } + Date: Thu, 3 Aug 2023 16:04:01 -0700 Subject: [PATCH 010/339] Update method that checks isCanceledTaskReport --- src/libs/ReportUtils.js | 15 ++++++++++++--- src/pages/home/report/ReportActionItem.js | 6 +++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index d1d88986e385..f2402122eda0 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -159,13 +159,22 @@ function isOpenTaskReport(report) { } /** - * Checks if the current user is assigned to the task report + * Checks if a task has been cancelled + * When a task is deleted, the parentReportAction is updated to have a isDeletedParentAction deleted flag + * This is because when you delete a task, we still allow you to chat on the report itself + * There's another situation where you don't have access to the parentReportAction (because it was created in a chat you don't have access to) + * In this case, we have added the key to the report itself * * @param {Object} report + * @param {Object} parentReportAction * @returns {Boolean} */ -function isCanceledTaskReport(report) { - return isTaskReport(report) && report.stateNum === CONST.REPORT.STATE_NUM.SUBMITTED && report.statusNum === CONST.REPORT.STATUS.CLOSED; +function isCanceledTaskReport(report, parentReportAction = {}) { + if (parentReportAction && ReportActionsUtils.isMessageDeleted(parentReportAction)) { + return true; + } + + return isTaskReport(report) && report.isDeletedParentAction; } /** diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 52ae9e688a16..de107bd139fc 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -463,9 +463,9 @@ function ReportActionItem(props) { if (ReportActionsUtils.isDeletedParentAction(parentReportAction)) { return ( ) } From 0665968fbda982bc2cc0e28edc55842326a6066e Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 3 Aug 2023 16:16:45 -0700 Subject: [PATCH 011/339] Update places we check isCancelled task report --- src/components/ReportActionItem/TaskPreview.js | 2 +- src/libs/ReportUtils.js | 10 +++++++--- src/pages/home/HeaderView.js | 4 ++-- src/pages/home/ReportScreen.js | 2 +- src/pages/home/report/ReportActionItem.js | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/components/ReportActionItem/TaskPreview.js b/src/components/ReportActionItem/TaskPreview.js index 9179858163d8..b1babba2c220 100644 --- a/src/components/ReportActionItem/TaskPreview.js +++ b/src/components/ReportActionItem/TaskPreview.js @@ -72,7 +72,7 @@ function TaskPreview(props) { const assigneeDisplayName = lodashGet(props.personalDetailsList, [taskAssigneeAccountID, 'displayName'], ''); const taskAssignee = assigneeLogin || assigneeDisplayName; const htmlForTaskPreview = taskAssignee ? `@${taskAssignee} ${taskTitle}` : `${taskTitle}`; - const isDeletedParentAction = ReportActionsUtils.isDeletedParentAction(props.action); + const isDeletedParentAction = ReportUtils.isCanceledTaskReport(props.taskReport, props.action); if (isDeletedParentAction) { return ${props.translate('parentReportAction.deletedTask')}`} />; diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index f2402122eda0..14d7987ad09b 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -169,12 +169,16 @@ function isOpenTaskReport(report) { * @param {Object} parentReportAction * @returns {Boolean} */ -function isCanceledTaskReport(report, parentReportAction = {}) { - if (parentReportAction && ReportActionsUtils.isMessageDeleted(parentReportAction)) { +function isCanceledTaskReport(report = {}, parentReportAction = {}) { + if (!_.isEmpty(parentReportAction) && ReportActionsUtils.isMessageDeleted(parentReportAction)) { return true; } - return isTaskReport(report) && report.isDeletedParentAction; + if (!_.isEmpty(report) && report.isDeletedParentAction) { + return true; + } + + return false; } /** diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 0d707239bb28..afd9d98c0391 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -95,13 +95,13 @@ function HeaderView(props) { const isAutomatedExpensifyAccount = ReportUtils.hasSingleParticipant(props.report) && ReportUtils.hasAutomatedExpensifyAccountIDs(participants); const guideCalendarLink = lodashGet(props.account, 'guideCalendarLink'); const parentReportAction = ReportActionsUtils.getParentReportAction(props.report); - const isDeletedParentAction = ReportActionsUtils.isDeletedParentAction(parentReportAction); + const isCanceledTaskReport = ReportUtils.isCanceledTaskReport(props.report, parentReportAction); // We hide the button when we are chatting with an automated Expensify account since it's not possible to contact // these users via alternative means. It is possible to request a call with Concierge so we leave the option for them. const shouldShowCallButton = (isConcierge && guideCalendarLink) || (!isAutomatedExpensifyAccount && !isTaskReport); const threeDotMenuItems = []; - if (isTaskReport && !isDeletedParentAction) { + if (isTaskReport && !isCanceledTaskReport) { const canModifyTask = Task.canModifyTask(props.report, props.session.accountID); if (ReportUtils.isOpenTaskReport(props.report) && canModifyTask) { threeDotMenuItems.push({ diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 94fe5e2beb00..7036dc1c5c9f 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -328,7 +328,7 @@ class ReportScreen extends React.Component { needsOffscreenAlphaCompositing > {headerView} - {ReportUtils.isTaskReport(this.props.report) && this.props.isSmallScreenWidth && ReportUtils.isOpenTaskReport(this.props.report) && ( + {ReportUtils.isTaskReport(this.props.report) && this.props.isSmallScreenWidth && ReportUtils.isOpenTaskReport(this.props.report) && !ReportUtils.isCanceledTaskReport(this.props.report, parentReportAction) && ( diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index de107bd139fc..1a7c5cd65d0e 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -460,7 +460,7 @@ function ReportActionItem(props) { ); } if (ReportUtils.isTaskReport(props.report)) { - if (ReportActionsUtils.isDeletedParentAction(parentReportAction)) { + if (ReportUtils.isCanceledTaskReport(props.taskReport, parentReportAction)) { return ( Date: Thu, 3 Aug 2023 16:27:20 -0700 Subject: [PATCH 012/339] Update places isCanceledTaskReport --- src/libs/ReportUtils.js | 4 ++-- src/pages/home/HeaderView.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 14d7987ad09b..9c7d95162a5b 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -170,7 +170,7 @@ function isOpenTaskReport(report) { * @returns {Boolean} */ function isCanceledTaskReport(report = {}, parentReportAction = {}) { - if (!_.isEmpty(parentReportAction) && ReportActionsUtils.isMessageDeleted(parentReportAction)) { + if (!_.isEmpty(parentReportAction) && lodashGet(parentReportAction, ['message', 0, 'isDeletedParentAction'], false)) { return true; } @@ -1328,7 +1328,7 @@ function getReportName(report, policy = undefined) { return parentReportActionMessage || Localize.translateLocal('parentReportAction.deletedMessage'); } - if (isTaskReport(report) && ReportActionsUtils.isDeletedParentAction(parentReportAction)) { + if (isTaskReport(report) && isCanceledTaskReport(report, parentReportAction)) { return Localize.translateLocal('parentReportAction.deletedTask'); } diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index afd9d98c0391..f7eefce127b9 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -218,7 +218,7 @@ function HeaderView(props) { )} - {isTaskReport && !props.isSmallScreenWidth && ReportUtils.isOpenTaskReport(props.report) && } + {isTaskReport && !props.isSmallScreenWidth && ReportUtils.isOpenTaskReport(props.report) && !isCanceledTaskReport && } {shouldShowCallButton && ( Date: Thu, 3 Aug 2023 16:27:31 -0700 Subject: [PATCH 013/339] onyx updates --- src/libs/ReportActionsUtils.js | 7 +++---- src/libs/actions/Task.js | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index d6a59921dc0b..495e79558071 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -564,18 +564,17 @@ function isMessageDeleted(reportAction) { /** * When you change assignees, a task created reportAction is added to that specific assignee's report. * You can do this multiple times, so when we perform an action that modifies the parent report, we need to update all the parent report actions - * @param {*} taskReportID + * @param {*} taskReportID * @returns {Array} taskCreatedReportActions */ function getTaskCreatedReportActions(taskReportID) { const taskCreatedReportActions = []; _.each(allReports, (report) => { _.each(report.reportActions, (reportAction) => { - if (reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT || reportAction.originalMessage.taskReportID !== taskReportID) - { + if (reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT || reportAction.originalMessage.taskReportID !== taskReportID) { return; } - + taskCreatedReportActions.push(reportAction); }); }); diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.js index 97b105e3a8ad..9d4f2e0f0417 100644 --- a/src/libs/actions/Task.js +++ b/src/libs/actions/Task.js @@ -651,14 +651,16 @@ function cancelTask(taskReportID, taskTitle, originalStateNum, originalStatusNum [parentReportAction.reportActionID]: { pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, previousMessage: parentReportAction.message, - message: [{ - translationKey: '', - type: 'COMMENT', - html: '', - text: '', - isEdited: true, - isDeletedParentAction: true, - }], + message: [ + { + translationKey: '', + type: 'COMMENT', + html: '', + text: '', + isEdited: true, + isDeletedParentAction: true, + }, + ], errors: null, linkMetaData: [], }, @@ -675,6 +677,7 @@ function cancelTask(taskReportID, taskTitle, originalStateNum, originalStatusNum lastMessageText: message, lastActorAccountID: optimisticCancelReportAction.actorAccountID, updateReportInLHN: true, + isDeletedParentAction: true, }, }, { From 84d289b9a0e19cdf3f59104089e0bc036091bd56 Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 3 Aug 2023 16:41:49 -0700 Subject: [PATCH 014/339] pass the actual report --- src/pages/home/report/ReportActionItem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 1a7c5cd65d0e..3c2f4ce7c438 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -460,7 +460,7 @@ function ReportActionItem(props) { ); } if (ReportUtils.isTaskReport(props.report)) { - if (ReportUtils.isCanceledTaskReport(props.taskReport, parentReportAction)) { + if (ReportUtils.isCanceledTaskReport(props.report, parentReportAction)) { return ( Date: Thu, 10 Aug 2023 16:42:08 -0700 Subject: [PATCH 015/339] Make sure we don't include cancelled tasks in the selector --- src/pages/tasks/TaskShareDestinationSelectorModal.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/tasks/TaskShareDestinationSelectorModal.js b/src/pages/tasks/TaskShareDestinationSelectorModal.js index 8272406b4cbe..61d6868ebb1e 100644 --- a/src/pages/tasks/TaskShareDestinationSelectorModal.js +++ b/src/pages/tasks/TaskShareDestinationSelectorModal.js @@ -52,7 +52,8 @@ function TaskShareDestinationSelectorModal(props) { if ( !ReportUtils.isAllowedToComment(props.reports[reportKey]) || ReportUtils.isArchivedRoom(props.reports[reportKey]) || - ReportUtils.isExpensifyOnlyParticipantInReport(props.reports[reportKey]) + ReportUtils.isExpensifyOnlyParticipantInReport(props.reports[reportKey]) || + ReportUtils.isCanceledTaskReport(props.reports[reportKey]) ) { return; } From 6d8f9f9dfdecfbea553992e87d938f86b28db002 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Sun, 13 Aug 2023 16:04:25 +0200 Subject: [PATCH 016/339] Add overscrollContain style --- src/components/InvertedFlatList/index.js | 1 + src/styles/styles.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/components/InvertedFlatList/index.js b/src/components/InvertedFlatList/index.js index 923a17210af7..fee37a9c1514 100644 --- a/src/components/InvertedFlatList/index.js +++ b/src/components/InvertedFlatList/index.js @@ -43,6 +43,7 @@ class InvertedFlatList extends React.Component { ref={(el) => (this.list = el)} shouldMeasureItems contentContainerStyle={StyleSheet.compose(this.props.contentContainerStyle, styles.justifyContentEnd)} + style={styles.overscrollContain} /> ); } diff --git a/src/styles/styles.js b/src/styles/styles.js index 581410e0e5a5..c9de6658a84e 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3677,6 +3677,10 @@ const styles = { rotate90: { transform: [{rotate: '90deg'}], }, + + overscrollContain: { + overscrollBehavior: 'contain', + }, }; export default styles; From 46666557d14ce2d3f32a716145d5030b5339e876 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 15 Aug 2023 08:21:47 +0200 Subject: [PATCH 017/339] Move style to the overflow.js --- src/components/InvertedFlatList/index.js | 2 +- src/styles/styles.js | 4 ---- src/styles/utilities/overflow.js | 4 ++++ 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/InvertedFlatList/index.js b/src/components/InvertedFlatList/index.js index fee37a9c1514..505fec32ddbd 100644 --- a/src/components/InvertedFlatList/index.js +++ b/src/components/InvertedFlatList/index.js @@ -43,7 +43,7 @@ class InvertedFlatList extends React.Component { ref={(el) => (this.list = el)} shouldMeasureItems contentContainerStyle={StyleSheet.compose(this.props.contentContainerStyle, styles.justifyContentEnd)} - style={styles.overscrollContain} + style={styles.overscrollBehaviorContain} /> ); } diff --git a/src/styles/styles.js b/src/styles/styles.js index aa952358e0b7..174662ed1d29 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3676,10 +3676,6 @@ const styles = { rotate90: { transform: [{rotate: '90deg'}], }, - - overscrollContain: { - overscrollBehavior: 'contain', - }, }; export default styles; diff --git a/src/styles/utilities/overflow.js b/src/styles/utilities/overflow.js index c190abfa912b..9b7f92cd156f 100644 --- a/src/styles/utilities/overflow.js +++ b/src/styles/utilities/overflow.js @@ -22,5 +22,9 @@ export default { overscrollBehavior: 'none', }, + overscrollBehaviorContain: { + overscrollBehavior: 'contain', + }, + overflowAuto, }; From d1391af1f305ec0f4961b37fc65c0f4c7fb99f90 Mon Sep 17 00:00:00 2001 From: Ana Margarida Silva Date: Thu, 17 Aug 2023 14:00:56 +0100 Subject: [PATCH 018/339] feat: migrate PressableWithSecondaryInteraction to function component --- .../index.js | 162 ++++++++++-------- 1 file changed, 92 insertions(+), 70 deletions(-) diff --git a/src/components/PressableWithSecondaryInteraction/index.js b/src/components/PressableWithSecondaryInteraction/index.js index 2771db6206ae..fd50c6ff0994 100644 --- a/src/components/PressableWithSecondaryInteraction/index.js +++ b/src/components/PressableWithSecondaryInteraction/index.js @@ -1,106 +1,128 @@ import _ from 'underscore'; -import React, {Component} from 'react'; -import * as pressableWithSecondaryInteractionPropTypes from './pressableWithSecondaryInteractionPropTypes'; +import React, {forwardRef, useCallback, useEffect, useRef} from 'react'; import styles from '../../styles/styles'; import * as DeviceCapabilities from '../../libs/DeviceCapabilities'; import * as StyleUtils from '../../styles/StyleUtils'; import PressableWithFeedback from '../Pressable/PressableWithFeedback'; +import * as pressableWithSecondaryInteractionPropTypes from './pressableWithSecondaryInteractionPropTypes'; /** * This is a special Pressable that calls onSecondaryInteraction when LongPressed, or right-clicked. */ -class PressableWithSecondaryInteraction extends Component { - constructor(props) { - super(props); - this.executeSecondaryInteraction = this.executeSecondaryInteraction.bind(this); - this.executeSecondaryInteractionOnContextMenu = this.executeSecondaryInteractionOnContextMenu.bind(this); - } - - componentDidMount() { - if (this.props.forwardedRef) { - if (_.isFunction(this.props.forwardedRef)) { - this.props.forwardedRef(this.pressableRef); - } else if (_.isObject(this.props.forwardedRef)) { - this.props.forwardedRef.current = this.pressableRef; - } - } - this.pressableRef.addEventListener('contextmenu', this.executeSecondaryInteractionOnContextMenu); - } - componentWillUnmount() { - this.pressableRef.removeEventListener('contextmenu', this.executeSecondaryInteractionOnContextMenu); - } +function PressableWithSecondaryInteraction(props) { + const { + children, + inline, + style, + enableLongPressWithHover, + withoutFocusOnSecondaryInteraction, + preventDefaultContextMenu, + onSecondaryInteraction, + onPressIn, + onPress, + onPressOut, + activeOpacity, + innerRef, + ...rest + } = props; + + const pressableRef = useRef(null); /** * @param {Event} e - the secondary interaction event */ - executeSecondaryInteraction(e) { - if (DeviceCapabilities.hasHoverSupport() && !this.props.enableLongPressWithHover) { + const executeSecondaryInteraction = (e) => { + if (DeviceCapabilities.hasHoverSupport() && !enableLongPressWithHover) { return; } - if (this.props.withoutFocusOnSecondaryInteraction && this.pressableRef) { - this.pressableRef.blur(); + if (withoutFocusOnSecondaryInteraction && pressableRef && pressableRef.current) { + pressableRef.current.blur(); } - this.props.onSecondaryInteraction(e); - } + onSecondaryInteraction(e); + }; /** * @param {contextmenu} e - A right-click MouseEvent. * https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event */ - executeSecondaryInteractionOnContextMenu(e) { - if (!this.props.onSecondaryInteraction) { + const executeSecondaryInteractionOnContextMenu = useCallback( + (e) => { + if (!onSecondaryInteraction) { + return; + } + + e.stopPropagation(); + if (preventDefaultContextMenu) { + e.preventDefault(); + } + + onSecondaryInteraction(e); + + /** + * This component prevents the tapped element from capturing focus. + * We need to blur this element when clicked as it opens modal that implements focus-trapping. + * When the modal is closed it focuses back to the last active element. + * Therefore it shifts the element to bring it back to focus. + * https://github.com/Expensify/App/issues/14148 + */ + if (withoutFocusOnSecondaryInteraction && pressableRef && pressableRef.current) { + pressableRef.current.blur(); + } + }, + [onSecondaryInteraction, preventDefaultContextMenu, pressableRef, withoutFocusOnSecondaryInteraction], + ); + + useEffect(() => { + if (!pressableRef || !pressableRef.current) { return; } - e.stopPropagation(); - if (this.props.preventDefaultContextMenu) { - e.preventDefault(); + if (innerRef) { + if (_.isFunction(innerRef)) { + innerRef(pressableRef); + } else if (_.isObject(innerRef)) { + innerRef.current = pressableRef.current; + } } - this.props.onSecondaryInteraction(e); - /** - * This component prevents the tapped element from capturing focus. - * We need to blur this element when clicked as it opens modal that implements focus-trapping. - * When the modal is closed it focuses back to the last active element. - * Therefore it shifts the element to bring it back to focus. - * https://github.com/Expensify/App/issues/14148 - */ - if (this.props.withoutFocusOnSecondaryInteraction && this.pressableRef) { - this.pressableRef.blur(); - } - } - - render() { - const defaultPressableProps = _.omit(this.props, ['onSecondaryInteraction', 'children', 'onLongPress']); - const inlineStyle = this.props.inline ? styles.dInline : {}; - - // On Web, Text does not support LongPress events thus manage inline mode with styling instead of using Text. - return ( - (this.pressableRef = el)} - // eslint-disable-next-line react/jsx-props-no-spreading - {...defaultPressableProps} - style={(state) => [StyleUtils.parseStyleFromFunction(this.props.style, state), inlineStyle]} - > - {this.props.children} - - ); - } + const element = pressableRef.current; + element.addEventListener('contextmenu', executeSecondaryInteractionOnContextMenu); + + return () => { + element.removeEventListener('contextmenu', executeSecondaryInteractionOnContextMenu); + }; + }, [executeSecondaryInteractionOnContextMenu, innerRef, pressableRef]); + + const defaultPressableProps = _.omit(rest, ['onLongPress']); + const inlineStyle = inline ? styles.dInline : {}; + + return ( + [StyleUtils.parseStyleFromFunction(style, state), inlineStyle]} + > + {children} + + ); } PressableWithSecondaryInteraction.propTypes = pressableWithSecondaryInteractionPropTypes.propTypes; PressableWithSecondaryInteraction.defaultProps = pressableWithSecondaryInteractionPropTypes.defaultProps; -export default React.forwardRef((props, ref) => ( +PressableWithSecondaryInteraction.displayName = 'PressableWithSecondaryInteraction'; + +export default forwardRef((props, ref) => ( )); From aa4e245d6deee5c0ad2af2af21f2d51ef46b0617 Mon Sep 17 00:00:00 2001 From: Ana Margarida Silva Date: Thu, 17 Aug 2023 15:14:48 +0100 Subject: [PATCH 019/339] refactor: code improvements --- .../index.js | 81 +++++++++---------- 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/src/components/PressableWithSecondaryInteraction/index.js b/src/components/PressableWithSecondaryInteraction/index.js index fd50c6ff0994..ce1204967a8b 100644 --- a/src/components/PressableWithSecondaryInteraction/index.js +++ b/src/components/PressableWithSecondaryInteraction/index.js @@ -1,5 +1,5 @@ import _ from 'underscore'; -import React, {forwardRef, useCallback, useEffect, useRef} from 'react'; +import React, {forwardRef, useEffect, useRef} from 'react'; import styles from '../../styles/styles'; import * as DeviceCapabilities from '../../libs/DeviceCapabilities'; import * as StyleUtils from '../../styles/StyleUtils'; @@ -10,23 +10,21 @@ import * as pressableWithSecondaryInteractionPropTypes from './pressableWithSeco * This is a special Pressable that calls onSecondaryInteraction when LongPressed, or right-clicked. */ -function PressableWithSecondaryInteraction(props) { - const { - children, - inline, - style, - enableLongPressWithHover, - withoutFocusOnSecondaryInteraction, - preventDefaultContextMenu, - onSecondaryInteraction, - onPressIn, - onPress, - onPressOut, - activeOpacity, - innerRef, - ...rest - } = props; - +function PressableWithSecondaryInteraction({ + children, + inline, + style, + enableLongPressWithHover, + withoutFocusOnSecondaryInteraction, + preventDefaultContextMenu, + onSecondaryInteraction, + onPressIn, + onPress, + onPressOut, + activeOpacity, + forwardedRef, + ...rest +}) { const pressableRef = useRef(null); /** @@ -42,12 +40,25 @@ function PressableWithSecondaryInteraction(props) { onSecondaryInteraction(e); }; - /** - * @param {contextmenu} e - A right-click MouseEvent. - * https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event - */ - const executeSecondaryInteractionOnContextMenu = useCallback( - (e) => { + useEffect(() => { + if (!pressableRef || !pressableRef.current) { + return; + } + + if (forwardedRef) { + if (_.isFunction(forwardedRef)) { + forwardedRef(pressableRef); + } else if (_.isObject(forwardedRef)) { + // eslint-disable-next-line no-param-reassign + forwardedRef.current = pressableRef.current; + } + } + + /** + * @param {contextmenu} e - A right-click MouseEvent. + * https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event + */ + const executeSecondaryInteractionOnContextMenu = (e) => { if (!onSecondaryInteraction) { return; } @@ -69,22 +80,7 @@ function PressableWithSecondaryInteraction(props) { if (withoutFocusOnSecondaryInteraction && pressableRef && pressableRef.current) { pressableRef.current.blur(); } - }, - [onSecondaryInteraction, preventDefaultContextMenu, pressableRef, withoutFocusOnSecondaryInteraction], - ); - - useEffect(() => { - if (!pressableRef || !pressableRef.current) { - return; - } - - if (innerRef) { - if (_.isFunction(innerRef)) { - innerRef(pressableRef); - } else if (_.isObject(innerRef)) { - innerRef.current = pressableRef.current; - } - } + }; const element = pressableRef.current; element.addEventListener('contextmenu', executeSecondaryInteractionOnContextMenu); @@ -92,7 +88,8 @@ function PressableWithSecondaryInteraction(props) { return () => { element.removeEventListener('contextmenu', executeSecondaryInteractionOnContextMenu); }; - }, [executeSecondaryInteractionOnContextMenu, innerRef, pressableRef]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); const defaultPressableProps = _.omit(rest, ['onLongPress']); const inlineStyle = inline ? styles.dInline : {}; @@ -123,6 +120,6 @@ export default forwardRef((props, ref) => ( )); From dfd18964a115a0e7039e36dadcc13a8b1f8c866a Mon Sep 17 00:00:00 2001 From: Ana Margarida Silva Date: Thu, 17 Aug 2023 15:17:16 +0100 Subject: [PATCH 020/339] refactor: simplify --- src/components/PressableWithSecondaryInteraction/index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/PressableWithSecondaryInteraction/index.js b/src/components/PressableWithSecondaryInteraction/index.js index ce1204967a8b..ec74de1837b2 100644 --- a/src/components/PressableWithSecondaryInteraction/index.js +++ b/src/components/PressableWithSecondaryInteraction/index.js @@ -54,6 +54,8 @@ function PressableWithSecondaryInteraction({ } } + const element = pressableRef.current; + /** * @param {contextmenu} e - A right-click MouseEvent. * https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event @@ -77,12 +79,11 @@ function PressableWithSecondaryInteraction({ * Therefore it shifts the element to bring it back to focus. * https://github.com/Expensify/App/issues/14148 */ - if (withoutFocusOnSecondaryInteraction && pressableRef && pressableRef.current) { - pressableRef.current.blur(); + if (withoutFocusOnSecondaryInteraction) { + element.blur(); } }; - const element = pressableRef.current; element.addEventListener('contextmenu', executeSecondaryInteractionOnContextMenu); return () => { From 46d11cfea68cf4a609ab5748b5f052567294244a Mon Sep 17 00:00:00 2001 From: Ana Margarida Silva Date: Thu, 17 Aug 2023 15:18:45 +0100 Subject: [PATCH 021/339] fix: add missing comment --- src/components/PressableWithSecondaryInteraction/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/PressableWithSecondaryInteraction/index.js b/src/components/PressableWithSecondaryInteraction/index.js index ec74de1837b2..46de532156c9 100644 --- a/src/components/PressableWithSecondaryInteraction/index.js +++ b/src/components/PressableWithSecondaryInteraction/index.js @@ -89,6 +89,7 @@ function PressableWithSecondaryInteraction({ return () => { element.removeEventListener('contextmenu', executeSecondaryInteractionOnContextMenu); }; + // We only want this to run on mount // eslint-disable-next-line react-hooks/exhaustive-deps }, []); From c1dd8616fd6228b154a6d27c4c298b9c97c65273 Mon Sep 17 00:00:00 2001 From: Ana Margarida Silva Date: Thu, 17 Aug 2023 15:36:31 +0100 Subject: [PATCH 022/339] refactor: simplify --- src/components/PressableWithSecondaryInteraction/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/PressableWithSecondaryInteraction/index.js b/src/components/PressableWithSecondaryInteraction/index.js index 46de532156c9..2cd7004a68df 100644 --- a/src/components/PressableWithSecondaryInteraction/index.js +++ b/src/components/PressableWithSecondaryInteraction/index.js @@ -34,14 +34,14 @@ function PressableWithSecondaryInteraction({ if (DeviceCapabilities.hasHoverSupport() && !enableLongPressWithHover) { return; } - if (withoutFocusOnSecondaryInteraction && pressableRef && pressableRef.current) { + if (withoutFocusOnSecondaryInteraction && pressableRef.current) { pressableRef.current.blur(); } onSecondaryInteraction(e); }; useEffect(() => { - if (!pressableRef || !pressableRef.current) { + if (!pressableRef.current) { return; } From 56aff086e00fe074ab4308ebca9430d87d0c89e4 Mon Sep 17 00:00:00 2001 From: Ana Margarida Silva Date: Thu, 17 Aug 2023 15:48:33 +0100 Subject: [PATCH 023/339] revert: useEffect dependencies --- src/components/PressableWithSecondaryInteraction/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/PressableWithSecondaryInteraction/index.js b/src/components/PressableWithSecondaryInteraction/index.js index 2cd7004a68df..50fb48fc1525 100644 --- a/src/components/PressableWithSecondaryInteraction/index.js +++ b/src/components/PressableWithSecondaryInteraction/index.js @@ -89,9 +89,7 @@ function PressableWithSecondaryInteraction({ return () => { element.removeEventListener('contextmenu', executeSecondaryInteractionOnContextMenu); }; - // We only want this to run on mount - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, [forwardedRef, onSecondaryInteraction, preventDefaultContextMenu, withoutFocusOnSecondaryInteraction]); const defaultPressableProps = _.omit(rest, ['onLongPress']); const inlineStyle = inline ? styles.dInline : {}; From 3a0f64767d6ca9ce916e9be4e558ce496e684590 Mon Sep 17 00:00:00 2001 From: Ana Margarida Silva Date: Thu, 17 Aug 2023 16:04:08 +0100 Subject: [PATCH 024/339] docs: add more info to onSecondaryInteraction doc --- .../pressableWithSecondaryInteractionPropTypes.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/PressableWithSecondaryInteraction/pressableWithSecondaryInteractionPropTypes.js b/src/components/PressableWithSecondaryInteraction/pressableWithSecondaryInteractionPropTypes.js index de0adbe81297..f521a57957f3 100644 --- a/src/components/PressableWithSecondaryInteraction/pressableWithSecondaryInteractionPropTypes.js +++ b/src/components/PressableWithSecondaryInteraction/pressableWithSecondaryInteractionPropTypes.js @@ -12,7 +12,12 @@ const propTypes = { /** The function that should be called when this pressable is pressedOut */ onPressOut: PropTypes.func, - /** The function that should be called when this pressable is LongPressed or right-clicked. */ + /** + * The function that should be called when this pressable is LongPressed or right-clicked. + * + * This function should be stable, preferably wrapped in a `useCallback` so that it does not + * cause several re-renders. + */ onSecondaryInteraction: PropTypes.func, /** The children which should be contained in this wrapper component. */ From 61bc6ae3bcdee5484e966a70523c635da1be5736 Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 17 Aug 2023 11:43:09 -0500 Subject: [PATCH 025/339] Add RenderHTML to show deleted reportAction --- src/components/ReportActionItem/TaskPreview.js | 1 - src/pages/home/report/ReportActionItem.js | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/ReportActionItem/TaskPreview.js b/src/components/ReportActionItem/TaskPreview.js index 4f2c2c7dab8b..37a53aba35c4 100644 --- a/src/components/ReportActionItem/TaskPreview.js +++ b/src/components/ReportActionItem/TaskPreview.js @@ -22,7 +22,6 @@ import * as ReportUtils from '../../libs/ReportUtils'; import RenderHTML from '../RenderHTML'; import PressableWithoutFeedback from '../Pressable/PressableWithoutFeedback'; import personalDetailsPropType from '../../pages/personalDetailsPropType'; -import * as ReportActionsUtils from '../../libs/ReportActionsUtils'; import * as Session from '../../libs/actions/Session'; const propTypes = { diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 2d2b090b75ae..9eb83e5c6648 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -66,6 +66,7 @@ import * as store from '../../../libs/actions/ReimbursementAccount/store'; import * as BankAccounts from '../../../libs/actions/BankAccounts'; import ReportScreenContext from '../ReportScreenContext'; import Permissions from '../../../libs/Permissions'; +import RenderHTML from '../../../components/RenderHTML'; const propTypes = { ...windowDimensionsPropTypes, @@ -484,7 +485,9 @@ function ReportActionItem(props) { showHeader={!props.draftMessage} wrapperStyles={[styles.chatItem]} report={props.report} - /> + > + ${props.translate('parentReportAction.deletedTask')}`} /> + ) } From 91246ad1cf30475bc1aa8f3815402e166a160de0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ord=C3=B3=C3=B1ez?= Date: Fri, 18 Aug 2023 15:54:45 -0500 Subject: [PATCH 026/339] fix: Unify iou and task description ux --- src/components/ReportActionItem/MoneyRequestView.js | 2 ++ src/pages/EditRequestDescriptionPage.js | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index c05cf14f2fc1..70b55a466848 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -113,6 +113,8 @@ function MoneyRequestView({report, parentReport, shouldShowHorizontalRule, polic disabled={isSettled || !canEdit} shouldShowRightIcon={canEdit} onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))} + wrapperStyle={[styles.pv2, styles.taskDescriptionMenuItem]} + numberOfLinesTitle={0} /> (descriptionInputRef.current = e)} + autoGrowHeight + containerStyles={[styles.autoGrowHeightMultilineInput]} + textAlignVertical="top" /> From 65edf96b211f0b3a238161bc7732ee1f99e4004c Mon Sep 17 00:00:00 2001 From: Maciej Dobosz Date: Mon, 21 Aug 2023 11:40:59 +0200 Subject: [PATCH 027/339] English and spanish translations --- src/languages/en.js | 15 +++++++++++---- src/languages/es.js | 16 +++++++++++----- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index 19dbd9c63187..c0ed7b27a071 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -353,19 +353,23 @@ export default { }, }, sidebarScreen: { - fabAction: 'New chat', + chat: 'Chat', + room: 'Room', newChat: 'New chat', newGroup: 'New group', newRoom: 'New room', buttonSearch: 'Search', buttonMySettings: 'My settings', - fabNewChat: 'New chat (Floating action)', + fabNewChat: 'Send message', + fabNewChatExplained: 'Send message (Floating action)', chatPinned: 'Chat pinned', draftedMessage: 'Drafted message', listOfChatMessages: 'List of chat messages', listOfChats: 'List of chats', }, tabSelector: { + chat: 'Chat', + room: 'Room', manual: 'Manual', scan: 'Scan', distance: 'Distance', @@ -391,9 +395,10 @@ export default { amount: 'Amount', cash: 'Cash', split: 'Split', + addToSplit: 'Add to split', + splitBill: 'Split bill', request: 'Request', participants: 'Participants', - splitBill: 'Split bill', requestMoney: 'Request money', sendMoney: 'Send money', pay: 'Pay', @@ -862,7 +867,9 @@ export default { localTime: 'Local time', }, newChatPage: { + createChat: 'Create chat', createGroup: 'Create group', + addToGroup: 'Add to group', }, yearPickerPage: { year: 'Year', @@ -1410,7 +1417,7 @@ export default { openShortcutDialog: 'Opens the keyboard shortcuts dialog', escape: 'Escape dialogs', search: 'Open search dialog', - newGroup: 'New group screen', + newChat: 'New chat screen', copy: 'Copy comment', }, }, diff --git a/src/languages/es.js b/src/languages/es.js index bb3306417e17..605e6c3c5760 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -352,19 +352,22 @@ export default { }, }, sidebarScreen: { - fabAction: 'Nuevo chat', - newChat: 'Nuevo chat', + chat: 'Chat', + room: 'Sala', newGroup: 'Nuevo grupo', newRoom: 'Nueva sala de chat', buttonSearch: 'Buscar', buttonMySettings: 'Mi configuración', - fabNewChat: 'Nuevo chat', + fabNewChat: 'Enviar mensaje', + fabNewChatExplained: 'Enviar mensaje', chatPinned: 'Chat fijado', draftedMessage: 'Mensaje borrador', listOfChatMessages: 'Lista de mensajes del chat', listOfChats: 'lista de chats', }, tabSelector: { + chat: 'Chat', + room: 'Sala', manual: 'Manual', scan: 'Escanear', distance: 'Distancia', @@ -390,9 +393,10 @@ export default { amount: 'Importe', cash: 'Efectivo', split: 'Dividir', + addToSplit: 'Añadir para dividir', + splitBill: 'Dividir factura', request: 'Solicitar', participants: 'Participantes', - splitBill: 'Dividir factura', requestMoney: 'Pedir dinero', sendMoney: 'Enviar dinero', pay: 'Pagar', @@ -866,7 +870,9 @@ export default { localTime: 'Hora local', }, newChatPage: { + createChat: 'Crear chat', createGroup: 'Crear grupo', + addToGroup: 'Añadir al grupo', }, yearPickerPage: { year: 'Año', @@ -1437,7 +1443,7 @@ export default { openShortcutDialog: 'Abre el cuadro de diálogo de métodos abreviados de teclado', escape: 'Diálogos de escape', search: 'Abrir diálogo de búsqueda', - newGroup: 'Nueva pantalla de grupo', + newChat: 'Nueva pantalla de chat', copy: 'Copiar comentario', }, }, From d0ef97a5a3354cf25a2629325ba24a679f1b435a Mon Sep 17 00:00:00 2001 From: Maciej Dobosz Date: Mon, 21 Aug 2023 11:45:41 +0200 Subject: [PATCH 028/339] Assign icons to new tabs --- src/components/TabSelector/TabSelector.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/TabSelector/TabSelector.js b/src/components/TabSelector/TabSelector.js index 3e0ff7eb4e99..2d3901a237fe 100644 --- a/src/components/TabSelector/TabSelector.js +++ b/src/components/TabSelector/TabSelector.js @@ -29,12 +29,18 @@ const defaultProps = { const getIcon = (route) => { switch (route) { + case CONST.TAB.MANUAL: + return Expensicons.Pencil; case CONST.TAB.SCAN: return Expensicons.Receipt; + case CONST.TAB.NEW_CHAT: + return Expensicons.User; + case CONST.TAB.NEW_ROOM: + return Expensicons.Hashtag; case CONST.TAB.DISTANCE: return Expensicons.Car; default: - return Expensicons.Pencil; + throw new Error(`Route ${route} has no icon set.`); } }; From 3e61212d2bc8a441dfb872be6c446fbb32cd947d Mon Sep 17 00:00:00 2001 From: Maciej Dobosz Date: Mon, 21 Aug 2023 11:57:31 +0200 Subject: [PATCH 029/339] Checkbox can become a button --- src/components/OptionRow.js | 29 ++++++++++++++++++- src/components/OptionsList/BaseOptionsList.js | 3 ++ .../OptionsSelector/BaseOptionsSelector.js | 3 ++ .../optionsSelectorPropTypes.js | 9 ++++++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js index adaa4457bbd9..e65b2cf5eda8 100644 --- a/src/components/OptionRow.js +++ b/src/components/OptionRow.js @@ -8,6 +8,7 @@ import * as StyleUtils from '../styles/StyleUtils'; import optionPropTypes from './optionPropTypes'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; +import Button from './Button'; import MultipleAvatars from './MultipleAvatars'; import Hoverable from './Hoverable'; import DisplayNames from './DisplayNames'; @@ -39,6 +40,15 @@ const propTypes = { /** Whether we should show the selected state */ showSelectedState: PropTypes.bool, + /** Whether to show a button pill instead of a tickbox */ + shouldShowSelectedStateAsButton: PropTypes.bool, + + /** Text for button pill */ + selectedStateButtonText: PropTypes.string, + + /** Callback to fire when the multiple selector (tickbox or button) is clicked */ + onSelectedStatePressed: PropTypes.func, + /** Whether this item is selected */ isSelected: PropTypes.bool, @@ -65,6 +75,9 @@ const propTypes = { const defaultProps = { hoverStyle: styles.sidebarLinkHover, showSelectedState: false, + shouldShowSelectedStateAsButton: false, + selectedStateButtonText: 'Select', + onSelectedStatePressed: undefined, isSelected: false, boldStyle: false, showTitleTooltip: false, @@ -248,7 +261,21 @@ class OptionRow extends Component { /> )} - {this.props.showSelectedState && } + {this.props.showSelectedState && ( + <> + {this.props.shouldShowSelectedStateAsButton && !this.props.isSelected ? ( +