Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
bd2ca74
Implement system message for card freeze and unfreeze actions
ShridharGoel Mar 10, 2026
c0fe4f5
Implement system message for card freeze and unfreeze actions
ShridharGoel Mar 12, 2026
0cee92b
Update `deleteMoneyRequest` to pass currentuseremail
parasharrajat Mar 28, 2026
80aee86
fix
parasharrajat Mar 28, 2026
a77cdfa
Clean up ReportActionCompose: remove manual memo, dead code, derive s…
adhorodyski Apr 1, 2026
db163b4
Remove didHideComposerInput latch — modal refocus is platform-driven
adhorodyski Apr 1, 2026
7c8ffac
SuggestionMention: fix double sub, self-subscribe, remove manual memo
adhorodyski Apr 1, 2026
99ff238
useAttachmentUploadValidation: self-subscribe to policy, parentReport…
adhorodyski Apr 1, 2026
5ec8f1a
Extract ComposerDropZone: guard-wrapped, self-subscribing drop zone
adhorodyski Apr 1, 2026
4e05c2c
Extract ComposerLocalTime (guard-wrapped) and ComposerFooter
adhorodyski Apr 1, 2026
e51aa0b
Extract useComposerSubmit + useComposerFocus hooks
adhorodyski Apr 1, 2026
a791e48
ComposerProvider + ComposerBox + Composer orchestrator with compound API
adhorodyski Apr 1, 2026
3cf0100
Lift text value to ComposerProvider, derive isEmpty inline
adhorodyski Apr 1, 2026
f790a57
ComposerFooter: read from context directly, remove wrapper
adhorodyski Apr 1, 2026
747c13f
Extract useLastEditableAction: isolate arrow-up-to-edit subscriptions
adhorodyski Apr 1, 2026
9a35791
DropZone wraps Box, remove shouldAddOrReplaceReceipt prop drilling
adhorodyski Apr 1, 2026
967a0dd
Skip filter iteration when offline — condition is always true
adhorodyski Apr 1, 2026
350d00d
useComposerSubmit: self-compute effectiveTransactionThreadReportID
adhorodyski Apr 1, 2026
e773bcd
Simplify ComposerLocalTime: remove unnecessary guard pattern
adhorodyski Apr 1, 2026
4b5d826
Rename ComposerInternals* → ComposerData/ComposerDataActions
adhorodyski Apr 1, 2026
fa383a2
Move emoji picker cleanup to ComposerBoxContent, co-located with trigger
adhorodyski Apr 1, 2026
a44b7cc
pendingAction: derive in consumers, stop drilling from orchestrator
adhorodyski Apr 1, 2026
71e25f6
ComposerLocalTime: read isComposerFullSize from context
adhorodyski Apr 1, 2026
1d3f809
Replace IIFEs with inline definitions
adhorodyski Apr 1, 2026
23811f5
Extract ComposerBoxContent to own file, orchestrator is 60 LOC
adhorodyski Apr 1, 2026
be7f848
Remove redundant report guard and subscription from orchestrator
adhorodyski Apr 1, 2026
3bad8ad
Extract Composer.SendButton + Composer.EmojiPicker as compound compon…
adhorodyski Apr 1, 2026
969e889
ComposerEmojiPicker: use reportID prop directly, drop report subscrip…
adhorodyski Apr 1, 2026
eb84627
Split ComposerBoxContent into Composer.ActionMenu + Composer.Input
adhorodyski Apr 1, 2026
e6eaefb
Rename ComposerData → ComposerMeta across contexts and consumers
adhorodyski Apr 1, 2026
0e893c2
Move containerRef to ComposerMeta, delete ComposerBoxContext
adhorodyski Apr 1, 2026
790f1db
Remove unconditional chatItemComposeWithFirstRow — test if layout hol…
adhorodyski Apr 1, 2026
227fcd2
Remove accidentally committed plan file
adhorodyski Apr 1, 2026
16606fa
Merge branch 'Expensify:main' into onyx/session-2
parasharrajat Apr 1, 2026
0796a7e
Bump react-native-onyx from 3.0.54 to 3.0.57.
Krishna2323 Apr 1, 2026
2e0b4a5
Restructure ComposerContext: 6 contexts by change frequency
adhorodyski Apr 2, 2026
08e66ab
Split useComposerSubmit: accept attachmentFileRef as param, return on…
adhorodyski Apr 2, 2026
4531ae2
Rewrite ComposerProvider: 6 context providers, inline addAttachment +…
adhorodyski Apr 2, 2026
b85935c
Update leaf consumers to new context API
adhorodyski Apr 2, 2026
1402e64
Update ComposerBox + ComposerActionMenu to new context API
adhorodyski Apr 2, 2026
d563c0a
Update InputWrapper + ComposerWithSuggestions to new context API
adhorodyski Apr 2, 2026
c2beb2f
Fix lint errors — remove unused imports, remove leftover useComposerS…
adhorodyski Apr 2, 2026
68bfc12
Merge branch 'main' of https://github.com/Expensify/App into cardfree…
ShridharGoel Apr 2, 2026
2761058
Prettier and cspell update
ShridharGoel Apr 2, 2026
3446527
Update tests
ShridharGoel Apr 2, 2026
882ccd2
Fix: Show all payment options for non-reimbursable expenses in report…
MelvinBot Apr 2, 2026
98be929
fix: Per attendee amount on the table does not show negative sign
nkdengineer Apr 3, 2026
d222a21
Merge pull request #86924 from Krishna2323/krishna2323/chore/84192-bu…
robertjchen Apr 3, 2026
0eda3f5
Merge pull request #85016 from ShridharGoel/cardfreeze-systemmessage
MariaHCD Apr 3, 2026
70e6890
Add non-reimbursable payment guard to PayPrimaryAction
MelvinBot Apr 3, 2026
bb8de58
Merge pull request #87048 from nkdengineer/fix/87006
justinpersaud Apr 3, 2026
687fb80
Merge pull request #87023 from Expensify/claude-fixNonReimbursablePay…
cristipaval Apr 3, 2026
f98114f
Remove attachment/receipt actions from ComposerContext, add clearComp…
adhorodyski Apr 3, 2026
e8d1877
Remove attachment/receipt logic from ComposerProvider, add clearComposer
adhorodyski Apr 3, 2026
f747fdc
Add useAttachmentPicker hook
adhorodyski Apr 3, 2026
0e3bdf5
Add useReceiptDrop hook
adhorodyski Apr 3, 2026
5bf80d2
Update consumers to use local attachment hooks
adhorodyski Apr 3, 2026
b16129f
Delete useAttachmentUploadValidation — replaced by useAttachmentPicke…
adhorodyski Apr 3, 2026
d145c25
Fix unused param lint error in useReceiptDrop
adhorodyski Apr 3, 2026
576f0e1
Remove dead context fields: isEmpty, setIsFocused, validateMaxLength,…
adhorodyski Apr 3, 2026
978ca84
Move isFocused state ownership into useComposerFocus
adhorodyski Apr 3, 2026
c76158c
Merge pull request #86606 from parasharrajat/onyx/session-2
tgolen Apr 3, 2026
535dc54
Wrap PopoverMenu and EmojiPicker in Activity to skip hidden subtree r…
adhorodyski Apr 3, 2026
7f59f26
Merge exfy/main, port AI placeholder to ComposerInputWrapper
adhorodyski Apr 3, 2026
2c42028
Remove plan and spec files from PR
adhorodyski Apr 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,9 @@
"Synovus",
"Wallester",
"Wintrust",
"Zürcher"
"Zürcher",
"CARDFROZEN",
"CARDUNFROZEN"
],
"ignorePaths": [
"src/languages/de.ts",
Expand Down
14 changes: 5 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@
"react-native-localize": "^3.5.4",
"react-native-nitro-modules": "0.29.4",
"react-native-nitro-sqlite": "9.2.0",
"react-native-onyx": "3.0.54",
"react-native-onyx": "3.0.57",
"react-native-pager-view": "8.0.0",
"react-native-pdf": "7.0.2",
"react-native-permissions": "^5.4.0",
Expand Down
2 changes: 2 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,8 @@ const CONST = {
CARD_REPLACED_VIRTUAL: 'CARDREPLACEDVIRTUAL',
CARD_REPLACED: 'CARDREPLACED',
CARD_ASSIGNED: 'CARDASSIGNED',
CARD_FROZEN: 'CARDFROZEN',
CARD_UNFROZEN: 'CARDUNFROZEN',
PERSONAL_CARD_CONNECTION_BROKEN: 'PERSONALCARDCONNECTIONBROKEN',
CHANGE_FIELD: 'CHANGEFIELD', // OldDot Action
CHANGE_POLICY: 'CHANGEPOLICY',
Expand Down
82 changes: 42 additions & 40 deletions src/components/EmojiPicker/EmojiPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react';
import React, {Activity, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react';
import type {ForwardedRef, RefObject} from 'react';
import {Dimensions, View} from 'react-native';
import type {Emoji} from '@assets/emojis/types';
Expand Down Expand Up @@ -236,45 +236,47 @@ function EmojiPicker({viewportOffsetTop, ref}: EmojiPickerProps) {
}, [isEmojiPickerVisible, shouldUseNarrowLayout, emojiPopoverAnchorOrigin, getEmojiPopoverAnchor, hideEmojiPicker]);

return (
<PopoverWithMeasuredContent
shouldHandleNavigationBack={isMobileChrome()}
isVisible={isEmojiPickerVisible}
onClose={hideEmojiPicker}
onModalShow={focusEmojiSearchInput}
onModalHide={handleModalHide}
shouldSetModalVisibility={false}
anchorPosition={{
vertical: emojiPopoverAnchorPosition.vertical,
horizontal: emojiPopoverAnchorPosition.horizontal,
}}
anchorRef={getEmojiPopoverAnchor() as RefObject<View | HTMLDivElement>}
withoutOverlay={isWithoutOverlay}
popoverDimensions={{
width: CONST.EMOJI_PICKER_SIZE.WIDTH,
height: CONST.EMOJI_PICKER_SIZE.HEIGHT,
}}
anchorAlignment={emojiPopoverAnchorOrigin}
outerStyle={StyleUtils.getOuterModalStyle(windowHeight, viewportOffsetTop)}
innerContainerStyle={styles.popoverInnerContainer}
anchorDimensions={emojiAnchorDimension.current}
avoidKeyboard
shouldSwitchPositionIfOverflow
shouldEnableNewFocusManagement
restoreFocusType={CONST.MODAL.RESTORE_FOCUS_TYPE.DELETE}
shouldSkipRemeasurement
>
<FocusTrapForModal active={isEmojiPickerVisible}>
<View>
<EmojiPickerMenu
onEmojiSelected={selectEmoji}
activeEmoji={activeEmoji.current}
ref={(el) => {
emojiSearchInput.current = el;
}}
/>
</View>
</FocusTrapForModal>
</PopoverWithMeasuredContent>
<Activity mode={isEmojiPickerVisible ? 'visible' : 'hidden'}>
<PopoverWithMeasuredContent
shouldHandleNavigationBack={isMobileChrome()}
isVisible={isEmojiPickerVisible}
onClose={hideEmojiPicker}
onModalShow={focusEmojiSearchInput}
onModalHide={handleModalHide}
shouldSetModalVisibility={false}
anchorPosition={{
vertical: emojiPopoverAnchorPosition.vertical,
horizontal: emojiPopoverAnchorPosition.horizontal,
}}
anchorRef={getEmojiPopoverAnchor() as RefObject<View | HTMLDivElement>}
withoutOverlay={isWithoutOverlay}
popoverDimensions={{
width: CONST.EMOJI_PICKER_SIZE.WIDTH,
height: CONST.EMOJI_PICKER_SIZE.HEIGHT,
}}
anchorAlignment={emojiPopoverAnchorOrigin}
outerStyle={StyleUtils.getOuterModalStyle(windowHeight, viewportOffsetTop)}
innerContainerStyle={styles.popoverInnerContainer}
anchorDimensions={emojiAnchorDimension.current}
avoidKeyboard
shouldSwitchPositionIfOverflow
shouldEnableNewFocusManagement
restoreFocusType={CONST.MODAL.RESTORE_FOCUS_TYPE.DELETE}
shouldSkipRemeasurement
>
<FocusTrapForModal active={isEmojiPickerVisible}>
<View>
<EmojiPickerMenu
onEmojiSelected={selectEmoji}
activeEmoji={activeEmoji.current}
ref={(el) => {
emojiSearchInput.current = el;
}}
/>
</View>
</FocusTrapForModal>
</PopoverWithMeasuredContent>
</Activity>
);
}

Expand Down
65 changes: 41 additions & 24 deletions src/components/MoneyReportHeaderPrimaryAction/PayPrimaryAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import AnimatedSettlementButton from '@components/SettlementButton/AnimatedSettl
import type {PaymentActionParams} from '@components/SettlementButton/types';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useNetwork from '@hooks/useNetwork';
import useNonReimbursablePaymentModal from '@hooks/useNonReimbursablePaymentModal';
import useOnyx from '@hooks/useOnyx';
import useParticipantsInvoiceReport from '@hooks/useParticipantsInvoiceReport';
import usePolicy from '@hooks/usePolicy';
Expand All @@ -14,7 +15,13 @@ import useTransactionsAndViolationsForReport from '@hooks/useTransactionsAndViol
import {search} from '@libs/actions/Search';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import {getTotalAmountForIOUReportPreviewButton} from '@libs/MoneyRequestReportUtils';
import {hasHeldExpenses as hasHeldExpensesReportUtils, hasUpdatedTotal, isAllowedToApproveExpenseReport, isInvoiceReport as isInvoiceReportUtil} from '@libs/ReportUtils';
import {
hasHeldExpenses as hasHeldExpensesReportUtils,
hasOnlyNonReimbursableTransactions,
hasUpdatedTotal,
isAllowedToApproveExpenseReport,
isInvoiceReport as isInvoiceReportUtil,
} from '@libs/ReportUtils';
import {isExpensifyCardTransaction, isPending} from '@libs/TransactionUtils';
import {canApproveIOU, canIOUBePaid as canIOUBePaidAction, payInvoice, payMoneyRequest} from '@userActions/IOU';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -76,9 +83,12 @@ function PayPrimaryAction({
const hasOnlyPendingTransactions = transactions.length > 0 && transactions.every((t) => isExpensifyCardTransaction(t) && isPending(t));

const canIOUBePaid = canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, transaction ? [transaction] : undefined, false, undefined, invoiceReceiverPolicy);
const onlyShowPayElsewhere =
!canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, transaction ? [transaction] : undefined, true, undefined, invoiceReceiverPolicy);
const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere;
const reportHasOnlyNonReimbursableTransactions = hasOnlyNonReimbursableTransactions(moneyRequestReport?.reportID, transactions);
const {showNonReimbursablePaymentErrorModal, shouldBlockDirectPayment, nonReimbursablePaymentErrorDecisionModal} = useNonReimbursablePaymentModal(moneyRequestReport, transactions);
const onlyShowPayElsewhere = reportHasOnlyNonReimbursableTransactions
? false
: !canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, transaction ? [transaction] : undefined, true, undefined, invoiceReceiverPolicy);
const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere || reportHasOnlyNonReimbursableTransactions;
const shouldShowApproveButton = (canApproveIOU(moneyRequestReport, policy, reportMetadata, transactions) && !hasOnlyPendingTransactions) || isApprovedAnimationRunning;
const shouldDisableApproveButton = shouldShowApproveButton && !isAllowedToApproveExpenseReport(moneyRequestReport);
const canAllowSettlement = hasUpdatedTotal(moneyRequestReport, policy);
Expand All @@ -94,6 +104,10 @@ function PayPrimaryAction({
if (!type || !chatReport) {
return;
}
if (shouldBlockDirectPayment(type)) {
showNonReimbursablePaymentErrorModal();
return;
}
if (isDelegateAccessRestricted) {
showDelegateNoAccessModal();
} else if (isAnyTransactionOnHold) {
Expand Down Expand Up @@ -149,26 +163,29 @@ function PayPrimaryAction({
};

return (
<AnimatedSettlementButton
isPaidAnimationRunning={isPaidAnimationRunning}
isApprovedAnimationRunning={isApprovedAnimationRunning}
onAnimationFinish={stopAnimation}
formattedAmount={totalAmount}
canIOUBePaid
onlyShowPayElsewhere={onlyShowPayElsewhere}
currency={moneyRequestReport?.currency}
confirmApproval={confirmApproval}
policyID={moneyRequestReport?.policyID}
chatReportID={chatReport?.reportID}
iouReport={moneyRequestReport}
onPress={confirmPayment}
enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS}
shouldHidePaymentOptions={!shouldShowPayButton}
shouldShowApproveButton={shouldShowApproveButton}
shouldDisableApproveButton={shouldDisableApproveButton}
isDisabled={isOffline && !canAllowSettlement}
isLoading={!isOffline && !canAllowSettlement}
/>
<>
<AnimatedSettlementButton
isPaidAnimationRunning={isPaidAnimationRunning}
isApprovedAnimationRunning={isApprovedAnimationRunning}
onAnimationFinish={stopAnimation}
formattedAmount={totalAmount}
canIOUBePaid
onlyShowPayElsewhere={onlyShowPayElsewhere}
currency={moneyRequestReport?.currency}
confirmApproval={confirmApproval}
policyID={moneyRequestReport?.policyID}
chatReportID={chatReport?.reportID}
iouReport={moneyRequestReport}
onPress={confirmPayment}
enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS}
shouldHidePaymentOptions={!shouldShowPayButton}
shouldShowApproveButton={shouldShowApproveButton}
shouldDisableApproveButton={shouldDisableApproveButton}
isDisabled={isOffline && !canAllowSettlement}
isLoading={!isOffline && !canAllowSettlement}
/>
{nonReimbursablePaymentErrorDecisionModal}
</>
);
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/TransactionItemRow/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -280,14 +280,14 @@ function TransactionItemRow({

const totalPerAttendee = useMemo(() => {
const attendeesCount = transactionAttendees.length ?? 0;
const totalAmount = getAmount(transactionItem);
const totalAmount = getAmount(transactionItem, isExpenseReport(report));

if (!attendeesCount || totalAmount === undefined) {
return undefined;
}

return totalAmount / attendeesCount;
}, [transactionAttendees.length, transactionItem]);
}, [report, transactionAttendees.length, transactionItem]);

const renderColumn = (column: SearchColumnType): React.ReactNode => {
switch (column) {
Expand Down
1 change: 1 addition & 0 deletions src/hooks/useDeleteTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ function useDeleteTransactions({report, reportActions, policy}: UseDeleteTransac
selectedTransactionIDs: transactionIDs,
allTransactionViolationsParam: transactionViolations,
currentUserAccountID: currentUserPersonalDetails.accountID,
currentUserEmail: currentUserPersonalDetails.email ?? '',
});
deletedTransactionIDs.push(transactionID);
if (action.childReportID) {
Expand Down
21 changes: 5 additions & 16 deletions src/libs/actions/IOU/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,7 @@
selectedTransactionIDs?: string[];
allTransactionViolationsParam: OnyxCollection<OnyxTypes.TransactionViolations>;
currentUserAccountID: number;
currentUserEmail: string;
};

type PayMoneyRequestFunctionParams = {
Expand Down Expand Up @@ -8608,6 +8609,7 @@
selectedTransactionIDs,
allTransactionViolationsParam,
currentUserAccountID,
currentUserEmail,

Check failure

Code scanning / CodeQL

Insecure randomness High

This uses a cryptographically insecure random number generated at
Math.random()
in a security context.
This uses a cryptographically insecure random number generated at
Math.random()
in a security context.
}: DeleteMoneyRequestFunctionParams) {
if (!transactionID) {
return;
Expand Down Expand Up @@ -8691,14 +8693,7 @@
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport?.reportID}`,
value: {
hasOutstandingChildRequest: hasOutstandingChildRequest(
chatReport,
updatedIOUReport,
deprecatedCurrentUserEmail,
currentUserAccountID,
allTransactionViolationsParam,
undefined,
),
hasOutstandingChildRequest: hasOutstandingChildRequest(chatReport, updatedIOUReport, currentUserEmail, currentUserAccountID, allTransactionViolationsParam, undefined),
},
});
}
Expand All @@ -8717,14 +8712,7 @@
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport?.reportID}`,
value: {
hasOutstandingChildRequest: hasOutstandingChildRequest(
chatReport,
iouReport?.reportID,
deprecatedCurrentUserEmail,
currentUserAccountID,
allTransactionViolationsParam,
undefined,
),
hasOutstandingChildRequest: hasOutstandingChildRequest(chatReport, iouReport?.reportID, currentUserEmail, currentUserAccountID, allTransactionViolationsParam, undefined),
iouReportID: null,
...optimisticLastReportData,
},
Expand Down Expand Up @@ -8936,6 +8924,7 @@
isSingleTransactionView,
allTransactionViolationsParam,
currentUserAccountID,
currentUserEmail: deprecatedCurrentUserEmail,
});
return urlToNavigateBack;
}
Expand Down
1 change: 1 addition & 0 deletions src/libs/actions/Search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,7 @@ function bulkDeleteReports({
selectedTransactionIDs: batchTransactionIDsForReport.length > 0 ? batchTransactionIDsForReport : undefined,
allTransactionViolationsParam: transactionsViolations,
currentUserAccountID: currentUserAccountIDParam,
currentUserEmail: currentUserEmailParam,
});
}

