diff --git a/src/components/DisplayNames/index.native.tsx b/src/components/DisplayNames/index.native.tsx index 3ca810aa4d36..c37c299f4094 100644 --- a/src/components/DisplayNames/index.native.tsx +++ b/src/components/DisplayNames/index.native.tsx @@ -1,6 +1,8 @@ import React from 'react'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; +import Parser from '@libs/Parser'; +import StringUtils from '@libs/StringUtils'; import type DisplayNamesProps from './types'; // As we don't have to show tooltips of the Native platform so we simply render the full display names list. @@ -13,7 +15,7 @@ function DisplayNames({accessibilityLabel, fullTitle, textStyles = [], numberOfL numberOfLines={numberOfLines} testID={DisplayNames.displayName} > - {fullTitle || translate('common.hidden')} + {StringUtils.lineBreaksToSpaces(Parser.htmlToText(fullTitle)) || translate('common.hidden')} {renderAdditionalText?.()} ); diff --git a/src/components/DisplayNames/index.tsx b/src/components/DisplayNames/index.tsx index 43e29af6e3c0..a9f9e579d483 100644 --- a/src/components/DisplayNames/index.tsx +++ b/src/components/DisplayNames/index.tsx @@ -1,12 +1,14 @@ import React from 'react'; import useLocalize from '@hooks/useLocalize'; +import Parser from '@libs/Parser'; +import StringUtils from '@libs/StringUtils'; import DisplayNamesWithoutTooltip from './DisplayNamesWithoutTooltip'; import DisplayNamesWithToolTip from './DisplayNamesWithTooltip'; import type DisplayNamesProps from './types'; function DisplayNames({fullTitle, tooltipEnabled, textStyles, numberOfLines, shouldAddEllipsis, shouldUseFullTitle, displayNamesWithTooltips, renderAdditionalText}: DisplayNamesProps) { const {translate} = useLocalize(); - const title = fullTitle || translate('common.hidden'); + const title = StringUtils.lineBreaksToSpaces(Parser.htmlToText(fullTitle)) || translate('common.hidden'); if (!tooltipEnabled) { return ( diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 2037d5251518..ba1b16ee6336 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -105,17 +105,17 @@ function MoneyRequestPreviewContent({ const {windowWidth} = useWindowDimensions(); const route = useRoute>(); const {shouldUseNarrowLayout} = useResponsiveLayout(); - const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); - const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`); - const [session] = useOnyx(ONYXKEYS.SESSION); - const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`); + const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); + const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`, {canBeMissing: false}); + const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false}); + const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, {canBeMissing: false}); const {isOnSearch} = useSearchContext(); const policy = usePolicy(iouReport?.policyID); const isMoneyRequestAction = isMoneyRequestActionReportActionsUtils(action); const transactionID = isMoneyRequestAction ? getOriginalMessage(action)?.IOUTransactionID : undefined; - const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`); - const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS); + const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {canBeMissing: true}); + const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS, {canBeMissing: true}); const violations = useTransactionViolations(transaction?.transactionID); const sessionAccountID = session?.accountID; @@ -142,7 +142,7 @@ function MoneyRequestPreviewContent({ category, } = useMemo>(() => getTransactionDetails(transaction) ?? {}, [transaction]); - const description = truncate(StringUtils.lineBreaksToSpaces(Parser.htmlToMarkdown(requestComment ?? '')), {length: CONST.REQUEST_PREVIEW.MAX_LENGTH}); + const description = truncate(StringUtils.lineBreaksToSpaces(Parser.htmlToText(requestComment ?? '')), {length: CONST.REQUEST_PREVIEW.MAX_LENGTH}); const requestMerchant = truncate(merchant, {length: CONST.REQUEST_PREVIEW.MAX_LENGTH}); const hasReceipt = hasReceiptTransactionUtils(transaction); const isScanning = hasReceipt && isReceiptBeingScanned(transaction); @@ -184,7 +184,7 @@ function MoneyRequestPreviewContent({ // We don't use isOnHold because it's true for duplicated transaction too and we only want to show hold message if the transaction is truly on hold const shouldShowHoldMessage = !(isSettled && !isSettlementOrApprovalPartial) && !!transaction?.comment?.hold; - const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params?.threadReportID}`); + const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params?.threadReportID}`, {canBeMissing: false}); const parentReportAction = getReportAction(report?.parentReportID, report?.parentReportActionID); const reviewingTransactionID = isMoneyRequestActionReportActionsUtils(parentReportAction) ? getOriginalMessage(parentReportAction)?.IOUTransactionID : undefined; diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 6df707f23571..ab5b7df312b1 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -150,17 +150,19 @@ function ReportPreview({ shouldDisplayContextMenu = true, }: ReportPreviewProps) { const policy = usePolicy(policyID); - const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`); + const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`, {canBeMissing: false}); const [iouReport, transactions, violations] = useReportWithTransactionsAndViolations(iouReportID); const lastTransaction = transactions?.at(0); const transactionIDList = transactions?.map((reportTransaction) => reportTransaction.transactionID) ?? []; - const [userWallet] = useOnyx(ONYXKEYS.USER_WALLET); + const [userWallet] = useOnyx(ONYXKEYS.USER_WALLET, {canBeMissing: false}); const [invoiceReceiverPolicy] = useOnyx( - `${ONYXKEYS.COLLECTION.POLICY}${chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : CONST.DEFAULT_NUMBER_ID}`, + `${ONYXKEYS.COLLECTION.POLICY}${chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : undefined}`, + {canBeMissing: true}, ); const [invoiceReceiverPersonalDetail] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, { selector: (personalDetails) => personalDetails?.[chatReport?.invoiceReceiver && 'accountID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.accountID : CONST.DEFAULT_NUMBER_ID], + canBeMissing: true, }); const theme = useTheme(); const styles = useThemeStyles(); @@ -200,7 +202,7 @@ function ReportPreview({ const managerID = iouReport?.managerID ?? action.childManagerAccountID ?? CONST.DEFAULT_NUMBER_ID; const {totalDisplaySpend, reimbursableSpend} = getMoneyRequestSpendBreakdown(iouReport); - const [reports] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}`); + const [reports] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}`, {canBeMissing: false}); const iouSettled = isSettled(iouReportID, isOnSearch ? reports : undefined) || action?.childStatusNum === CONST.REPORT.STATUS_NUM.REIMBURSED; const previewMessageOpacity = useSharedValue(1); const previewMessageStyle = useAnimatedStyle(() => ({ @@ -413,7 +415,7 @@ function ReportPreview({ const shouldShowSubtitle = !isScanning && (shouldShowSingleRequestMerchantOrDescription || numberOfRequests > 1) && !isDisplayAmountZero(getDisplayAmount()); const isPayAtEndExpense = isPayAtEndExpenseReport(iouReportID, transactions); - const [archiveReason] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, {selector: getArchiveReason}); + const [archiveReason] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, {selector: getArchiveReason, canBeMissing: false}); const getPendingMessageProps: () => PendingMessageProps = () => { if (isPayAtEndExpense) { @@ -441,7 +443,11 @@ function ReportPreview({ return {supportText: truncate(formattedMerchant, {length: CONST.REQUEST_PREVIEW.MAX_LENGTH})}; } if (formattedDescription ?? moneyRequestComment) { - return {supportText: truncate(StringUtils.lineBreaksToSpaces(formattedDescription ?? moneyRequestComment), {length: CONST.REQUEST_PREVIEW.MAX_LENGTH})}; + return { + supportText: truncate(StringUtils.lineBreaksToSpaces(Parser.htmlToText(Parser.replace(formattedDescription ?? moneyRequestComment))), { + length: CONST.REQUEST_PREVIEW.MAX_LENGTH, + }), + }; } if (numberOfRequests === 1) { diff --git a/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx b/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx index 8389f4521d3a..814f10d507db 100644 --- a/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx +++ b/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx @@ -16,6 +16,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {convertToDisplayString} from '@libs/CurrencyUtils'; import {calculateAmount} from '@libs/IOUUtils'; import {getAvatarsForAccountIDs} from '@libs/OptionsListUtils'; +import Parser from '@libs/Parser'; import {getCleanedTagName} from '@libs/PolicyUtils'; import {getThumbnailAndImageURIs} from '@libs/ReceiptUtils'; import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils'; @@ -116,7 +117,7 @@ function TransactionPreviewContent({ const shouldShowCategoryOrTag = shouldShowCategory || shouldShowTag; const shouldShowMerchantOrDescription = shouldShowDescription || shouldShowMerchant; const shouldShowIOUHeader = !!from && !!to; - const description = truncate(StringUtils.lineBreaksToSpaces(requestComment), {length: CONST.REQUEST_PREVIEW.MAX_LENGTH}); + const description = truncate(StringUtils.lineBreaksToSpaces(Parser.htmlToText(requestComment ?? '')), {length: CONST.REQUEST_PREVIEW.MAX_LENGTH}); const requestMerchant = truncate(merchant, {length: CONST.REQUEST_PREVIEW.MAX_LENGTH}); const hasReceipt = hasReceiptTransactionUtils(transaction); const isApproved = isReportApproved({report: iouReport}); diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 2c2098d9686e..d27fc4243df4 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -45,6 +45,7 @@ import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {ReportDetailsNavigatorParamList} from '@libs/Navigation/types'; import {getPersonalDetailsForAccountIDs} from '@libs/OptionsListUtils'; +import Parser from '@libs/Parser'; import {getConnectedIntegration, isPolicyAdmin as isPolicyAdminUtil, isPolicyEmployee as isPolicyEmployeeUtil, shouldShowPolicy} from '@libs/PolicyUtils'; import {getOneTransactionThreadReportID, getOriginalMessage, getTrackExpenseActionableWhisper, isDeletedAction, isMoneyRequestAction, isTrackExpenseAction} from '@libs/ReportActionsUtils'; import { @@ -181,7 +182,7 @@ function ReportDetailsPage({policies, report, route, reportMetadata}: ReportDeta selector: (actions) => (report?.parentReportActionID ? actions?.[report.parentReportActionID] : undefined), canBeMissing: true, }); - const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true}); + const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: false}); const [parentReportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.parentReportID}`, {canBeMissing: true}); /* eslint-enable @typescript-eslint/prefer-nullish-coalescing */ const {reportActions} = usePaginatedReportActions(report.reportID); @@ -382,7 +383,7 @@ function ReportDetailsPage({policies, report, route, reportMetadata}: ReportDeta const shouldShowLeaveButton = canLeaveChat(report, policy); const shouldShowGoToWorkspace = shouldShowPolicy(policy, false, session?.email) && !policy?.isJoinRequestPending; - const reportName = getReportName(report); + const reportName = Parser.htmlToText(getReportName(report)); const additionalRoomDetails = (isPolicyExpenseChat && !!report?.isOwnPolicyExpenseChat) || isExpenseReportUtil(report) || isPolicyExpenseChat || isInvoiceRoom diff --git a/src/pages/TransactionDuplicate/ReviewDescription.tsx b/src/pages/TransactionDuplicate/ReviewDescription.tsx index ad6d25960cb4..d261591b4c45 100644 --- a/src/pages/TransactionDuplicate/ReviewDescription.tsx +++ b/src/pages/TransactionDuplicate/ReviewDescription.tsx @@ -8,7 +8,9 @@ import useReviewDuplicatesNavigation from '@hooks/useReviewDuplicatesNavigation' import {setReviewDuplicatesKey} from '@libs/actions/Transaction'; import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types'; import type {TransactionDuplicateNavigatorParamList} from '@libs/Navigation/types'; -import * as TransactionUtils from '@libs/TransactionUtils'; +import Parser from '@libs/Parser'; +import StringUtils from '@libs/StringUtils'; +import {compareDuplicateTransactionFields, getTransactionID} from '@libs/TransactionUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type {FieldItemType} from './ReviewFields'; @@ -17,14 +19,14 @@ import ReviewFields from './ReviewFields'; function ReviewDescription() { const route = useRoute>(); const {translate} = useLocalize(); - const transactionID = TransactionUtils.getTransactionID(route.params.threadReportID ?? ''); - const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES); - const compareResult = TransactionUtils.compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID ?? '-1'); + const transactionID = getTransactionID(route.params.threadReportID); + const [reviewDuplicates] = useOnyx(ONYXKEYS.REVIEW_DUPLICATES, {canBeMissing: false}); + const compareResult = compareDuplicateTransactionFields(transactionID, reviewDuplicates?.reportID); const stepNames = Object.keys(compareResult.change ?? {}).map((key, index) => (index + 1).toString()); const {currentScreenIndex, goBack, navigateToNextScreen} = useReviewDuplicatesNavigation( Object.keys(compareResult.change ?? {}), 'description', - route.params.threadReportID ?? '', + route.params.threadReportID, route.params.backTo, ); const options = useMemo( @@ -33,7 +35,7 @@ function ReviewDescription() { !description?.comment ? {text: translate('violations.none'), value: ''} : { - text: description.comment, + text: StringUtils.lineBreaksToSpaces(Parser.htmlToText(description.comment)), value: description.comment, }, ),