Skip to content

Commit 1082c1d

Browse files
committed
fix: strip @expensify.sms from joined attendee string
1 parent f61c540 commit 1082c1d

14 files changed

Lines changed: 42 additions & 112 deletions

File tree

src/components/MoneyRequestConfirmationList/sections/AttendeeField.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import useLocalize from '@hooks/useLocalize';
88
import useThemeStyles from '@hooks/useThemeStyles';
99
import {enrichAndSortAttendees} from '@libs/AttendeeUtils';
1010
import Navigation from '@libs/Navigation/Navigation';
11-
import {getAttendees} from '@libs/TransactionUtils';
11+
import {getAttendees, getAttendeesListDisplayString} from '@libs/TransactionUtils';
1212
import CONST from '@src/CONST';
1313
import type {IOUAction, IOUType} from '@src/CONST';
1414
import type {TranslationPaths} from '@src/languages/types';
@@ -40,7 +40,7 @@ function AttendeeField({formattedAmountPerAttendee, isReadOnly, transactionID, a
4040
<MenuItemWithTopDescription
4141
key="attendees"
4242
shouldShowRightIcon={!isReadOnly}
43-
accessibilityLabel={`${translate('iou.attendees')}, ${iouAttendees?.map((a) => a?.displayName ?? a?.login).join(', ')}`}
43+
accessibilityLabel={`${translate('iou.attendees')}, ${Array.isArray(iouAttendees) ? getAttendeesListDisplayString(iouAttendees) : ''}`}
4444
description={`${translate('iou.attendees')} ${
4545
iouAttendees?.length && iouAttendees.length > 1 && formattedAmountPerAttendee ? `\u00B7 ${formattedAmountPerAttendee} ${translate('common.perPerson')}` : ''
4646
}`}

src/components/ReportActionItem/MoneyRequestView.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ import {
8282
} from '@libs/ReportUtils';
8383
import {hasEnabledTags, shouldShowDependentTagList} from '@libs/TagsOptionsListUtils';
8484
import {
85+
getAttendeesListDisplayString,
8586
getBillable,
8687
getCurrency,
8788
getDescription,
@@ -803,7 +804,8 @@ function MoneyRequestView({
803804
const previousTagLength = getLengthOfTag(previousTag ?? '');
804805
const currentTagLength = getLengthOfTag(currentTransactionTag ?? '');
805806

806-
const getAttendeesTitle = Array.isArray(actualAttendees) ? actualAttendees.map((item) => item?.displayName ?? item?.login).join(', ') : '';
807+
// actualAttendees is already sorted by enrichAndSortAttendees above; pass without localeCompare to preserve that order while stripping the SMS domain.
808+
const getAttendeesTitle = Array.isArray(actualAttendees) ? getAttendeesListDisplayString(actualAttendees) : '';
807809
const attendeesCopyValue = !canEdit ? getAttendeesTitle : undefined;
808810

809811
const tagList = policyTagLists.map(({name, orderWeight, tags}, index) => {

src/libs/Localize/index.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -199,20 +199,5 @@ function getDevicePreferredLocale(): Locale {
199199
return RNLocalize.findBestLanguageTag(Object.values(CONST.LOCALES))?.languageTag ?? CONST.LOCALES.DEFAULT;
200200
}
201201

202-
const COLLATOR_OPTIONS: Intl.CollatorOptions = {usage: 'sort', sensitivity: 'variant', numeric: true, caseFirst: 'upper'};
203-
const localeCompareCache = new Map<string, (a: string, b: string) => number>();
204-
205-
/** Mirrors `translateLocal` for non-React callers. React code should use `useLocalize().localeCompare`. */
206-
function localeCompareLocal(a: string, b: string): number {
207-
const locale = IntlStore.getCurrentLocale() ?? '';
208-
let compare = localeCompareCache.get(locale);
209-
if (!compare) {
210-
const collator = new Intl.Collator(locale || undefined, COLLATOR_OPTIONS);
211-
compare = (left, right) => collator.compare(left, right);
212-
localeCompareCache.set(locale, compare);
213-
}
214-
return compare(a, b);
215-
}
216-
217202
// eslint-disable-next-line @typescript-eslint/no-deprecated
218-
export {translate, translateLocal, localeCompareLocal, formatList, formatMessageElementList, getDevicePreferredLocale};
203+
export {translate, translateLocal, formatList, formatMessageElementList, getDevicePreferredLocale};

src/libs/ModifiedExpenseMessage.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import isEmpty from 'lodash/isEmpty';
22
import type {OnyxEntry} from 'react-native-onyx';
33
import type {Entries, ValueOf} from 'type-fest';
4-
import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleContextProvider';
4+
import type {LocalizedTranslate} from '@components/LocaleContextProvider';
55
import CONST from '@src/CONST';
66
import ROUTES from '@src/ROUTES';
77
import type {Policy, PolicyTagLists, Report, ReportAction, ReportAttributesDerivedValue} from '@src/types/onyx';
@@ -246,7 +246,6 @@ function getRulesModifiedMessage(
246246
*/
247247
function getForReportAction({
248248
translate,
249-
localeCompare,
250249
reportAction,
251250
policy,
252251
movedFromReport,
@@ -256,7 +255,6 @@ function getForReportAction({
256255
reportAttributes,
257256
}: {
258257
translate: LocalizedTranslate;
259-
localeCompare: LocaleContextProps['localeCompare'];
260258
reportAction: OnyxEntry<ReportAction>;
261259
policy: OnyxEntry<Policy>;
262260
movedFromReport?: OnyxEntry<Report>;
@@ -454,7 +452,7 @@ function getForReportAction({
454452

455453
const hasModifiedAttendees = isReportActionOriginalMessageAnObject && 'oldAttendees' in reportActionOriginalMessage && 'newAttendees' in reportActionOriginalMessage;
456454
if (hasModifiedAttendees) {
457-
const [oldAttendees, attendees] = getFormattedAttendees(localeCompare, reportActionOriginalMessage.newAttendees, reportActionOriginalMessage.oldAttendees);
455+
const [oldAttendees, attendees] = getFormattedAttendees(reportActionOriginalMessage.newAttendees, reportActionOriginalMessage.oldAttendees);
458456
buildMessageFragmentForValue(translate, oldAttendees, attendees, translate('iou.attendees'), false, setFragments, removalFragments, changeFragments);
459457
}
460458

src/libs/Notification/LocalNotification/BrowserNotifications.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {Str} from 'expensify-common';
33
import type {ImageSourcePropType} from 'react-native';
44
import EXPENSIFY_ICON_URL from '@assets/images/expensify-logo-round-clearspace.png';
55
import * as AppUpdate from '@libs/actions/AppUpdate';
6-
import {localeCompareLocal, translateLocal} from '@libs/Localize';
6+
import {translateLocal} from '@libs/Localize';
77
import {getForReportAction} from '@libs/ModifiedExpenseMessage';
88
import {getTextFromHtml} from '@libs/ReportActionsUtils';
99
import {getReportName} from '@libs/ReportNameUtils';
@@ -152,7 +152,6 @@ export default {
152152
const bodyWithHTML = getForReportAction({
153153
// eslint-disable-next-line @typescript-eslint/no-deprecated -- translateLocal is deprecated; BrowserNotifications is non-React code that cannot use the translate hook
154154
translate: translateLocal,
155-
localeCompare: localeCompareLocal,
156155
reportAction,
157156
policy,
158157
movedFromReport,

src/libs/OptionsListUtils/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import filterArrayByMatch from '@libs/filterArrayByMatch';
1414
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
1515
import {isReportMessageAttachment} from '@libs/isReportMessageAttachment';
1616
import {formatPhoneNumber as formatPhoneNumberPhoneUtils} from '@libs/LocalePhoneNumber';
17-
import {localeCompareLocal, translateLocal} from '@libs/Localize';
17+
import {translateLocal} from '@libs/Localize';
1818
import {appendCountryCode, getPhoneNumberWithoutSpecialChars} from '@libs/LoginUtils';
1919
import {MaxHeap} from '@libs/MaxHeap';
2020
import {MinHeap} from '@libs/MinHeap';
@@ -750,7 +750,6 @@ function getLastMessageTextForReport({
750750
} else if (isModifiedExpenseAction(lastReportAction)) {
751751
const properSchemaForModifiedExpenseMessageWithHTML = getForReportAction({
752752
translate,
753-
localeCompare: localeCompareLocal,
754753
reportAction: lastReportAction,
755754
policy,
756755
movedFromReport,

src/libs/ReportNameUtils.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import type {SelectedParticipant} from '@src/types/onyx/NewGroupChatDraft';
2424
import {isEmptyObject} from '@src/types/utils/EmptyObject';
2525
import {convertToDisplayString} from './CurrencyUtils';
2626
import {formatPhoneNumber as formatPhoneNumberPhoneUtils} from './LocalePhoneNumber';
27-
import {localeCompareLocal, translateLocal} from './Localize';
27+
import {translateLocal} from './Localize';
2828
// eslint-disable-next-line import/no-cycle
2929
import {getForReportAction, getMovedReportID} from './ModifiedExpenseMessage';
3030
import Parser from './Parser';
@@ -844,7 +844,6 @@ function computeChatThreadReportName(
844844
const movedToReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(parentReportAction, CONST.REPORT.MOVE_TYPE.TO)}`];
845845
const modifiedMessageWithHTML = getForReportAction({
846846
translate,
847-
localeCompare: localeCompareLocal,
848847
reportAction: parentReportAction,
849848
movedFromReport,
850849
movedToReport,

src/libs/ReportUtils.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ import type {FormulaContext} from './Formula';
118118
import getBase62ReportID from './getBase62ReportID';
119119
import {isReportMessageAttachment} from './isReportMessageAttachment';
120120
import {formatPhoneNumber as formatPhoneNumberPhoneUtils} from './LocalePhoneNumber';
121-
import {localeCompareLocal, translateLocal} from './Localize';
121+
import {translateLocal} from './Localize';
122122
import Log from './Log';
123123
import {isEmailPublicDomain} from './LoginUtils';
124124
// eslint-disable-next-line import/no-cycle
@@ -5878,7 +5878,6 @@ function getReportName(reportNameInformation: GetReportNameParams): string {
58785878
const modifiedMessageWithHTML = getForReportAction({
58795879
// eslint-disable-next-line @typescript-eslint/no-deprecated -- translateLocal is deprecated; getReportName is non-React code that cannot use the translate hook
58805880
translate: translateLocal,
5881-
localeCompare: localeCompareLocal,
58825881
reportAction: parentReportAction,
58835882
policy,
58845883
movedFromReport,

src/libs/TransactionUtils/index.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {format, isValid, parse} from 'date-fns';
2+
import {Str} from 'expensify-common';
23
import {deepEqual} from 'fast-equals';
34
import lodashDeepClone from 'lodash/cloneDeep';
45
import lodashSet from 'lodash/set';
@@ -1205,20 +1206,23 @@ function getAttendees(transaction: OnyxInputOrEntry<Transaction>, currentUserPer
12051206
}
12061207

12071208
/**
1208-
* Returns attendees joined as an alphabetically sorted display string. Sort is part of the contract — every consumer relies on it.
1209+
* Returns attendees joined as a display string. Pass `localeCompare` to sort alphabetically (matches the pill sort);
1210+
* omit it to keep insertion order — used by non-React callers that don't want to thread the comparator.
1211+
* Strips the SMS domain so phone-login attendees render the same as in the rendered pills.
12091212
*/
1210-
function getAttendeesListDisplayString(attendees: Attendee[], localeCompare: LocaleContextProps['localeCompare']): string {
1211-
// Lowercase to match sortAlphabetically (the pill sort) so joined string and pill order never disagree on case.
1212-
return [...attendees]
1213-
.sort((a, b) => localeCompare((a.displayName ?? a.login ?? '').toLowerCase(), (b.displayName ?? b.login ?? '').toLowerCase()))
1214-
.map((item) => item.displayName ?? item.login)
1215-
.join(', ');
1213+
function getAttendeesListDisplayString(attendees: Attendee[], localeCompare?: LocaleContextProps['localeCompare']): string {
1214+
const getName = (a: Attendee) => Str.removeSMSDomain(a.displayName ?? a.login ?? '');
1215+
const ordered = localeCompare
1216+
? // Lowercase to match sortAlphabetically (the pill sort) so joined string and pill order never disagree on case.
1217+
[...attendees].sort((a, b) => localeCompare(getName(a).toLowerCase(), getName(b).toLowerCase()))
1218+
: attendees;
1219+
return ordered.map(getName).join(', ');
12161220
}
12171221

12181222
/**
12191223
* Return the list of attendees as a string and modified list of attendees as a string if present.
12201224
*/
1221-
function getFormattedAttendees(localeCompare: LocaleContextProps['localeCompare'], modifiedAttendees?: Attendee[], attendees?: Attendee[]): [string, string] {
1225+
function getFormattedAttendees(modifiedAttendees?: Attendee[], attendees?: Attendee[], localeCompare?: LocaleContextProps['localeCompare']): [string, string] {
12221226
const oldAttendees = modifiedAttendees ?? [];
12231227
const newAttendees = attendees ?? [];
12241228
return [getAttendeesListDisplayString(oldAttendees, localeCompare), getAttendeesListDisplayString(newAttendees, localeCompare)];

src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {getEnvironmentURL} from '@libs/Environment/Environment';
1818
import fileDownload from '@libs/fileDownload';
1919
import getAttachmentDetails from '@libs/fileDownload/getAttachmentDetails';
2020
import {formatPhoneNumber as formatPhoneNumberPhoneUtils} from '@libs/LocalePhoneNumber';
21-
import {localeCompareLocal} from '@libs/Localize';
2221
import {getForReportAction} from '@libs/ModifiedExpenseMessage';
2322
import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
2423
import Navigation from '@libs/Navigation/Navigation';
@@ -857,7 +856,6 @@ const ContextMenuActions: ContextMenuAction[] = [
857856
} else if (isModifiedExpenseAction(reportAction)) {
858857
const modifyExpenseMessageWithHTML = getForReportAction({
859858
translate,
860-
localeCompare: localeCompareLocal,
861859
reportAction,
862860
policy,
863861
movedFromReport,

0 commit comments

Comments
 (0)