Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion core/src/utils/hardware-back-button.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { win } from '@utils/browser';
import type { CloseWatcher } from '@utils/browser';
import { win } from '@utils/browser';
import { printIonError } from '@utils/logging';

import { config } from '../global/config';
Expand Down Expand Up @@ -69,6 +69,21 @@ export const startHardwareBackButton = () => {
});
doc.dispatchEvent(ev);

/**
* If no handlers have been registered, fall back to the default
* behavior of navigating back in history. This ensures the hardware
* back button works even when no router or custom handler is present.
*/
if (handlers.length === 0) {
handlers.push({
priority: FALLBACK_BACK_BUTTON_PRIORITY,
handler: () => {
win?.history.back();
},
id: index++,
});
}

const executeAction = async (handlerRegister: HandlerRegister | undefined) => {
try {
if (handlerRegister?.handler) {
Expand Down Expand Up @@ -138,3 +153,4 @@ export const startHardwareBackButton = () => {

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
const FALLBACK_BACK_BUTTON_PRIORITY = -1; // Fallback when no other handlers are registered
41 changes: 41 additions & 0 deletions core/src/utils/test/hardware-back-button.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,47 @@ describe('Hardware Back Button', () => {
dispatchBackButtonEvent();
expect(cbSpyTwo).toHaveBeenCalled();
});

it('should fall back to history.back() when no handlers are registered', () => {
const historyBackSpy = jest.fn();
const originalBack = win?.history?.back;
if (win?.history) {
win.history.back = historyBackSpy;
}

// Don't register any ionBackButton handlers
dispatchBackButtonEvent();

expect(historyBackSpy).toHaveBeenCalled();

// Restore original
if (win?.history && originalBack) {
win.history.back = originalBack;
}
});

it('should not call history.back() when a handler is registered', () => {
const historyBackSpy = jest.fn();
const originalBack = win?.history?.back;
if (win?.history) {
win.history.back = historyBackSpy;
}

const cbSpy = jest.fn();
document.addEventListener('ionBackButton', (ev) => {
(ev as BackButtonEvent).detail.register(0, cbSpy);
});

dispatchBackButtonEvent();

expect(cbSpy).toHaveBeenCalled();
expect(historyBackSpy).not.toHaveBeenCalled();

// Restore original
if (win?.history && originalBack) {
win.history.back = originalBack;
}
});
});

describe('Experimental Close Watcher', () => {
Expand Down
Loading