diff --git a/src/libs/ActiveClientManager/index.ts b/src/libs/ActiveClientManager/index.ts index 55583cd0b083..96f7cd6d0fa2 100644 --- a/src/libs/ActiveClientManager/index.ts +++ b/src/libs/ActiveClientManager/index.ts @@ -5,7 +5,8 @@ */ import {Str} from 'expensify-common'; import Onyx from 'react-native-onyx'; -import * as ActiveClients from '@userActions/ActiveClients'; +import {isOpeningRouteInDesktop, resetIsOpeningRouteInDesktop} from '@libs/Browser/index.website'; +import {setActiveClients} from '@userActions/ActiveClients'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Init, IsClientTheLeader, IsReady} from './types'; @@ -16,6 +17,7 @@ let resolveSavedSelfPromise: () => void; const savedSelfPromise = new Promise((resolve) => { resolveSavedSelfPromise = resolve; }); +let beforeunloadListenerAdded = false; /** * Determines when the client is ready. We need to wait both till we saved our ID in onyx AND the init method was called @@ -40,7 +42,7 @@ Onyx.connect({ // Save the clients back to onyx, if they changed if (removed) { - ActiveClients.setActiveClients(activeClients); + setActiveClients(activeClients); } }, }); @@ -70,7 +72,15 @@ const isClientTheLeader: IsClientTheLeader = () => { const cleanUpClientId = () => { isPromotingNewLeader = isClientTheLeader(); activeClients = activeClients.filter((id) => id !== clientID); - ActiveClients.setActiveClients(activeClients); + setActiveClients(activeClients); +}; + +const removeBeforeUnloadListener = () => { + if (!beforeunloadListenerAdded) { + return; + } + beforeunloadListenerAdded = false; + window.removeEventListener('beforeunload', cleanUpClientId); }; /** @@ -78,11 +88,21 @@ const cleanUpClientId = () => { * We want to ensure we have no duplicates and that the activeClient gets added at the end of the array (see isClientTheLeader) */ const init: Init = () => { + removeBeforeUnloadListener(); activeClients = activeClients.filter((id) => id !== clientID); activeClients.push(clientID); - ActiveClients.setActiveClients(activeClients).then(resolveSavedSelfPromise); + setActiveClients(activeClients).then(resolveSavedSelfPromise); - window.addEventListener('beforeunload', cleanUpClientId); + beforeunloadListenerAdded = true; + window.addEventListener('beforeunload', () => { + // When we open route in desktop, beforeunload is fired unexpectedly here. + // So we should return early in this case to prevent cleaning the clientID + if (isOpeningRouteInDesktop()) { + resetIsOpeningRouteInDesktop(); + return; + } + cleanUpClientId(); + }); }; export {init, isClientTheLeader, isReady}; diff --git a/src/libs/Browser/index.website.ts b/src/libs/Browser/index.website.ts index 2007f2c6cbc0..2f0ba7f0e289 100644 --- a/src/libs/Browser/index.website.ts +++ b/src/libs/Browser/index.website.ts @@ -3,6 +3,7 @@ import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type {GetBrowser, IsChromeIOS, IsMobile, IsMobileChrome, IsMobileSafari, IsMobileWebKit, IsSafari, OpenRouteInDesktopApp} from './types'; +let isOpenRouteInDesktop = false; /** * Fetch browser name from UA string * @@ -29,7 +30,7 @@ const getBrowser: GetBrowser = () => { } } - browserName = match[1] ?? navigator.appName; + browserName = match[1]; return browserName ? browserName.toLowerCase() : CONST.BROWSER.OTHER; }; @@ -113,8 +114,17 @@ const openRouteInDesktopApp: OpenRouteInDesktopApp = (shortLivedAuthToken = '', document.body.removeChild(iframe); }, 0); } else { + isOpenRouteInDesktop = true; window.location.href = expensifyDeeplinkUrl; } }; -export {getBrowser, isMobile, isMobileSafari, isMobileWebKit, isSafari, isMobileChrome, isChromeIOS, openRouteInDesktopApp}; +const isOpeningRouteInDesktop = () => { + return isOpenRouteInDesktop; +}; + +const resetIsOpeningRouteInDesktop = () => { + isOpenRouteInDesktop = false; +}; + +export {getBrowser, isMobile, isMobileSafari, isMobileWebKit, isSafari, isMobileChrome, isChromeIOS, openRouteInDesktopApp, isOpeningRouteInDesktop, resetIsOpeningRouteInDesktop};