diff --git a/react/features/app/functions.native.ts b/react/features/app/functions.native.ts index 8743fa202a..513f48852e 100644 --- a/react/features/app/functions.native.ts +++ b/react/features/app/functions.native.ts @@ -5,6 +5,7 @@ import { toState } from '../base/redux/functions'; import { getServerURL } from '../base/settings/functions.native'; export * from './functions.any'; +import logger from './logger'; /** * Retrieves the default URL for the app. This can either come from a prop to @@ -38,3 +39,18 @@ export function getName() { export function getSdkBundlePath() { return NativeModules.AppInfo.sdkBundlePath; } + +/** + * This is a dummy implementation for compatibility with web. It executes the passed handler right away. + * + * @param {Function} handler - The callback function to execute. + * @returns {void} + */ +export function executeAfterLoad(handler: () => void) { + try { + handler(); + } catch (error) { + logger.error('Error executing handler after load:', error); + } +} + diff --git a/react/features/app/functions.web.ts b/react/features/app/functions.web.ts index 804fd4170f..4771e9366f 100644 --- a/react/features/app/functions.web.ts +++ b/react/features/app/functions.web.ts @@ -1,8 +1,10 @@ import { IStateful } from '../base/app/types'; import { toState } from '../base/redux/functions'; import { getServerURL } from '../base/settings/functions.web'; +import { getJitsiMeetGlobalNS } from '../base/util/helpers'; export * from './functions.any'; +import logger from './logger'; /** * Retrieves the default URL for the app. This can either come from a prop to @@ -31,3 +33,27 @@ export function getDefaultURL(stateful: IStateful) { export function getName() { return interfaceConfig.APP_NAME; } + +/** + * Executes a handler function after the window load event has been received. + * If the app has already loaded, the handler is executed immediately. + * Otherwise, the handler is registered as a 'load' event listener. + * + * @param {Function} handler - The callback function to execute. + * @returns {void} + */ +export function executeAfterLoad(handler: () => void) { + const safeHandler = () => { + try { + handler(); + } catch (error) { + logger.error('Error executing handler after load:', error); + } + }; + + if (getJitsiMeetGlobalNS()?.hasLoaded) { + safeHandler(); + } else { + window.addEventListener('load', safeHandler); + } +} diff --git a/react/features/deep-linking/openDesktopApp.ts b/react/features/deep-linking/openDesktopApp.ts index 8b7d19a131..3793dd5b29 100644 --- a/react/features/deep-linking/openDesktopApp.ts +++ b/react/features/deep-linking/openDesktopApp.ts @@ -1,3 +1,4 @@ +import { executeAfterLoad } from '../app/functions'; import { IReduxState } from '../app/types'; import { URI_PROTOCOL_PATTERN } from '../base/util/uri'; @@ -16,7 +17,10 @@ export function _openDesktopApp(_state: Object) { const { appScheme } = deeplinkingDesktop; const regex = new RegExp(URI_PROTOCOL_PATTERN, 'gi'); - window.location.href = window.location.href.replace(regex, `${appScheme}:`); + // This is needed to workaround https://issues.chromium.org/issues/41398687 + executeAfterLoad(() => { + window.location.href = window.location.href.replace(regex, `${appScheme}:`); + }); return Promise.resolve(true); } diff --git a/react/index.web.js b/react/index.web.js index 361e7ef985..2f05f2dfd4 100644 --- a/react/index.web.js +++ b/react/index.web.js @@ -47,11 +47,15 @@ if (Platform.OS === 'ios') { const globalNS = getJitsiMeetGlobalNS(); const connectionTimes = getJitsiMeetGlobalNSConnectionTimes(); +// Used to check if the load event has been fired. +globalNS.hasLoaded = false; + // Used for automated performance tests. connectionTimes['index.loaded'] = window.indexLoadedTime; window.addEventListener('load', () => { connectionTimes['window.loaded'] = window.loadedEventTime; + globalNS.hasLoaded = true; }); document.addEventListener('DOMContentLoaded', () => {