diff --git a/src/components/OptionRow.tsx b/src/components/OptionRow.tsx index 6027d3468a71..d856eddb536a 100644 --- a/src/components/OptionRow.tsx +++ b/src/components/OptionRow.tsx @@ -22,18 +22,20 @@ import ReportActionAvatars from './ReportActionAvatars'; import SelectCircle from './SelectCircle'; import Text from './Text'; +type OptionDataWithOptionalReportID = Omit & {reportID?: string}; + type OptionRowProps = { /** Style for hovered state */ hoverStyle?: StyleProp; /** Option to allow the user to choose from can be type 'report' or 'user' */ - option: OptionData; + option: OptionDataWithOptionalReportID; /** Whether this option is currently in focus so we can modify its style */ optionIsFocused?: boolean; /** A function that is called when an option is selected. Selected option is passed as a param */ - onSelectRow?: (option: OptionData, refElement: View | HTMLDivElement | null) => void | Promise; + onSelectRow?: (option: OptionDataWithOptionalReportID, refElement: View | HTMLDivElement | null) => void | Promise; /** Whether we should show the selected state */ showSelectedState?: boolean; @@ -45,7 +47,7 @@ type OptionRowProps = { selectedStateButtonText?: string; /** Callback to fire when the multiple selector (checkbox or button) is clicked */ - onSelectedStatePressed?: (option: OptionData) => void; + onSelectedStatePressed?: (option: OptionDataWithOptionalReportID) => void; /** Whether we highlight selected option */ highlightSelected?: boolean; @@ -148,12 +150,19 @@ function OptionRow({ const firstIcon = option?.icons?.at(0); // We only create tooltips for the first 10 users or so since some reports have hundreds of users, causing performance to degrade. - const displayNamesWithTooltips = getDisplayNamesWithTooltips((option.participantsList ?? (option.accountID ? [option] : [])).slice(0, 10), shouldUseShortFormInTooltip, localeCompare); + const displayNamesWithTooltips = getDisplayNamesWithTooltips( + (option.participantsList ?? (option.accountID ? [option as OptionData] : [])).slice(0, 10), + shouldUseShortFormInTooltip, + localeCompare, + ); let subscriptColor = theme.appBG; if (optionIsFocused) { subscriptColor = focusedBackgroundColor; } + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const reportID = (option.iouReportID ?? option.reportID) || undefined; + return ( {(hovered) => ( @@ -209,10 +218,11 @@ function OptionRow({ {!!option.icons?.length && !!firstIcon && ( )} diff --git a/src/components/ReportActionAvatars/useReportActionAvatars.ts b/src/components/ReportActionAvatars/useReportActionAvatars.ts index 5a9cec6d8bac..1a4c6e724b80 100644 --- a/src/components/ReportActionAvatars/useReportActionAvatars.ts +++ b/src/components/ReportActionAvatars/useReportActionAvatars.ts @@ -62,6 +62,10 @@ function useReportActionAvatars({ action = getReportAction(reportChatReport?.reportID, chatReport.parentReportActionID); } + const [actionChildReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${action?.childReportID}`, {canBeMissing: true}); + + const isAReportPreviewAction = action?.actionName === CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW; + const isReportArchived = useReportIsArchived(iouReport?.reportID); const reportPreviewSenderID = useReportPreviewSenderID({ @@ -70,19 +74,26 @@ function useReportActionAvatars({ chatReport, }); - const policyID = passedPolicyID ?? (chatReport?.policyID === CONST.POLICY.ID_FAKE || !chatReport?.policyID ? (iouReport?.policyID ?? chatReport?.policyID) : chatReport?.policyID); + const reportPolicyID = iouReport?.policyID ?? chatReport?.policyID; + const chatReportPolicyIDExists = chatReport?.policyID === CONST.POLICY.ID_FAKE || !chatReport?.policyID; + const changedPolicyID = actionChildReport?.policyID ?? iouReport?.policyID; + const shouldUseChangedPolicyID = !!changedPolicyID && changedPolicyID !== chatReport?.policyID; + const retrievedPolicyID = chatReportPolicyIDExists ? reportPolicyID : chatReport?.policyID; + + const policyID = shouldUseChangedPolicyID ? changedPolicyID : (passedPolicyID ?? retrievedPolicyID); const policy = usePolicy(policyID); const invoiceReceiverPolicyID = chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : undefined; const invoiceReceiverPolicy = usePolicy(invoiceReceiverPolicyID); const {chatReportIDAdmins, chatReportIDAnnounce, workspaceAccountID} = policy ?? {}; - const [policyChatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportIDAnnounce ?? chatReportIDAdmins}`, {canBeMissing: true}); + + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const [policyChatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportIDAnnounce || chatReportIDAdmins}`, {canBeMissing: true}); const delegatePersonalDetails = action?.delegateAccountID ? personalDetails?.[action?.delegateAccountID] : undefined; const actorAccountID = getReportActionActorAccountID(action, iouReport, chatReport, delegatePersonalDetails); - const isAReportPreviewAction = action?.actionName === CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW; const isAInvoiceReport = isInvoiceReport(iouReport ?? null); const shouldUseActorAccountID = isAInvoiceReport && !isAReportPreviewAction; @@ -267,6 +278,13 @@ function useReportActionAvatars({ let avatars = [primaryAvatar, secondaryAvatar]; + const isUserWithWorkspaceAvatar = + avatarType === CONST.REPORT_ACTION_AVATARS.TYPE.SUBSCRIPT && avatars.at(0)?.type === CONST.ICON_TYPE_AVATAR && avatars.at(1)?.type === CONST.ICON_TYPE_WORKSPACE; + const isWorkspaceWithUserAvatar = + avatars.at(0)?.type === CONST.ICON_TYPE_WORKSPACE && avatars.at(1)?.type === CONST.ICON_TYPE_AVATAR && avatarType === CONST.REPORT_ACTION_AVATARS.TYPE.MULTIPLE; + // eslint-disable-next-line rulesdir/no-negated-variables + const wasReportPreviewMovedToDifferentPolicy = shouldUseChangedPolicyID && isAReportPreviewAction; + if (shouldUseInvoiceExpenseIcons) { avatars = getIconsWithDefaults(invoiceReport); } else if (shouldUseMappedAccountIDs) { @@ -278,14 +296,13 @@ function useReportActionAvatars({ if (avatars.every(({type}) => type === CONST.ICON_TYPE_WORKSPACE)) { avatarType = isAReportPreviewAction ? CONST.REPORT_ACTION_AVATARS.TYPE.MULTIPLE : CONST.REPORT_ACTION_AVATARS.TYPE.SUBSCRIPT; // But if it is a report preview between workspace and another user it should never be displayed as a multiple avatar - } else if ( - avatars.at(0)?.type === CONST.ICON_TYPE_WORKSPACE && - avatars.at(1)?.type === CONST.ICON_TYPE_AVATAR && - avatarType === CONST.REPORT_ACTION_AVATARS.TYPE.MULTIPLE && - isAReportPreviewAction - ) { + } else if (isWorkspaceWithUserAvatar && isAReportPreviewAction) { avatarType = CONST.REPORT_ACTION_AVATARS.TYPE.SUBSCRIPT; } + } else if (isUserWithWorkspaceAvatar && wasReportPreviewMovedToDifferentPolicy) { + const policyChatReportIcon = {...getWorkspaceIcon(policyChatReport, policy), id: policyID, name: policy?.name}; + const [firstAvatar] = avatars; + avatars = [firstAvatar, policyChatReportIcon]; } return { diff --git a/src/components/SelectionList/UserListItem.tsx b/src/components/SelectionList/UserListItem.tsx index bd3b8c56bfaa..daeee5c13435 100644 --- a/src/components/SelectionList/UserListItem.tsx +++ b/src/components/SelectionList/UserListItem.tsx @@ -62,6 +62,10 @@ function UserListItem({ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const itemAccountID = Number(item.accountID || item.icons?.at(1)?.id) || 0; + const isThereOnlyWorkspaceIcon = item.icons?.length === 1 && item.icons?.at(0)?.type === CONST.ICON_TYPE_WORKSPACE; + const shouldUseIconPolicyID = !item.reportID && !item.accountID && !item.policyID; + const policyID = isThereOnlyWorkspaceIcon && shouldUseIconPolicyID ? String(item.icons?.at(0)?.id) : item.policyID; + return ( ({ )} - {(!!reportExists || !!itemAccountID || !!item.policyID) && ( + {(!!reportExists || !!itemAccountID || !!policyID) && ( ({ reportID={reportExists ? item.reportID : undefined} /* eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing */ accountIDs={!reportExists && !!itemAccountID ? [itemAccountID] : []} - policyID={!reportExists && !itemAccountID ? item.policyID : undefined} + policyID={!reportExists && !!policyID ? policyID : undefined} singleAvatarContainerStyle={[styles.actionAvatar, styles.mr3]} fallbackDisplayName={item.text ?? item.alternateText ?? undefined} /> diff --git a/src/libs/MoneyRequestReportUtils.ts b/src/libs/MoneyRequestReportUtils.ts index edad81f52a12..0d920f2fc3d6 100644 --- a/src/libs/MoneyRequestReportUtils.ts +++ b/src/libs/MoneyRequestReportUtils.ts @@ -4,7 +4,7 @@ import type {TransactionListItemType} from '@components/SelectionList/types'; import CONST from '@src/CONST'; import type {OriginalMessageIOU, Policy, Report, ReportAction, ReportMetadata, Transaction} from '@src/types/onyx'; import {convertToDisplayString} from './CurrencyUtils'; -import {getIOUActionForTransactionID, getOriginalMessage, isDeletedParentAction, isMoneyRequestAction} from './ReportActionsUtils'; +import {getIOUActionForTransactionID, getOriginalMessage, isDeletedAction, isDeletedParentAction, isMoneyRequestAction} from './ReportActionsUtils'; import { getMoneyRequestSpendBreakdown, getNonHeldAndFullAmount, @@ -69,7 +69,7 @@ function getReportIDForTransaction(transactionItem: TransactionListItemType) { } /** - * Filters all available transactions and returns the ones that belong to not removed parent action. + * Filters all available transactions and returns the ones that belong to not removed action and not removed parent action. */ function getAllNonDeletedTransactions(transactions: OnyxCollection, reportActions: ReportAction[]) { return Object.values(transactions ?? {}).filter((transaction): transaction is Transaction => { @@ -77,7 +77,7 @@ function getAllNonDeletedTransactions(transactions: OnyxCollection, return false; } const action = getIOUActionForTransactionID(reportActions, transaction.transactionID); - return !isDeletedParentAction(action); + return !isDeletedParentAction(action) && (reportActions.length === 0 || !isDeletedAction(action)); }); } diff --git a/src/pages/home/report/ReactionList/BaseReactionList.tsx b/src/pages/home/report/ReactionList/BaseReactionList.tsx index 0652761ffdc4..3fb3d66d39a4 100755 --- a/src/pages/home/report/ReactionList/BaseReactionList.tsx +++ b/src/pages/home/report/ReactionList/BaseReactionList.tsx @@ -65,7 +65,7 @@ function BaseReactionList({hasUserReacted = false, users, isVisible = false, emo }); }} option={{ - reportID: String(item.accountID), + accountID: item.accountID, text: Str.removeSMSDomain(item.displayName ?? ''), alternateText: Str.removeSMSDomain(item.login ?? ''), participantsList: [item],