Skip to content

Commit c93cde5

Browse files
authored
Merge pull request Expensify#60886 from bernhardoj/fix/60582-report-name-not-updated-dynamically
Fix group chat name doesn't update immediately
2 parents 0b9bab2 + e79165f commit c93cde5

11 files changed

Lines changed: 93 additions & 26 deletions

File tree

src/components/LHNOptionsList/LHNOptionsList.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
4141
const route = useRoute();
4242

4343
const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false});
44+
const [reportAttributes] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {selector: (attributes) => attributes?.reports, canBeMissing: false});
4445
const [reportNameValuePairs] = useOnyx(ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS, {canBeMissing: false});
4546
const [reportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS, {canBeMissing: false});
4647
const [policy] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: false});
@@ -184,6 +185,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
184185
<OptionRowLHNData
185186
reportID={reportID}
186187
fullReport={itemFullReport}
188+
reportAttributes={reportAttributes ?? {}}
187189
oneTransactionThreadReport={itemOneTransactionThreadReport}
188190
reportNameValuePairs={itemReportNameValuePairs}
189191
reportActions={itemReportActions}
@@ -215,6 +217,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
215217
preferredLocale,
216218
reportActions,
217219
reports,
220+
reportAttributes,
218221
reportNameValuePairs,
219222
shouldDisableFocusOptions,
220223
transactions,
@@ -228,6 +231,22 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
228231
() => [
229232
reportActions,
230233
reports,
234+
reportAttributes,
235+
reportNameValuePairs,
236+
transactionViolations,
237+
policy,
238+
personalDetails,
239+
data.length,
240+
draftComments,
241+
optionMode,
242+
preferredLocale,
243+
transactions,
244+
isOffline,
245+
],
246+
[
247+
reportActions,
248+
reports,
249+
reportAttributes,
231250
reportNameValuePairs,
232251
transactionViolations,
233252
policy,
@@ -239,7 +258,6 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
239258
transactions,
240259
isOffline,
241260
],
242-
[reportActions, reports, reportNameValuePairs, transactionViolations, policy, personalDetails, data.length, draftComments, optionMode, preferredLocale, transactions, isOffline],
243261
);
244262

245263
const previousOptionMode = usePrevious(optionMode);

