mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
fix(core): add fallback handler for hardware back button when no router is present (#30878)
Issue number: 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 new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> This pull request enhances the hardware back button functionality to ensure a consistent user experience, especially when no custom handlers are registered. The main improvement is the addition of a fallback handler that triggers the default browser back navigation when no other handlers are present. **Hardware Back Button Improvements:** * Added a fallback handler in `startHardwareBackButton` that navigates back in browser history (`win?.history.back()`) if no custom handlers are registered, ensuring the hardware back button always performs a meaningful action. * Introduced a constant `FALLBACK_BACK_BUTTON_PRIORITY` with a value of `-1` to manage the priority of the fallback handler. **Code Consistency:** * Moved the import of `win` from `@utils/browser` to group it with other imports for consistency. ## 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. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> --------- Co-authored-by: ShaneK <shane@shanessite.net>
This commit is contained in:
@@ -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';
|
||||
@@ -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) {
|
||||
@@ -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
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
Reference in New Issue
Block a user