mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 03:00:58 +08:00
85 lines
2.3 KiB
TypeScript
85 lines
2.3 KiB
TypeScript
import type { BackButtonEvent } from '../interface';
|
|
|
|
// TODO(FW-2832): type
|
|
type Handler = (processNextHandler: () => void) => Promise<any> | void | null;
|
|
|
|
interface HandlerRegister {
|
|
priority: number;
|
|
handler: Handler;
|
|
id: number;
|
|
}
|
|
|
|
/**
|
|
* When hardwareBackButton: false in config,
|
|
* we need to make sure we also block the default
|
|
* webview behavior. If we don't then it will be
|
|
* possible for users to navigate backward while
|
|
* an overlay is still open. Additionally, it will
|
|
* give the appearance that the hardwareBackButton
|
|
* config is not working as the page transition
|
|
* will still happen.
|
|
*/
|
|
export const blockHardwareBackButton = () => {
|
|
document.addEventListener('backbutton', () => {}); // eslint-disable-line
|
|
};
|
|
|
|
export const startHardwareBackButton = () => {
|
|
const doc = document;
|
|
|
|
let busy = false;
|
|
doc.addEventListener('backbutton', () => {
|
|
if (busy) {
|
|
return;
|
|
}
|
|
|
|
let index = 0;
|
|
let handlers: HandlerRegister[] = [];
|
|
const ev: BackButtonEvent = new CustomEvent('ionBackButton', {
|
|
bubbles: false,
|
|
detail: {
|
|
register(priority: number, handler: Handler) {
|
|
handlers.push({ priority, handler, id: index++ });
|
|
},
|
|
},
|
|
});
|
|
doc.dispatchEvent(ev);
|
|
|
|
const executeAction = async (handlerRegister: HandlerRegister | undefined) => {
|
|
try {
|
|
if (handlerRegister?.handler) {
|
|
const result = handlerRegister.handler(processHandlers);
|
|
if (result != null) {
|
|
await result;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
};
|
|
|
|
const processHandlers = () => {
|
|
if (handlers.length > 0) {
|
|
let selectedHandler: HandlerRegister = {
|
|
priority: Number.MIN_SAFE_INTEGER,
|
|
handler: () => undefined,
|
|
id: -1,
|
|
};
|
|
handlers.forEach((handler) => {
|
|
if (handler.priority >= selectedHandler.priority) {
|
|
selectedHandler = handler;
|
|
}
|
|
});
|
|
|
|
busy = true;
|
|
handlers = handlers.filter((handler) => handler.id !== selectedHandler.id);
|
|
executeAction(selectedHandler).then(() => (busy = false));
|
|
}
|
|
};
|
|
|
|
processHandlers();
|
|
});
|
|
};
|
|
|
|
export const OVERLAY_BACK_BUTTON_PRIORITY = 100;
|
|
export const MENU_BACK_BUTTON_PRIORITY = 99; // 1 less than overlay priority since menu is displayed behind overlays
|