diff --git a/patches/@react-navigation+native+6.1.6.patch b/patches/@react-navigation+native+6.1.6.patch
new file mode 100644
index 000000000000..61e5eb9892e1
--- /dev/null
+++ b/patches/@react-navigation+native+6.1.6.patch
@@ -0,0 +1,269 @@
+diff --git a/node_modules/@react-navigation/native/lib/module/createMemoryHistory.js b/node_modules/@react-navigation/native/lib/module/createMemoryHistory.js
+index 16fdbef..bc2c96a 100644
+--- a/node_modules/@react-navigation/native/lib/module/createMemoryHistory.js
++++ b/node_modules/@react-navigation/native/lib/module/createMemoryHistory.js
+@@ -1,8 +1,23 @@
+ import { nanoid } from 'nanoid/non-secure';
++import { findFocusedRouteKey } from './findFocusedRouteKey';
+ export default function createMemoryHistory() {
+ let index = 0;
+ let items = [];
+-
++ const log = () => {
++ console.log(JSON.stringify({
++ index,
++ indexGetter: history.index,
++ items: items.map((item, i) => {
++ var _item$state;
++ return {
++ selected: history.index === i ? '<<<<<<<' : undefined,
++ path: item.path,
++ id: item.id,
++ state: ((_item$state = item.state) === null || _item$state === void 0 ? void 0 : _item$state.key) || null
++ };
++ })
++ }, null, 4));
++ };
+ // Pending callbacks for `history.go(n)`
+ // We might modify the callback stored if it was interrupted, so we have a ref to identify it
+ const pending = [];
+@@ -16,6 +31,9 @@ export default function createMemoryHistory() {
+ });
+ };
+ const history = {
++ get items() {
++ return items;
++ },
+ get index() {
+ var _window$history$state;
+ // We store an id in the state instead of an index
+@@ -32,12 +50,13 @@ export default function createMemoryHistory() {
+ },
+ backIndex(_ref) {
+ let {
+- path
++ path,
++ state
+ } = _ref;
+ // We need to find the index from the element before current to get closest path to go back to
+ for (let i = index - 1; i >= 0; i--) {
+ const item = items[i];
+- if (item.path === path) {
++ if (item.path === path && findFocusedRouteKey(item.state) === findFocusedRouteKey(state)) {
+ return i;
+ }
+ }
+@@ -68,7 +87,9 @@ export default function createMemoryHistory() {
+ window.history.pushState({
+ id
+ }, '', path);
++ // log();
+ },
++
+ replace(_ref3) {
+ var _window$history$state2;
+ let {
+@@ -108,7 +129,9 @@ export default function createMemoryHistory() {
+ window.history.replaceState({
+ id
+ }, '', pathWithHash);
++ // log();
+ },
++
+ // `history.go(n)` is asynchronous, there are couple of things to keep in mind:
+ // - it won't do anything if we can't go `n` steps, the `popstate` event won't fire.
+ // - each `history.go(n)` call will trigger a separate `popstate` event with correct location.
+@@ -175,20 +198,17 @@ export default function createMemoryHistory() {
+ // But on Firefox, it seems to take much longer, around 50ms from our testing
+ // We're using a hacky timeout since there doesn't seem to be way to know for sure
+ const timer = setTimeout(() => {
+- const index = pending.findIndex(it => it.ref === done);
+- if (index > -1) {
+- pending[index].cb();
+- pending.splice(index, 1);
++ const foundIndex = pending.findIndex(it => it.ref === done);
++ if (foundIndex > -1) {
++ pending[foundIndex].cb();
++ pending.splice(foundIndex, 1);
+ }
++ index = this.index;
+ }, 100);
+ const onPopState = () => {
+- var _window$history$state3;
+- const id = (_window$history$state3 = window.history.state) === null || _window$history$state3 === void 0 ? void 0 : _window$history$state3.id;
+- const currentIndex = items.findIndex(item => item.id === id);
+-
+ // Fix createMemoryHistory.index variable's value
+ // as it may go out of sync when navigating in the browser.
+- index = Math.max(currentIndex, 0);
++ index = this.index;
+ const last = pending.pop();
+ window.removeEventListener('popstate', onPopState);
+ last === null || last === void 0 ? void 0 : last.cb();
+@@ -202,12 +222,17 @@ export default function createMemoryHistory() {
+ // Here we normalize it so that only external changes (e.g. user pressing back/forward) trigger the listener
+ listen(listener) {
+ const onPopState = () => {
++ // Fix createMemoryHistory.index variable's value
++ // as it may go out of sync when navigating in the browser.
++ index = this.index;
+ if (pending.length) {
+ // This was triggered by `history.go(n)`, we shouldn't call the listener
+ return;
+ }
+ listener();
++ // log();
+ };
++
+ window.addEventListener('popstate', onPopState);
+ return () => window.removeEventListener('popstate', onPopState);
+ }
+diff --git a/node_modules/@react-navigation/native/lib/module/findFocusedRouteKey.js b/node_modules/@react-navigation/native/lib/module/findFocusedRouteKey.js
+new file mode 100644
+index 0000000..16da117
+--- /dev/null
++++ b/node_modules/@react-navigation/native/lib/module/findFocusedRouteKey.js
+@@ -0,0 +1,7 @@
++import { findFocusedRoute } from '@react-navigation/core';
++export const findFocusedRouteKey = state => {
++ var _findFocusedRoute;
++ // @ts-ignore
++ return (_findFocusedRoute = findFocusedRoute(state)) === null || _findFocusedRoute === void 0 ? void 0 : _findFocusedRoute.key;
++};
++//# sourceMappingURL=findFocusedRouteKey.js.map
+\ No newline at end of file
+diff --git a/node_modules/@react-navigation/native/lib/module/useLinking.js b/node_modules/@react-navigation/native/lib/module/useLinking.js
+index 5bf2a88..a6d0670 100644
+--- a/node_modules/@react-navigation/native/lib/module/useLinking.js
++++ b/node_modules/@react-navigation/native/lib/module/useLinking.js
+@@ -2,6 +2,7 @@ import { findFocusedRoute, getActionFromState as getActionFromStateDefault, getP
+ import isEqual from 'fast-deep-equal';
+ import * as React from 'react';
+ import createMemoryHistory from './createMemoryHistory';
++import { findFocusedRouteKey } from './findFocusedRouteKey';
+ import ServerContext from './ServerContext';
+ /**
+ * Find the matching navigation state that changed between 2 navigation states
+@@ -60,6 +61,44 @@ const series = cb => {
+ return callback;
+ };
+ let linkingHandlers = [];
++const getAllStateKeys = state => {
++ let current = state;
++ const keys = [];
++ if (current.routes) {
++ for (let route of current.routes) {
++ keys.push(route.key);
++ if (route.state) {
++ // @ts-ignore
++ keys.push(...getAllStateKeys(route.state));
++ }
++ }
++ }
++ return keys;
++};
++const getStaleHistoryDiff = (items, newState) => {
++ const newStateKeys = getAllStateKeys(newState);
++ for (let i = items.length - 1; i >= 0; i--) {
++ const itemFocusedKey = findFocusedRouteKey(items[i].state);
++ if (newStateKeys.includes(itemFocusedKey)) {
++ return items.length - i - 1;
++ }
++ }
++ return -1;
++};
++const getHistoryDeltaByKeys = (focusedState, previousFocusedState) => {
++ const focusedStateKeys = focusedState.routes.map(r => r.key);
++ const previousFocusedStateKeys = previousFocusedState.routes.map(r => r.key);
++ const minLength = Math.min(focusedStateKeys.length, previousFocusedStateKeys.length);
++ let matchingKeys = 0;
++ for (let i = 0; i < minLength; i++) {
++ if (focusedStateKeys[i] === previousFocusedStateKeys[i]) {
++ matchingKeys++;
++ } else {
++ break;
++ }
++ }
++ return -(previousFocusedStateKeys.length - matchingKeys);
++};
+ export default function useLinking(ref, _ref) {
+ let {
+ independent,
+@@ -251,6 +290,9 @@ export default function useLinking(ref, _ref) {
+ // Otherwise it's likely a change triggered by `popstate`
+ path !== pendingPath) {
+ const historyDelta = (focusedState.history ? focusedState.history.length : focusedState.routes.length) - (previousFocusedState.history ? previousFocusedState.history.length : previousFocusedState.routes.length);
++
++ // The historyDelta and historyDeltaByKeys may differ if the new state has an entry that didn't exist in previous state
++ const historyDeltaByKeys = getHistoryDeltaByKeys(focusedState, previousFocusedState);
+ if (historyDelta > 0) {
+ // If history length is increased, we should pushState
+ // Note that path might not actually change here, for example, drawer open should pushState
+@@ -262,34 +304,55 @@ export default function useLinking(ref, _ref) {
+ // If history length is decreased, i.e. entries were removed, we want to go back
+
+ const nextIndex = history.backIndex({
+- path
++ path,
++ state
+ });
+ const currentIndex = history.index;
+ try {
+ if (nextIndex !== -1 && nextIndex < currentIndex) {
+ // An existing entry for this path exists and it's less than current index, go back to that
+ await history.go(nextIndex - currentIndex);
++ history.replace({
++ path,
++ state
++ });
+ } else {
+ // We couldn't find an existing entry to go back to, so we'll go back by the delta
+ // This won't be correct if multiple routes were pushed in one go before
+ // Usually this shouldn't happen and this is a fallback for that
+- await history.go(historyDelta);
++ await history.go(historyDeltaByKeys);
++ if (historyDeltaByKeys + 1 === historyDelta) {
++ history.push({
++ path,
++ state
++ });
++ } else {
++ history.replace({
++ path,
++ state
++ });
++ }
+ }
+-
+- // Store the updated state as well as fix the path if incorrect
+- history.replace({
+- path,
+- state
+- });
+ } catch (e) {
+ // The navigation was interrupted
+ }
+ } else {
+ // If history length is unchanged, we want to replaceState
+- history.replace({
+- path,
+- state
+- });
++ // and remove any entries from history which focued route no longer exists in state
++ // That may happen if we replace a whole navigator.
++ const staleHistoryDiff = getStaleHistoryDiff(history.items.slice(0, history.index + 1), state);
++ if (staleHistoryDiff <= 0) {
++ history.replace({
++ path,
++ state
++ });
++ } else {
++ await history.go(-staleHistoryDiff);
++ history.push({
++ path,
++ state
++ });
++ }
+ }
+ } else {
+ // If no common navigation state was found, assume it's a replace
diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js
index ec26c351de57..533b6d0af650 100644
--- a/src/libs/actions/Report.js
+++ b/src/libs/actions/Report.js
@@ -1774,6 +1774,10 @@ function leaveRoom(reportID) {
],
},
);
+ Navigation.dismissModal();
+ if (Navigation.getTopmostReportId() === reportID) {
+ Navigation.goBack();
+ }
navigateToConciergeChat();
}
diff --git a/src/pages/home/report/withReportOrNotFound.js b/src/pages/home/report/withReportOrNotFound.js
index 1db297c4b883..5829ac7a6015 100644
--- a/src/pages/home/report/withReportOrNotFound.js
+++ b/src/pages/home/report/withReportOrNotFound.js
@@ -46,12 +46,30 @@ export default function (WrappedComponent) {
// eslint-disable-next-line rulesdir/no-negated-variables
function WithReportOrNotFound(props) {
- if (props.isLoadingReportData && (_.isEmpty(props.report) || !props.report.reportID)) {
+ const contentShown = React.useRef(false);
+
+ const shouldShowFullScreenLoadingIndicator = props.isLoadingReportData && (_.isEmpty(props.report) || !props.report.reportID);
+ // eslint-disable-next-line rulesdir/no-negated-variables
+ const shouldShowNotFoundPage = _.isEmpty(props.report) || !props.report.reportID || !ReportUtils.canAccessReport(props.report, props.policies, props.betas);
+
+ // If the content was shown but it's not anymore that means the report was deleted and we are probably navigating out of this screen.
+ // Return null for this case to avoid rendering FullScreenLoadingIndicator or NotFoundPage when animating transition.
+ if (shouldShowNotFoundPage && contentShown.current) {
+ return null;
+ }
+
+ if (shouldShowFullScreenLoadingIndicator) {
return ;
}
- if (_.isEmpty(props.report) || !props.report.reportID || !ReportUtils.canAccessReport(props.report, props.policies, props.betas)) {
+
+ if (shouldShowNotFoundPage) {
return ;
}
+
+ if (!contentShown.current) {
+ contentShown.current = true;
+ }
+
const rest = _.omit(props, ['forwardedRef']);
return (