Skip to content
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

[$250] Tasks - App goes back to main chat or LHN when editing a task's description #47671

Open
1 of 6 tasks
lanitochka17 opened this issue Aug 19, 2024 · 72 comments
Open
1 of 6 tasks
Assignees
Labels
Engineering External Added to denote the issue can be worked on by a contributor Reviewing Has a PR in review Weekly KSv2

Comments

@lanitochka17
Copy link

lanitochka17 commented Aug 19, 2024

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.0.22-5
Reproducible in staging?: Y
Reproducible in production?: 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/4872853
Email or phone of affected tester (no customers): gatantm+82@gmail.com
Issue reported by: Applause - Internal Team

Action Performed:

  1. Go to any chat and create a task
  2. Open the task and click on description
  3. Make any edits > Save

Expected Result:

The task is saved and user stays on task view

Actual Result:

The user is returned back to the LHN on mobile or the chat that the task was in. The same happens on the name field after the description was edited once

Unknown

Platforms:

Which of our officially supported platforms is this issue occurring on?

  • Android: Native
  • Android: mWeb Chrome
  • iOS: Native
  • iOS: mWeb Safari
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Add any screenshot/video evidence

Bug6576464_1724099959731.Recording__994.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~0135f56d92cfd4346d
  • Upwork Job ID: 1826020469224260035
  • Last Price Increase: 2024-10-15
  • Automatic offers:
    • tsa321 | Contributor | 104546362
Issue OwnerCurrent Issue Owner: @getusha
@lanitochka17 lanitochka17 added the DeployBlockerCash This issue or pull request should block deployment label Aug 19, 2024
Copy link

melvin-bot bot commented Aug 19, 2024

Triggered auto assignment to @deetergp (DeployBlockerCash), see https://stackoverflowteams.com/c/expensify/questions/9980/ for more details.

Copy link
Contributor

👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:

  1. Identify the pull request that introduced this issue and revert it.
  2. Find someone who can quickly fix the issue.
  3. Fix the issue yourself.

@lanitochka17
Copy link
Author

We think that this bug might be related to #vip-vsp

@daledah
Copy link
Contributor

daledah commented Aug 19, 2024

Edited by proposal-police: This proposal was edited at {your_timestamp_here}.

Proposal

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

The user is returned back to the LHN on mobile or the chat that the task was in. The same happens on the name field after the description was edited once

What is the root cause of that problem?

then:

Navigation.dismissModal(report?.reportID);

then In PR, we call:

Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report.reportID));

  • In above, function Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report.reportID)) can be called before Navigation.dismissModal(report?.reportID) hence the app go back to main chat.

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

We can dismiss modal before call editTask in:

Task.editTask(report, {description: values.description});

The same should be applied in edit title flow.

What alternative solutions did you explore? (Optional)

In case Task.editTask will be called, we can move logic:

Navigation.dismissModal(report?.reportID);

to below:

API.write(WRITE_COMMANDS.EDIT_TASK, parameters, {optimisticData, successData, failureData});

@daledah
Copy link
Contributor

daledah commented Aug 19, 2024

Proposal updated

@bernhardoj
Copy link
Contributor

Proposal

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

The main chat opens after editing task description.

What is the root cause of that problem?

When we edit the task, we notify the report that a new action has been added.

Report.notifyNewAction(report.reportID, currentUserAccountID);
}

It will trigger scrollToBottomForCurrentUserAction and if hasNewestReportActionRef is false, then we navigate to the self-report to clear the reportActionID params.

const scrollToBottomForCurrentUserAction = useCallback(
(isFromCurrentUser: boolean) => {
// If a new comment is added and it's from the current user scroll to the bottom otherwise leave the user positioned where
// they are now in the list.
if (!isFromCurrentUser) {
return;
}
if (!hasNewestReportActionRef.current) {
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report.reportID));
return;
}

After editing the task, we call dismissModal to close the RHP.

Task.editTask(report, {description: values.description});
}
Navigation.dismissModal(report?.reportID);

In dismissModal, if the target report ID is the same as the topmost report ID, which is true in our case, we simply pop the current screen.

} else {
navigationRef.dispatch({...StackActions.pop(), target: state.key});
}