Expand Down
8 changes: 7 additions & 1 deletion src/pages/inbox/report/PureReportActionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ import {
getRemovedFromApprovalChainMessage,
getRenamedAction,
getRenamedCardFeedMessage,
getReportActionHtml,
getReportActionMessage,
getReportActionText,
getSetAutoJoinMessage,
Expand Down Expand Up @@ -1523,6 +1524,12 @@ function PureReportActionItem({
children = <UnreportedTransactionAction action={action as OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.UNREPORTED_TRANSACTION>} />;
} else if (action.actionName === CONST.REPORT.ACTIONS.TYPE.MERGED_WITH_CASH_TRANSACTION) {
children = <ReportActionItemBasicMessage message={translate('systemMessage.mergedWithCashTransaction')} />;
} else if (action.actionName === CONST.REPORT.ACTIONS.TYPE.CARD_FROZEN || action.actionName === CONST.REPORT.ACTIONS.TYPE.CARD_UNFROZEN) {
children = (
<ReportActionItemBasicMessage message="">
<RenderHTML html={`<comment><muted-text>${getReportActionHtml(action)}</muted-text></comment>`} />
</ReportActionItemBasicMessage>
);
} else if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.DISMISSED_VIOLATION)) {
children = <ReportActionItemBasicMessage message={getDismissedViolationMessageText(translate, getOriginalMessage(action))} />;
} else if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.RESOLVED_DUPLICATES)) {
Expand Down Expand Up @@ -1871,7 +1878,6 @@ function PureReportActionItem({
draftMessage={draftMessage}
reportID={reportID}
originalReportID={originalReportID}
policyID={report?.policyID}
index={index}
ref={composerTextInputRef}
shouldDisableEmojiPicker={
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import useShouldSuppressConciergeIndicators from '@hooks/useShouldSuppressConciergeIndicators';
import ReportTypingIndicator from '@pages/inbox/report/ReportTypingIndicator';

function AgentZeroAwareTypingIndicator({reportID}: {reportID: string}) {
const shouldSuppress = useShouldSuppressConciergeIndicators(reportID);
if (shouldSuppress) {
return null;
}
return <ReportTypingIndicator reportID={reportID} />;
}

export default AgentZeroAwareTypingIndicator;
Loading
Loading