src/components/LHNOptionsList/OptionRowLHNData.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {OptionRowLHNDataProps} from './types';
1717
function OptionRowLHNData({
1818
isFocused = false,
1919
fullReport,
20+
reportAttributes,
2021
oneTransactionThreadReport,
2122
reportNameValuePairs,
2223
reportActions,
@@ -47,6 +48,7 @@ function OptionRowLHNData({
4748
// Note: ideally we'd have this as a dependent selector in onyx!
4849
const item = SidebarUtils.getOptionData({
4950
report: fullReport,
51+
reportAttributes,
5052
oneTransactionThreadReport,
5153
reportNameValuePairs,
5254
reportActions,
@@ -74,6 +76,7 @@ function OptionRowLHNData({
7476
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
7577
}, [
7678
fullReport,
79+
reportAttributes,
7780
oneTransactionThreadReport,
7881
reportNameValuePairs,
7982
lastReportActionTransaction,

src/components/LHNOptionsList/types.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,18 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
55
import type {ValueOf} from 'type-fest';
66
import type CONST from '@src/CONST';
77
import type {OptionData} from '@src/libs/ReportUtils';
8-
import type {Locale, PersonalDetailsList, Policy, Report, ReportAction, ReportActions, ReportNameValuePairs, Transaction, TransactionViolation} from '@src/types/onyx';
8+
import type {
9+
Locale,
10+
PersonalDetailsList,
11+
Policy,
12+
Report,
13+
ReportAction,
14+
ReportActions,
15+
ReportAttributesDerivedValue,
16+
ReportNameValuePairs,
17+
Transaction,
18+
TransactionViolation,
19+
} from '@src/types/onyx';
920

1021
type OptionMode = ValueOf<typeof CONST.OPTION_MODE>;
1122

@@ -47,6 +58,9 @@ type OptionRowLHNDataProps = {
4758
/** The full data of the report */
4859
fullReport: OnyxEntry<Report>;
4960

61+
/** The report derived attributes */
62+
reportAttributes: ReportAttributesDerivedValue['reports'];
63+
5064
/** The transaction thread report associated with the current report, if any */
5165
oneTransactionThreadReport: OnyxEntry<Report>;
5266

src/components/ReportWelcomeText.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,20 @@ type ReportWelcomeTextProps = {
4545
function ReportWelcomeText({report, policy}: ReportWelcomeTextProps) {
4646
const {translate} = useLocalize();
4747
const styles = useThemeStyles();
48-
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
48+
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false});
4949
const isPolicyExpenseChat = isPolicyExpenseChatReportUtils(report);
5050
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
51-
const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID || undefined}`);
51+
const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID || undefined}`, {canBeMissing: false});
52+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
53+
const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID || undefined}`, {canBeMissing: false});
5254
const isArchivedRoom = isArchivedNonExpenseReport(report, reportNameValuePairs);
5355
const isChatRoom = isChatRoomReportUtils(report);
5456
const isSelfDM = isSelfDMReportUtils(report);
5557
const isInvoiceRoom = isInvoiceRoomReportUtils(report);
5658
const isSystemChat = isSystemChatReportUtils(report);
5759
const isAdminRoom = isAdminRoomReportUtils(report);
5860
const isDefault = !(isChatRoom || isPolicyExpenseChat || isSelfDM || isInvoiceRoom || isSystemChat);
59-
const participantAccountIDs = getParticipantsAccountIDsForDisplay(report, undefined, true, true);
61+
const participantAccountIDs = getParticipantsAccountIDsForDisplay(report, undefined, true, true, reportMetadata);
6062
const isMultipleParticipant = participantAccountIDs.length > 1;
6163
const displayNamesWithTooltips = getDisplayNamesWithTooltips(getPersonalDetailsForAccountIDs(participantAccountIDs, personalDetails), isMultipleParticipant);
6264
const welcomeMessage = SidebarUtils.getWelcomeMessage(report, policy);

src/libs/ReportUtils.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2700,9 +2700,15 @@ function getDisplayNameForParticipant({
27002700
return shouldUseShortForm ? shortName : longName;
27012701
}
27022702

2703-
function getParticipantsAccountIDsForDisplay(report: OnyxEntry<Report>, shouldExcludeHidden = false, shouldExcludeDeleted = false, shouldForceExcludeCurrentUser = false): number[] {
2703+
function getParticipantsAccountIDsForDisplay(
2704+
report: OnyxEntry<Report>,
2705+
shouldExcludeHidden = false,
2706+
shouldExcludeDeleted = false,
2707+
shouldForceExcludeCurrentUser = false,
2708+
reportMetadataParam?: OnyxEntry<ReportMetadata>,
2709+
): number[] {
27042710
const reportParticipants = report?.participants ?? {};
2705-
const reportMetadata = getReportMetadata(report?.reportID);
2711+
const reportMetadata = reportMetadataParam ?? getReportMetadata(report?.reportID);
27062712
let participantsEntries = Object.entries(reportParticipants);
27072713

27082714
// We should not show participants that have an optimistic entry with the same login in the personal details
@@ -2797,13 +2803,13 @@ function buildParticipantsFromAccountIDs(accountIDs: number[]): Participants {
27972803
/**
27982804
* Returns the report name if the report is a group chat
27992805
*/
2800-
function getGroupChatName(participants?: SelectedParticipant[], shouldApplyLimit = false, report?: OnyxEntry<Report>): string | undefined {
2806+
function getGroupChatName(participants?: SelectedParticipant[], shouldApplyLimit = false, report?: OnyxEntry<Report>, reportMetadataParam?: OnyxEntry<ReportMetadata>): string | undefined {
28012807
// If we have a report always try to get the name from the report.
28022808
if (report?.reportName) {
28032809
return report.reportName;
28042810
}
28052811

2806-
const reportMetadata = getReportMetadata(report?.reportID);
2812+
const reportMetadata = reportMetadataParam ?? getReportMetadata(report?.reportID);
28072813

28082814
const pendingMemberAccountIDs = new Set(
28092815
reportMetadata?.pendingChatMembers?.filter((member) => member.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE).map((member) => member.accountID),
@@ -4595,12 +4601,14 @@ function getReportName(
45954601
parentReportActionParam?: OnyxInputOrEntry<ReportAction>,
45964602
personalDetails?: Partial<PersonalDetailsList>,
45974603
invoiceReceiverPolicy?: OnyxEntry<Policy>,
4604+
reportAttributesParam?: ReportAttributesDerivedValue['reports'],
45984605
): string {
45994606
// Check if we can use report name in derived values - only when we have report but no other params
46004607
const canUseDerivedValue = report && policy === undefined && parentReportActionParam === undefined && personalDetails === undefined && invoiceReceiverPolicy === undefined;
4601-
const derivedNameExists = report && !!reportAttributes?.[report.reportID]?.reportName;
4608+
const attributes = reportAttributesParam ?? reportAttributes;
4609+
const derivedNameExists = report && !!attributes?.[report.reportID]?.reportName;
46024610
if (canUseDerivedValue && derivedNameExists) {
4603-
return reportAttributes[report.reportID].reportName;
4611+
return attributes[report.reportID].reportName;
46044612
}
46054613
return getReportNameInternal({report, policy, parentReportActionParam, personalDetails, invoiceReceiverPolicy});
46064614
}

src/libs/SidebarUtils.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type {ValueOf} from 'type-fest';
55
import type {PartialPolicyForSidebar} from '@hooks/useSidebarOrderedReportIDs';
66
import CONST from '@src/CONST';
77
import ONYXKEYS from '@src/ONYXKEYS';
8-
import type {PersonalDetails, PersonalDetailsList, ReportActions, ReportNameValuePairs, TransactionViolation} from '@src/types/onyx';
8+
import type {PersonalDetails, PersonalDetailsList, ReportActions, ReportAttributesDerivedValue, ReportNameValuePairs, TransactionViolation} from '@src/types/onyx';
99
import type Beta from '@src/types/onyx/Beta';
1010
import type Policy from '@src/types/onyx/Policy';
1111
import type PriorityMode from '@src/types/onyx/PriorityMode';
@@ -403,6 +403,7 @@ function shouldShowRedBrickRoad(report: Report, reportActions: OnyxEntry<ReportA
403403
*/
404404
function getOptionData({
405405
report,
406+
reportAttributes,
406407
oneTransactionThreadReport,
407408
reportNameValuePairs,
408409
reportActions,
@@ -416,6 +417,7 @@ function getOptionData({
416417
invoiceReceiverPolicy,
417418
}: {
418419
report: OnyxEntry<Report>;
420+
reportAttributes: ReportAttributesDerivedValue['reports'];
419421
oneTransactionThreadReport: OnyxEntry<Report>;
420422
reportNameValuePairs: OnyxEntry<ReportNameValuePairs>;
421423
reportActions: OnyxEntry<ReportActions>;
@@ -688,7 +690,7 @@ function getOptionData({
688690
result.phoneNumber = personalDetail?.phoneNumber ?? '';
689691
}
690692

691-
const reportName = getReportName(report, policy, undefined, undefined, invoiceReceiverPolicy);
693+
const reportName = getReportName(report, policy, undefined, undefined, invoiceReceiverPolicy, reportAttributes);
692694

693695
result.text = reportName;
694696
result.subtitle = subtitle;

src/libs/actions/OnyxDerived/configs/reportAttributes.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {generateReportName, isValidReport} from '@libs/ReportUtils';
22
import createOnyxDerivedValueConfig from '@userActions/OnyxDerived/createOnyxDerivedValueConfig';
33
import ONYXKEYS from '@src/ONYXKEYS';
4-
import type {ReportAttributesDerivedValue} from '@src/types/onyx';
4+
import type {Report, ReportAttributesDerivedValue, ReportMetadata} from '@src/types/onyx';
55

66
let isFullyComputed = false;
77

@@ -19,6 +19,7 @@ export default createOnyxDerivedValueConfig({
1919
ONYXKEYS.COLLECTION.REPORT_ACTIONS,
2020
ONYXKEYS.COLLECTION.POLICY,
2121
ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS,
22+
ONYXKEYS.COLLECTION.REPORT_METADATA,
2223
],
2324
compute: (dependencies, {currentValue, sourceValues}) => {
2425
const areAllDependenciesSet = [...dependencies].every((dependency) => dependency !== undefined);
@@ -36,17 +37,25 @@ export default createOnyxDerivedValueConfig({
3637
}
3738

3839
const reportUpdates = sourceValues?.[ONYXKEYS.COLLECTION.REPORT];
40+
const reportMetadataUpdates = sourceValues?.[ONYXKEYS.COLLECTION.REPORT_METADATA];
3941

4042
// if we already computed the report attributes and there is no new reports data, return the current value
41-
if ((isFullyComputed && reportUpdates === undefined) || !reports) {
43+
if ((isFullyComputed && reportUpdates === undefined && reportMetadataUpdates === undefined) || !reports) {
4244
return currentValue ?? {reports: {}, locale: null};
4345
}
4446

45-
const dataToIterate = isFullyComputed && reportUpdates !== undefined ? reportUpdates : reports ?? {};
46-
const reportAttributes = Object.keys(dataToIterate).reduce<ReportAttributesDerivedValue['reports']>((acc, reportID) => {
47-
// source value sends partial data, so we need an entire report object to do computations
48-
const report = reports[reportID];
47+
let dataToIterate: Record<string, Report | ReportMetadata | undefined> = reports;
48+
if (isFullyComputed) {
49+
if (reportUpdates) {
50+
dataToIterate = reportUpdates;
51+
} else if (reportMetadataUpdates) {
52+
dataToIterate = reportMetadataUpdates;
53+
}
54+
}
4955

56+
const reportAttributes = Object.keys(dataToIterate).reduce<ReportAttributesDerivedValue['reports']>((acc, key) => {
57+
// source value sends partial data, so we need an entire report object to do computations
58+
const report = reports[`${ONYXKEYS.COLLECTION.REPORT}${key.replace(ONYXKEYS.COLLECTION.REPORT, '').replace(ONYXKEYS.COLLECTION.REPORT_METADATA, '')}`];
5059
if (!report || !isValidReport(report)) {
5160
return acc;
5261
}

src/pages/ReportParticipantsPage.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,13 @@ function ReportParticipantsPage({report, route}: ReportParticipantsPageProps) {
6969
const {shouldUseNarrowLayout, isSmallScreenWidth} = useResponsiveLayout();
7070
const selectionListRef = useRef<SelectionListHandle>(null);
7171
const textInputRef = useRef<TextInput>(null);
72-
const [userSearchPhrase] = useOnyx(ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE);
73-
const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`);
74-
const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID}`);
72+
const [userSearchPhrase] = useOnyx(ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE, {canBeMissing: true});
73+
const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: false});
74+
const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID}`, {canBeMissing: false});
75+
const [reportAttributes] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {selector: (attributes) => attributes?.reports, canBeMissing: false});
7576
const {selectionMode} = useMobileSelectionMode();
76-
const [session] = useOnyx(ONYXKEYS.SESSION);
77-
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
77+
const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false});
78+
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false});
7879
const currentUserAccountID = Number(session?.accountID);
7980
const isCurrentUserAdmin = isGroupChatAdmin(report, currentUserAccountID);
8081
const isGroupChat = useMemo(() => isGroupChatUtils(report), [report]);
@@ -397,7 +398,7 @@ function ReportParticipantsPage({report, route}: ReportParticipantsPageProps) {
397398
Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID, backTo));
398399
}
399400
}}
400-
subtitle={StringUtils.lineBreaksToSpaces(getReportName(report))}
401+
subtitle={StringUtils.lineBreaksToSpaces(getReportName(report, undefined, undefined, undefined, undefined, reportAttributes))}
401402
/>
402403
<View style={[styles.pl5, styles.pr5]}>{headerButtons}</View>
403404
<ConfirmModal

