From 0b621c56628808b35fe8b5b6a9b1589eb556245a Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Fri, 13 Sep 2024 13:38:46 +0100 Subject: [PATCH 01/18] Fix Report Names --- src/libs/ReportUtils.ts | 2 +- src/pages/home/report/ReportActionItemSingle.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 7001dedea2f1..28e3038a0503 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -7527,7 +7527,7 @@ function canLeaveChat(report: OnyxEntry, policy: OnyxEntry): boo function getReportActionActorAccountID(reportAction: OnyxInputOrEntry, iouReport: OnyxInputOrEntry | undefined): number | undefined { switch (reportAction?.actionName) { case CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW: - return !isEmptyObject(iouReport) ? iouReport.managerID : reportAction?.childManagerAccountID; + return !isEmptyObject(iouReport) ? reportAction?.actorAccountID : reportAction?.childManagerAccountID; case CONST.REPORT.ACTIONS.TYPE.SUBMITTED: return reportAction?.adminAccountID ?? reportAction?.actorAccountID; diff --git a/src/pages/home/report/ReportActionItemSingle.tsx b/src/pages/home/report/ReportActionItemSingle.tsx index 95a7332f0606..f9cf1346f20b 100644 --- a/src/pages/home/report/ReportActionItemSingle.tsx +++ b/src/pages/home/report/ReportActionItemSingle.tsx @@ -90,7 +90,7 @@ function ReportActionItemSingle({ let actorHint = (login || (displayName ?? '')).replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, ''); const isTripRoom = ReportUtils.isTripRoom(report); const isReportPreviewAction = action?.actionName === CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW; - const displayAllActors = isReportPreviewAction && !isTripRoom; + const displayAllActors = isReportPreviewAction && !isTripRoom && ReportUtils.isIOUReport(iouReport ?? null); const isInvoiceReport = ReportUtils.isInvoiceReport(iouReport ?? null); const isWorkspaceActor = isInvoiceReport || (ReportUtils.isPolicyExpenseChat(report) && (!actorAccountID || displayAllActors)); const ownerAccountID = iouReport?.ownerAccountID ?? action?.childOwnerAccountID; From dbd5314a38449d5e6d7a7b05591c5e8b1c9ec0bc Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Fri, 13 Sep 2024 15:18:50 +0100 Subject: [PATCH 02/18] use .childOwnerAccountID instead --- src/libs/ReportUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 28e3038a0503..668a349b2144 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -7527,7 +7527,7 @@ function canLeaveChat(report: OnyxEntry, policy: OnyxEntry): boo function getReportActionActorAccountID(reportAction: OnyxInputOrEntry, iouReport: OnyxInputOrEntry | undefined): number | undefined { switch (reportAction?.actionName) { case CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW: - return !isEmptyObject(iouReport) ? reportAction?.actorAccountID : reportAction?.childManagerAccountID; + return !isEmptyObject(iouReport) ? reportAction?.childOwnerAccountID : reportAction?.childManagerAccountID; case CONST.REPORT.ACTIONS.TYPE.SUBMITTED: return reportAction?.adminAccountID ?? reportAction?.actorAccountID; From 149e14393fabb3ca95c546743be2e6800b5d5822 Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Fri, 13 Sep 2024 16:24:30 +0100 Subject: [PATCH 03/18] remove check --- src/libs/ReportUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 668a349b2144..dd68522114a0 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -7527,7 +7527,7 @@ function canLeaveChat(report: OnyxEntry, policy: OnyxEntry): boo function getReportActionActorAccountID(reportAction: OnyxInputOrEntry, iouReport: OnyxInputOrEntry | undefined): number | undefined { switch (reportAction?.actionName) { case CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW: - return !isEmptyObject(iouReport) ? reportAction?.childOwnerAccountID : reportAction?.childManagerAccountID; + return reportAction?.childOwnerAccountID ?? reportAction?.actorAccountID; case CONST.REPORT.ACTIONS.TYPE.SUBMITTED: return reportAction?.adminAccountID ?? reportAction?.actorAccountID; From 1abbebe42aa277874f33c5089730d23423f46c77 Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Tue, 17 Sep 2024 18:42:34 +0100 Subject: [PATCH 04/18] Add multi-user reportpreview displayname --- .../home/report/ReportActionItemSingle.tsx | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/pages/home/report/ReportActionItemSingle.tsx b/src/pages/home/report/ReportActionItemSingle.tsx index 2b44d8daa4b3..95aa00771ad8 100644 --- a/src/pages/home/report/ReportActionItemSingle.tsx +++ b/src/pages/home/report/ReportActionItemSingle.tsx @@ -83,8 +83,8 @@ function ReportActionItemSingle({ const personalDetails = usePersonalDetails() ?? CONST.EMPTY_OBJECT; const actorAccountID = ReportUtils.getReportActionActorAccountID(action, iouReport); const [invoiceReceiverPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report.invoiceReceiver && 'policyID' in report.invoiceReceiver ? report.invoiceReceiver.policyID : -1}`); - let displayName = ReportUtils.getDisplayNameForParticipant(actorAccountID); + const {avatar, login, pendingFields, status, fallbackIcon} = personalDetails[actorAccountID ?? -1] ?? {}; // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing let actorHint = (login || (displayName ?? '')).replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, ''); @@ -94,6 +94,7 @@ function ReportActionItemSingle({ const isInvoiceReport = ReportUtils.isInvoiceReport(iouReport ?? null); const isWorkspaceActor = isInvoiceReport || (ReportUtils.isPolicyExpenseChat(report) && (!actorAccountID || displayAllActors)); const ownerAccountID = iouReport?.ownerAccountID ?? action?.childOwnerAccountID; + const managerID = iouReport?.managerID ?? action?.childManagerAccountID; let avatarSource = avatar; let avatarId: number | string | undefined = actorAccountID; @@ -130,7 +131,7 @@ function ReportActionItemSingle({ }; } else { // The ownerAccountID and actorAccountID can be the same if a user submits an expense back from the IOU's original creator, in that case we need to use managerID to avoid displaying the same user twice - const secondaryAccountId = ownerAccountID === actorAccountID || isInvoiceReport ? actorAccountID : ownerAccountID; + const secondaryAccountId = ownerAccountID === actorAccountID || isInvoiceReport ? managerID : ownerAccountID; const secondaryUserAvatar = personalDetails?.[secondaryAccountId ?? -1]?.avatar ?? FallbackAvatar; const secondaryDisplayName = ReportUtils.getDisplayNameForParticipant(secondaryAccountId); @@ -165,9 +166,25 @@ function ReportActionItemSingle({ { type: 'TEXT', text: displayName, + accountID: actorAccountID, }, ] - : action?.person; + : action?.person ?? []; + + if (displayAllActors && secondaryAvatar.name) { + personArray.push( + { + type: 'TEXT', + text: ' & ', + accountID: -1, + }, + { + type: 'TEXT', + text: secondaryAvatar.name ?? '', + accountID: parseInt(secondaryAvatar?.id?.toString() ?? '-1', 10) ?? -1, + }, + ); + } const reportID = report?.reportID; const iouReportID = iouReport?.reportID; @@ -231,6 +248,7 @@ function ReportActionItemSingle({ ); }; + const hasEmojiStatus = !displayAllActors && status?.emojiCode; const formattedDate = DateUtils.getStatusUntilDate(status?.clearAfter ?? ''); const statusText = status?.text ?? ''; @@ -261,18 +279,21 @@ function ReportActionItemSingle({ accessibilityLabel={actorHint} role={CONST.ROLE.BUTTON} > - {personArray?.map((fragment, index) => ( - - ))} + + {personArray?.map((fragment, index) => ( + + ))} + {!!hasEmojiStatus && ( @@ -290,7 +311,6 @@ function ReportActionItemSingle({ ); } - ReportActionItemSingle.displayName = 'ReportActionItemSingle'; export default ReportActionItemSingle; From 97e31a0cceeb4f8563ebbb05147c16308b96a89f Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Wed, 18 Sep 2024 13:52:17 +0100 Subject: [PATCH 05/18] clean up --- .../home/report/ReportActionItemSingle.tsx | 87 +++++++++++++------ 1 file changed, 59 insertions(+), 28 deletions(-) diff --git a/src/pages/home/report/ReportActionItemSingle.tsx b/src/pages/home/report/ReportActionItemSingle.tsx index 95aa00771ad8..8dcbcd180273 100644 --- a/src/pages/home/report/ReportActionItemSingle.tsx +++ b/src/pages/home/report/ReportActionItemSingle.tsx @@ -166,24 +166,15 @@ function ReportActionItemSingle({ { type: 'TEXT', text: displayName, - accountID: actorAccountID, }, ] : action?.person ?? []; if (displayAllActors && secondaryAvatar.name) { - personArray.push( - { - type: 'TEXT', - text: ' & ', - accountID: -1, - }, - { - type: 'TEXT', - text: secondaryAvatar.name ?? '', - accountID: parseInt(secondaryAvatar?.id?.toString() ?? '-1', 10) ?? -1, - }, - ); + personArray.push({ + type: 'TEXT', + text: secondaryAvatar.name ?? '', + }); } const reportID = report?.reportID; @@ -249,6 +240,60 @@ function ReportActionItemSingle({ ); }; + const getHeading = () => { + if (displayAllActors && secondaryAvatar.name) { + return ( + + + + {` & `} + + + + ); + } + return ( + + {personArray?.map((fragment, index) => ( + + ))} + + ); + }; + const hasEmojiStatus = !displayAllActors && status?.emojiCode; const formattedDate = DateUtils.getStatusUntilDate(status?.clearAfter ?? ''); const statusText = status?.text ?? ''; @@ -279,21 +324,7 @@ function ReportActionItemSingle({ accessibilityLabel={actorHint} role={CONST.ROLE.BUTTON} > - - {personArray?.map((fragment, index) => ( - - ))} - + {getHeading()} {!!hasEmojiStatus && ( From 175b400b6da35189728a3a42aded2b8bc14b1c9e Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Wed, 18 Sep 2024 13:57:03 +0100 Subject: [PATCH 06/18] useMemo for the helper functions --- .../home/report/ReportActionItemSingle.tsx | 201 ++++++++++-------- 1 file changed, 114 insertions(+), 87 deletions(-) diff --git a/src/pages/home/report/ReportActionItemSingle.tsx b/src/pages/home/report/ReportActionItemSingle.tsx index 8dcbcd180273..1128bbb781b6 100644 --- a/src/pages/home/report/ReportActionItemSingle.tsx +++ b/src/pages/home/report/ReportActionItemSingle.tsx @@ -200,99 +200,126 @@ function ReportActionItemSingle({ [action, isWorkspaceActor, actorAccountID], ); - const getAvatar = () => { - if (displayAllActors) { - return ( - - ); - } - if (shouldShowSubscriptAvatar) { + const getAvatar = useMemo(() => { + return () => { + if (displayAllActors) { + return ( + + ); + } + if (shouldShowSubscriptAvatar) { + return ( + + ); + } return ( - + + + + + ); - } - return ( - - - - - - ); - }; + }; + }, [ + displayAllActors, + shouldShowSubscriptAvatar, + actorAccountID, + action?.delegateAccountID, + icon, + styles.actionAvatar, + fallbackIcon, + secondaryAvatar, + StyleUtils, + theme.appBG, + theme.hoverComponentBG, + isHovered, + ]); - const getHeading = () => { - if (displayAllActors && secondaryAvatar.name) { + const getHeading = useMemo(() => { + return () => { + if (displayAllActors && secondaryAvatar.name && isReportPreviewAction) { + return ( + + + + {` & `} + + + + ); + } return ( - - - - {` & `} - - + + {personArray?.map((fragment) => ( + + ))} ); - } - return ( - - {personArray?.map((fragment, index) => ( - - ))} - - ); - }; + }; + }, [ + displayAllActors, + secondaryAvatar, + isReportPreviewAction, + personArray, + styles.flexRow, + styles.flex1, + styles.chatItemMessageHeaderSender, + styles.pre, + action, + actorAccountID, + displayName, + icon, + ]); const hasEmojiStatus = !displayAllActors && status?.emojiCode; const formattedDate = DateUtils.getStatusUntilDate(status?.clearAfter ?? ''); From 4e616e1730882c1f3557fb8e2c7ef53b2ac95be2 Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Wed, 18 Sep 2024 14:14:05 +0100 Subject: [PATCH 07/18] clean up --- .../home/report/ReportActionItemSingle.tsx | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/pages/home/report/ReportActionItemSingle.tsx b/src/pages/home/report/ReportActionItemSingle.tsx index 1128bbb781b6..b537aee5f9b2 100644 --- a/src/pages/home/report/ReportActionItemSingle.tsx +++ b/src/pages/home/report/ReportActionItemSingle.tsx @@ -151,31 +151,41 @@ function ReportActionItemSingle({ } else { secondaryAvatar = {name: '', source: '', type: 'avatar'}; } - const icon = { - source: avatarSource ?? FallbackAvatar, - type: isWorkspaceActor ? CONST.ICON_TYPE_WORKSPACE : CONST.ICON_TYPE_AVATAR, - name: primaryDisplayName ?? '', - id: avatarId, - }; + + const icon = useMemo( + () => ({ + source: avatarSource ?? FallbackAvatar, + type: isWorkspaceActor ? CONST.ICON_TYPE_WORKSPACE : CONST.ICON_TYPE_AVATAR, + name: primaryDisplayName ?? '', + id: avatarId, + }), + [avatarSource, isWorkspaceActor, primaryDisplayName, avatarId], + ); // Since the display name for a report action message is delivered with the report history as an array of fragments // we'll need to take the displayName from personal details and have it be in the same format for now. Eventually, // we should stop referring to the report history items entirely for this information. - const personArray = displayName - ? [ - { - type: 'TEXT', - text: displayName, - }, - ] - : action?.person ?? []; + const personArray = useMemo(() => { + const baseArray = displayName + ? [ + { + type: 'TEXT', + text: displayName, + }, + ] + : action?.person ?? []; - if (displayAllActors && secondaryAvatar.name) { - personArray.push({ - type: 'TEXT', - text: secondaryAvatar.name ?? '', - }); - } + if (displayAllActors && secondaryAvatar?.name) { + return [ + ...baseArray, + { + type: 'TEXT', + text: secondaryAvatar.name ?? '', + }, + ]; + } + return baseArray; + }, [displayName, action?.person, displayAllActors, secondaryAvatar?.name]); const reportID = report?.reportID; const iouReportID = iouReport?.reportID; @@ -370,5 +380,4 @@ function ReportActionItemSingle({ ); } ReportActionItemSingle.displayName = 'ReportActionItemSingle'; - export default ReportActionItemSingle; From e81f87e97491897262c55a7751c290d5f0b3c538 Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Thu, 19 Sep 2024 12:26:47 +0100 Subject: [PATCH 08/18] Match report header to report preview avatars --- src/libs/ReportUtils.ts | 4 ++-- src/pages/home/report/ReportActionItemSingle.tsx | 15 +++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 87dddb096a0c..9621ac5acd06 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1605,7 +1605,7 @@ function hasOnlyNonReimbursableTransactions(iouReportID: string | undefined): bo */ function isOneTransactionReport(reportID: string): boolean { const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`] ?? ([] as ReportAction[]); - return ReportActionsUtils.getOneTransactionThreadReportID(reportID, reportActions) !== null; + return !!ReportActionsUtils.getOneTransactionThreadReportID(reportID, reportActions); } /* @@ -6657,7 +6657,7 @@ function shouldReportShowSubscript(report: OnyxEntry): boolean { return true; } - if (isExpenseReport(report) && isOneTransactionReport(report?.reportID ?? '-1')) { + if (isExpenseReport(report)) { return true; } diff --git a/src/pages/home/report/ReportActionItemSingle.tsx b/src/pages/home/report/ReportActionItemSingle.tsx index b537aee5f9b2..0c1367646d1a 100644 --- a/src/pages/home/report/ReportActionItemSingle.tsx +++ b/src/pages/home/report/ReportActionItemSingle.tsx @@ -84,13 +84,13 @@ function ReportActionItemSingle({ const actorAccountID = ReportUtils.getReportActionActorAccountID(action, iouReport); const [invoiceReceiverPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report.invoiceReceiver && 'policyID' in report.invoiceReceiver ? report.invoiceReceiver.policyID : -1}`); let displayName = ReportUtils.getDisplayNameForParticipant(actorAccountID); - + const icons = ReportUtils.getIcons(iouReport ?? null, personalDetails); const {avatar, login, pendingFields, status, fallbackIcon} = personalDetails[actorAccountID ?? -1] ?? {}; // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing let actorHint = (login || (displayName ?? '')).replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, ''); const isTripRoom = ReportUtils.isTripRoom(report); const isReportPreviewAction = action?.actionName === CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW; - const displayAllActors = isReportPreviewAction && !isTripRoom && ReportUtils.isIOUReport(iouReport ?? null); + const displayAllActors = isReportPreviewAction && !isTripRoom && ReportUtils.isIOUReport(iouReport ?? null) && icons.length > 1; const isInvoiceReport = ReportUtils.isInvoiceReport(iouReport ?? null); const isWorkspaceActor = isInvoiceReport || (ReportUtils.isPolicyExpenseChat(report) && (!actorAccountID || displayAllActors)); const ownerAccountID = iouReport?.ownerAccountID ?? action?.childOwnerAccountID; @@ -134,7 +134,6 @@ function ReportActionItemSingle({ const secondaryAccountId = ownerAccountID === actorAccountID || isInvoiceReport ? managerID : ownerAccountID; const secondaryUserAvatar = personalDetails?.[secondaryAccountId ?? -1]?.avatar ?? FallbackAvatar; const secondaryDisplayName = ReportUtils.getDisplayNameForParticipant(secondaryAccountId); - secondaryAvatar = { source: secondaryUserAvatar, type: CONST.ICON_TYPE_AVATAR, @@ -175,7 +174,7 @@ function ReportActionItemSingle({ ] : action?.person ?? []; - if (displayAllActors && secondaryAvatar?.name) { + if (displayAllActors) { return [ ...baseArray, { @@ -215,7 +214,7 @@ function ReportActionItemSingle({ if (displayAllActors) { return ( ); @@ -258,11 +257,11 @@ function ReportActionItemSingle({ icon, styles.actionAvatar, fallbackIcon, - secondaryAvatar, StyleUtils, theme.appBG, theme.hoverComponentBG, isHovered, + icons, ]); const getHeading = useMemo(() => { From cc25e240b50328b79be3bd8e3af65220bb81a413 Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Thu, 19 Sep 2024 13:18:46 +0100 Subject: [PATCH 09/18] clean up subscript --- src/pages/home/report/ReportActionItemSingle.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionItemSingle.tsx b/src/pages/home/report/ReportActionItemSingle.tsx index 0c1367646d1a..1681734bd81f 100644 --- a/src/pages/home/report/ReportActionItemSingle.tsx +++ b/src/pages/home/report/ReportActionItemSingle.tsx @@ -225,8 +225,9 @@ function ReportActionItemSingle({ return ( ); } From 14e95b2db8375c632ab81d610fb5bb628ddef25b Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Thu, 19 Sep 2024 13:53:06 +0100 Subject: [PATCH 10/18] fix eslint #1 --- src/libs/ReportUtils.ts | 4 ++-- src/pages/home/report/ReportActionItemSingle.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 9621ac5acd06..51edeffb5422 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2226,7 +2226,7 @@ function getIcons( if (isChatThread(report)) { const parentReportAction = ReportActionsUtils.getParentReportAction(report); - const actorAccountID = getReportActionActorAccountID(parentReportAction, report); + const actorAccountID = getReportActionActorAccountID(parentReportAction); const actorDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(allPersonalDetails?.[actorAccountID ?? -1], '', false); const actorIcon = { id: actorAccountID, @@ -7551,7 +7551,7 @@ function canLeaveChat(report: OnyxEntry, policy: OnyxEntry): boo return (isChatThread(report) && !!getReportNotificationPreference(report)) || isUserCreatedPolicyRoom(report) || isNonAdminOrOwnerOfPolicyExpenseChat(report, policy); } -function getReportActionActorAccountID(reportAction: OnyxInputOrEntry, iouReport: OnyxInputOrEntry | undefined): number | undefined { +function getReportActionActorAccountID(reportAction: OnyxInputOrEntry): number | undefined { switch (reportAction?.actionName) { case CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW: return reportAction?.childOwnerAccountID ?? reportAction?.actorAccountID; diff --git a/src/pages/home/report/ReportActionItemSingle.tsx b/src/pages/home/report/ReportActionItemSingle.tsx index 1681734bd81f..d61f7d67f6f8 100644 --- a/src/pages/home/report/ReportActionItemSingle.tsx +++ b/src/pages/home/report/ReportActionItemSingle.tsx @@ -81,7 +81,7 @@ function ReportActionItemSingle({ const StyleUtils = useStyleUtils(); const {translate} = useLocalize(); const personalDetails = usePersonalDetails() ?? CONST.EMPTY_OBJECT; - const actorAccountID = ReportUtils.getReportActionActorAccountID(action, iouReport); + const actorAccountID = ReportUtils.getReportActionActorAccountID(action); const [invoiceReceiverPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report.invoiceReceiver && 'policyID' in report.invoiceReceiver ? report.invoiceReceiver.policyID : -1}`); let displayName = ReportUtils.getDisplayNameForParticipant(actorAccountID); const icons = ReportUtils.getIcons(iouReport ?? null, personalDetails); From 72149001d86b9d5120c28209c2bb6ba5343f020b Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Thu, 19 Sep 2024 14:08:51 +0100 Subject: [PATCH 11/18] Fix lint --- src/pages/home/report/ReportActionItemSingle.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionItemSingle.tsx b/src/pages/home/report/ReportActionItemSingle.tsx index d61f7d67f6f8..afeb317da49b 100644 --- a/src/pages/home/report/ReportActionItemSingle.tsx +++ b/src/pages/home/report/ReportActionItemSingle.tsx @@ -258,11 +258,13 @@ function ReportActionItemSingle({ icon, styles.actionAvatar, fallbackIcon, + icons, StyleUtils, theme.appBG, theme.hoverComponentBG, + theme.componentBG, isHovered, - icons, + secondaryAvatar, ]); const getHeading = useMemo(() => { From 52fd8e096787646b8925b1b5261de40d05e9a3ca Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Thu, 19 Sep 2024 21:27:03 +0100 Subject: [PATCH 12/18] add support for reports with multiple expenses with one sender --- src/libs/ReportActionsUtils.ts | 47 ++++++++++++++++++++++++++++------ src/libs/ReportUtils.ts | 11 +++++++- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index f584f694edd0..a8b5f07b7640 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -994,20 +994,20 @@ const iouRequestTypes = new Set>([ CONST.IOU.REPORT_ACTION_TYPE.TRACK, ]); -/** - * Gets the reportID for the transaction thread associated with a report by iterating over the reportActions and identifying the IOU report actions. - * Returns a reportID if there is exactly one transaction thread for the report, and null otherwise. - */ -function getOneTransactionThreadReportID(reportID: string, reportActions: OnyxEntry | ReportAction[], isOffline: boolean | undefined = undefined): string | undefined { - // If the report is not an IOU, Expense report, or Invoice, it shouldn't be treated as one-transaction report. +function getMoneyRequestActions( + reportID: string, + reportActions: OnyxEntry | ReportAction[], + isOffline: boolean | undefined = undefined, +): Array> { + // If the report is not an IOU, Expense report, or Invoice, it shouldn't have money request actions. const report = ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; if (report?.type !== CONST.REPORT.TYPE.IOU && report?.type !== CONST.REPORT.TYPE.EXPENSE && report?.type !== CONST.REPORT.TYPE.INVOICE) { - return; + return []; } const reportActionsArray = Array.isArray(reportActions) ? reportActions : Object.values(reportActions ?? {}); if (!reportActionsArray.length) { - return; + return []; } const iouRequestActions = []; @@ -1035,6 +1035,15 @@ function getOneTransactionThreadReportID(reportID: string, reportActions: OnyxEn iouRequestActions.push(action); } } + return iouRequestActions; +} + +/** + * Gets the reportID for the transaction thread associated with a report by iterating over the reportActions and identifying the IOU report actions. + * Returns a reportID if there is exactly one transaction thread for the report, and null otherwise. + */ +function getOneTransactionThreadReportID(reportID: string, reportActions: OnyxEntry | ReportAction[], isOffline: boolean | undefined = undefined): string | undefined { + const iouRequestActions = getMoneyRequestActions(reportID, reportActions, isOffline); // If we don't have any IOU request actions, or we have more than one IOU request actions, this isn't a oneTransaction report if (!iouRequestActions.length || iouRequestActions.length > 1) { @@ -1054,6 +1063,27 @@ function getOneTransactionThreadReportID(reportID: string, reportActions: OnyxEn return singleAction.childReportID; } +/** + * Returns true if all transactions on the report have the same ownerID + */ +function isSingleActorMoneyReport(reportID: string, reportActions: OnyxEntry | ReportAction[], isOffline: boolean | undefined = undefined): boolean { + const iouRequestActions = getMoneyRequestActions(reportID, reportActions, isOffline); + if (!iouRequestActions.length) { + return true; + } + + let actorID: number | undefined; + + for (const action of iouRequestActions) { + if (actorID !== undefined && actorID !== action?.actorAccountID) { + return false; + } + actorID = action?.actorAccountID; + } + + return true; +} + /** * When we delete certain reports, we want to check whether there are any visible actions left to display. * If there are no visible actions left (including system messages), we can hide the report from view entirely @@ -1834,6 +1864,7 @@ export { getRenamedAction, isCardIssuedAction, getCardIssuedMessage, + isSingleActorMoneyReport, }; export type {LastVisibleMessage}; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 345ad56c01a9..a89c9b7be9f5 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1601,6 +1601,14 @@ function hasOnlyNonReimbursableTransactions(iouReportID: string | undefined): bo return transactions.every((transaction) => !TransactionUtils.getReimbursable(transaction)); } +/** + * Checks if a report has only transactions with different owners + */ +function isSingleOwnerReport(reportID: string): boolean { + const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`] ?? ([] as ReportAction[]); + return !!ReportActionsUtils.isSingleActorMoneyReport(reportID, reportActions); +} + /** * Checks if a report has only one transaction associated with it */ @@ -2322,7 +2330,7 @@ function getIcons( const isManager = currentUserAccountID === report?.managerID; // For one transaction IOUs, display a simplified report icon - if (isOneTransactionReport(report?.reportID ?? '-1')) { + if (isOneTransactionReport(report?.reportID ?? '-1') || isSingleOwnerReport(report?.reportID ?? '-1')) { return [ownerIcon]; } @@ -8137,6 +8145,7 @@ export { isIndividualInvoiceRoom, isAuditor, hasMissingInvoiceBankAccount, + isSingleOwnerReport, }; export type { From 66345a4c7cf57aadb8e3e5854861577797d444a5 Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Thu, 19 Sep 2024 21:30:44 +0100 Subject: [PATCH 13/18] function rename --- src/libs/ReportActionsUtils.ts | 4 ++-- src/libs/ReportUtils.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index a8b5f07b7640..37920fad0a4c 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -1066,7 +1066,7 @@ function getOneTransactionThreadReportID(reportID: string, reportActions: OnyxEn /** * Returns true if all transactions on the report have the same ownerID */ -function isSingleActorMoneyReport(reportID: string, reportActions: OnyxEntry | ReportAction[], isOffline: boolean | undefined = undefined): boolean { +function isSingleActorForAllTransactions(reportID: string, reportActions: OnyxEntry | ReportAction[], isOffline: boolean | undefined = undefined): boolean { const iouRequestActions = getMoneyRequestActions(reportID, reportActions, isOffline); if (!iouRequestActions.length) { return true; @@ -1864,7 +1864,7 @@ export { getRenamedAction, isCardIssuedAction, getCardIssuedMessage, - isSingleActorMoneyReport, + isSingleActorForAllTransactions, }; export type {LastVisibleMessage}; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a89c9b7be9f5..5368afc11c3f 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1606,7 +1606,7 @@ function hasOnlyNonReimbursableTransactions(iouReportID: string | undefined): bo */ function isSingleOwnerReport(reportID: string): boolean { const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`] ?? ([] as ReportAction[]); - return !!ReportActionsUtils.isSingleActorMoneyReport(reportID, reportActions); + return !!ReportActionsUtils.isSingleActorForAllTransactions(reportID, reportActions); } /** From 9da4550457a42c432dea40f46ffa51ee8fb31042 Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Fri, 20 Sep 2024 10:22:10 +0100 Subject: [PATCH 14/18] function rename --- src/libs/ReportActionsUtils.ts | 4 ++-- src/libs/ReportUtils.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index 37920fad0a4c..a268b41eea0a 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -1066,7 +1066,7 @@ function getOneTransactionThreadReportID(reportID: string, reportActions: OnyxEn /** * Returns true if all transactions on the report have the same ownerID */ -function isSingleActorForAllTransactions(reportID: string, reportActions: OnyxEntry | ReportAction[], isOffline: boolean | undefined = undefined): boolean { +function hasSameActorForAllTransactions(reportID: string, reportActions: OnyxEntry | ReportAction[], isOffline: boolean | undefined = undefined): boolean { const iouRequestActions = getMoneyRequestActions(reportID, reportActions, isOffline); if (!iouRequestActions.length) { return true; @@ -1864,7 +1864,7 @@ export { getRenamedAction, isCardIssuedAction, getCardIssuedMessage, - isSingleActorForAllTransactions, + hasSameActorForAllTransactions, }; export type {LastVisibleMessage}; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 5368afc11c3f..b41bf1e07daa 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1604,9 +1604,9 @@ function hasOnlyNonReimbursableTransactions(iouReportID: string | undefined): bo /** * Checks if a report has only transactions with different owners */ -function isSingleOwnerReport(reportID: string): boolean { +function isSingleActorMoneyReport(reportID: string): boolean { const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`] ?? ([] as ReportAction[]); - return !!ReportActionsUtils.isSingleActorForAllTransactions(reportID, reportActions); + return !!ReportActionsUtils.hasSameActorForAllTransactions(reportID, reportActions); } /** @@ -2330,7 +2330,7 @@ function getIcons( const isManager = currentUserAccountID === report?.managerID; // For one transaction IOUs, display a simplified report icon - if (isOneTransactionReport(report?.reportID ?? '-1') || isSingleOwnerReport(report?.reportID ?? '-1')) { + if (isOneTransactionReport(report?.reportID ?? '-1') || isSingleActorMoneyReport(report?.reportID ?? '-1')) { return [ownerIcon]; } @@ -8145,7 +8145,7 @@ export { isIndividualInvoiceRoom, isAuditor, hasMissingInvoiceBankAccount, - isSingleOwnerReport, + isSingleActorMoneyReport, }; export type { From 8147b15155bfdb172e17438d96f7603d78fe2975 Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Tue, 24 Sep 2024 12:08:16 +0100 Subject: [PATCH 15/18] fix invoice icon --- src/CONST.ts | 2 +- src/libs/ReportUtils.ts | 2 +- src/pages/home/report/ReportActionsListItemRenderer.tsx | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 9ee9ec4d9147..debbb3ce658a 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -171,7 +171,7 @@ const CONST = { }, // Note: Group and Self-DM excluded as these are not tied to a Workspace - WORKSPACE_ROOM_TYPES: [chatTypes.POLICY_ADMINS, chatTypes.POLICY_ANNOUNCE, chatTypes.DOMAIN_ALL, chatTypes.POLICY_ROOM, chatTypes.POLICY_EXPENSE_CHAT], + WORKSPACE_ROOM_TYPES: [chatTypes.POLICY_ADMINS, chatTypes.POLICY_ANNOUNCE, chatTypes.DOMAIN_ALL, chatTypes.POLICY_ROOM, chatTypes.POLICY_EXPENSE_CHAT, chatTypes.INVOICE], ANDROID_PACKAGE_NAME, WORKSPACE_ENABLE_FEATURE_REDIRECT_DELAY: 100, ANIMATED_HIGHLIGHT_ENTRY_DELAY: 50, diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a4d835112857..b216160ca52c 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -6664,7 +6664,7 @@ function shouldReportShowSubscript(report: OnyxEntry): boolean { return true; } - if (isInvoiceRoom(report)) { + if (isInvoiceRoom(report) || isInvoiceReport(report)) { return true; } diff --git a/src/pages/home/report/ReportActionsListItemRenderer.tsx b/src/pages/home/report/ReportActionsListItemRenderer.tsx index 48c578fd743a..7115238ef98b 100644 --- a/src/pages/home/report/ReportActionsListItemRenderer.tsx +++ b/src/pages/home/report/ReportActionsListItemRenderer.tsx @@ -171,6 +171,14 @@ function ReportActionsListItemRenderer({ shouldDisplayNewMarker={shouldDisplayNewMarker} shouldShowSubscriptAvatar={ ReportUtils.isPolicyExpenseChat(report) && + [ + CONST.REPORT.ACTIONS.TYPE.IOU, + CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW, + CONST.REPORT.ACTIONS.TYPE.SUBMITTED, + CONST.REPORT.ACTIONS.TYPE.APPROVED, + CONST.REPORT.ACTIONS.TYPE.FORWARDED, + ].some((type) => type === reportAction.actionName) || + ReportUtils.isInvoiceRoom(report) && [ CONST.REPORT.ACTIONS.TYPE.IOU, CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW, From df55001359ca7d65725d6185d4044094e3678bbd Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Tue, 24 Sep 2024 12:55:44 +0100 Subject: [PATCH 16/18] prettier --- .../report/ReportActionsListItemRenderer.tsx | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/pages/home/report/ReportActionsListItemRenderer.tsx b/src/pages/home/report/ReportActionsListItemRenderer.tsx index 7115238ef98b..383c253121bf 100644 --- a/src/pages/home/report/ReportActionsListItemRenderer.tsx +++ b/src/pages/home/report/ReportActionsListItemRenderer.tsx @@ -170,22 +170,22 @@ function ReportActionsListItemRenderer({ displayAsGroup={displayAsGroup} shouldDisplayNewMarker={shouldDisplayNewMarker} shouldShowSubscriptAvatar={ - ReportUtils.isPolicyExpenseChat(report) && - [ - CONST.REPORT.ACTIONS.TYPE.IOU, - CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW, - CONST.REPORT.ACTIONS.TYPE.SUBMITTED, - CONST.REPORT.ACTIONS.TYPE.APPROVED, - CONST.REPORT.ACTIONS.TYPE.FORWARDED, - ].some((type) => type === reportAction.actionName) || - ReportUtils.isInvoiceRoom(report) && - [ - CONST.REPORT.ACTIONS.TYPE.IOU, - CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW, - CONST.REPORT.ACTIONS.TYPE.SUBMITTED, - CONST.REPORT.ACTIONS.TYPE.APPROVED, - CONST.REPORT.ACTIONS.TYPE.FORWARDED, - ].some((type) => type === reportAction.actionName) + (ReportUtils.isPolicyExpenseChat(report) && + [ + CONST.REPORT.ACTIONS.TYPE.IOU, + CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW, + CONST.REPORT.ACTIONS.TYPE.SUBMITTED, + CONST.REPORT.ACTIONS.TYPE.APPROVED, + CONST.REPORT.ACTIONS.TYPE.FORWARDED, + ].some((type) => type === reportAction.actionName)) || + (ReportUtils.isInvoiceRoom(report) && + [ + CONST.REPORT.ACTIONS.TYPE.IOU, + CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW, + CONST.REPORT.ACTIONS.TYPE.SUBMITTED, + CONST.REPORT.ACTIONS.TYPE.APPROVED, + CONST.REPORT.ACTIONS.TYPE.FORWARDED, + ].some((type) => type === reportAction.actionName)) } isMostRecentIOUReportAction={reportAction.reportActionID === mostRecentIOUReportActionID} index={index} From 65bf81dbf231ebac48a23f7591d75dc5074ce2e7 Mon Sep 17 00:00:00 2001 From: Georgia Monahan <38015950+grgia@users.noreply.github.com> Date: Wed, 25 Sep 2024 14:07:37 +0100 Subject: [PATCH 17/18] Apply suggestions from code review Co-authored-by: Eric Han <117511920+eh2077@users.noreply.github.com> --- src/libs/ReportUtils.ts | 2 +- .../report/ReportActionsListItemRenderer.tsx | 24 +++++++------------ 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index e443a02b8fda..7c72d3d55b16 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1581,7 +1581,7 @@ function hasOnlyNonReimbursableTransactions(iouReportID: string | undefined): bo } /** - * Checks if a report has only transactions with different owners + * Checks if a report has only transactions with same ownerID */ function isSingleActorMoneyReport(reportID: string): boolean { const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`] ?? ([] as ReportAction[]); diff --git a/src/pages/home/report/ReportActionsListItemRenderer.tsx b/src/pages/home/report/ReportActionsListItemRenderer.tsx index ff240da27047..63b2cb43d836 100644 --- a/src/pages/home/report/ReportActionsListItemRenderer.tsx +++ b/src/pages/home/report/ReportActionsListItemRenderer.tsx @@ -171,22 +171,14 @@ function ReportActionsListItemRenderer({ displayAsGroup={displayAsGroup} shouldDisplayNewMarker={shouldDisplayNewMarker} shouldShowSubscriptAvatar={ - (ReportUtils.isPolicyExpenseChat(report) && - [ - CONST.REPORT.ACTIONS.TYPE.IOU, - CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW, - CONST.REPORT.ACTIONS.TYPE.SUBMITTED, - CONST.REPORT.ACTIONS.TYPE.APPROVED, - CONST.REPORT.ACTIONS.TYPE.FORWARDED, - ].some((type) => type === reportAction.actionName)) || - (ReportUtils.isInvoiceRoom(report) && - [ - CONST.REPORT.ACTIONS.TYPE.IOU, - CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW, - CONST.REPORT.ACTIONS.TYPE.SUBMITTED, - CONST.REPORT.ACTIONS.TYPE.APPROVED, - CONST.REPORT.ACTIONS.TYPE.FORWARDED, - ].some((type) => type === reportAction.actionName)) + (ReportUtils.isPolicyExpenseChat(report) || ReportUtils.isInvoiceRoom(report)) && + [ + CONST.REPORT.ACTIONS.TYPE.IOU, + CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW, + CONST.REPORT.ACTIONS.TYPE.SUBMITTED, + CONST.REPORT.ACTIONS.TYPE.APPROVED, + CONST.REPORT.ACTIONS.TYPE.FORWARDED, + ].some((type) => type === reportAction.actionName) } isMostRecentIOUReportAction={reportAction.reportActionID === mostRecentIOUReportActionID} index={index} From b704277034c4e9dad12c0d2e09d3820458dc2823 Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Wed, 25 Sep 2024 14:31:19 +0100 Subject: [PATCH 18/18] use ownerID since this is an optimistic report preview, so that means they would have also created the report --- src/libs/ReportUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 7c72d3d55b16..158c56e54a02 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4827,9 +4827,9 @@ function buildOptimisticReportPreview( }, ], created, - accountID: iouReport?.managerID ?? -1, + accountID: iouReport?.ownerAccountID ?? -1, // The preview is initially whispered if created with a receipt, so the actor is the current user as well - actorAccountID: hasReceipt ? currentUserAccountID : iouReport?.managerID ?? -1, + actorAccountID: hasReceipt ? currentUserAccountID : iouReport?.ownerAccountID ?? -1, childReportID: childReportID ?? iouReport?.reportID, childMoneyRequestCount: 1, childLastMoneyRequestComment: comment,