Skip to content

[$250] Group - After removing user, it is reflected under members group chat name #60582

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
3 of 18 tasks
lanitochka17 opened this issue Apr 21, 2025 · 10 comments
Open
3 of 18 tasks
Assignees
Labels
Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 External Added to denote the issue can be worked on by a contributor

Comments

@lanitochka17
Copy link

lanitochka17 commented Apr 21, 2025

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Version Number: 9.1.30-0
Reproducible in staging?: Y
Reproducible in production?: Y
If this was caught on HybridApp, is this reproducible on New Expensify Standalone?: N
If this was caught during regression testing, add the test name, ID and link from TestRail: https://expensify.testrail.io/index.php?/tests/view/5968674
Email or phone of affected tester (no customers): Slottwo1+op1@gmail.com
Issue reported by: Applause - Internal Team

Action Performed:

  1. Go to https://staging.new.expensify.com/home
  2. Go to group chat created with no members

header

  1. Add a user
  2. Note under members header, group name is changed after user invited
  3. Remove the user
  4. Revisit the members page

Expected Result:

After removing or inviting user, it must be reflected immediately under members group chat name

Actual Result:

After inviting an user immediately reflected under members "group chat" name but when user is removed , it is reflected only on revisiting the page

Workaround:

Unknown

Platforms:

Select the officially supported platforms where the issue was reproduced:

  • Android: Standalone
  • Android: HybridApp
  • Android: mWeb Chrome
  • iOS: Standalone
  • iOS: HybridApp
  • iOS: mWeb Safari
  • Windows: Chrome
  • MacOS: Chrome / Safari
  • MacOS: Desktop
Platforms Tested: On which of our officially supported platforms was this issue tested:
  • Android: Standalone
  • Android: HybridApp
  • Android: mWeb Chrome
  • iOS: Standalone
  • iOS: HybridApp
  • iOS: mWeb Safari
  • Windows: Chrome
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Add any screenshot/video evidence
Bug6808512_1745254204099.Screenrecorder-2025-04-21-22-10-46-597.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021915486246733096549
  • Upwork Job ID: 1915486246733096549
  • Last Price Increase: 2025-04-24
Issue OwnerCurrent Issue Owner: @carlosmiceli
@lanitochka17 lanitochka17 added Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 labels Apr 21, 2025
Copy link

melvin-bot bot commented Apr 21, 2025

