Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 6 additions & 4 deletions src/libs/OptionsListUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
*/
let currentUserLogin: string | undefined;
let currentUserAccountID: number | undefined;
Onyx.connect({

Check warning on line 188 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
currentUserLogin = value?.email;
Expand All @@ -194,19 +194,19 @@
});

let loginList: OnyxEntry<Login>;
Onyx.connect({

Check warning on line 197 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.LOGIN_LIST,
callback: (value) => (loginList = isEmptyObject(value) ? {} : value),
});

let allPersonalDetails: OnyxEntry<PersonalDetailsList>;
Onyx.connect({

Check warning on line 203 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => (allPersonalDetails = isEmptyObject(value) ? {} : value),
});

const policies: OnyxCollection<Policy> = {};
Onyx.connect({

Check warning on line 209 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY,
callback: (policy, key) => {
if (!policy || !key || !policy.name) {
Expand All @@ -218,14 +218,14 @@
});

let allPolicies: OnyxCollection<Policy> = {};
Onyx.connect({

Check warning on line 221 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY,
waitForCollectionCallback: true,
callback: (val) => (allPolicies = val),
});

let allReports: OnyxCollection<Report>;
Onyx.connect({

Check warning on line 228 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -234,7 +234,7 @@
});

let allReportNameValuePairs: OnyxCollection<ReportNameValuePairs>;
Onyx.connect({

Check warning on line 237 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -246,7 +246,7 @@
const allSortedReportActions: Record<string, ReportAction[]> = {};
let allReportActions: OnyxCollection<ReportActions>;
const lastVisibleReportActions: ReportActions = {};
Onyx.connect({

Check warning on line 249 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (actions) => {
Expand Down Expand Up @@ -306,13 +306,13 @@
});

let activePolicyID: OnyxEntry<string>;
Onyx.connect({

Check warning on line 309 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NVP_ACTIVE_POLICY_ID,
callback: (value) => (activePolicyID = value),
});

let nvpDismissedProductTraining: OnyxEntry<DismissedProductTraining>;
Onyx.connect({

Check warning on line 315 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING,
callback: (value) => (nvpDismissedProductTraining = value),
});
Expand Down Expand Up @@ -451,13 +451,13 @@
/**
* Update alternate text for the option when applicable
*/
function getAlternateText(option: OptionData, {showChatPreviewLine = false, forcePolicyNamePreview = false}: PreviewConfig) {
function getAlternateText(option: OptionData, {showChatPreviewLine = false, forcePolicyNamePreview = false}: PreviewConfig, lastActorDetails: Partial<PersonalDetails> | null = {}) {
const report = getReportOrDraftReport(option.reportID);
const isAdminRoom = reportUtilsIsAdminRoom(report);
const isAnnounceRoom = reportUtilsIsAnnounceRoom(report);
const isGroupChat = reportUtilsIsGroupChat(report);
const isExpenseThread = isMoneyRequest(report);
const formattedLastMessageText = formatReportLastMessageText(option.lastMessageText ?? '');
const formattedLastMessageText = formatReportLastMessageText(Parser.htmlToText(option.lastMessageText ?? '')) || getLastMessageTextForReport({report, lastActorDetails});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change introduced a regression (#82036, fixed in #82451). Adding Parser.htmlToText()on option.lastMessageText strips user-typed HTML-like content (e.g., <br>test becomes test) from search previews, while LHN shows the message correctly — creating an inconsistency.

const reportPrefix = getReportSubtitlePrefix(report);
const formattedLastMessageTextWithPrefix = reportPrefix + formattedLastMessageText;

Expand Down Expand Up @@ -839,8 +839,9 @@
subtitle = getChatRoomSubtitle(report, true, !!result.private_isArchived);

// If displaying chat preview line is needed, let's overwrite the default alternate text
result.alternateText = showPersonalDetails && personalDetail?.login ? personalDetail.login : getAlternateText(result, {showChatPreviewLine, forcePolicyNamePreview});

const lastActorDetails = personalDetails?.[report?.lastActorAccountID ?? String(CONST.DEFAULT_NUMBER_ID)];
result.alternateText =
showPersonalDetails && personalDetail?.login ? personalDetail.login : getAlternateText(result, {showChatPreviewLine, forcePolicyNamePreview}, lastActorDetails);
reportName = showPersonalDetails ? getDisplayNameForParticipant({accountID: accountIDs.at(0)}) || formatPhoneNumber(personalDetail?.login ?? '') : getReportName(report);
} else {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
Expand Down Expand Up @@ -2587,6 +2588,7 @@
combineOrderingOfReportsAndPersonalDetails,
createOptionFromReport,
createOptionList,
createOption,
filterAndOrderOptions,
filterOptions,
filterReports,
Expand Down
122 changes: 121 additions & 1 deletion tests/unit/OptionsListUtilsTest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import DateUtils from '@libs/DateUtils';
import type {OptionList, Options, SearchOption} from '@libs/OptionsListUtils';
import {
canCreateOptimisticPersonalDetailOption,
createOption,
createOptionList,
filterAndOrderOptions,
filterReports,
Expand All @@ -35,7 +36,7 @@ import initOnyxDerivedValues from '@userActions/OnyxDerived';
import CONST from '@src/CONST';
import IntlStore from '@src/languages/IntlStore';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetails, Policy, Report} from '@src/types/onyx';
import type {PersonalDetails, Policy, Report, ReportAction, Transaction} from '@src/types/onyx';
import {getFakeAdvancedReportAction} from '../utils/LHNTestUtils';
import {localeCompare} from '../utils/TestHelper';
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
Expand Down Expand Up @@ -2081,4 +2082,123 @@ describe('OptionsListUtils', () => {
expect(result).toBe('');
});
});

describe('createOption', () => {
it('should return alternative text correctly when the last action is report preview action', async () => {
const report = {
chatType: '',
currency: 'USD',
description: '',
errorFields: {},
hasOutstandingChildRequest: false,
hasOutstandingChildTask: false,
iouReportID: '456',
lastMessageHtml: '',
lastMessageText: '',
participants: {
'1': {
notificationPreference: 'always',
},
'2': {
notificationPreference: 'always',
},
},
reportID: '123',
type: 'chat',
lastActorAccountID: 1,
} as unknown as Report;

const reportPreviewAction = {
actionName: 'REPORTPREVIEW',
actorAccountID: 1,
childManagerAccountID: 2,
childOwnerAccountID: 1,
childReportID: '456',
childReportName: 'IOU',
created: '2025-10-02 06:50:36.302',
reportActionID: '12345678',
shouldShow: true,
message: [
{
html: 'Iron Man owes ₫34',
text: 'Iron Man owes ₫34',
type: 'COMMENT',
whisperedTo: [],
},
],
} as unknown as ReportAction;

const iouReport = {
chatReportID: '123',
currency: 'VND',
managerID: 2,
ownerAccountID: 1,
parentReportActionID: '12345678',
parentReportID: '123',
participants: {
'19960856': {
notificationPreference: '',
},
'20669492': {
notificationPreference: '',
},
},
reportID: '456',
reportName: 'IOU',
total: 3400,
} as unknown as Report;

const iouAction = {
actorAccountID: 1,
message: [
{
type: 'COMMENT',
html: '₫34 expense',
text: '₫34 expense',
isEdited: false,
whisperedTo: [],
isDeletedParentAction: false,
deleted: '',
reactions: [],
},
],
originalMessage: {
IOUReportID: '456',
IOUTransactionID: '123456',
amount: 3400,
comment: '',
currency: 'VND',
participantAccountIDs: [1, 2],
},
actionName: 'IOU',
reportActionID: '789',
} as unknown as ReportAction;

const transaction = {
transactionID: '123456',
amount: 3400,
currency: 'VND',
reportID: '3993091505909230',
comment: {
comment: '',
},
merchant: '(none)',
created: '2025-10-02',
category: '',
taxAmount: 0,
reimbursable: true,
} as unknown as Transaction;

await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, report);
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, {[reportPreviewAction.reportActionID]: reportPreviewAction});
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, iouReport);
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`, {[iouAction.reportActionID]: iouAction});
await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, transaction);
await waitForBatchedUpdates();

const result = createOption([1, 2], PERSONAL_DETAILS, report, {showChatPreviewLine: true});

expect(result.alternateText).toBe('Iron Man owes ₫34');
});
});
});
Loading