feat(app): move ion-app init logic to initialize function (#29930)

Issue number: resolves internal

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Some app functionality (like focus management, keyboard utils, and
shimming) are tied to the `ion-app` which requires all Ionic
applications to have a root `ion-app` element.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

`ion-app` specific init functionality is moved to the global
`initialize` function

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->

Although it is not expected that this introduces a breaking change,
these changes were introduced on the `next` branch as a precaution.

## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

NOTE: This is **NOT** a recommended pattern for Ionic applications and
was created for a specific internal use case

---------

Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
This commit is contained in:
Tanner Reits
2024-10-16 15:15:54 -04:00
committed by GitHub
parent 5d4a9893ef
commit 15d6104c6f
12 changed files with 122 additions and 94 deletions

View File

@ -1,7 +1,8 @@
import { getMode, setMode, setPlatformHelpers, getElement } from '@stencil/core';
import { Build, getMode, setMode, setPlatformHelpers, getElement } from '@stencil/core';
import { printIonWarning } from '@utils/logging';
import type { IonicConfig, Mode, Theme } from '../interface';
import { shouldUseCloseWatcher } from '../utils/hardware-back-button';
import { isPlatform, setupPlatforms } from '../utils/platform';
import { config, configFromSession, configFromURL, saveConfig } from './config';
@ -131,6 +132,36 @@ export const getIonTheme = (ref?: any): Theme => {
return defaultTheme;
};
export const rIC = (callback: () => void) => {
if ('requestIdleCallback' in window) {
(window as any).requestIdleCallback(callback);
} else {
setTimeout(callback, 32);
}
};
export const needInputShims = () => {
/**
* iOS always needs input shims
*/
const needsShimsIOS = isPlatform(window, 'ios') && isPlatform(window, 'mobile');
if (needsShimsIOS) {
return true;
}
/**
* Android only needs input shims when running
* in the browser and only if the browser is using the
* new Chrome 108+ resize behavior: https://developer.chrome.com/blog/viewport-resize-behavior/
*/
const isAndroidMobileWeb = isPlatform(window, 'android') && isPlatform(window, 'mobileweb');
if (isAndroidMobileWeb) {
return true;
}
return false;
};
export const initialize = (userConfig: IonicConfig = {}) => {
if (typeof (window as any) === 'undefined') {
return;
@ -255,6 +286,50 @@ export const initialize = (userConfig: IonicConfig = {}) => {
}
return defaultTheme;
});
// `IonApp` code
// ----------------------------------------------
if (Build.isBrowser) {
rIC(async () => {
const isHybrid = isPlatform(window, 'hybrid');
if (!config.getBoolean('_testing')) {
import('../utils/tap-click').then((module) => module.startTapClick(config));
}
if (config.getBoolean('statusTap', isHybrid)) {
import('../utils/status-tap').then((module) => module.startStatusTap());
}
if (config.getBoolean('inputShims', needInputShims())) {
/**
* needInputShims() ensures that only iOS and Android
* platforms proceed into this block.
*/
const platform = isPlatform(window, 'ios') ? 'ios' : 'android';
import('../utils/input-shims/input-shims').then((module) => module.startInputShims(config, platform));
}
const hardwareBackButtonModule = await import('../utils/hardware-back-button');
const supportsHardwareBackButtonEvents = isHybrid || shouldUseCloseWatcher();
if (config.getBoolean('hardwareBackButton', supportsHardwareBackButtonEvents)) {
hardwareBackButtonModule.startHardwareBackButton();
} else {
/**
* If an app sets hardwareBackButton: false and experimentalCloseWatcher: true
* then the close watcher will not be used.
*/
if (shouldUseCloseWatcher()) {
printIonWarning(
'experimentalCloseWatcher was set to `true`, but hardwareBackButton was set to `false`. Both config options must be `true` for the Close Watcher API to be used.'
);
}
hardwareBackButtonModule.blockHardwareBackButton();
}
if (typeof (window as any) !== 'undefined') {
import('../utils/keyboard/keyboard').then((module) => module.startKeyboardAssist(window));
}
import('../utils/focus-visible').then((module) => module.getOrInitFocusVisibleUtility());
});
}
};
export default initialize;