From 60630ccb42700d3f5f7aa2b0f5c1d060f1751b7f Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Wed, 25 Oct 2023 10:44:58 -0400 Subject: [PATCH] refactor: improve hardware back button types (#28335) Issue number: Internal --------- ## What is the current behavior? As part of FW-2832, the team would like to swap out usages of the `any` type for stronger types. ## What is the new behavior? - Added `ionBackButton` event types to the browser utilities - Updated menuController to use the `doc` utility instead of `document` so we can get proper types - Moved the definitions for back button types out of `interface.d.ts` and into `hardware-back-button`. `interface.d.ts` still exports these back button interfaces. - Updated all `BackButtonEvent` imports inside of `@ionic/core` to import from the utility file instead of the public interface file. ## Does this introduce a breaking change? - [ ] Yes - [x] No ## Other information Note: This PR was separated from other type updates associated with the FW-3832 work because I had to modify the implementation of a feature in Ionic. While I don't expect there to be any functional differences, I have opted to pull this work out into a separate branch and target a feature branch to a) reduce the impact of any unintended bugs and b) make it easier to do a `git bisect` if a bug is introduced. --- core/src/components/router/router.tsx | 3 ++- core/src/interface.d.ts | 6 +----- core/src/utils/browser/index.ts | 12 ++++++++++++ core/src/utils/hardware-back-button.ts | 8 ++++++-- core/src/utils/menu-controller/index.ts | 25 ++++++++++++------------- core/src/utils/overlays.ts | 2 +- 6 files changed, 34 insertions(+), 22 deletions(-) diff --git a/core/src/components/router/router.tsx b/core/src/components/router/router.tsx index cc80971996..3f30e6f975 100644 --- a/core/src/components/router/router.tsx +++ b/core/src/components/router/router.tsx @@ -1,8 +1,9 @@ import type { ComponentInterface, EventEmitter } from '@stencil/core'; import { Component, Element, Event, Listen, Method, Prop } from '@stencil/core'; +import type { BackButtonEvent } from '@utils/hardware-back-button'; import { debounce } from '@utils/helpers'; -import type { AnimationBuilder, BackButtonEvent } from '../../interface'; +import type { AnimationBuilder } from '../../interface'; import type { NavigationHookResult } from '../route/route-interface'; import { ROUTER_INTENT_BACK, ROUTER_INTENT_FORWARD, ROUTER_INTENT_NONE } from './utils/constants'; diff --git a/core/src/interface.d.ts b/core/src/interface.d.ts index 377af9398a..3ac6705855 100644 --- a/core/src/interface.d.ts +++ b/core/src/interface.d.ts @@ -32,6 +32,7 @@ export { TabsCustomEvent } from './components/tabs/tabs-interface'; export { TextareaCustomEvent } from './components/textarea/textarea-interface'; export { ToastOptions } from './components/toast/toast-interface'; export { ToggleCustomEvent } from './components/toggle/toggle-interface'; +export { BackButtonEvent, BackButtonEventDetail } from './utils/hardware-back-button'; // Types from utils export { @@ -140,17 +141,12 @@ export type ComponentRef = Function | HTMLElement | string | null; // eslint-disable-next-line export type ComponentProps = { [key: string]: any }; export type CssClassMap = { [className: string]: boolean }; -export type BackButtonEvent = CustomEvent; export interface FrameworkDelegate { attachViewToDom(container: any, component: any, propsOrDataObj?: any, cssClasses?: string[]): Promise; removeViewFromDom(container: any, component: any): Promise; } -export interface BackButtonEventDetail { - register(priority: number, handler: (processNextHandler: () => void) => Promise | void): void; -} - export interface KeyboardEventDetail { keyboardHeight: number; } diff --git a/core/src/utils/browser/index.ts b/core/src/utils/browser/index.ts index d50ceb5701..fb400d142c 100644 --- a/core/src/utils/browser/index.ts +++ b/core/src/utils/browser/index.ts @@ -1,3 +1,5 @@ +import type { BackButtonEvent } from '@utils/hardware-back-button'; + /** * When accessing the document or window, it is important * to account for SSR applications where the @@ -58,6 +60,16 @@ type IonicEvents = { listener: (ev: CustomEvent) => void, options?: boolean | AddEventListenerOptions ): void; + addEventListener( + type: 'ionBackButton', + listener: (ev: BackButtonEvent) => void, + options?: boolean | AddEventListenerOptions + ): void; + removeEventListener( + type: 'ionBackButton', + listener: (ev: BackButtonEvent) => void, + options?: boolean | AddEventListenerOptions + ): void; }; type IonicWindow = Window & IonicEvents; diff --git a/core/src/utils/hardware-back-button.ts b/core/src/utils/hardware-back-button.ts index 7445dbedbd..91a0bc540f 100644 --- a/core/src/utils/hardware-back-button.ts +++ b/core/src/utils/hardware-back-button.ts @@ -1,8 +1,12 @@ -import type { BackButtonEvent } from '../interface'; - // TODO(FW-2832): type type Handler = (processNextHandler: () => void) => Promise | void | null; +export interface BackButtonEventDetail { + register(priority: number, handler: (processNextHandler: () => void) => Promise | void): void; +} + +export type BackButtonEvent = CustomEvent; + interface HandlerRegister { priority: number; handler: Handler; diff --git a/core/src/utils/menu-controller/index.ts b/core/src/utils/menu-controller/index.ts index ab5a1ffc01..aa09e8a825 100644 --- a/core/src/utils/menu-controller/index.ts +++ b/core/src/utils/menu-controller/index.ts @@ -1,8 +1,10 @@ +import { doc } from '@utils/browser'; +import type { BackButtonEvent } from '@utils/hardware-back-button'; +import { MENU_BACK_BUTTON_PRIORITY } from '@utils/hardware-back-button'; import { printIonWarning } from '@utils/logging'; import type { MenuI, MenuControllerI } from '../../components/menu/menu-interface'; -import type { AnimationBuilder, BackButtonEvent } from '../../interface'; -import { MENU_BACK_BUTTON_PRIORITY } from '../hardware-back-button'; +import type { AnimationBuilder } from '../../interface'; import { componentOnReady } from '../helpers'; import { menuOverlayAnimation } from './animations/overlay'; @@ -227,17 +229,14 @@ const createMenuController = (): MenuControllerI => { registerAnimation('push', menuPushAnimation); registerAnimation('overlay', menuOverlayAnimation); - if (typeof document !== 'undefined') { - document.addEventListener('ionBackButton', (ev: any) => { - // TODO(FW-2832): type - const openMenu = _getOpenSync(); - if (openMenu) { - (ev as BackButtonEvent).detail.register(MENU_BACK_BUTTON_PRIORITY, () => { - return openMenu.close(); - }); - } - }); - } + doc?.addEventListener('ionBackButton', (ev: BackButtonEvent) => { + const openMenu = _getOpenSync(); + if (openMenu) { + ev.detail.register(MENU_BACK_BUTTON_PRIORITY, () => { + return openMenu.close(); + }); + } + }); return { registerAnimation, diff --git a/core/src/utils/overlays.ts b/core/src/utils/overlays.ts index 07d8fc8c1d..98df03aa4d 100644 --- a/core/src/utils/overlays.ts +++ b/core/src/utils/overlays.ts @@ -1,4 +1,5 @@ import { doc } from '@utils/browser'; +import type { BackButtonEvent } from '@utils/hardware-back-button'; import { config } from '../global/config'; import { getIonMode } from '../global/ionic-global'; @@ -7,7 +8,6 @@ import type { AlertOptions, Animation, AnimationBuilder, - BackButtonEvent, FrameworkDelegate, HTMLIonOverlayElement, IonicConfig,