diff --git a/src/libs/actions/QuickActionNavigation.ts b/src/libs/actions/QuickActionNavigation.ts index a7201904b4aa..3d6b94a8823f 100644 --- a/src/libs/actions/QuickActionNavigation.ts +++ b/src/libs/actions/QuickActionNavigation.ts @@ -1,5 +1,6 @@ import {generateReportID} from '@libs/ReportUtils'; import CONST from '@src/CONST'; +import type {PersonalDetails} from '@src/types/onyx'; import type {DistanceExpenseType} from '@src/types/onyx/IOU'; import type {QuickActionName} from '@src/types/onyx/QuickAction'; import type QuickAction from '@src/types/onyx/QuickAction'; @@ -12,6 +13,7 @@ type NavigateToQuickActionParams = { quickAction: QuickAction; selectOption: (onSelected: () => void, shouldRestrictAction: boolean) => void; lastDistanceExpenseType?: DistanceExpenseType; + targetAccountPersonalDetails: PersonalDetails; currentUserAccountID: number; }; @@ -35,7 +37,7 @@ function getQuickActionRequestType(action: QuickActionName | undefined, lastDist } function navigateToQuickAction(params: NavigateToQuickActionParams) { - const {isValidReport, quickAction, selectOption, lastDistanceExpenseType, currentUserAccountID} = params; + const {isValidReport, quickAction, selectOption, lastDistanceExpenseType, targetAccountPersonalDetails, currentUserAccountID} = params; const reportID = isValidReport && quickAction?.chatReportID ? quickAction?.chatReportID : generateReportID(); const requestType = getQuickActionRequestType(quickAction?.action, lastDistanceExpenseType); @@ -54,7 +56,7 @@ function navigateToQuickAction(params: NavigateToQuickActionParams) { selectOption(() => startMoneyRequest(CONST.IOU.TYPE.PAY, reportID, undefined, true), false); break; case CONST.QUICK_ACTIONS.ASSIGN_TASK: - selectOption(() => startOutCreateTaskQuickAction(currentUserAccountID, isValidReport ? reportID : '', quickAction.targetAccountID ?? CONST.DEFAULT_NUMBER_ID), false); + selectOption(() => startOutCreateTaskQuickAction(currentUserAccountID, isValidReport ? reportID : '', targetAccountPersonalDetails), false); break; case CONST.QUICK_ACTIONS.TRACK_MANUAL: case CONST.QUICK_ACTIONS.TRACK_SCAN: diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 084017d66a7c..e410c8f5c6ae 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -57,12 +57,6 @@ type CreateTaskAndNavigateParams = { quickAction?: OnyxEntry; }; -let allPersonalDetails: OnyxEntry; -Onyx.connect({ - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - callback: (value) => (allPersonalDetails = value), -}); - let allReportActions: OnyxCollection; Onyx.connect({ key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, @@ -827,9 +821,9 @@ function setAssigneeChatReport(chatReport: OnyxTypes.Report, isOptimisticReport } } -function setNewOptimisticAssignee(assigneeLogin: string, assigneeAccountID: number, currentUserAccountID: number) { +function setNewOptimisticAssignee(currentUserAccountID: number, assigneePersonalDetails: OnyxTypes.PersonalDetails) { const report: ReportUtils.OptimisticChatReport = ReportUtils.buildOptimisticChatReport({ - participantList: [assigneeAccountID, currentUserAccountID], + participantList: [assigneePersonalDetails.accountID, currentUserAccountID], reportName: '', policyID: CONST.POLICY.OWNER_EMAIL_FAKE, ownerAccountID: CONST.POLICY.OWNER_ACCOUNT_ID_FAKE, @@ -839,12 +833,12 @@ function setNewOptimisticAssignee(assigneeLogin: string, assigneeAccountID: numb Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, report); const optimisticPersonalDetailsListAction: OnyxTypes.PersonalDetails = { - accountID: assigneeAccountID, - avatar: allPersonalDetails?.[assigneeAccountID]?.avatar, - displayName: allPersonalDetails?.[assigneeAccountID]?.displayName ?? assigneeLogin, - login: assigneeLogin, + accountID: assigneePersonalDetails.accountID, + avatar: assigneePersonalDetails?.avatar, + displayName: assigneePersonalDetails?.displayName ?? assigneePersonalDetails?.login, + login: assigneePersonalDetails?.login, }; - Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, {[assigneeAccountID]: optimisticPersonalDetailsListAction}); + Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, {[assigneePersonalDetails.accountID]: optimisticPersonalDetailsListAction}); return {assignee: optimisticPersonalDetailsListAction, assigneeReport: report}; } @@ -854,9 +848,8 @@ function setNewOptimisticAssignee(assigneeLogin: string, assigneeAccountID: numb * It also sets the shareDestination as that chat report if a share destination isn't already set */ function setAssigneeValue( - assigneeEmail: string, - assigneeAccountID: number, currentUserAccountID: number, + assigneePersonalDetails: OnyxTypes.PersonalDetails, shareToReportID?: string, chatReport?: OnyxEntry, isCurrentUser = false, @@ -873,11 +866,11 @@ function setAssigneeValue( } else { // Check for the chatReport by participants IDs if (!report) { - report = ReportUtils.getChatByParticipants([assigneeAccountID, currentUserAccountID]); + report = ReportUtils.getChatByParticipants([assigneePersonalDetails.accountID, currentUserAccountID]); } // If chat report is still not found we need to build new optimistic chat report if (!report) { - report = setNewOptimisticAssignee(assigneeEmail, assigneeAccountID, currentUserAccountID).assigneeReport; + report = setNewOptimisticAssignee(currentUserAccountID, assigneePersonalDetails).assigneeReport; } const reportMetadata = ReportUtils.getReportMetadata(report?.reportID); @@ -900,7 +893,7 @@ function setAssigneeValue( } // This is only needed for creation of a new task and so it should only be stored locally - Onyx.merge(ONYXKEYS.TASK, {assignee: assigneeEmail, assigneeAccountID}); + Onyx.merge(ONYXKEYS.TASK, {assignee: assigneePersonalDetails?.login ?? '', assigneeAccountID: assigneePersonalDetails.accountID}); // When we're editing the assignee, we immediately call editTaskAssignee. Since setting the assignee is async, // the chatReport is not yet set when editTaskAssignee is called. So we return the chatReport here so that @@ -919,14 +912,20 @@ function setParentReportID(parentReportID: string) { /** * Clears out the task info from the store and navigates to the NewTaskDetails page */ -function clearOutTaskInfoAndNavigate(currentUserAccountID: number, reportID?: string, chatReport?: OnyxEntry, accountID = 0, skipConfirmation = false) { +function clearOutTaskInfoAndNavigate( + currentUserAccountID: number, + assigneePersonalDetails?: OnyxTypes.PersonalDetails, + reportID?: string, + chatReport?: OnyxEntry, + skipConfirmation = false, +) { clearOutTaskInfo(skipConfirmation); if (reportID && reportID !== '0') { setParentReportID(reportID); } - if (accountID > 0) { - const accountLogin = allPersonalDetails?.[accountID]?.login ?? ''; - setAssigneeValue(accountLogin, accountID, currentUserAccountID, reportID, chatReport, accountID === currentUserAccountID, skipConfirmation); + const assigneeAccountID = assigneePersonalDetails?.accountID ?? CONST.DEFAULT_NUMBER_ID; + if (assigneePersonalDetails && assigneeAccountID > 0) { + setAssigneeValue(currentUserAccountID, assigneePersonalDetails, reportID, chatReport, assigneeAccountID === currentUserAccountID, skipConfirmation); } Navigation.navigate(ROUTES.NEW_TASK_DETAILS.getRoute(Navigation.getReportRHPActiveRoute())); } @@ -934,12 +933,12 @@ function clearOutTaskInfoAndNavigate(currentUserAccountID: number, reportID?: st /** * Start out create task action quick action step */ -function startOutCreateTaskQuickAction(currentUserAccountID: number, reportID: string, targetAccountID: number) { +function startOutCreateTaskQuickAction(currentUserAccountID: number, reportID: string, targetAccountPersonalDetails: OnyxTypes.PersonalDetails) { // The second parameter of clearOutTaskInfoAndNavigate is the chat report or DM report // between the user and the person to whom the task is assigned. // Since chatReportID isn't stored in NVP_QUICK_ACTION_GLOBAL_CREATE, we set // it to undefined. This will make setAssigneeValue to search for the correct report. - clearOutTaskInfoAndNavigate(currentUserAccountID, reportID, undefined, targetAccountID, true); + clearOutTaskInfoAndNavigate(currentUserAccountID, targetAccountPersonalDetails, reportID, undefined, true); } /** diff --git a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx index f08e161c93fe..5627058eff50 100644 --- a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx +++ b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx @@ -305,7 +305,7 @@ function AttachmentPickerWithMenuItems({ icon: Expensicons.Task, text: translate('newTaskPage.assignTask'), shouldCallAfterModalHide: shouldUseNarrowLayout, - onSelected: () => clearOutTaskInfoAndNavigate(currentUserPersonalDetails.accountID, reportID, report), + onSelected: () => clearOutTaskInfoAndNavigate(currentUserPersonalDetails.accountID, undefined, reportID, report), }, ]; }, [report, translate, shouldUseNarrowLayout, currentUserPersonalDetails.accountID, reportID]); diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index 6ffe045a57ca..559868c2749e 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -144,8 +144,10 @@ function ReportFooter({ if (isValidMention) { assignee = Object.values(allPersonalDetails ?? {}).find((value) => value?.login === mentionWithDomain) ?? undefined; if (!Object.keys(assignee ?? {}).length) { - const assigneeAccountID = generateAccountID(mentionWithDomain); - const optimisticDataForNewAssignee = setNewOptimisticAssignee(mentionWithDomain, assigneeAccountID, personalDetail.accountID); + const optimisticDataForNewAssignee = setNewOptimisticAssignee(personalDetail.accountID, { + accountID: generateAccountID(mentionWithDomain), + login: mentionWithDomain, + }); assignee = optimisticDataForNewAssignee.assignee; assigneeChatReport = optimisticDataForNewAssignee.assigneeReport; } diff --git a/src/pages/home/sidebar/FloatingActionButtonAndPopover.tsx b/src/pages/home/sidebar/FloatingActionButtonAndPopover.tsx index 3d4d759073bd..da9a17aad5b7 100644 --- a/src/pages/home/sidebar/FloatingActionButtonAndPopover.tsx +++ b/src/pages/home/sidebar/FloatingActionButtonAndPopover.tsx @@ -428,7 +428,19 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, ref showDelegateNoAccessModal(); return; } - navigateToQuickAction({isValidReport, quickAction, selectOption, lastDistanceExpenseType, currentUserAccountID: currentUserPersonalDetails.accountID}); + const targetAccountPersonalDetails = { + ...personalDetails?.[quickAction.targetAccountID ?? CONST.DEFAULT_NUMBER_ID], + accountID: quickAction.targetAccountID ?? CONST.DEFAULT_NUMBER_ID, + }; + + navigateToQuickAction({ + isValidReport, + quickAction, + selectOption, + lastDistanceExpenseType, + targetAccountPersonalDetails, + currentUserAccountID: currentUserPersonalDetails.accountID, + }); }); }; return [ @@ -489,6 +501,7 @@ function FloatingActionButtonAndPopover({onHideCreateMenu, onShowCreateMenu, ref isValidReport, selectOption, lastDistanceExpenseType, + personalDetails, currentUserPersonalDetails.accountID, showDelegateNoAccessModal, reportID, diff --git a/src/pages/tasks/TaskAssigneeSelectorModal.tsx b/src/pages/tasks/TaskAssigneeSelectorModal.tsx index 96b23921b8f6..86e31f23e370 100644 --- a/src/pages/tasks/TaskAssigneeSelectorModal.tsx +++ b/src/pages/tasks/TaskAssigneeSelectorModal.tsx @@ -5,6 +5,7 @@ import {InteractionManager, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import {usePersonalDetails} from '@components/OnyxListItemProvider'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionListWithSections'; import type {ListItem} from '@components/SelectionListWithSections/types'; @@ -76,6 +77,8 @@ function TaskAssigneeSelectorModal() { ); }, [optionsWithoutCurrentUser, debouncedSearchTerm, countryCode]); + const allPersonalDetails = usePersonalDetails(); + const report: OnyxEntry = useMemo(() => { if (!route.params?.reportID) { return; @@ -141,13 +144,18 @@ function TaskAssigneeSelectorModal() { return; } + const assigneePersonalDetails = { + ...allPersonalDetails?.[option?.accountID ?? CONST.DEFAULT_NUMBER_ID], + accountID: option.accountID ?? CONST.DEFAULT_NUMBER_ID, + login: option.login ?? '', + }; + // Check to see if we're editing a task and if so, update the assignee if (report) { if (option.accountID !== report.managerID) { const assigneeChatReport = setAssigneeValue( - option?.login ?? '', - option?.accountID ?? CONST.DEFAULT_NUMBER_ID, currentUserPersonalDetails.accountID, + assigneePersonalDetails, report.reportID, undefined, // passing null as report because for editing task the report will be task details report page not the actual report where task was created isCurrentUser({...option, accountID: option?.accountID ?? CONST.DEFAULT_NUMBER_ID, login: option?.login ?? ''}), @@ -169,9 +177,8 @@ function TaskAssigneeSelectorModal() { // If there's no report, we're creating a new task } else if (option.accountID) { setAssigneeValue( - option?.login ?? '', - option.accountID ?? CONST.DEFAULT_NUMBER_ID, currentUserPersonalDetails.accountID, + assigneePersonalDetails, task?.shareDestination ?? '', undefined, // passing null as report is null in this condition isCurrentUser({...option, accountID: option?.accountID ?? CONST.DEFAULT_NUMBER_ID, login: option?.login ?? undefined}), @@ -182,7 +189,7 @@ function TaskAssigneeSelectorModal() { }); } }, - [report, currentUserPersonalDetails.accountID, task?.shareDestination, backTo], + [report, currentUserPersonalDetails.accountID, allPersonalDetails, task?.shareDestination, backTo], ); const handleBackButtonPress = useCallback(() => Navigation.goBack(!route.params?.reportID ? ROUTES.NEW_TASK.getRoute(backTo) : backTo), [route.params, backTo]); diff --git a/tests/unit/QuickActionNavigationTest.ts b/tests/unit/QuickActionNavigationTest.ts index d0faffa18fe6..af64b1146740 100644 --- a/tests/unit/QuickActionNavigationTest.ts +++ b/tests/unit/QuickActionNavigationTest.ts @@ -3,6 +3,7 @@ import {navigateToQuickAction} from '@libs/actions/QuickActionNavigation'; import {startOutCreateTaskQuickAction} from '@libs/actions/Task'; import {generateReportID} from '@libs/ReportUtils'; import CONST from '@src/CONST'; +import createPersonalDetails from '../utils/collections/personalDetails'; jest.mock('@libs/actions/IOU', () => ({ startMoneyRequest: jest.fn(), @@ -28,6 +29,7 @@ describe('IOU Utils', () => { selectOption: (onSelected: () => void) => { onSelected(); }, + targetAccountPersonalDetails: createPersonalDetails(1), currentUserAccountID: CONST.DEFAULT_NUMBER_ID, }); @@ -43,6 +45,7 @@ describe('IOU Utils', () => { selectOption: (onSelected: () => void) => { onSelected(); }, + targetAccountPersonalDetails: createPersonalDetails(1), currentUserAccountID: CONST.DEFAULT_NUMBER_ID, }); @@ -58,6 +61,7 @@ describe('IOU Utils', () => { selectOption: (onSelected: () => void) => { onSelected(); }, + targetAccountPersonalDetails: createPersonalDetails(1), currentUserAccountID: CONST.DEFAULT_NUMBER_ID, }); @@ -73,6 +77,7 @@ describe('IOU Utils', () => { selectOption: (onSelected: () => void) => { onSelected(); }, + targetAccountPersonalDetails: createPersonalDetails(1), currentUserAccountID: CONST.DEFAULT_NUMBER_ID, }); @@ -88,6 +93,7 @@ describe('IOU Utils', () => { selectOption: (onSelected: () => void) => { onSelected(); }, + targetAccountPersonalDetails: createPersonalDetails(1), lastDistanceExpenseType: CONST.IOU.REQUEST_TYPE.DISTANCE_MANUAL, currentUserAccountID: CONST.DEFAULT_NUMBER_ID, }); @@ -104,6 +110,7 @@ describe('IOU Utils', () => { selectOption: (onSelected: () => void) => { onSelected(); }, + targetAccountPersonalDetails: createPersonalDetails(1), currentUserAccountID: CONST.DEFAULT_NUMBER_ID, }); @@ -122,6 +129,7 @@ describe('Non IOU quickActions test:', () => { selectOption: (onSelected: () => void) => { onSelected(); }, + targetAccountPersonalDetails: createPersonalDetails(123), currentUserAccountID: CONST.DEFAULT_NUMBER_ID, }); expect(startOutCreateTaskQuickAction).toHaveBeenCalled();