From 3bb114b80887b6da5ef4d85d767f5eb6b3cae9a8 Mon Sep 17 00:00:00 2001
From: Qichen Zhu <57348009+QichenZhu@users.noreply.github.com>
Date: Thu, 20 Nov 2025 01:25:35 +1300
Subject: [PATCH] Revert #74928

---
 src/components/DisplayNames/index.native.tsx  |   9 +-
 src/components/DisplayNames/index.tsx         |   5 +-
 src/components/DisplayNames/types.ts          |   3 -
 src/libs/ReportUtils.ts                       |   2 +-
 src/pages/ReportDetailsPage.tsx               |   9 +-
 .../unit/DisplayNamesShouldParseHTMLTest.tsx  | 113 ------------------
 tests/unit/ReportUtilsTest.ts                 |  27 -----
 7 files changed, 9 insertions(+), 159 deletions(-)
 delete mode 100644 tests/unit/DisplayNamesShouldParseHTMLTest.tsx

diff --git a/src/components/DisplayNames/index.native.tsx b/src/components/DisplayNames/index.native.tsx
index ab0e659cdb6f..cae91c80272e 100644
--- a/src/components/DisplayNames/index.native.tsx
+++ b/src/components/DisplayNames/index.native.tsx
@@ -8,11 +8,8 @@ import TextWithEmojiFragment from '@pages/home/report/comment/TextWithEmojiFragm
 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.
