Skip to content

Commit 7fecc50

Browse files
committedJan 14, 2025
prevent beforeunload firing when opening route in desktop
1 parent 1ef3f73 commit 7fecc50

File tree

2 files changed

+35
-12
lines changed

2 files changed

+35
-12
lines changed
 

‎src/libs/ActiveClientManager/index.ts

+24-11
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
*/
66
import {Str} from 'expensify-common';
77
import Onyx from 'react-native-onyx';
8+
import {isOpeningRouteInDesktop, resetIsOpeningRouteInDesktop} from '@libs/Browser/index.website';
9+
import Log from '@libs/Log';
810
import * as ActiveClients from '@userActions/ActiveClients';
911
import ONYXKEYS from '@src/ONYXKEYS';
1012
import type {Init, IsClientTheLeader, IsReady} from './types';
11-
import Log from '@libs/Log';
12-
import { isDevelopment } from '@libs/Environment/Environment';
1313

1414
const clientID = Str.guid();
1515
const maxClients = 20;
@@ -18,8 +18,8 @@ let resolveSavedSelfPromise: () => void;
1818
const savedSelfPromise = new Promise<void>((resolve) => {
1919
resolveSavedSelfPromise = resolve;
2020
});
21-
// The first time before unload is triggered by `openRouteInDesktopApp` function so we don't want to clear the clientID in this case.
22-
let shouldPreventBeforeUnload = !isDevelopment();
21+
let beforeunloadListenerAdded = false;
22+
2323
/**
2424
* Determines when the client is ready. We need to wait both till we saved our ID in onyx AND the init method was called
2525
*/
@@ -34,7 +34,7 @@ Onyx.connect({
3434

3535
activeClients = val;
3636

37-
console.log("[Active Clients] the client value is changed to", activeClients);
37+
console.log('[Active Clients] the client value is changed to', activeClients);
3838
// Remove from the beginning of the list any clients that are past the limit, to avoid having thousands of them
3939
let removed = false;
4040
while (activeClients.length >= maxClients) {
@@ -70,15 +70,10 @@ const isClientTheLeader: IsClientTheLeader = () => {
7070

7171
Log.info(`[Active Clients] checking the leader lastActiveClient=${lastActiveClient} clientID=${clientID}`);
7272

73-
7473
return lastActiveClient === clientID;
7574
};
7675

7776
const cleanUpClientId = () => {
78-
if (shouldPreventBeforeUnload) {
79-
shouldPreventBeforeUnload = false;
80-
return;
81-
}
8277
isPromotingNewLeader = isClientTheLeader();
8378
activeClients = activeClients.filter((id) => id !== clientID);
8479
Log.info(`[Active Clients] removed a client here clientID=${clientID}`);
@@ -89,18 +84,36 @@ const cleanUpClientId = () => {
8984
});
9085
};
9186

87+
const removeBeforeUnloadListener = () => {
88+
if (!beforeunloadListenerAdded) {
89+
return;
90+
}
91+
beforeunloadListenerAdded = false;
92+
window.removeEventListener('beforeunload', cleanUpClientId);
93+
};
94+
9295
/**
9396
* Add our client ID to the list of active IDs.
9497
* We want to ensure we have no duplicates and that the activeClient gets added at the end of the array (see isClientTheLeader)
9598
*/
9699
const init: Init = () => {
100+
removeBeforeUnloadListener();
97101
activeClients = activeClients.filter((id) => id !== clientID);
98102
activeClients.push(clientID);
99103
Log.info(`[Active Clients] added a client here clientID=${clientID}`);
100104
console.log(JSON.parse(JSON.stringify(activeClients)));
101105
ActiveClients.setActiveClients(activeClients).then(resolveSavedSelfPromise);
102106

103-
window.addEventListener('beforeunload', cleanUpClientId);
107+
beforeunloadListenerAdded = true;
108+
window.addEventListener('beforeunload', () => {
109+
// When we open route in desktop, beforeunload is fired unexpectedly here.
110+
// So we should return early in this case to prevent cleaning the clientID
111+
if (isOpeningRouteInDesktop()) {
112+
resetIsOpeningRouteInDesktop();
113+
return;
114+
}
115+
cleanUpClientId();
116+
});
104117
};
105118

106119
export {init, isClientTheLeader, isReady};

‎src/libs/Browser/index.website.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import CONST from '@src/CONST';
33
import ROUTES from '@src/ROUTES';
44
import type {GetBrowser, IsChromeIOS, IsMobile, IsMobileChrome, IsMobileSafari, IsMobileWebKit, IsSafari, OpenRouteInDesktopApp} from './types';
55

6+
let isOpenRouteInDesktop = false;
67
/**
78
* Fetch browser name from UA string
89
*
@@ -113,8 +114,17 @@ const openRouteInDesktopApp: OpenRouteInDesktopApp = (shortLivedAuthToken = '',
113114
document.body.removeChild(iframe);
114115
}, 0);
115116
} else {
117+
isOpenRouteInDesktop = true;
116118
window.location.href = expensifyDeeplinkUrl;
117119
}
118120
};
119121

120-
export {getBrowser, isMobile, isMobileSafari, isMobileWebKit, isSafari, isMobileChrome, isChromeIOS, openRouteInDesktopApp};
122+
const isOpeningRouteInDesktop = () => {
123+
return isOpenRouteInDesktop;
124+
};
125+
126+
const resetIsOpeningRouteInDesktop = () => {
127+
isOpenRouteInDesktop = false;
128+
};
129+
130+
export {getBrowser, isMobile, isMobileSafari, isMobileWebKit, isSafari, isMobileChrome, isChromeIOS, openRouteInDesktopApp, isOpeningRouteInDesktop, resetIsOpeningRouteInDesktop};

0 commit comments

Comments
 (0)