So, the first navigate to the self-report already closes the RHP and the dismissModal calls pop which brings us back to the parent report.

Even though this happens after my PR where I add the navigate to self-report logic, but we already guard it with hasNewestReportActionRef condition. So, the real issue here is, why is hasNewestReportActionRef false?

The issue is both FE and BE. hasNewestReportAction compares the last report action created with the report lastVisibleActionCreated.

const hasNewestReportAction = sortedVisibleReportActions[0]?.created === report.lastVisibleActionCreated;

In FE, we optimistically add the update task description system message, but we don't update the lastVisibleActionCreated.

const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`,
value: {[editTaskReportAction.reportActionID]: editTaskReportAction as OnyxTypes.ReportAction},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`,
value: {
reportName,
description: reportDescription,
pendingFields: {
...(title && {reportName: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}),
...(description && {description: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}),
},
errorFields: null,
},
},
];

For the BE issue, looks like the BE doesn't consider the update task system message created as the report lastVisibleActionCreated.
Screenshot 2024-08-20 at 13 40 36

From the screenshot above, we can see that after the EditTask is completed, there are 2 reports onyx data. The first one contains the correct lastVisibleActionCreated but the second one contains the wrong lastVisbibleActionCreated (it contains the report CREATED action created value).

This makes hasNewestReportActionRef always false even if we fix it optimistically because when scrollToBottomForCurrentUserAction is called, the optimistic data is not merged yet, so hasNewestReportActionRef is still false because the report lastVisibleActionCreated from the BE is wrong.

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

The fix must be done for both BE and FE. The BE needs to return the correct lastVisibleActionCreated. In FE, we can optimistically update the report lastVisibleActionCreated in editTask to be the same as the edit task system message created. buildOptimisticEditedTaskFieldReportAction will accept a created param to be used as the created value.

const created = DateUtils.getDBTime();
const editTaskReportAction = ReportUtils.buildOptimisticEditedTaskFieldReportAction({title, description}, created);
const optimisticData: OnyxUpdate[] = [
    {
        onyxMethod: Onyx.METHOD.MERGE,
        key: `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`,
        value: {
            ...,
            lastVisibleActionCreated: created,
        },
    },
];

@tsa321
Copy link
Contributor

tsa321 commented Aug 20, 2024

Edited by proposal-police: This proposal was edited at 2023-10-01T00:00:00Z.

Proposal

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

Tasks - App goes back to main chat or LHN when editing a task's description

What is the root cause of that problem?

When user edit task, dismissModal will be executed:

