diff --git a/src/components/ReportActionItem/TaskAction.js b/src/components/ReportActionItem/TaskAction.js
index f30d8c3908de..d79bb6f78b93 100644
--- a/src/components/ReportActionItem/TaskAction.js
+++ b/src/components/ReportActionItem/TaskAction.js
@@ -3,8 +3,8 @@ import React from 'react';
import {View} from 'react-native';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
+import * as TaskUtils from '@libs/TaskUtils';
import useThemeStyles from '@styles/useThemeStyles';
-import * as Task from '@userActions/Task';
const propTypes = {
/** Name of the reportAction action */
@@ -22,7 +22,7 @@ function TaskAction(props) {
return (
<>
- {Task.getTaskReportActionMessage(props.actionName, props.taskReportID, false)}
+ {TaskUtils.getTaskReportActionMessage(props.actionName)}
>
);
diff --git a/src/components/ReportActionItem/TaskPreview.js b/src/components/ReportActionItem/TaskPreview.js
index 5d1c9972666a..e293a7d28579 100644
--- a/src/components/ReportActionItem/TaskPreview.js
+++ b/src/components/ReportActionItem/TaskPreview.js
@@ -21,6 +21,7 @@ import getButtonState from '@libs/getButtonState';
import * as LocalePhoneNumber from '@libs/LocalePhoneNumber';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
+import * as TaskUtils from '@libs/TaskUtils';
import reportActionPropTypes from '@pages/home/report/reportActionPropTypes';
import useStyleUtils from '@styles/useStyleUtils';
import useThemeStyles from '@styles/useThemeStyles';
@@ -84,7 +85,7 @@ function TaskPreview(props) {
const isTaskCompleted = !_.isEmpty(props.taskReport)
? props.taskReport.stateNum === CONST.REPORT.STATE_NUM.SUBMITTED && props.taskReport.statusNum === CONST.REPORT.STATUS.APPROVED
: props.action.childStateNum === CONST.REPORT.STATE_NUM.SUBMITTED && props.action.childStatusNum === CONST.REPORT.STATUS.APPROVED;
- const taskTitle = props.taskReport.reportName || props.action.childReportName;
+ const taskTitle = TaskUtils.getTaskTitle(props.taskReportID, props.action.childReportName);
const taskAssigneeAccountID = Task.getTaskAssigneeAccountID(props.taskReport) || props.action.childManagerAccountID;
const assigneeLogin = lodashGet(personalDetails, [taskAssigneeAccountID, 'login'], '');
const assigneeDisplayName = lodashGet(personalDetails, [taskAssigneeAccountID, 'displayName'], '');
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 5972b64cd7f3..c3f663eee4e0 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -63,6 +63,7 @@ import type {
SplitAmountParams,
StepCounterParams,
TagSelectionParams,
+ TaskCreatedActionParams,
ThreadRequestReportNameParams,
ThreadSentMoneyReportNameParams,
ToValidateLoginParams,
@@ -1673,6 +1674,7 @@ export default {
assignee: 'Assignee',
completed: 'Completed',
messages: {
+ created: ({title}: TaskCreatedActionParams) => `task for ${title}`,
completed: 'marked as complete',
canceled: 'deleted task',
reopened: 'marked as incomplete',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 4ebca857a617..b4e0e37d0614 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -63,6 +63,7 @@ import type {
SplitAmountParams,
StepCounterParams,
TagSelectionParams,
+ TaskCreatedActionParams,
ThreadRequestReportNameParams,
ThreadSentMoneyReportNameParams,
ToValidateLoginParams,
@@ -1697,6 +1698,7 @@ export default {
assignee: 'Usuario asignado',
completed: 'Completada',
messages: {
+ created: ({title}: TaskCreatedActionParams) => `tarea para ${title}`,
completed: 'marcada como completa',
canceled: 'tarea eliminado',
reopened: 'marcada como incompleta',
diff --git a/src/languages/types.ts b/src/languages/types.ts
index 9f66dc6f97ec..22977fe90c38 100644
--- a/src/languages/types.ts
+++ b/src/languages/types.ts
@@ -205,6 +205,8 @@ type TagSelectionParams = {tagName: string};
type WalletProgramParams = {walletProgram: string};
+type TaskCreatedActionParams = {title: string};
+
/* Translation Object types */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type TranslationBaseValue = string | string[] | ((...args: any[]) => string);
@@ -324,4 +326,5 @@ export type {
SetTheDistanceParams,
UpdatedTheDistanceParams,
WalletProgramParams,
+ TaskCreatedActionParams,
};
diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js
index 13586b6c5d2e..514271a56280 100644
--- a/src/libs/OptionsListUtils.js
+++ b/src/libs/OptionsListUtils.js
@@ -18,6 +18,7 @@ import Permissions from './Permissions';
import * as PersonalDetailsUtils from './PersonalDetailsUtils';
import * as ReportActionUtils from './ReportActionsUtils';
import * as ReportUtils from './ReportUtils';
+import * as TaskUtils from './TaskUtils';
import * as TransactionUtils from './TransactionUtils';
import * as UserUtils from './UserUtils';
@@ -414,6 +415,8 @@ function getLastMessageTextForReport(report) {
lastActionName === CONST.REPORT.ACTIONS.TYPE.TASKCANCELLED
) {
lastMessageTextFromReport = lodashGet(lastReportAction, 'message[0].text', '');
+ } else if (ReportActionUtils.isCreatedTaskReportAction(lastReportAction)) {
+ lastMessageTextFromReport = TaskUtils.getTaskCreatedMessage(lastReportAction);
} else {
lastMessageTextFromReport = report ? report.lastMessageText || '' : '';
}
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 8657a695c7e5..1da1469a2687 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -10,7 +10,6 @@ import * as OnyxCommon from '@src/types/onyx/OnyxCommon';
import Policy from '@src/types/onyx/Policy';
import Report from '@src/types/onyx/Report';
import ReportAction, {ReportActions} from '@src/types/onyx/ReportAction';
-import * as Task from './actions/Task';
import * as CollectionUtils from './CollectionUtils';
import * as LocalePhoneNumber from './LocalePhoneNumber';
import * as Localize from './Localize';
@@ -18,6 +17,7 @@ import * as OptionsListUtils from './OptionsListUtils';
import * as PersonalDetailsUtils from './PersonalDetailsUtils';
import * as ReportActionsUtils from './ReportActionsUtils';
import * as ReportUtils from './ReportUtils';
+import * as TaskUtils from './TaskUtils';
import * as UserUtils from './UserUtils';
const visibleReportActionItems: ReportActions = {};
@@ -363,7 +363,7 @@ function getOptionData(
const newName = lastAction?.originalMessage?.newName ?? '';
result.alternateText = Localize.translate(preferredLocale, 'newRoomPage.roomRenamedTo', {newName});
} else if (ReportActionsUtils.isTaskAction(lastAction)) {
- result.alternateText = Task.getTaskReportActionMessage(lastAction.actionName, report.reportID, false);
+ result.alternateText = TaskUtils.getTaskReportActionMessage(lastAction.actionName);
} else if (
lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.ROOMCHANGELOG.INVITE_TO_ROOM ||
lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.ROOMCHANGELOG.REMOVE_FROM_ROOM ||
diff --git a/src/libs/TaskUtils.ts b/src/libs/TaskUtils.ts
new file mode 100644
index 000000000000..3026e33edc8c
--- /dev/null
+++ b/src/libs/TaskUtils.ts
@@ -0,0 +1,51 @@
+import Onyx, {OnyxEntry} from 'react-native-onyx';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import {Report} from '@src/types/onyx';
+import ReportAction from '@src/types/onyx/ReportAction';
+import * as CollectionUtils from './CollectionUtils';
+import * as Localize from './Localize';
+
+const allReports: Record = {};
+Onyx.connect({
+ key: ONYXKEYS.COLLECTION.REPORT,
+ callback: (report, key) => {
+ if (!key || !report) {
+ return;
+ }
+ const reportID = CollectionUtils.extractCollectionItemID(key);
+ allReports[reportID] = report;
+ },
+});
+
+/**
+ * Given the Task reportAction name, return the appropriate message to be displayed and copied to clipboard.
+ */
+function getTaskReportActionMessage(actionName: string): string {
+ switch (actionName) {
+ case CONST.REPORT.ACTIONS.TYPE.TASKCOMPLETED:
+ return Localize.translateLocal('task.messages.completed');
+ case CONST.REPORT.ACTIONS.TYPE.TASKCANCELLED:
+ return Localize.translateLocal('task.messages.canceled');
+ case CONST.REPORT.ACTIONS.TYPE.TASKREOPENED:
+ return Localize.translateLocal('task.messages.reopened');
+ default:
+ return Localize.translateLocal('task.task');
+ }
+}
+
+function getTaskTitle(taskReportID: string, fallbackTitle = ''): string {
+ const taskReport = allReports[taskReportID] ?? {};
+ // We need to check for reportID, not just reportName, because when a receiver opens the task for the first time,
+ // an optimistic report is created with the only property – reportName: 'Chat report',
+ // and it will be displayed as the task title without checking for reportID to be present.
+ return Object.hasOwn(taskReport, 'reportID') && taskReport.reportName ? taskReport.reportName : fallbackTitle;
+}
+
+function getTaskCreatedMessage(reportAction: OnyxEntry) {
+ const taskReportID = reportAction?.childReportID ?? '';
+ const taskTitle = getTaskTitle(taskReportID, reportAction?.childReportName);
+ return Localize.translateLocal('task.messages.created', {title: taskTitle});
+}
+
+export {getTaskReportActionMessage, getTaskTitle, getTaskCreatedMessage};
diff --git a/src/libs/actions/Task.js b/src/libs/actions/Task.js
index bf816d0a62a7..e5037d250d2e 100644
--- a/src/libs/actions/Task.js
+++ b/src/libs/actions/Task.js
@@ -6,7 +6,6 @@ import * as API from '@libs/API';
import DateUtils from '@libs/DateUtils';
import * as ErrorUtils from '@libs/ErrorUtils';
import * as LocalePhoneNumber from '@libs/LocalePhoneNumber';
-import * as Localize from '@libs/Localize';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
@@ -906,35 +905,6 @@ function clearTaskErrors(reportID) {
});
}
-/**
- * @param {string} actionName
- * @param {string} reportID
- * @param {boolean} isCreateTaskAction
- * @returns {string}
- */
-function getTaskReportActionMessage(actionName, reportID, isCreateTaskAction) {
- const report = ReportUtils.getReport(reportID);
- if (isCreateTaskAction) {
- return `task for ${report.reportName}`;
- }
- let taskStatusText = '';
- switch (actionName) {
- case CONST.REPORT.ACTIONS.TYPE.TASKCOMPLETED:
- taskStatusText = Localize.translateLocal('task.messages.completed');
- break;
- case CONST.REPORT.ACTIONS.TYPE.TASKCANCELLED:
- taskStatusText = Localize.translateLocal('task.messages.canceled');
- break;
- case CONST.REPORT.ACTIONS.TYPE.TASKREOPENED:
- taskStatusText = Localize.translateLocal('task.messages.reopened');
- break;
- default:
- taskStatusText = Localize.translateLocal('task.task');
- }
-
- return `${taskStatusText}`;
-}
-
export {
createTaskAndNavigate,
editTask,
@@ -956,5 +926,4 @@ export {
getTaskAssigneeAccountID,
clearTaskErrors,
canModifyTask,
- getTaskReportActionMessage,
};
diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.js b/src/pages/home/report/ContextMenu/ContextMenuActions.js
index 832b3352b2e5..7d12edc24d3c 100644
--- a/src/pages/home/report/ContextMenu/ContextMenuActions.js
+++ b/src/pages/home/report/ContextMenu/ContextMenuActions.js
@@ -17,6 +17,7 @@ import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
+import * as TaskUtils from '@libs/TaskUtils';
import * as Download from '@userActions/Download';
import * as Report from '@userActions/Report';
import * as Task from '@userActions/Task';
@@ -259,15 +260,13 @@ export default [
type === CONTEXT_MENU_TYPES.REPORT_ACTION && !ReportActionsUtils.isReportActionAttachment(reportAction) && !ReportActionsUtils.isMessageDeleted(reportAction),
// If return value is true, we switch the `text` and `icon` on
- // `ContextMenuItem` with `successText` and `successIcon` which will fallback to
+ // `ContextMenuItem` with `successText` and `successIcon` which will fall back to
// the `text` and `icon`
onPress: (closePopover, {reportAction, selection}) => {
const isTaskAction = ReportActionsUtils.isTaskAction(reportAction);
- const isCreateTaskAction = ReportActionsUtils.isCreatedTaskReportAction(reportAction);
const isReportPreviewAction = ReportActionsUtils.isReportPreviewAction(reportAction);
const message = _.last(lodashGet(reportAction, 'message', [{}]));
- const reportID = lodashGet(reportAction, 'originalMessage.taskReportID', '').toString();
- const messageHtml = isTaskAction || isCreateTaskAction ? Task.getTaskReportActionMessage(reportAction.actionName, reportID, isCreateTaskAction) : lodashGet(message, 'html', '');
+ const messageHtml = isTaskAction ? Task.getTaskReportActionMessage(reportAction) : lodashGet(message, 'html', '');
const isAttachment = ReportActionsUtils.isReportActionAttachment(reportAction);
if (!isAttachment) {
@@ -282,6 +281,9 @@ export default [
} else if (ReportActionsUtils.isMoneyRequestAction(reportAction)) {
const displayMessage = ReportUtils.getIOUReportActionDisplayMessage(reportAction);
Clipboard.setString(displayMessage);
+ } else if (ReportActionsUtils.isCreatedTaskReportAction(reportAction)) {
+ const taskPreviewMessage = TaskUtils.getTaskCreatedMessage(reportAction);
+ Clipboard.setString(taskPreviewMessage);
} else if (ReportActionsUtils.isChannelLogMemberAction(reportAction)) {
const logMessage = ReportUtils.getChannelLogMemberMessage(reportAction);
Clipboard.setString(logMessage);