src/pages/home/HeaderView.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked,
116116
const [lastDayFreeTrial] = useOnyx(ONYXKEYS.NVP_LAST_DAY_FREE_TRIAL, {canBeMissing: true});
117117
const [account] = useOnyx(ONYXKEYS.ACCOUNT, {canBeMissing: true});
118118
const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true});
119+
const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID}`, {canBeMissing: true});
119120
const [isDismissedDiscountBanner, setIsDismissedDiscountBanner] = useState(false);
120121

121122
const {translate} = useLocalize();
@@ -126,7 +127,7 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked,
126127
const {canUseTalkToAISales, canUseLeftHandBar} = usePermissions();
127128
const shouldShowTalkToSales = !!canUseTalkToAISales && isAdminRoom(report);
128129

129-
const allParticipants = getParticipantsAccountIDsForDisplay(report, false, true);
130+
const allParticipants = getParticipantsAccountIDsForDisplay(report, false, true, undefined, reportMetadata);
130131
const shouldAddEllipsis = allParticipants?.length > CONST.DISPLAY_PARTICIPANTS_LIMIT;
131132
const participants = allParticipants.slice(0, CONST.DISPLAY_PARTICIPANTS_LIMIT);
132133
const isMultipleParticipant = participants.length > 1;

tests/perf-test/SidebarUtils.perf-test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ describe('SidebarUtils', () => {
8383
await measureFunction(() =>
8484
SidebarUtils.getOptionData({
8585
report,
86+
reportAttributes: {},
8687
reportNameValuePairs,
8788
reportActions,
8889
personalDetails,

0 commit comments

Comments
 (0)