const submit = useCallback(
(values: FormOnyxValues<typeof ONYXKEYS.FORMS.EDIT_TASK_FORM>) => {
if (values.description !== Parser.htmlToMarkdown(report?.description ?? '') && !isEmptyObject(report)) {
// Set the description of the report in the store and then call EditTask API
// to update the description of the report on the server
Task.editTask(report, {description: values.description});
}
Navigation.dismissModal(report?.reportID);

and when before calling API write of edit_task:

API.write(WRITE_COMMANDS.EDIT_TASK, parameters, {optimisticData, successData, failureData});
Report.notifyNewAction(report.reportID, currentUserAccountID);

Report.notifyNewAction will be executed first and will execute it's subcribtion function :

const scrollToBottomForCurrentUserAction = useCallback(
(isFromCurrentUser: boolean) => {
// If a new comment is added and it's from the current user scroll to the bottom otherwise leave the user positioned where
// they are now in the list.
if (!isFromCurrentUser) {
return;
}
if (!hasNewestReportActionRef.current) {
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report.reportID));
return;
}

which will navigate to the report or scroll to bottom of the report. The navigate is executed first which will make the report screen go back to previous report.

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

If the expected solution is to not scroll to bottom after editing the task, we could remove the Report.notifyNewAction after the API.WRITE EDIT_TASK. This could be used for other similar issues.

What alternative solutions did you explore? (1)

If the expected solution involves scrolling to the bottom, we can move the Report.notifyNewAction from Task.ts to TaskDescriptionPage, placing it below Navigation.dismissModal (ensure to check all usages of the editTaskLibrary function).

If scrolling is only necessary when the page report action list does not have the hasNewestReportAction, we can modify the scrollToBottomForCurrentUserAction function so that it does not scroll when there is a hasNewestReportAction. Alternatively, we could pass a parameter to scrollToBottomForCurrentUserAction to determine whether it should scroll when there is no newestReportAction.

What alternative solutions did you explore? (Optional)

To fix the hasNewestReportAction bug (I think it is different bug), we could use add this code in ReportActionList

    const newestVisibleReportAction = sortedVisibleReportActions[0];
    const newestPendingActionTime = useRef(report.lastVisibleActionCreated);
    const newCreatedUserActions = useMemo(() => {
        const previousLastReportAction = ReportActionsUtils.getReportAction(report.reportID, previousLastIndex.current);
        const previousCreatedDate = new Date(previousLastReportAction.created);
        const previousIndex = sortedVisibleReportActions.findIndex((action) => new Date(action.created) < previousCreatedDate);
        const addedActions = sortedVisibleReportActions.slice(0, previousIndex.current === -1 ? -1 : previousIndex - 1);

        const newCreatedActions = addedActions.filter((action) => (action.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) && (new Date(action.created) > new Date(newestPendingActionTime.current)));
        if (newCreatedActions.length > 0) {
            newestPendingActionTime.current = newCreatedActions.reduce((a, b) => Math.max(new Date(a.created), new Date(b.created))).created;
        }
        return newCreatedActions;
   },   [lastActionIndex]);

    const hasNewestReportAction = (newCreatedUserActions.length > 0) || (new Date(newestVisibleReportAction?.created) >= new Date(report.lastVisibleActionCreated));

@deetergp
Copy link
Contributor

I think this blocker may be a result of this PR from yesterday's staging deploy #47209

@bernhardoj
Copy link
Contributor

It's actually happening after my PR #46724, but the root cause is actually an existing issue coming from both BE and FE optimistic data issues which is why I posted a proposal for this one.

@deetergp deetergp added Daily KSv2 External Added to denote the issue can be worked on by a contributor and removed DeployBlockerCash This issue or pull request should block deployment Hourly KSv2 labels Aug 20, 2024
Copy link

melvin-bot bot commented Aug 20, 2024

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

@melvin-bot melvin-bot bot changed the title Tasks - App goes back to main chat or LHN when editing a task's description [$250] Tasks - App goes back to main chat or LHN when editing a task's description Aug 20, 2024
@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Aug 20, 2024
Copy link

melvin-bot bot commented Aug 20, 2024

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

@nkdengineer
Copy link
Contributor

nkdengineer commented Aug 21, 2024

Edited by proposal-police: This proposal was edited at 2024-09-16 06:45:28 UTC.

Proposal

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

The user is returned back to the LHN on mobile or the chat that the task was in. The same happens on the name field after the description was edited once

What is the root cause of that problem?

When we edit the task title, we will dismiss the modal

Navigation.dismissModal(report?.reportID);

But before that, we have a logic to that will trigger scrollToBottomForCurrentUserAction here

Report.notifyNewAction(report.reportID, currentUserAccountID);

In the normal case, we will scroll to the bottom but in this case hasNewestReportActionRef is false because we don't update lastVisibleActionCreated of the task report in optimistic data, and BE also returns the wrong created of the task report then we will navigate to the task report before we dismiss the modal. These actions are called almost simultaneously when the task report is removed from the stack navigator.

It doesn't happen when we update the assignee because we wrap the dismiss logic in InteractionManager.runAfterInteractions. But when we edit the assignee, lastVisibleActionCreated is also not updated in optimistic data

InteractionManager.runAfterInteractions(() => {
Navigation.dismissModal(report.reportID);
});
// If there's no report, we're creating a new task
} else if (option.accountID) {

Screen.Recording.2024-08-12.at.12.34.32.mp4

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

On the FE side, we should update lastVisibleActionCreated of task report when we edit the task title, and description here. We can simply update this to editTaskReportAction.created instead of adding new created param

lastVisibleActionCreated: editTaskReportAction.created

key: `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`,
value: {
reportName,

and the same when editing the task assignee here

lastVisibleActionCreated: editTaskReportAction.created,

const optimisticReport: OptimisticReport = {

OPTIONAL: We can also wrap dismiss modal in InteractionManager.runAfterInteractions as we do for task assignee page

Navigation.dismissModal(report?.reportID);

For BE, we should store and return the correct lastVisibleActionCreated when we call OpenReport API as we did in EditTask API

What alternative solutions did you explore? (Optional)

NA

@deetergp
Copy link
Contributor

@getusha We've got a good number of proposals here for you to review 🎉

@melvin-bot melvin-bot bot added the Overdue label Aug 23, 2024
@deetergp deetergp added Weekly KSv2 and removed Daily KSv2 labels Oct 7, 2024
@melvin-bot melvin-bot bot removed the Overdue label Oct 7, 2024
Copy link

melvin-bot bot commented Oct 8, 2024

📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸

@tsa321
Copy link
Contributor

tsa321 commented Oct 9, 2024

@deetergp still reproducible in staging:

bug-d.mp4

cc @getusha for my comment here

@deetergp
Copy link
Contributor

Well dang. Moving back to Daily.

@getusha, care to weigh in on @tsa321's comment?

@deetergp deetergp added Daily KSv2 and removed Weekly KSv2 labels Oct 11, 2024
Copy link

melvin-bot bot commented Oct 14, 2024

@deetergp, @getusha Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

@melvin-bot melvin-bot bot added the Overdue label Oct 14, 2024
Copy link

melvin-bot bot commented Oct 15, 2024

📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸

@tsa321
Copy link
Contributor

tsa321 commented Oct 16, 2024

Waiting for @getusha 's reply...
Maybe @getusha is too busy?

@getusha
Copy link
Contributor

getusha commented Oct 16, 2024

Sorry this fell out of my radar.

@melvin-bot melvin-bot bot removed the Overdue label Oct 16, 2024
@getusha
Copy link
Contributor

getusha commented Oct 16, 2024

@tsa321 the issue occurs only when we have over 10ish edits. until then it doesn't seem to happen when editing the description. any explanation on that?

Copy link

melvin-bot bot commented Oct 21, 2024

@deetergp, @getusha Eep! 4 days overdue now. Issues have feelings too...

@melvin-bot melvin-bot bot added the Overdue label Oct 21, 2024
@tsa321
Copy link
Contributor

tsa321 commented Oct 22, 2024

@getusha Sorry for the late reply. When I open another chat, such as the Concierge chat, and then edit a task (even with minimal edits), the app returns to the Concierge chat after editing. So, it's not a matter of reaching the 10th edit— I can reproduce the issue with just a minimal number of edits:

bug-d.mp4

Either way the root cause is in this line:

Report.notifyNewAction(report.reportID, currentUserAccountID);

@getusha
Copy link
Contributor

getusha commented Oct 22, 2024

@tsa321's proposal looks good to me
🎀 👀 🎀 C+ Reviewed

@melvin-bot melvin-bot bot removed the Overdue label Oct 22, 2024
Copy link

melvin-bot bot commented Oct 22, 2024

Current assignee @deetergp is eligible for the choreEngineerContributorManagement assigner, not assigning anyone new.

@melvin-bot melvin-bot bot removed the Help Wanted Apply this label when an issue is open to proposals by contributors label Oct 22, 2024
Copy link

melvin-bot bot commented Oct 22, 2024

📣 @tsa321 🎉 An offer has been automatically sent to your Upwork account for the Contributor role 🎉 Thanks for contributing to the Expensify app!

Offer link
Upwork job
Please accept the offer and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review 🧑‍💻
Keep in mind: Code of Conduct | Contributing 📖

@melvin-bot melvin-bot bot added Reviewing Has a PR in review Weekly KSv2 and removed Daily KSv2 labels Oct 24, 2024
@tsa321
Copy link
Contributor

tsa321 commented Oct 24, 2024

@getusha PR is ready

@deetergp
Copy link
Contributor

deetergp commented Nov 6, 2024

PR review is ongoing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Engineering External Added to denote the issue can be worked on by a contributor Reviewing Has a PR in review Weekly KSv2
Projects
None yet
Development

No branches or pull requests

8 participants