From 8aed339c463ed43acbaaebec24da0abea9fe3943 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Fri, 26 Apr 2024 14:54:19 +0200 Subject: [PATCH 1/4] omit replies config --- src/libs/ReportUtils.ts | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 121518130cb4..0a69629d24a6 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -3322,12 +3322,6 @@ function buildOptimisticTaskCommentReportAction( parentReportID: string, actorAccountID?: number, createdOffset = 0, - repliesConfig?: { - childVisibleActionCount?: number; - childCommenterCount?: number; - childLastVisibleActionCreated?: string; - childOldestFourAccountIDs?: string; - }, ): OptimisticReportAction { const reportAction = buildOptimisticAddCommentReportAction(text, undefined, undefined, createdOffset); if (reportAction.reportAction.message?.[0]) { @@ -3352,22 +3346,6 @@ function buildOptimisticTaskCommentReportAction( reportAction.reportAction.actorAccountID = actorAccountID; } - if (repliesConfig?.childVisibleActionCount) { - reportAction.reportAction.childVisibleActionCount = repliesConfig.childVisibleActionCount; - } - - if (repliesConfig?.childCommenterCount) { - reportAction.reportAction.childCommenterCount = repliesConfig.childCommenterCount; - } - - if (repliesConfig?.childLastVisibleActionCreated) { - reportAction.reportAction.childLastVisibleActionCreated = repliesConfig.childLastVisibleActionCreated; - } - - if (repliesConfig?.childOldestFourAccountIDs) { - reportAction.reportAction.childOldestFourAccountIDs = repliesConfig.childOldestFourAccountIDs; - } - return reportAction; } From 042c9a82fae4460c2c3cbca69992c47559ada776 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Fri, 26 Apr 2024 14:59:04 +0200 Subject: [PATCH 2/4] move comments to task description --- src/CONST.ts | 63 +++--- src/components/MenuItem.tsx | 8 +- src/components/ReportActionItem/TaskView.tsx | 2 + src/libs/actions/Report.ts | 205 +++++++------------ 4 files changed, 116 insertions(+), 162 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 2e14aa7cf21f..8ad9eda06501 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -3683,8 +3683,9 @@ const CONST = { type: 'createWorkspace', autoCompleted: true, title: 'Create a workspace', - subtitle: 'Create a workspace to track expenses, scan receipts, chat, and more.', - message: + description: + 'Create a workspace to track expenses, scan receipts, chat, and more.\n' + + '\n' + 'Here’s how to create a workspace:\n' + '\n' + '1. Click your profile picture.\n' + @@ -3696,8 +3697,9 @@ const CONST = { type: 'trackExpense', autoCompleted: false, title: 'Track an expense', - subtitle: 'Track an expense in any currency, in just a few clicks.', - message: + description: + 'Track an expense in any currency, in just a few clicks.\n' + + '\n' + 'Here’s how to track an expense:\n' + '\n' + '1. Click the green + button.\n' + @@ -3723,8 +3725,9 @@ const CONST = { type: 'submitExpense', autoCompleted: false, title: 'Submit an expense', - subtitle: 'Submit an expense by entering an amount or scanning a receipt.', - message: + description: + 'Submit an expense by entering an amount or scanning a receipt.\n' + + '\n' + 'Here’s how to submit an expense:\n' + '\n' + '1. Click the green + button.\n' + @@ -3738,8 +3741,9 @@ const CONST = { type: 'enableWallet', autoCompleted: false, title: 'Enable your wallet', - subtitle: 'You’ll need to enable your Expensify Wallet to get paid back. Don’t worry, it’s easy!', - message: + description: + 'You’ll need to enable your Expensify Wallet to get paid back. Don’t worry, it’s easy!\n' + + '\n' + 'Here’s how to set up your wallet:\n' + '\n' + '1. Click your profile picture.\n' + @@ -3764,8 +3768,9 @@ const CONST = { type: 'createWorkspace', autoCompleted: true, title: 'Create a workspace', - subtitle: 'Create a workspace to track expenses, scan receipts, chat, and more.', - message: + description: + 'Create a workspace to track expenses, scan receipts, chat, and more.\n' + + '\n' + 'Here’s how to create a workspace:\n' + '\n' + '1. Click your profile picture.\n' + @@ -3777,8 +3782,7 @@ const CONST = { type: 'meetGuide', autoCompleted: false, title: 'Meet your setup specialist', - subtitle: '', - message: ({adminsRoomLink, guideCalendarLink}: {adminsRoomLink: string; guideCalendarLink: string}) => + description: ({adminsRoomLink, guideCalendarLink}: {adminsRoomLink: string; guideCalendarLink: string}) => `Meet your setup specialist, who can answer any questions as you get started with Expensify. Yes, a real human!\n` + '\n' + `Chat with the specialist in your [#admins room](${adminsRoomLink}) or [schedule a call](${guideCalendarLink}) today.`, @@ -3787,8 +3791,9 @@ const CONST = { type: 'setupCategories', autoCompleted: false, title: 'Set up categories', - subtitle: 'Set up categories so your team can code expenses for easy reporting.', - message: + description: + 'Set up categories so your team can code expenses for easy reporting.\n' + + '\n' + 'Here’s how to set up categories:\n' + '\n' + '1. Click your profile picture.\n' + @@ -3803,8 +3808,9 @@ const CONST = { type: 'addExpenseApprovals', autoCompleted: false, title: 'Add expense approvals', - subtitle: 'Add expense approvals to review your team’s spend and keep it under control.', - message: + description: + 'Add expense approvals to review your team’s spend and keep it under control.\n' + + '\n' + 'Here’s how to add expense approvals:\n' + '\n' + '1. Click your profile picture.\n' + @@ -3819,8 +3825,9 @@ const CONST = { type: 'inviteTeam', autoCompleted: false, title: 'Invite your team', - subtitle: 'Invite your team to Expensify so they can start tracking expenses today.', - message: + description: + 'Invite your team to Expensify so they can start tracking expenses today.\n' + + '\n' + 'Here’s how to invite your team:\n' + '\n' + '1. Click your profile picture.\n' + @@ -3847,8 +3854,9 @@ const CONST = { type: 'trackExpense', autoCompleted: false, title: 'Track an expense', - subtitle: 'Track an expense in any currency, whether you have a receipt or not.', - message: + description: + 'Track an expense in any currency, whether you have a receipt or not.\n' + + '\n' + 'Here’s how to track an expense:\n' + '\n' + '1. Click the green + button.\n' + @@ -3874,8 +3882,9 @@ const CONST = { type: 'startChat', autoCompleted: false, title: 'Start a chat', - subtitle: 'Start a chat with a friend or group using their email or phone number.', - message: + description: + 'Start a chat with a friend or group using their email or phone number.\n' + + '\n' + 'Here’s how to start a chat:\n' + '\n' + '1. Click the green + button.\n' + @@ -3890,8 +3899,9 @@ const CONST = { type: 'splitExpense', autoCompleted: false, title: 'Split an expense', - subtitle: 'Split an expense right in your chat with one or more friends.', - message: + description: + 'Split an expense right in your chat with one or more friends.\n' + + '\n' + 'Here’s how to request money:\n' + '\n' + '1. Click the green + button.\n' + @@ -3905,8 +3915,9 @@ const CONST = { type: 'enableWallet', autoCompleted: false, title: 'Enable your wallet', - subtitle: 'You’ll need to enable your Expensify Wallet to get paid back. Don’t worry, it’s easy!', - message: + description: + 'You’ll need to enable your Expensify Wallet to get paid back. Don’t worry, it’s easy!\n' + + '\n' + 'Here’s how to enable your wallet:\n' + '\n' + '1. Click your profile picture.\n' + diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 1afadd8ea856..9efdefd02b08 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -212,6 +212,9 @@ type MenuItemBaseProps = { /** Should render the content in HTML format */ shouldRenderAsHTML?: boolean; + /** Whether or not the text should be escaped */ + shouldEscapeText?: boolean; + /** Should we grey out the menu item when it is disabled? */ shouldGreyOutWhenDisabled?: boolean; @@ -313,6 +316,7 @@ function MenuItem( isSmallAvatarSubscriptMenu = false, brickRoadIndicator, shouldRenderAsHTML = false, + shouldEscapeText = undefined, shouldGreyOutWhenDisabled = true, shouldUseDefaultCursorWhenDisabled = false, isAnonymousAction = false, @@ -366,8 +370,8 @@ function MenuItem( return ''; } const parser = new ExpensiMark(); - return parser.replace(title); - }, [title, shouldParseTitle]); + return parser.replace(title, {shouldEscapeText}); + }, [title, shouldParseTitle, shouldEscapeText]); const processedTitle = useMemo(() => { let titleToWrap = ''; diff --git a/src/components/ReportActionItem/TaskView.tsx b/src/components/ReportActionItem/TaskView.tsx index e3e07ab0d7ad..0c8b23109104 100644 --- a/src/components/ReportActionItem/TaskView.tsx +++ b/src/components/ReportActionItem/TaskView.tsx @@ -149,6 +149,8 @@ function TaskView({report, shouldShowHorizontalRule, ...props}: TaskViewProps) { shouldGreyOutWhenDisabled={false} numberOfLinesTitle={0} interactive={!isDisableInteractive} + shouldRenderAsHTML + shouldEscapeText={false} /> diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 7542ca12c592..0efc85c1ae0c 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -3066,13 +3066,19 @@ function completeOnboarding( } const tasksData = data.tasks.map((task, index) => { - const hasSubtitle = !!task.subtitle; + const taskDescription = + typeof task.description === 'function' + ? task.description({ + adminsRoomLink: `${CONFIG.EXPENSIFY.NEW_EXPENSIFY_URL}${ROUTES.REPORT_WITH_ID.getRoute(adminsChatReportID ?? '')}`, + guideCalendarLink: guideCalendarLink ?? CONFIG.EXPENSIFY.NEW_EXPENSIFY_URL, + }) + : task.description; const currentTask = ReportUtils.buildOptimisticTaskReport( actorAccountID, undefined, targetChatReportID, task.title, - undefined, + taskDescription, targetChatPolicyID, CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, ); @@ -3085,22 +3091,8 @@ function completeOnboarding( targetChatReportID, actorAccountID, index + 3, - { - childVisibleActionCount: hasSubtitle ? 2 : 1, - childCommenterCount: 1, - childLastVisibleActionCreated: DateUtils.getDBTime(), - childOldestFourAccountIDs: `${actorAccountID}`, - }, ); - const subtitleComment = hasSubtitle ? ReportUtils.buildOptimisticAddCommentReportAction(task.subtitle, undefined, actorAccountID, 0, false) : null; - const isTaskMessageFunction = typeof task.message === 'function'; - const taskMessage = isTaskMessageFunction - ? task.message({ - adminsRoomLink: `${CONFIG.EXPENSIFY.NEW_EXPENSIFY_URL}${ROUTES.REPORT_WITH_ID.getRoute(adminsChatReportID ?? '')}`, - guideCalendarLink: guideCalendarLink ?? CONFIG.EXPENSIFY.NEW_EXPENSIFY_URL, - }) - : task.message; - const instructionComment = ReportUtils.buildOptimisticAddCommentReportAction(taskMessage, undefined, actorAccountID, 1, isTaskMessageFunction ? undefined : false); + const completedTaskReportAction = task.autoCompleted ? ReportUtils.buildOptimisticTaskReportAction(currentTask.reportID, CONST.REPORT.ACTIONS.TYPE.TASK_COMPLETED, 'marked as complete', actorAccountID, 2) : null; @@ -3110,134 +3102,79 @@ function completeOnboarding( currentTask, taskCreatedAction, taskReportAction, - subtitleComment, - instructionComment, + taskDescription, completedTaskReportAction, }; }); - const tasksForParameters = tasksData.reduce( - (acc, {task, currentTask, taskCreatedAction, taskReportAction, subtitleComment, instructionComment, completedTaskReportAction}) => { - const instructionCommentAction: OptimisticAddCommentReportAction = instructionComment.reportAction; - const instructionCommentText = instructionComment.commentText; - const instructionMessage: TaskMessage = { - reportID: currentTask.reportID, - reportActionID: instructionCommentAction.reportActionID, - reportComment: instructionCommentText, - }; - - const tasksForParametersAcc: TaskForParameters[] = [ - ...acc, - { - type: 'task', - task: task.type, - taskReportID: currentTask.reportID, - parentReportID: currentTask.parentReportID ?? '', - parentReportActionID: taskReportAction.reportAction.reportActionID, - assigneeChatReportID: '', - createdTaskReportActionID: taskCreatedAction.reportActionID, - completedTaskReportActionID: completedTaskReportAction?.reportActionID ?? undefined, - title: currentTask.reportName ?? '', - description: currentTask.description ?? '', - }, - { - type: 'message', - ...instructionMessage, - }, - ]; - - if (subtitleComment) { - const subtitleCommentAction: OptimisticAddCommentReportAction = subtitleComment.reportAction; - const subtitleCommentText = subtitleComment.commentText; - const subtitleMessage: TaskMessage = { - reportID: currentTask.reportID, - reportActionID: subtitleCommentAction.reportActionID, - reportComment: subtitleCommentText, - }; - - tasksForParametersAcc.push({ - type: 'message', - ...subtitleMessage, - }); - } - - return tasksForParametersAcc; - }, - [], - ); - - const tasksForOptimisticData = tasksData.reduce( - (acc, {currentTask, taskCreatedAction, taskReportAction, subtitleComment, instructionComment, completedTaskReportAction}) => { - const instructionCommentAction: OptimisticAddCommentReportAction = instructionComment.reportAction; - - const tasksForOptimisticDataAcc: OnyxUpdate[] = [ - ...acc, - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetChatReportID}`, - value: { - [taskReportAction.reportAction.reportActionID]: taskReportAction.reportAction as ReportAction, - }, + const tasksForParameters = tasksData.map(({task, currentTask, taskCreatedAction, taskReportAction, taskDescription, completedTaskReportAction}) => ({ + type: 'task', + task: task.type, + taskReportID: currentTask.reportID, + parentReportID: currentTask.parentReportID ?? '', + parentReportActionID: taskReportAction.reportAction.reportActionID, + assigneeChatReportID: '', + createdTaskReportActionID: taskCreatedAction.reportActionID, + completedTaskReportActionID: completedTaskReportAction?.reportActionID ?? undefined, + title: currentTask.reportName ?? '', + description: taskDescription, + })); + + const tasksForOptimisticData = tasksData.reduce((acc, {currentTask, taskCreatedAction, taskReportAction, taskDescription, completedTaskReportAction}) => { + const tasksForOptimisticDataAcc: OnyxUpdate[] = [ + ...acc, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${targetChatReportID}`, + value: { + [taskReportAction.reportAction.reportActionID]: taskReportAction.reportAction as ReportAction, }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.REPORT}${currentTask.reportID}`, - value: { - ...currentTask, - pendingFields: { - createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - reportName: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - description: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - managerID: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - }, - isOptimisticReport: true, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${currentTask.reportID}`, + value: { + ...currentTask, + description: taskDescription, + pendingFields: { + createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + reportName: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + description: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + managerID: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, }, + isOptimisticReport: true, }, - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${currentTask.reportID}`, - value: { - [taskCreatedAction.reportActionID]: taskCreatedAction as ReportAction, - [instructionCommentAction.reportActionID]: instructionCommentAction as ReportAction, - }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${currentTask.reportID}`, + value: { + [taskCreatedAction.reportActionID]: taskCreatedAction as ReportAction, }, - ]; - - if (subtitleComment) { - const subtitleCommentAction: OptimisticAddCommentReportAction = subtitleComment.reportAction; + }, + ]; - tasksForOptimisticDataAcc.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${currentTask.reportID}`, - value: { - [subtitleCommentAction.reportActionID]: subtitleCommentAction as ReportAction, - }, - }); - } + if (completedTaskReportAction) { + tasksForOptimisticDataAcc.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${currentTask.reportID}`, + value: { + [completedTaskReportAction.reportActionID]: completedTaskReportAction as ReportAction, + }, + }); - if (completedTaskReportAction) { - tasksForOptimisticDataAcc.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${currentTask.reportID}`, - value: { - [completedTaskReportAction.reportActionID]: completedTaskReportAction as ReportAction, - }, - }); - - tasksForOptimisticDataAcc.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${currentTask.reportID}`, - value: { - stateNum: CONST.REPORT.STATE_NUM.APPROVED, - statusNum: CONST.REPORT.STATUS_NUM.APPROVED, - }, - }); - } + tasksForOptimisticDataAcc.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${currentTask.reportID}`, + value: { + stateNum: CONST.REPORT.STATE_NUM.APPROVED, + statusNum: CONST.REPORT.STATUS_NUM.APPROVED, + }, + }); + } - return tasksForOptimisticDataAcc; - }, - [], - ); + return tasksForOptimisticDataAcc; + }, []); const tasksForFailureData = tasksData.reduce((acc, {currentTask, taskReportAction}) => { const tasksForFailureDataAcc: OnyxUpdate[] = [ From 65bdee128ecfa3e03a2fd5a4fd4a22f344d3c045 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Fri, 26 Apr 2024 15:32:49 +0200 Subject: [PATCH 3/4] create hasURL --- src/libs/Url.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libs/Url.ts b/src/libs/Url.ts index 4e3282e7bdb3..80ca98c712cf 100644 --- a/src/libs/Url.ts +++ b/src/libs/Url.ts @@ -56,4 +56,10 @@ function appendParam(url: string, paramName: string, paramValue: string) { return `${url}${separator}${paramName}=${paramValue}`; } -export {addTrailingForwardSlash, hasSameExpensifyOrigin, getPathFromURL, appendParam}; +function hasURL(text: string) { + const urlPattern = /((https|http)?:\/\/[^\s]+)/g; + + return urlPattern.test(text); +} + +export {addTrailingForwardSlash, hasSameExpensifyOrigin, getPathFromURL, appendParam, hasURL}; From 857433fc027da888f1b4c25cb0f990eb844db0e8 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Fri, 26 Apr 2024 15:33:01 +0200 Subject: [PATCH 4/4] integrate hasURL --- src/components/ReportActionItem/TaskView.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/TaskView.tsx b/src/components/ReportActionItem/TaskView.tsx index 0c8b23109104..181e259408d6 100644 --- a/src/components/ReportActionItem/TaskView.tsx +++ b/src/components/ReportActionItem/TaskView.tsx @@ -23,6 +23,7 @@ import getButtonState from '@libs/getButtonState'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as ReportUtils from '@libs/ReportUtils'; +import * as Url from '@libs/Url'; import * as Session from '@userActions/Session'; import * as Task from '@userActions/Task'; import CONST from '@src/CONST'; @@ -150,7 +151,7 @@ function TaskView({report, shouldShowHorizontalRule, ...props}: TaskViewProps) { numberOfLinesTitle={0} interactive={!isDisableInteractive} shouldRenderAsHTML - shouldEscapeText={false} + shouldEscapeText={Url.hasURL(report.description ?? '') ? undefined : false} />