diff --git a/src/pages/inbox/report/PureReportActionItem.tsx b/src/pages/inbox/report/PureReportActionItem.tsx index 5cd0f49fe7df..c7bb3bf70713 100644 --- a/src/pages/inbox/report/PureReportActionItem.tsx +++ b/src/pages/inbox/report/PureReportActionItem.tsx @@ -5,15 +5,13 @@ import mapValues from 'lodash/mapValues'; import React, {memo, use, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react'; import type {GestureResponderEvent, TextInput} from 'react-native'; import {InteractionManager, Keyboard, View} from 'react-native'; -import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import type {Emoji} from '@assets/emojis/types'; import * as ActionSheetAwareScrollView from '@components/ActionSheetAwareScrollView'; -import {AttachmentContext} from '@components/AttachmentContext'; import Button from '@components/Button'; import DisplayNames from '@components/DisplayNames'; import Hoverable from '@components/Hoverable'; -import MentionReportContext from '@components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/MentionReportContext'; import Icon from '@components/Icon'; import InlineSystemMessage from '@components/InlineSystemMessage'; import KYCWall from '@components/KYCWall'; @@ -23,8 +21,6 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import PressableWithSecondaryInteraction from '@components/PressableWithSecondaryInteraction'; import ReportActionItemEmojiReactions from '@components/Reactions/ReportActionItemEmojiReactions'; import RenderHTML from '@components/RenderHTML'; -import type {ActionableItem} from '@components/ReportActionItem/ActionableItemButtons'; -import ActionableItemButtons from '@components/ReportActionItem/ActionableItemButtons'; import ChronosOOOListActions from '@components/ReportActionItem/ChronosOOOListActions'; import CreatedReportForUnapprovedTransactionsAction from '@components/ReportActionItem/CreatedReportForUnapprovedTransactionsAction'; import CreateHarvestReportAction from '@components/ReportActionItem/CreateHarvestReportAction'; @@ -44,14 +40,12 @@ import {ShowContextMenuActionsContext, ShowContextMenuStateContext} from '@compo import Text from '@components/Text'; import TextLink from '@components/TextLink'; import UnreadActionIndicator from '@components/UnreadActionIndicator'; -import useActivePolicy from '@hooks/useActivePolicy'; import useConfirmModal from '@hooks/useConfirmModal'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useEnvironment from '@hooks/useEnvironment'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; -import usePreferredPolicy from '@hooks/usePreferredPolicy'; import usePrevious from '@hooks/usePrevious'; import useReportIsArchived from '@hooks/useReportIsArchived'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; @@ -59,7 +53,6 @@ import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {cleanUpMoneyRequest} from '@libs/actions/IOU/DeleteMoneyRequest'; -import {resolveSuggestedFollowup} from '@libs/actions/Report/SuggestedFollowup'; import {isPersonalCardBrokenConnection} from '@libs/CardUtils'; import {isChronosOOOListAction} from '@libs/ChronosUtils'; import ControlSelection from '@libs/ControlSelection'; @@ -75,7 +68,6 @@ import type {ReportsSplitNavigatorParamList} from '@libs/Navigation/types'; import Permissions from '@libs/Permissions'; import {getDisplayNameOrDefault} from '@libs/PersonalDetailsUtils'; import {isPolicyAdmin} from '@libs/PolicyUtils'; -import {containsActionableFollowUps, parseFollowupsFromHtml} from '@libs/ReportActionFollowupUtils'; import { extractLinksFromMessageHtml, getCardConnectionBrokenMessage, @@ -93,18 +85,14 @@ import { getSettlementAccountLockedMessage, getTravelUpdateMessage, getWhisperedTo, - isActionableAddPaymentCard, isActionableCardFraudAlert, isActionableJoinRequest, isActionableMentionInviteToSubmitExpenseConfirmWhisper, isActionableMentionWhisper, isActionableReportMentionWhisper, - isActionableTrackExpense, isActionOfType, isCardBrokenConnectionAction, isCardIssuedAction, - isConciergeCategoryOptions, - isConciergeDescriptionOptions, isCreatedTaskReportAction, isDeletedAction, isDeletedParentAction as isDeletedParentActionUtils, @@ -115,8 +103,6 @@ import { isReimbursementDeQueuedOrCanceledAction, isReimbursementQueuedAction, isRenamedAction, - isResolvedConciergeCategoryOptions, - isResolvedConciergeDescriptionOptions, isSplitBillAction as isSplitBillActionReportActionsUtils, isTaskAction, isTrackExpenseAction as isTrackExpenseActionReportActionsUtils, @@ -124,15 +110,13 @@ import { isWhisperActionTargetedToOthers, useTableReportViewActionRenderConditionals, } from '@libs/ReportActionsUtils'; -import type {CreateDraftTransactionParams, MissingPaymentMethod} from '@libs/ReportUtils'; +import type {MissingPaymentMethod} from '@libs/ReportUtils'; import { canWriteInReport, - chatIncludesConcierge, getChatListItemReportName, getDisplayNamesWithTooltips, getMovedActionMessage, getWhisperDisplayNames, - isArchivedNonExpenseReport, isChatThread, isCompletedTaskReport, isExpenseReport, @@ -141,16 +125,14 @@ import { shouldDisplayThreadReplies as shouldDisplayThreadRepliesUtils, } from '@libs/ReportUtils'; import SelectionScraper from '@libs/SelectionScraper'; -import shouldRenderAddPaymentCard from '@libs/shouldRenderAppPaymentCard'; import {ReactionListContext} from '@pages/inbox/ReportScreenContext'; import AttachmentModalContext from '@pages/media/AttachmentModalScreen/AttachmentModalContext'; import variables from '@styles/variables'; import {openPersonalBankAccountSetupView} from '@userActions/BankAccounts'; import type {IgnoreDirection} from '@userActions/ClearReportActionErrors'; import {hideEmojiPicker, isActive} from '@userActions/EmojiPickerAction'; -import {createTransactionThreadReport, expandURLPreview, resolveConciergeCategoryOptions, resolveConciergeDescriptionOptions} from '@userActions/Report'; +import {createTransactionThreadReport, expandURLPreview} from '@userActions/Report'; import {isAnonymousUser, signOutAndRedirectToSignIn} from '@userActions/Session'; -import {isBlockedFromConcierge} from '@userActions/User'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -159,6 +141,7 @@ import type * as OnyxTypes from '@src/types/onyx'; import type {Errors} from '@src/types/onyx/OnyxCommon'; import {isEmptyObject, isEmptyValueObject} from '@src/types/utils/EmptyObject'; import ApprovalFlowContent, {isApprovalFlowAction} from './actionContents/ApprovalFlowContent'; +import ChatMessageContent from './actionContents/ChatMessageContent'; import ConfirmWhisperContent from './actionContents/ConfirmWhisperContent'; import FraudAlertContent from './actionContents/FraudAlertContent'; import JoinRequestContent from './actionContents/JoinRequestContent'; @@ -176,8 +159,6 @@ import ReportActionItemBasicMessage from './ReportActionItemBasicMessage'; import ReportActionItemContentCreated from './ReportActionItemContentCreated'; import ReportActionItemDraft from './ReportActionItemDraft'; import ReportActionItemGrouped from './ReportActionItemGrouped'; -import ReportActionItemMessage from './ReportActionItemMessage'; -import ReportActionItemMessageEdit from './ReportActionItemMessageEdit'; import ReportActionItemMessageWithExplain from './ReportActionItemMessageWithExplain'; import ReportActionItemSingle from './ReportActionItemSingle'; import ReportActionItemThread from './ReportActionItemThread'; @@ -193,9 +174,6 @@ type PureReportActionItemProps = { /** Beta features list */ betas: OnyxEntry; - /** All transaction draft IDs */ - draftTransactionIDs: string[] | undefined; - /** Report for this action */ report: OnyxEntry; @@ -277,9 +255,6 @@ type PureReportActionItemProps = { /** Personal details list */ personalDetails?: OnyxTypes.PersonalDetailsList; - /** Whether or not the user is blocked from concierge */ - blockedFromConcierge?: OnyxTypes.BlockedFromConcierge; - /** ID of the original report from which the given reportAction is first created */ originalReportID?: string; @@ -309,9 +284,6 @@ type PureReportActionItemProps = { ignoreSkinToneOnCompare: boolean | undefined, ) => void; - /** Function to create a draft transaction and navigate to participant selector */ - createDraftTransactionAndNavigateToParticipantSelector?: (params: CreateDraftTransactionParams) => void; - /** Function to resolve actionable report mention whisper */ resolveActionableReportMentionWhisper?: ( report: OnyxEntry, @@ -358,9 +330,6 @@ type PureReportActionItemProps = { keys?: string[], ) => void; - /** Function to dismiss the actionable whisper for tracking expenses */ - dismissTrackExpenseActionableWhisper?: (reportID: string | undefined, reportAction: OnyxEntry) => void; - /** User payment card ID */ userBillingFundID?: number; @@ -376,9 +345,6 @@ type PureReportActionItemProps = { /** Current user's account id */ currentUserAccountID: number; - /** Current user's email */ - currentUserEmail: string | undefined; - /** The bank account list */ bankAccountList?: OnyxTypes.BankAccountList | undefined; @@ -390,9 +356,6 @@ type PureReportActionItemProps = { /** Report metadata for the report */ reportMetadata?: OnyxEntry; - - /** The billing grace end period's shared NVP collection */ - userBillingGracePeriodEnds: OnyxCollection; }; // This is equivalent to returning a negative boolean in normal functions, but we can keep the element return type @@ -405,7 +368,6 @@ function PureReportActionItem({ personalPolicyID, introSelected, betas, - draftTransactionIDs, action, report, policy, @@ -433,14 +395,12 @@ function PureReportActionItem({ isUserValidated, parentReport, personalDetails, - blockedFromConcierge, originalReportID = '-1', originalReport, deleteReportActionDraft = () => {}, isArchivedRoom, isChronosReport, toggleEmojiReaction = () => {}, - createDraftTransactionAndNavigateToParticipantSelector = () => {}, resolveActionableReportMentionWhisper = () => {}, resolveActionableMentionWhisper = () => {}, isClosedExpenseReportWithNoExpenses, @@ -451,24 +411,19 @@ function PureReportActionItem({ getTransactionsWithReceipts = () => [], clearError = () => {}, clearAllRelatedReportActionErrors = () => {}, - dismissTrackExpenseActionableWhisper = () => {}, userBillingFundID, shouldShowBorder, shouldHighlight = false, isTryNewDotNVPDismissed = false, currentUserAccountID, - currentUserEmail, bankAccountList, reportNameValuePairsOrigin, reportNameValuePairsOriginalID, reportMetadata, - userBillingGracePeriodEnds, }: PureReportActionItemProps) { const isConciergeGreeting = action.reportActionID === CONST.CONCIERGE_GREETING_ACTION_ID; const shouldDisplayContextMenuValue = shouldDisplayContextMenu && !isConciergeGreeting; - const [amountOwed] = useOnyx(ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED); - const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END); const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const {transitionActionSheetState} = ActionSheetAwareScrollView.useActionSheetAwareScrollViewActions(); const {translate, formatPhoneNumber, localeCompare, formatTravelDate, datetimeToCalendarTime} = useLocalize(); @@ -482,8 +437,6 @@ function PureReportActionItem({ const [isContextMenuActive, setIsContextMenuActive] = useState(() => isActiveReportAction(action.reportActionID)); const [isEmojiPickerActive, setIsEmojiPickerActive] = useState(); const [isPaymentMethodPopoverActive, setIsPaymentMethodPopoverActive] = useState(); - const {isRestrictedToPreferredPolicy, preferredPolicyID} = usePreferredPolicy(); - const activePolicy = useActivePolicy(); const shouldRenderViewBasedOnAction = useTableReportViewActionRenderConditionals(action); const [isHidden, setIsHidden] = useState(false); const [moderationDecision, setModerationDecision] = useState(CONST.MODERATION.MODERATOR_DECISION_APPROVED); @@ -504,8 +457,6 @@ function PureReportActionItem({ const [childReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(action.childReportID)}`); const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.chatReportID)}`); - const trackExpenseTransactionID = isActionableTrackExpense(action) ? getOriginalMessage(action)?.transactionID : undefined; - const [trackExpenseTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(trackExpenseTransactionID)}`); const highlightedBackgroundColorIfNeeded = useMemo( // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing @@ -776,194 +727,6 @@ function PureReportActionItem({ [toggleContextMenuFromActiveReportAction, handleShowContextMenu], ); - const attachmentContextValue = useMemo(() => { - if (isOnSearch) { - return {type: CONST.ATTACHMENT_TYPE.SEARCH, currentSearchHash}; - } - return {reportID, type: CONST.ATTACHMENT_TYPE.REPORT}; - }, [reportID, isOnSearch, currentSearchHash]); - - const mentionReportContextValue = useMemo(() => ({currentReportID: report?.reportID, exactlyMatch: true}), [report?.reportID]); - const actionableItemButtons: ActionableItem[] = useMemo(() => { - if (isActionableAddPaymentCard(action) && userBillingFundID === undefined && shouldRenderAddPaymentCard()) { - return [ - { - text: 'subscription.cardSection.addCardButton', - key: `${action.reportActionID}-actionableAddPaymentCard-submit`, - onPress: () => { - Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_ADD_PAYMENT_CARD); - }, - isPrimary: true, - }, - ]; - } - - const reportActionReport = originalReport ?? report; - if (isConciergeCategoryOptions(action)) { - const options = getOriginalMessage(action)?.options; - if (!options) { - return []; - } - - if (isResolvedConciergeCategoryOptions(action)) { - return []; - } - - if (!reportActionReport) { - return []; - } - - return options.map((option, i) => ({ - text: `${i + 1} - ${option}`, - key: `${action.reportActionID}-conciergeCategoryOptions-${option}`, - onPress: () => { - resolveConciergeCategoryOptions(reportActionReport, reportID, action.reportActionID, option, personalDetail.timezone ?? CONST.DEFAULT_TIME_ZONE, currentUserAccountID); - }, - })); - } - - if (isConciergeDescriptionOptions(action)) { - const options = getOriginalMessage(action)?.options; - if (!options) { - return []; - } - - if (isResolvedConciergeDescriptionOptions(action)) { - return []; - } - - if (!reportActionReport) { - return []; - } - - return options.map((option, i) => ({ - text: `${i + 1} - ${option}`, - key: `${action.reportActionID}-conciergeDescriptionOptions-${option}`, - onPress: () => { - resolveConciergeDescriptionOptions(reportActionReport, reportID, action.reportActionID, option, personalDetail.timezone ?? CONST.DEFAULT_TIME_ZONE, currentUserAccountID); - }, - })); - } - const messageHtml = getReportActionMessage(action)?.html; - if (messageHtml && reportActionReport) { - const followups = parseFollowupsFromHtml(messageHtml); - if (followups && followups.length > 0) { - return followups.map((followup) => ({ - text: followup.text, - shouldUseLocalization: false, - key: `${action.reportActionID}-followup-${followup.text}`, - onPress: () => { - resolveSuggestedFollowup(reportActionReport, reportID, action, followup, personalDetail.timezone ?? CONST.DEFAULT_TIME_ZONE, currentUserAccountID, currentUserEmail); - }, - })); - } - } - - if (isActionableTrackExpense(action)) { - const reportActionReportID = originalReportID ?? reportID; - const options = [ - { - text: 'actionableMentionTrackExpense.submit', - key: `${action.reportActionID}-actionableMentionTrackExpense-submit`, - onPress: () => { - createDraftTransactionAndNavigateToParticipantSelector({ - reportID: reportActionReportID, - actionName: CONST.IOU.ACTION.SUBMIT, - reportActionID: action.reportActionID, - introSelected, - draftTransactionIDs, - activePolicy, - userBillingGracePeriodEnds, - amountOwed, - ownerBillingGracePeriodEnd, - isRestrictedToPreferredPolicy, - preferredPolicyID, - transaction: trackExpenseTransaction, - currentUserAccountID: personalDetail.accountID, - currentUserEmail: personalDetail.email ?? '', - }); - }, - }, - ]; - - if (Permissions.canUseTrackFlows()) { - options.push( - { - text: 'actionableMentionTrackExpense.categorize', - key: `${action.reportActionID}-actionableMentionTrackExpense-categorize`, - onPress: () => { - createDraftTransactionAndNavigateToParticipantSelector({ - reportID: reportActionReportID, - actionName: CONST.IOU.ACTION.CATEGORIZE, - reportActionID: action.reportActionID, - introSelected, - draftTransactionIDs, - activePolicy, - userBillingGracePeriodEnds, - amountOwed, - ownerBillingGracePeriodEnd, - transaction: trackExpenseTransaction, - currentUserAccountID: personalDetail.accountID, - currentUserEmail: personalDetail.email ?? '', - }); - }, - }, - { - text: 'actionableMentionTrackExpense.share', - key: `${action.reportActionID}-actionableMentionTrackExpense-share`, - onPress: () => { - createDraftTransactionAndNavigateToParticipantSelector({ - reportID: reportActionReportID, - actionName: CONST.IOU.ACTION.SHARE, - reportActionID: action.reportActionID, - introSelected, - draftTransactionIDs, - activePolicy, - userBillingGracePeriodEnds, - amountOwed, - ownerBillingGracePeriodEnd, - transaction: trackExpenseTransaction, - currentUserAccountID: personalDetail.accountID, - currentUserEmail: personalDetail.email ?? '', - }); - }, - }, - ); - } - options.push({ - text: 'actionableMentionTrackExpense.nothing', - key: `${action.reportActionID}-actionableMentionTrackExpense-nothing`, - onPress: () => { - dismissTrackExpenseActionableWhisper(reportActionReportID, action); - }, - }); - return options; - } - - return []; - }, [ - action, - userBillingFundID, - originalReportID, - reportID, - currentUserAccountID, - currentUserEmail, - personalDetail.timezone, - createDraftTransactionAndNavigateToParticipantSelector, - isRestrictedToPreferredPolicy, - preferredPolicyID, - dismissTrackExpenseActionableWhisper, - introSelected, - draftTransactionIDs, - activePolicy, - report, - originalReport, - userBillingGracePeriodEnds, - amountOwed, - ownerBillingGracePeriodEnd, - trackExpenseTransaction, - ]); - /** * Get the content of ReportActionItem * @param hovered whether the ReportActionItem is hovered @@ -1349,74 +1112,28 @@ function PureReportActionItem({ ); } else { - const hasBeenFlagged = - ![CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING].some((item) => item === moderationDecision) && !isPendingRemove(action); - - const isConciergeOptions = isConciergeCategoryOptions(action) || isConciergeDescriptionOptions(action); - const actionContainsFollowUps = containsActionableFollowUps(action); - const isPhrasalConciergeOptions = isConciergeOptions || actionContainsFollowUps; - const actionableButtonsNoLines = isPhrasalConciergeOptions ? 3 : 1; - children = ( - - - - - {draftMessage === undefined ? ( - - - {hasBeenFlagged && ( - - )} - {actionableItemButtons.length > 0 && ( - - )} - - ) : ( - - )} - - - - + ); } const numberOfThreadReplies = action.childVisibleActionCount ?? 0; @@ -1778,7 +1495,6 @@ export default memo(PureReportActionItem, (prevProps, nextProps) => { deepEqual(prevProps.personalDetails, nextProps.personalDetails) && deepEqual(prevProps.introSelected, nextProps.introSelected) && deepEqual(prevProps.betas, nextProps.betas) && - deepEqual(prevProps.blockedFromConcierge, nextProps.blockedFromConcierge) && prevProps.originalReportID === nextProps.originalReportID && deepEqual(prevProps.originalReport?.participants, nextProps.originalReport?.participants) && prevProps.isArchivedRoom === nextProps.isArchivedRoom && @@ -1794,7 +1510,6 @@ export default memo(PureReportActionItem, (prevProps, nextProps) => { deepEqual(prevProps.cardList, nextProps.cardList) && prevProps.reportNameValuePairsOrigin === nextProps.reportNameValuePairsOrigin && prevProps.reportNameValuePairsOriginalID === nextProps.reportNameValuePairsOriginalID && - prevProps.reportMetadata?.pendingExpenseAction === nextProps.reportMetadata?.pendingExpenseAction && - deepEqual(prevProps.draftTransactionIDs, nextProps.draftTransactionIDs) + prevProps.reportMetadata?.pendingExpenseAction === nextProps.reportMetadata?.pendingExpenseAction ); }); diff --git a/src/pages/inbox/report/ReportActionItem.tsx b/src/pages/inbox/report/ReportActionItem.tsx index 114e4491d4e7..45c2c7148cd7 100644 --- a/src/pages/inbox/report/ReportActionItem.tsx +++ b/src/pages/inbox/report/ReportActionItem.tsx @@ -1,7 +1,5 @@ -import {validTransactionDraftIDsSelector} from '@selectors/TransactionDraft'; import React, {useCallback} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; -import {useBlockedFromConcierge} from '@components/OnyxListItemProvider'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; @@ -14,7 +12,6 @@ import {getForReportAction, getMovedReportID} from '@libs/ModifiedExpenseMessage import {getIOUReportIDFromReportActionPreview, getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils'; import { chatIncludesChronosWithID, - createDraftTransactionAndNavigateToParticipantSelector, getIndicatedMissingPaymentMethod, getReimbursementDeQueuedOrCanceledActionMessage, getTransactionsWithReceipts, @@ -24,13 +21,7 @@ import { isCurrentUserTheOnlyParticipant, } from '@libs/ReportUtils'; import {clearAllRelatedReportActionErrors} from '@userActions/ClearReportActionErrors'; -import { - deleteReportActionDraft, - dismissTrackExpenseActionableWhisper, - resolveActionableMentionWhisper, - resolveActionableReportMentionWhisper, - toggleEmojiReaction, -} from '@userActions/Report'; +import {deleteReportActionDraft, resolveActionableMentionWhisper, resolveActionableReportMentionWhisper, toggleEmojiReaction} from '@userActions/Report'; import {clearError} from '@userActions/Transaction'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -38,18 +29,7 @@ import type {PersonalDetailsList, ReportAction, ReportActionReactions, Transacti import type {PureReportActionItemProps} from './PureReportActionItem'; import PureReportActionItem from './PureReportActionItem'; -type ReportActionItemProps = Omit< - PureReportActionItemProps, - | 'taskReport' - | 'linkedReport' - | 'iouReportOfLinkedReport' - | 'currentUserAccountID' - | 'currentUserEmail' - | 'personalPolicyID' - | 'draftTransactionIDs' - | 'userBillingGracePeriodEnds' - | 'betas' -> & { +type ReportActionItemProps = Omit & { /** Whether to show the draft message or not */ shouldShowDraftMessage?: boolean; @@ -103,7 +83,6 @@ function ReportActionItem({ const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyIDForTags}`); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); const [betas] = useOnyx(ONYXKEYS.BETAS); - const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector}); const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`); const [originalReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${originalReportID}`); const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getIOUReportIDFromReportActionPreview(action)}`); @@ -122,7 +101,6 @@ function ReportActionItem({ const [cardList] = useOnyx(ONYXKEYS.CARD_LIST); const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST); const [personalPolicyID] = useOnyx(ONYXKEYS.PERSONAL_POLICY_ID); - const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); const transactionsOnIOUReport = useReportTransactions(iouReport?.reportID); const transactionID = isMoneyRequestAction(action) && getOriginalMessage(action)?.IOUTransactionID; @@ -135,7 +113,6 @@ function ReportActionItem({ const [linkedTransactionRouteError] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {selector: getLinkedTransactionRouteError}); - const blockedFromConcierge = useBlockedFromConcierge(); const targetReport = isChatThread(report) ? parentReport : report; const missingPaymentMethod = getIndicatedMissingPaymentMethod(userWalletTierName, targetReport?.reportID, action, bankAccountList); @@ -145,13 +122,11 @@ function ReportActionItem({ {...props} introSelected={introSelected} betas={betas} - draftTransactionIDs={draftTransactionIDs} personalPolicyID={personalPolicyID} action={action} report={report} policy={policy} currentUserAccountID={currentUserAccountID} - currentUserEmail={currentUserEmail} draftMessage={draftMessage} iouReport={iouReport} taskReport={taskReport} @@ -163,14 +138,12 @@ function ReportActionItem({ isUserValidated={isUserValidated} parentReport={parentReport} personalDetails={personalDetails} - blockedFromConcierge={blockedFromConcierge} originalReportID={originalReportID} originalReport={originalReport} deleteReportActionDraft={deleteReportActionDraft} isArchivedRoom={isArchivedNonExpenseReport(originalReport, isOriginalReportArchived)} isChronosReport={chatIncludesChronosWithID(originalReportID)} toggleEmojiReaction={toggleEmojiReaction} - createDraftTransactionAndNavigateToParticipantSelector={createDraftTransactionAndNavigateToParticipantSelector} resolveActionableReportMentionWhisper={resolveActionableReportMentionWhisper} resolveActionableMentionWhisper={resolveActionableMentionWhisper} isClosedExpenseReportWithNoExpenses={isClosedExpenseReportWithNoExpenses(iouReport, transactionsOnIOUReport)} @@ -193,12 +166,10 @@ function ReportActionItem({ getTransactionsWithReceipts={getTransactionsWithReceipts} clearError={clearError} clearAllRelatedReportActionErrors={clearAllRelatedReportActionErrors} - dismissTrackExpenseActionableWhisper={dismissTrackExpenseActionableWhisper} userBillingFundID={userBillingFundID} isTryNewDotNVPDismissed={isTryNewDotNVPDismissed} bankAccountList={bankAccountList} reportMetadata={reportMetadata} - userBillingGracePeriodEnds={userBillingGracePeriodEnds} /> ); } diff --git a/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx b/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx new file mode 100644 index 000000000000..37fbe01aae63 --- /dev/null +++ b/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx @@ -0,0 +1,229 @@ +import {validTransactionDraftIDsSelector} from '@selectors/TransactionDraft'; +import React from 'react'; +import type {OnyxEntry} from 'react-native-onyx'; +import type {ActionableItem} from '@components/ReportActionItem/ActionableItemButtons'; +import ActionableItemButtons from '@components/ReportActionItem/ActionableItemButtons'; +import useActivePolicy from '@hooks/useActivePolicy'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; +import useOnyx from '@hooks/useOnyx'; +import usePreferredPolicy from '@hooks/usePreferredPolicy'; +import useThemeStyles from '@hooks/useThemeStyles'; +import {resolveSuggestedFollowup} from '@libs/actions/Report/SuggestedFollowup'; +import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; +import Navigation from '@libs/Navigation/Navigation'; +import Permissions from '@libs/Permissions'; +import {containsActionableFollowUps, parseFollowupsFromHtml} from '@libs/ReportActionFollowupUtils'; +import { + getOriginalMessage, + getReportActionMessage, + isActionableAddPaymentCard, + isActionableTrackExpense, + isConciergeCategoryOptions, + isConciergeDescriptionOptions, + isResolvedConciergeCategoryOptions, + isResolvedConciergeDescriptionOptions, +} from '@libs/ReportActionsUtils'; +import type {CreateDraftTransactionParams} from '@libs/ReportUtils'; +import {createDraftTransactionAndNavigateToParticipantSelector} from '@libs/ReportUtils'; +import shouldRenderAddPaymentCard from '@libs/shouldRenderAppPaymentCard'; +import {dismissTrackExpenseActionableWhisper, resolveConciergeCategoryOptions, resolveConciergeDescriptionOptions} from '@userActions/Report'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type * as OnyxTypes from '@src/types/onyx'; + +type ChatActionableButtonsProps = { + action: OnyxTypes.ReportAction; + report: OnyxEntry; + originalReport: OnyxEntry; + reportID: string | undefined; + originalReportID: string; + userBillingFundID: number | undefined; + introSelected: OnyxEntry; +}; + +function ChatActionableButtons({action, report, originalReport, reportID, originalReportID, userBillingFundID, introSelected}: ChatActionableButtonsProps) { + const styles = useThemeStyles(); + const personalDetail = useCurrentUserPersonalDetails(); + const {isRestrictedToPreferredPolicy, preferredPolicyID} = usePreferredPolicy(); + const activePolicy = useActivePolicy(); + + const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector}); + const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); + const [amountOwed] = useOnyx(ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED); + const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END); + const trackExpenseTransactionID = isActionableTrackExpense(action) ? getOriginalMessage(action)?.transactionID : undefined; + const [trackExpenseTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(trackExpenseTransactionID)}`); + + const actionableItemButtons = ((): ActionableItem[] => { + if (isActionableAddPaymentCard(action) && userBillingFundID === undefined && shouldRenderAddPaymentCard()) { + return [ + { + text: 'subscription.cardSection.addCardButton', + key: `${action.reportActionID}-actionableAddPaymentCard-submit`, + onPress: () => { + Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_ADD_PAYMENT_CARD); + }, + isPrimary: true, + }, + ]; + } + + const reportActionReport = originalReport ?? report; + if (isConciergeCategoryOptions(action)) { + const options = getOriginalMessage(action)?.options; + if (!options) { + return []; + } + + if (isResolvedConciergeCategoryOptions(action)) { + return []; + } + + if (!reportActionReport) { + return []; + } + + return options.map((option, i) => ({ + text: `${i + 1} - ${option}`, + key: `${action.reportActionID}-conciergeCategoryOptions-${option}`, + onPress: () => { + resolveConciergeCategoryOptions( + reportActionReport, + reportID, + action.reportActionID, + option, + personalDetail.timezone ?? CONST.DEFAULT_TIME_ZONE, + personalDetail.accountID, + ); + }, + })); + } + + if (isConciergeDescriptionOptions(action)) { + const options = getOriginalMessage(action)?.options; + if (!options) { + return []; + } + + if (isResolvedConciergeDescriptionOptions(action)) { + return []; + } + + if (!reportActionReport) { + return []; + } + + return options.map((option, i) => ({ + text: `${i + 1} - ${option}`, + key: `${action.reportActionID}-conciergeDescriptionOptions-${option}`, + onPress: () => { + resolveConciergeDescriptionOptions( + reportActionReport, + reportID, + action.reportActionID, + option, + personalDetail.timezone ?? CONST.DEFAULT_TIME_ZONE, + personalDetail.accountID, + ); + }, + })); + } + const messageHtml = getReportActionMessage(action)?.html; + if (messageHtml && reportActionReport) { + const followups = parseFollowupsFromHtml(messageHtml); + if (followups && followups.length > 0) { + return followups.map((followup) => ({ + text: followup.text, + shouldUseLocalization: false, + key: `${action.reportActionID}-followup-${followup.text}`, + onPress: () => { + resolveSuggestedFollowup( + reportActionReport, + reportID, + action, + followup, + personalDetail.timezone ?? CONST.DEFAULT_TIME_ZONE, + personalDetail.accountID, + personalDetail.email, + ); + }, + })); + } + } + + if (isActionableTrackExpense(action)) { + const reportActionReportID = originalReportID ?? reportID; + const baseDraftTransactionParams = { + reportID: reportActionReportID, + reportActionID: action.reportActionID, + introSelected, + draftTransactionIDs, + activePolicy, + userBillingGracePeriodEnds, + amountOwed, + ownerBillingGracePeriodEnd, + transaction: trackExpenseTransaction, + currentUserAccountID: personalDetail.accountID, + currentUserEmail: personalDetail.email ?? '', + }; + const TRACK_EXPENSE_ACTIONS = { + submit: CONST.IOU.ACTION.SUBMIT, + categorize: CONST.IOU.ACTION.CATEGORIZE, + share: CONST.IOU.ACTION.SHARE, + } as const; + const prepareTrackExpenseButton = (actionKey: keyof typeof TRACK_EXPENSE_ACTIONS, extraParams?: Partial) => ({ + text: `actionableMentionTrackExpense.${actionKey}`, + key: `${action.reportActionID}-actionableMentionTrackExpense-${actionKey}`, + onPress: () => { + createDraftTransactionAndNavigateToParticipantSelector({ + ...baseDraftTransactionParams, + ...extraParams, + actionName: TRACK_EXPENSE_ACTIONS[actionKey], + }); + }, + }); + const options = [prepareTrackExpenseButton('submit', {isRestrictedToPreferredPolicy, preferredPolicyID})]; + + if (Permissions.canUseTrackFlows()) { + options.push(prepareTrackExpenseButton('categorize'), prepareTrackExpenseButton('share')); + } + options.push({ + text: 'actionableMentionTrackExpense.nothing', + key: `${action.reportActionID}-actionableMentionTrackExpense-nothing`, + onPress: () => { + dismissTrackExpenseActionableWhisper(reportActionReportID, action); + }, + }); + return options; + } + + return []; + })(); + + if (actionableItemButtons.length === 0) { + return null; + } + + const isConciergeOptions = isConciergeCategoryOptions(action) || isConciergeDescriptionOptions(action); + const actionContainsFollowUps = containsActionableFollowUps(action); + const isPhrasalConciergeOptions = isConciergeOptions || actionContainsFollowUps; + const actionableButtonsNoLines = isPhrasalConciergeOptions ? 3 : 1; + + return ( + + ); +} + +ChatActionableButtons.displayName = 'ChatActionableButtons'; + +export default ChatActionableButtons; diff --git a/src/pages/inbox/report/actionContents/ChatMessageContent.tsx b/src/pages/inbox/report/actionContents/ChatMessageContent.tsx new file mode 100644 index 000000000000..7ba2bcc2bcfd --- /dev/null +++ b/src/pages/inbox/report/actionContents/ChatMessageContent.tsx @@ -0,0 +1,170 @@ +import React from 'react'; +import type {TextInput} from 'react-native'; +import {View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; +import {AttachmentContext} from '@components/AttachmentContext'; +import Button from '@components/Button'; +import MentionReportContext from '@components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/MentionReportContext'; +import {useBlockedFromConcierge} from '@components/OnyxListItemProvider'; +import {ShowContextMenuActionsContext, ShowContextMenuStateContext} from '@components/ShowContextMenuContext'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import {parseFollowupsFromHtml} from '@libs/ReportActionFollowupUtils'; +import { + getReportActionMessage, + isActionableAddPaymentCard, + isActionableTrackExpense, + isConciergeCategoryOptions, + isConciergeDescriptionOptions, + isPendingRemove, +} from '@libs/ReportActionsUtils'; +import {chatIncludesConcierge, isArchivedNonExpenseReport} from '@libs/ReportUtils'; +import type {ContextMenuAnchor} from '@pages/inbox/report/ContextMenu/ReportActionContextMenu'; +import ReportActionItemMessage from '@pages/inbox/report/ReportActionItemMessage'; +import ReportActionItemMessageEdit from '@pages/inbox/report/ReportActionItemMessageEdit'; +import {isBlockedFromConcierge} from '@userActions/User'; +import CONST from '@src/CONST'; +import type * as OnyxTypes from '@src/types/onyx'; +import ChatActionableButtons from './ChatActionableButtons'; + +type ChatMessageContentProps = { + action: OnyxTypes.ReportAction; + report: OnyxEntry; + originalReport: OnyxEntry; + reportID: string | undefined; + originalReportID: string; + displayAsGroup: boolean; + draftMessage: string | undefined; + index: number; + isHidden: boolean; + moderationDecision: OnyxTypes.DecisionName; + updateHiddenState: (isHiddenValue: boolean) => void; + isArchivedRoom?: boolean; + composerTextInputRef: React.RefObject; + isOnSearch: boolean; + currentSearchHash: number | undefined; + contextMenuStateValue: { + anchor: ContextMenuAnchor | null; + report: OnyxEntry; + isReportArchived: boolean; + action: OnyxTypes.ReportAction; + transactionThreadReport?: OnyxEntry; + isDisabled: boolean; + shouldDisplayContextMenu: boolean; + originalReportID: string | undefined; + }; + contextMenuActionsValue: { + checkIfContextMenuActive: () => void; + onShowContextMenu: (callback: () => void) => void; + }; + userBillingFundID: number | undefined; + introSelected: OnyxEntry; +}; + +function ChatMessageContent({ + action, + report, + originalReport, + reportID, + originalReportID, + displayAsGroup, + draftMessage, + index, + isHidden, + moderationDecision, + updateHiddenState, + isArchivedRoom, + composerTextInputRef, + isOnSearch, + currentSearchHash, + contextMenuStateValue, + contextMenuActionsValue, + userBillingFundID, + introSelected, +}: ChatMessageContentProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + + const blockedFromConcierge = useBlockedFromConcierge(); + + const mentionReportContextValue = {currentReportID: report?.reportID, exactlyMatch: true}; + + const attachmentContextValue = isOnSearch ? {type: CONST.ATTACHMENT_TYPE.SEARCH, currentSearchHash} : {reportID, type: CONST.ATTACHMENT_TYPE.REPORT}; + + const hasBeenFlagged = + ![CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING].some((item) => item === moderationDecision) && !isPendingRemove(action); + + const messageHtml = getReportActionMessage(action)?.html; + const mayHaveActionableButtons = + isActionableAddPaymentCard(action) || + isConciergeCategoryOptions(action) || + isConciergeDescriptionOptions(action) || + isActionableTrackExpense(action) || + !!(messageHtml && parseFollowupsFromHtml(messageHtml)?.length); + + return ( + + + + + {draftMessage === undefined ? ( + + + {hasBeenFlagged && ( + + )} + {mayHaveActionableButtons && ( + + )} + + ) : ( + + )} + + + + + ); +} + +ChatMessageContent.displayName = 'ChatMessageContent'; + +export default ChatMessageContent; diff --git a/tests/ui/ClearReportActionErrorsUITest.tsx b/tests/ui/ClearReportActionErrorsUITest.tsx index 252f21f379f0..c60e78b67f85 100644 --- a/tests/ui/ClearReportActionErrorsUITest.tsx +++ b/tests/ui/ClearReportActionErrorsUITest.tsx @@ -93,7 +93,6 @@ describe('ClearReportActionErrors UI', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} clearAllRelatedReportActionErrors={clearErrorFn} originalReportID={originalReportID} /> diff --git a/tests/ui/PureReportActionItemTest.tsx b/tests/ui/PureReportActionItemTest.tsx index b3704eb3607f..94b90f345954 100644 --- a/tests/ui/PureReportActionItemTest.tsx +++ b/tests/ui/PureReportActionItemTest.tsx @@ -100,7 +100,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -394,7 +391,6 @@ describe('PureReportActionItem', () => { { reportMetadata={reportMetadata} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -453,7 +447,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -514,7 +505,6 @@ describe('PureReportActionItem', () => { { reportMetadata={reportMetadata} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -569,7 +557,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -648,7 +633,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -713,7 +695,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -798,7 +777,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} modifiedExpenseMessage={modifiedExpenseMessage} - userBillingGracePeriodEnds={undefined} /> @@ -1093,7 +1069,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} reimbursementDeQueuedOrCanceledActionMessage="Payment canceled" /> @@ -1281,7 +1254,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -1381,7 +1351,6 @@ describe('PureReportActionItem', () => { { currentUserAccountID={ACTOR_ACCOUNT_ID} isClosedExpenseReportWithNoExpenses betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -1417,7 +1384,6 @@ describe('PureReportActionItem', () => { { currentUserAccountID={ACTOR_ACCOUNT_ID} missingPaymentMethod="bankAccount" betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -1455,7 +1419,6 @@ describe('PureReportActionItem', () => { { currentUserAccountID={ACTOR_ACCOUNT_ID} missingPaymentMethod="wallet" betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -1496,7 +1457,6 @@ describe('PureReportActionItem', () => { { // eslint-disable-next-line @typescript-eslint/naming-convention bankAccountList={{12345: {accountData: {accountNumber: '000098765'}} as never}} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -1538,7 +1496,6 @@ describe('PureReportActionItem', () => { { // eslint-disable-next-line @typescript-eslint/naming-convention bankAccountList={{12345: {accountData: {accountNumber: '000098765'}} as never}} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -1583,7 +1538,6 @@ describe('PureReportActionItem', () => { { // eslint-disable-next-line @typescript-eslint/naming-convention bankAccountList={{55555: {accountData: {accountNumber: '000012345'}} as never}} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -1629,7 +1581,6 @@ describe('PureReportActionItem', () => { { // eslint-disable-next-line @typescript-eslint/naming-convention bankAccountList={{77777: {accountData: {accountNumber: '000067890'}} as never}} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -1726,7 +1675,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -1772,7 +1718,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -2301,7 +2244,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -2360,7 +2300,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} reportNameValuePairsOrigin="harvest" reportNameValuePairsOriginalID="origReport123" /> @@ -2417,7 +2354,6 @@ describe('PureReportActionItem', () => { { iouReportOfLinkedReport={undefined} currentUserAccountID={ACTOR_ACCOUNT_ID} betas={undefined} - draftTransactionIDs={[]} - userBillingGracePeriodEnds={undefined} /> @@ -2444,4 +2378,39 @@ describe('PureReportActionItem', () => { expect(screen.getByText(translateLocal('travel.tripSummary'))).toBeOnTheScreen(); }); }); + + describe('ChatMessageContent moderation and actionable buttons', () => { + it('flagged message shows "Reveal message" button when moderation decision is hidden', async () => { + const action = createReportAction(CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, {}); + action.message = [{type: 'COMMENT', html: 'bad message', text: 'bad message', moderationDecision: {decision: CONST.MODERATION.MODERATOR_DECISION_HIDDEN}}]; + renderItemWithAction(action); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByText('Reveal message')).toBeOnTheScreen(); + }); + + it('clicking "Reveal message" toggles to "Hide message"', async () => { + const action = createReportAction(CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, {}); + action.message = [{type: 'COMMENT', html: 'bad message', text: 'bad message', moderationDecision: {decision: CONST.MODERATION.MODERATOR_DECISION_HIDDEN}}]; + renderItemWithAction(action); + await waitForBatchedUpdatesWithAct(); + + fireEvent.press(screen.getByText('Reveal message')); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByText('Hide message')).toBeOnTheScreen(); + }); + + it('actionable track expense whisper renders track expense buttons', async () => { + const action = createReportAction(CONST.REPORT.ACTIONS.TYPE.ACTIONABLE_TRACK_EXPENSE_WHISPER, { + transactionID: 'tx123', + }); + action.message = [{type: 'COMMENT', html: 'Track this expense', text: 'Track this expense'}]; + renderItemWithAction(action); + await waitForBatchedUpdatesWithAct(); + + expect(screen.getByText(translateLocal('actionableMentionTrackExpense.submit' as TranslationPaths))).toBeOnTheScreen(); + expect(screen.getByText(translateLocal('actionableMentionTrackExpense.nothing' as TranslationPaths))).toBeOnTheScreen(); + }); + }); });