HOLD on #27996
Problem
We have a bit of code here to re-route the user if they are looking at an optimistically-generated reportID. However, it only works if that report is the active route, and doesn't work in a number of different situations. For example:
Actions taken
- Sign in as a new user, Alice
- Sign in as an existing user, Bob
- As Alice, go to
Settings -> Preferences and toggle Force Offline.
- As Alice, send a few messages in a new chat to Bob (offline)
- As Bob (online), send a message to Alice
- As Alice, go to
Settings -> Preferences and untoggle Force Offline.
Expected behavior
In the background, the report should rerender to the correct report, showing the messages from Alice and Bob. If you then close the Settings modal/RHP, then you should see the new report, not the unused optimistic one.
I'm quite certain there are other edge cases that won't work correctly, like pressing the browser back button a few times to return to the unused optimistic report.
Actual behavior
You'll see the 404 page.
Solution
At a high level, the solution should be to re-write the navigation state and history to replace all instances of the unused reportID with the correct one.
I started working on a solution to this in #27996, but decided to drop it and treat it as a separate issue.
The solution I'm most confident in leverages a function added in #27996, and looks like this:
diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js
index dc4f35a59c..569ffaf7d4 100644
--- a/src/libs/Navigation/Navigation.js
+++ b/src/libs/Navigation/Navigation.js
@@ -13,6 +13,7 @@ import originalGetTopmostReportId from './getTopmostReportId';
import getStateFromPath from './getStateFromPath';
import SCREENS from '../../SCREENS';
import CONST from '../../CONST';
+import deepReplaceKeysAndValues from '../deepReplaceKeysAndValues';
let resolveNavigationIsReadyPromise;
const navigationIsReadyPromise = new Promise((resolve) => {
@@ -255,6 +256,17 @@ function setIsNavigationReady() {
resolveNavigationIsReadyPromise();
}
+/**
+ * Replace a given reportID in the navigation stack.
+ *
+ * @param {String} oldReportID
+ * @param {String} newReportID
+ */
+function replaceReportIDInNavigationStack(oldReportID, newReportID) {
+ const updatedState = deepReplaceKeysAndValues(navigationRef.getRootState(), oldReportID, newReportID);
+ navigationRef.resetRoot(updatedState);
+}
+
export default {
setShouldPopAllStateOnUP,
canNavigate,
@@ -268,6 +280,7 @@ export default {
setIsNavigationReady,
getTopmostReportId,
getRouteNameFromStateEvent,
+ replaceReportIDInNavigationStack,
};
export {navigationRef};
diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js
index 66008ae5ae..28f3dbed14 100644
--- a/src/libs/actions/Report.js
+++ b/src/libs/actions/Report.js
@@ -969,11 +969,7 @@ function handleReportChanged(report) {
if (report && report.reportID && report.preexistingReportID) {
Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, null);
- // Only re-route them if they are still looking at the optimistically created report
- if (Navigation.getActiveRoute().includes(`/r/${report.reportID}`)) {
- // Pass 'FORCED_UP' type to replace new report on second login with proper one in the Navigation
- Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report.preexistingReportID), CONST.NAVIGATION.TYPE.FORCED_UP);
- }
+ Navigation.replaceReportIDInNavigationStack(report.reportID, report.preexistingReportID);
return;
}
I also put a good amount of work into writing automated UI tests to cover these kind of esoteric navigation changes. Those tests were definitely imperfect, but you can see them deleted in this commit and it's hopefully a good starting point.
Upwork Automation - Do Not Edit
- Upwork Job URL: https://www.upwork.com/jobs/~015e5d9751f42a757a
- Upwork Job ID: 1718973704710303744
- Last Price Increase: 2023-10-30
Issue Owner
Current Issue Owner: @roryabraham
HOLD on #27996
Problem
We have a bit of code here to re-route the user if they are looking at an optimistically-generated reportID. However, it only works if that report is the active route, and doesn't work in a number of different situations. For example:
Actions taken
Settings->Preferencesand toggleForce Offline.Settings->Preferencesand untoggleForce Offline.Expected behavior
In the background, the report should rerender to the correct report, showing the messages from Alice and Bob. If you then close the Settings modal/RHP, then you should see the new report, not the unused optimistic one.
I'm quite certain there are other edge cases that won't work correctly, like pressing the browser back button a few times to return to the unused optimistic report.
Actual behavior
You'll see the 404 page.
Solution
At a high level, the solution should be to re-write the navigation state and history to replace all instances of the unused reportID with the correct one.
I started working on a solution to this in #27996, but decided to drop it and treat it as a separate issue.
The solution I'm most confident in leverages a function added in #27996, and looks like this:
I also put a good amount of work into writing automated UI tests to cover these kind of esoteric navigation changes. Those tests were definitely imperfect, but you can see them deleted in this commit and it's hopefully a good starting point.
Upwork Automation - Do Not Edit
Issue Owner
Current Issue Owner: @roryabraham