Triggered auto assignment to @lydiabarclay (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

@nkdengineer
Copy link
Contributor

nkdengineer commented Apr 21, 2025

🚨 Edited by proposal-police: This proposal was edited at 2025-04-21 18:24:01 UTC.

Proposal

Please re-state the problem that we are trying to solve in this issue.

After inviting an user immediately reflected under members "group chat" name but when user is removed , it is reflected only on revisiting the page

What is the root cause of that problem?

  1. We called getReportName with only report param

subtitle={StringUtils.lineBreaksToSpaces(getReportName(report))}

Then the reportName is updated from reportAttributes

App/src/libs/ReportUtils.ts

Lines 4593 to 4595 in aab7aeb

if (canUseDerivedValue && reportAttributes?.[report.reportID]) {
return reportAttributes[report.reportID].reportName;
}

Although, the compute logic is triggered before we call the getReportName function again, reportAttributes isn't updated at this time

compute: ([reports, personalDetails, preferredLocale], {currentValue, sourceValues}) => {

The reason is we need to set the derived value to Onyx here

Onyx.set(key, derivedValue ?? null);

  1. In offline, if we remove the member the report name is also not updated because in offline, we only update the report metadata and it's not a dependency here

const optimisticData: OnyxUpdate[] = [

What changes do you think we should make in order to solve the problem?

  1. The resolve the problem 1, we can create a cached value in reportAttributes and then use this get the report name
const cachedReportAttributes: Record<string, ReportAttributes> = {};
cachedReportAttributes[report.reportID] = acc[report.reportID];
function getCachedReportAttributes(reportID: string) {
    return cachedReportAttributes[reportID];
}

dependencies: [ONYXKEYS.COLLECTION.REPORT, ONYXKEYS.PERSONAL_DETAILS_LIST, ONYXKEYS.NVP_PREFERRED_LOCALE],

if (canUseDerivedValue && (reportAttributes?.[report.reportID] || getCachedReportAttributes(report.reportID))) {
    return getCachedReportAttributes(report.reportID)?.reportName || reportAttributes?.[report.reportID].reportName;
}

App/src/libs/ReportUtils.ts

Lines 4593 to 4595 in aab7aeb

if (canUseDerivedValue && reportAttributes?.[report.reportID]) {
return reportAttributes[report.reportID].reportName;
}

  1. To resolve the problem 2 in offline, we need to add report metadata as dependency here
dependencies: [ONYXKEYS.COLLECTION.REPORT, ONYXKEYS.PERSONAL_DETAILS_LIST, ONYXKEYS.NVP_PREFERRED_LOCALE, ONYXKEYS.COLLECTION.REPORT_METADATA],

dependencies: [ONYXKEYS.COLLECTION.REPORT, ONYXKEYS.PERSONAL_DETAILS_LIST, ONYXKEYS.NVP_PREFERRED_LOCALE],

And we also need to create a useMemo to get report name and add report and reportMetadata as dependencies so this can be called again when reportMetadata is changed

const reportName = useMemo(() => {
    return getReportName(report);
}, [report, reportMetadata]);
subtitle={StringUtils.lineBreaksToSpaces(reportName)}

subtitle={StringUtils.lineBreaksToSpaces(getReportName(report))}

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

UI bug

What alternative solutions did you explore? (Optional)

NA

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

@bernhardoj
Copy link
Contributor

Proposal

Please re-state the problem that we are trying to solve in this issue.

The group chat name doesn't update dynamically immediately.

What is the root cause of that problem?

In get report name function, if only report param is passed, then we get the report name from reportAttributes.

App/src/libs/ReportUtils.ts

Lines 4585 to 4593 in a2b6087

): string {
// Check if we can use report name in derived values - only when we have report but no other params
const canUseDerivedValue = report && policy === undefined && parentReportActionParam === undefined && personalDetails === undefined && invoiceReceiverPolicy === undefined;
if (canUseDerivedValue && reportAttributes?.[report.reportID]) {
return reportAttributes[report.reportID].reportName;
}
return getReportNameInternal({report, policy, parentReportActionParam, personalDetails, invoiceReceiverPolicy});
}

reportAttributes is computed and recalculated every time the onyx dependency data changes, using Onyx.connect.

for (let i = 0; i < dependencies.length; i++) {
// eslint-disable-next-line rulesdir/prefer-at
const dependencyOnyxKey = dependencies[i];
if (OnyxUtils.isCollectionKey(dependencyOnyxKey)) {
Onyx.connect({
key: dependencyOnyxKey,
waitForCollectionCallback: true,
callback: (value, collectionKey, sourceValue) => {
Log.info(`[OnyxDerived] dependency ${collectionKey} for derived key ${key} changed, recomputing`);
setDependencyValue(i, value as Parameters<typeof compute>[0][typeof i]);
recomputeDerivedValue(dependencyOnyxKey, sourceValue);
},
});
} else {
Onyx.connect({
key: dependencyOnyxKey,
callback: (value) => {
Log.info(`[OnyxDerived] dependency ${dependencyOnyxKey} for derived key ${key} changed, recomputing`);
setDependencyValue(i, value as Parameters<typeof compute>[0][typeof i]);
recomputeDerivedValue(dependencyOnyxKey);
},
});
}
}

The first problem is that we subscribe to the reportAttributes using Onyx.connect, which means it won't re-render the component when it's updated. So, when the report is updated, getReportName is called, but reportAttributes isn't updated yet and it won't be called anymore after reportAttributes is updated.

App/src/libs/ReportUtils.ts

Lines 1042 to 1051 in a2b6087

let reportAttributes: OnyxEntry<Record<string, ReportAttributes>>;
Onyx.connect({
key: ONYXKEYS.DERIVED.REPORT_ATTRIBUTES,
callback: (value) => {
if (!value) {
return;
}
reportAttributes = value;
},
});

The second problem is that the a pending member removal is stored on a report metadata, and when calculating the participant, we exclude the pending delete member, however, report metadata isn't added as the dependency of the report attributes.

dependencies: [ONYXKEYS.COLLECTION.REPORT, ONYXKEYS.PERSONAL_DETAILS_LIST, ONYXKEYS.NVP_PREFERRED_LOCALE],

What changes do you think we should make in order to solve the problem?

First, add ONYXKEYS.COLLECTION.REPORT_METADATA to the report attributes deps.
Next, we can either:

  1. Subscribe the report attributes name in ReportParticipantsPage, then pass it as a new param to getReportName.
const [reportNameAttributes] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {selector: (attributes) => attributes?.[report.reportID].reportName});

Then, if it's available, use it instead of the reportAttributes from the Onyx.connect.

if (canUseDerivedValue && (reportNameAttributes || reportAttributes?.[report.reportID])) {
    return reportNameAttributes ?? reportAttributes?.[report.reportID].reportName;
}

OR

  1. Pass the other getReportName, such as policy, so we won't use the reportAttributes data.

This happens on other component too, such as the report header.

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

N/A

@lydiabarclay
Copy link

@lanitochka17 could you confirm whether an attempt was made to reproduce on Standalone or no?

@lanitochka17
Copy link
Author

Issue is not reproducible in Standalone app

Screenrecorder-2025-04-24-01-05-54-950.mp4

@lydiabarclay lydiabarclay added the Internal Requires API changes or must be handled by Expensify staff label Apr 23, 2025
@trjExpensify
Copy link
Contributor

👋 @lydiabarclay - I think you should ship this External now, yeah?

@lydiabarclay lydiabarclay added the External Added to denote the issue can be worked on by a contributor label Apr 24, 2025
Copy link

melvin-bot bot commented Apr 24, 2025

Job added to Upwork: https://www.upwork.com/jobs/~021915486246733096549

@lydiabarclay lydiabarclay removed the Internal Requires API changes or must be handled by Expensify staff label Apr 24, 2025
@melvin-bot melvin-bot bot changed the title Group - After removing user, it is reflected under members group chat name [$250] Group - After removing user, it is reflected under members group chat name Apr 24, 2025
@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Apr 24, 2025
Copy link

melvin-bot bot commented Apr 24, 2025

Triggered auto assignment to Contributor-plus team member for initial proposal review - @thesahindia (External)

@thesahindia
Copy link
Member

@bernhardoj's proposal looks good to me!

🎀 👀 🎀 C+ reviewed

Copy link

melvin-bot bot commented Apr 24, 2025

Triggered auto assignment to @carlosmiceli, see https://stackoverflow.com/c/expensify/questions/7972 for more details.

@melvin-bot melvin-bot bot removed the Help Wanted Apply this label when an issue is open to proposals by contributors label Apr 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 External Added to denote the issue can be worked on by a contributor
Projects
Status: No status
Development

No branches or pull requests

7 participants