-function DisplayNames({accessibilityLabel, fullTitle, textStyles = [], numberOfLines = 1, renderAdditionalText, forwardedFSClass, testID, shouldParseHtml = false}: DisplayNamesProps) {
+function DisplayNames({accessibilityLabel, fullTitle, textStyles = [], numberOfLines = 1, renderAdditionalText, forwardedFSClass, testID}: DisplayNamesProps) {
     const {translate} = useLocalize();
-    const title = shouldParseHtml
-        ? StringUtils.lineBreaksToSpaces(Parser.htmlToText(fullTitle)) || translate('common.hidden')
-        : StringUtils.lineBreaksToSpaces(fullTitle) || translate('common.hidden');
     const titleContainsTextAndCustomEmoji = useMemo(() => containsCustomEmoji(fullTitle) && !containsOnlyCustomEmoji(fullTitle), [fullTitle]);
     return (
         <Text
@@ -24,11 +21,11 @@ function DisplayNames({accessibilityLabel, fullTitle, textStyles = [], numberOfL
         >
             {titleContainsTextAndCustomEmoji ? (
                 <TextWithEmojiFragment
-                    message={title}
+                    message={StringUtils.lineBreaksToSpaces(Parser.htmlToText(fullTitle)) || translate('common.hidden')}
                     style={textStyles}
                 />
             ) : (
-                title
+                StringUtils.lineBreaksToSpaces(Parser.htmlToText(fullTitle)) || translate('common.hidden')
             )}
             {renderAdditionalText?.()}
         </Text>
diff --git a/src/components/DisplayNames/index.tsx b/src/components/DisplayNames/index.tsx
index 5e1a82104501..5158747e4c25 100644
--- a/src/components/DisplayNames/index.tsx
+++ b/src/components/DisplayNames/index.tsx
@@ -16,12 +16,9 @@ function DisplayNames({
     displayNamesWithTooltips,
     renderAdditionalText,
     forwardedFSClass,
-    shouldParseHtml = false,
 }: DisplayNamesProps) {
     const {translate} = useLocalize();
-    const title = shouldParseHtml
-        ? StringUtils.lineBreaksToSpaces(Parser.htmlToText(fullTitle)) || translate('common.hidden')
-        : StringUtils.lineBreaksToSpaces(fullTitle) || translate('common.hidden');
+    const title = StringUtils.lineBreaksToSpaces(Parser.htmlToText(fullTitle)) || translate('common.hidden');
 
     if (!tooltipEnabled) {
         return (
diff --git a/src/components/DisplayNames/types.ts b/src/components/DisplayNames/types.ts
index a1c3e1d4960b..1b9a69510da3 100644
--- a/src/components/DisplayNames/types.ts
+++ b/src/components/DisplayNames/types.ts
@@ -49,9 +49,6 @@ type DisplayNamesProps = ForwardedFSClassProps & {
 
     /** TestID indicating order */
     testID?: number;
-
-    /** Whether to parse HTML in the fullTitle */
-    shouldParseHtml?: boolean;
 };
 
 export default DisplayNamesProps;
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 37b9a27dc267..0b1712e3a07a 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -5682,7 +5682,7 @@ function getReportName(
     }
 
     if (isActionOfType(parentReportAction, CONST.REPORT.ACTIONS.TYPE.UNREPORTED_TRANSACTION)) {
-        return Parser.htmlToText(getUnreportedTransactionMessage());
+        return getUnreportedTransactionMessage();
     }
 
     if (isActionOfType(parentReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_MAX_EXPENSE_AMOUNT_NO_RECEIPT)) {
diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx
index 3900c1deeb18..8b645d1ace3b 100644
--- a/src/pages/ReportDetailsPage.tsx
+++ b/src/pages/ReportDetailsPage.tsx
@@ -10,6 +10,7 @@ import ConfirmModal from '@components/ConfirmModal';
 import DisplayNames from '@components/DisplayNames';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import MentionReportContext from '@components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/MentionReportContext';
+import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
 import OfflineWithFeedback from '@components/OfflineWithFeedback';
@@ -26,7 +27,6 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'
 import useDeleteTransactions from '@hooks/useDeleteTransactions';
 import useDuplicateTransactionsAndViolations from '@hooks/useDuplicateTransactionsAndViolations';
 import useGetIOUReportFromReportAction from '@hooks/useGetIOUReportFromReportAction';
-import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
@@ -41,6 +41,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 Permissions from '@libs/Permissions';
 import {isPolicyAdmin as isPolicyAdminUtil, isPolicyEmployee as isPolicyEmployeeUtil, shouldShowPolicy} from '@libs/PolicyUtils';
 import {getOneTransactionThreadReportID, getOriginalMessage, getTrackExpenseActionableWhisper, isDeletedAction, isMoneyRequestAction, isTrackExpenseAction} from '@libs/ReportActionsUtils';
@@ -148,7 +149,6 @@ const CASES = {
 type CaseID = ValueOf<typeof CASES>;
 
 function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetailsPageProps) {
-    const Expensicons = useMemoizedLazyExpensifyIcons(['Bug', 'Building', 'Camera', 'Checkmark', 'Exit', 'Folder', 'Gear', 'Pencil', 'Send', 'Trashcan', 'UserPlus', 'Users'] as const);
     const {translate, localeCompare} = useLocalize();
     const {isOffline} = useNetwork();
     const {isRestrictedToPreferredPolicy, preferredPolicyID} = usePreferredPolicy();
@@ -332,7 +332,8 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
 
     const shouldShowLeaveButton = canLeaveChat(report, policy, !!reportNameValuePairs?.private_isArchived);
     const shouldShowGoToWorkspace = shouldShowPolicy(policy, false, currentUserPersonalDetails?.email) && !policy?.isJoinRequestPending;
-    const reportName = getReportName(report, undefined, undefined, undefined, undefined, reportAttributes);
+
+    const reportName = Parser.htmlToText(getReportName(report, undefined, undefined, undefined, undefined, reportAttributes));
 
     const additionalRoomDetails =
         (isPolicyExpenseChat && !!report?.isOwnPolicyExpenseChat) || isExpenseReportUtil(report) || isPolicyExpenseChat || isInvoiceRoom
@@ -577,7 +578,6 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
         isRestrictedToPreferredPolicy,
         preferredPolicyID,
         introSelected,
-        Expensicons,
     ]);
 
     const displayNamesWithTooltips = useMemo(() => {
@@ -660,7 +660,6 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
         policy,
         participants,
         moneyRequestReport?.reportID,
-        Expensicons,
     ]);
 
     const canJoin = canJoinChat(report, parentReportAction, policy, !!reportNameValuePairs?.private_isArchived);
diff --git a/tests/unit/DisplayNamesShouldParseHTMLTest.tsx b/tests/unit/DisplayNamesShouldParseHTMLTest.tsx
deleted file mode 100644
index 95c99a3ce4c2..000000000000
--- a/tests/unit/DisplayNamesShouldParseHTMLTest.tsx
+++ /dev/null
@@ -1,113 +0,0 @@
-import {render, screen} from '@testing-library/react-native';
-import React from 'react';
-import DisplayNames from '@components/DisplayNames';
-
-jest.mock('@hooks/useLocalize', () => ({
-    // eslint-disable-next-line @typescript-eslint/naming-convention
-    __esModule: true,
-    default: () => ({
-        translate: jest.fn((key: string): string => {
-            if (key === 'common.hidden') {
-                return 'hidden';
-            }
-            return key;
-        }),
-    }),
-}));
-
-jest.mock('@libs/Parser', () => ({
-    // eslint-disable-next-line @typescript-eslint/naming-convention
-    __esModule: true,
-    default: {
-        htmlToText: jest.fn((html: string) => {
-            // Simulate stripTag behavior: remove anything that looks like HTML tags
-            return html.replaceAll(/(<([^>]+)>)/gi, '');
-        }),
-    },
-}));
-
-jest.mock('@libs/StringUtils', () => ({
-    // eslint-disable-next-line @typescript-eslint/naming-convention
-    __esModule: true,
-    default: {
-        lineBreaksToSpaces: jest.fn((text: string) => text),
-    },
-}));
-
-describe('DisplayNames - shouldParseHtml prop', () => {
-    const testTitle = '< >';
-
-    afterEach(() => {
-        jest.clearAllMocks();
-    });
-
-    it('should NOT parse HTML by default (shouldParseHtml defaults to false)', () => {
-        render(
-            <DisplayNames
-                fullTitle={testTitle}
-                numberOfLines={1}
-                tooltipEnabled={false}
-            />,
-        );
-
-        // With shouldParseHtml = false (default), "< >" should be preserved
-        expect(screen.getByText('< >')).toBeTruthy();
-    });
-
-    it('should parse HTML when shouldParseHtml is explicitly set to true', () => {
-        const htmlTitle = '<b>Bold Text</b>';
-        render(
-            <DisplayNames
-                fullTitle={htmlTitle}
-                numberOfLines={1}
-                tooltipEnabled={false}
-                shouldParseHtml
-            />,
-        );
-
-        // With shouldParseHtml = true, HTML tags should be stripped
-        expect(screen.getByText('Bold Text')).toBeTruthy();
-        expect(screen.queryByText('<b>Bold Text</b>')).toBeNull();
-    });
-
-    it('should preserve special characters when shouldParseHtml is false', () => {
-        const specialCharsTitle = '< > & " \' test';
-        render(
-            <DisplayNames
-                fullTitle={specialCharsTitle}
-                numberOfLines={1}
-                tooltipEnabled={false}
-            />,
-        );
-
-        // Special characters should be preserved when not parsing HTML
-        expect(screen.getByText(specialCharsTitle)).toBeTruthy();
-    });
-
-    it('should show "hidden" when title is empty and HTML parsing is disabled', () => {
-        render(
-            <DisplayNames
-                fullTitle=""
-                numberOfLines={1}
-                tooltipEnabled={false}
-            />,
-        );
-
-        expect(screen.getByText('hidden')).toBeTruthy();
-    });
-
-    it('should show "hidden" when title becomes empty after HTML parsing', () => {
-        const onlyTagsTitle = '<div></div>';
-        render(
-            <DisplayNames
-                fullTitle={onlyTagsTitle}
-                numberOfLines={1}
-                tooltipEnabled={false}
-                shouldParseHtml
-            />,
-        );
-
-        // After parsing, only tags remain which get stripped to empty string
-        expect(screen.getByText('hidden')).toBeTruthy();
-    });
-});
diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts
index 1acf4cc5fbc4..82607086fef6 100644
--- a/tests/unit/ReportUtilsTest.ts
+++ b/tests/unit/ReportUtilsTest.ts
@@ -1125,33 +1125,6 @@ describe('ReportUtils', () => {
                 );
             });
         });
-
-        describe('Unreported transaction thread', () => {
-            test('HTML is stripped from unreported transaction message', () => {
-                const transactionThread = {
-                    ...LHNTestUtils.getFakeReport(),
-                    type: CONST.REPORT.TYPE.CHAT,
-                    reportID: '123',
-                    parentReportID: '456',
-                };
-
-                const unreportedTransactionAction = {
-                    actionName: CONST.REPORT.ACTIONS.TYPE.UNREPORTED_TRANSACTION,
-                    originalMessage: {
-                        fromReportID: '789',
-                    },
-                } as ReportAction;
-
-                const reportName = getReportName(transactionThread, undefined, unreportedTransactionAction);
-
-                // Should NOT contain HTML tags
-                expect(reportName).not.toContain('<a href');
-                expect(reportName).not.toContain('</a>');
-                // Should contain the text content
-                expect(reportName).toContain('moved this expense');
-                expect(reportName).toContain('personal space');
-            });
-        });
     });
 
     // Need to merge the same tests
