From c64cc89200c4daa939c0a90fe73170d1e15c719e Mon Sep 17 00:00:00 2001 From: Johnny McQuade Date: Tue, 3 Dec 2024 15:41:19 +0000 Subject: [PATCH 1/5] wip: nav-stack close on back nav alt --- .../feature/nav-stack/nav-stack.service.ts | 54 +++++++++++++++++-- .../template/services/template-nav.service.ts | 48 +++++++++++++++++ 2 files changed, 98 insertions(+), 4 deletions(-) diff --git a/src/app/feature/nav-stack/nav-stack.service.ts b/src/app/feature/nav-stack/nav-stack.service.ts index 493969395..6f572b7bf 100644 --- a/src/app/feature/nav-stack/nav-stack.service.ts +++ b/src/app/feature/nav-stack/nav-stack.service.ts @@ -2,6 +2,7 @@ import { Injectable } from "@angular/core"; import { ModalController } from "@ionic/angular"; import { INavStackConfig, NavStackComponent } from "./components/nav-stack/nav-stack.component"; import { SyncServiceBase } from "src/app/shared/services/syncService.base"; +import { TemplateNavService } from "src/app/shared/components/template/services/template-nav.service"; interface NavStackModal extends HTMLIonModalElement {} @@ -11,9 +12,13 @@ interface NavStackModal extends HTMLIonModalElement {} export class NavStackService extends SyncServiceBase { private openNavStacks: HTMLIonModalElement[] = []; - constructor(private modalCtrl: ModalController) { + constructor( + private modalCtrl: ModalController, + private templateNavService: TemplateNavService + ) { super("navStack"); // NB: Actions are registered in nav-stack module + // setInterval(() => console.log("history state", history.state), 1000); } /** @@ -22,12 +27,16 @@ export class NavStackService extends SyncServiceBase { */ public async pushNavStack(navStackConfig: INavStackConfig) { const modal = await this.createNavStackModal(navStackConfig); + console.log("modal id", modal.id); + // add a history entry so that the page can be navigated back to + history.pushState({ modalId: modal.id }, ""); await this.presentAndTrackModal(modal); return modal; } public async closeAllNavStacks() { await Promise.all(this.openNavStacks.map(async (navStack) => await navStack.dismiss())); + console.log("openNavStacks", this.openNavStacks); } public async closeTopNavStack() { @@ -57,10 +66,11 @@ export class NavStackService extends SyncServiceBase { modal.onWillDismiss().then(() => { const index = this.getNavStackIndex(modal); if (index === -1) return; - this.openNavStacks.splice(index, 1); + this.removeNavStackFromArray(index); + // this.removeNavStackHistoryState(modal); }); await modal.present(); - this.openNavStacks.push(modal); + this.addNavStackToArray(modal); } private getNavStackIndex(modalElement: HTMLIonModalElement) { @@ -68,7 +78,43 @@ export class NavStackService extends SyncServiceBase { } private async closeNavStack(index: number) { - await this.openNavStacks[index].dismiss(); + await this.dismissNavStackModal(this.openNavStacks[index]); this.openNavStacks.splice(index, 1); } + + private async dismissNavStackModal(modal: NavStackModal) { + await modal.dismiss(); + this.removeNavStackHistoryState(modal); + } + + private removeNavStackHistoryState(modal: NavStackModal) { + const modalId = modal.id; + console.log("**modalId", modalId); + console.log("**history state", history.state); + console.log("**history state modalId", history.state?.modalId); + // If we pushed a state for this modal, go back + if (history.state?.modalId === modalId) { + console.log("going back"); + history.back(); + } + } + + private addNavStackToArray(modal: NavStackModal) { + if (this.openNavStacks.length === 0) { + this.setCustomBackHandler(); + } + this.openNavStacks.push(modal); + } + + private removeNavStackFromArray(index: number) { + this.openNavStacks.splice(index, 1); + console.log("openNavStacks", this.openNavStacks); + if (this.openNavStacks.length === 0) { + this.templateNavService.destroyBackButtonHandler(); + } + } + + private setCustomBackHandler() { + this.templateNavService.initializeBackButtonHandler(() => this.closeTopNavStack()); + } } diff --git a/src/app/shared/components/template/services/template-nav.service.ts b/src/app/shared/components/template/services/template-nav.service.ts index 26303895a..047999708 100644 --- a/src/app/shared/components/template/services/template-nav.service.ts +++ b/src/app/shared/components/template/services/template-nav.service.ts @@ -16,6 +16,8 @@ import { TemplateContainerComponent } from "../template-container.component"; const SHOW_DEBUG_LOGS = false; const log = SHOW_DEBUG_LOGS ? console.log : () => null; +type ICustomBackHandler = () => any; + @Injectable({ providedIn: "root", }) @@ -24,6 +26,11 @@ const log = SHOW_DEBUG_LOGS ? console.log : () => null; * ... */ export class TemplateNavService extends SyncServiceBase { + // Custom function to handle browser's back button press + customBackHandler: ICustomBackHandler | null = null; + popStateListener: ((event: PopStateEvent) => void) | null = null; + ignorePopState: boolean = false; + constructor( private modalCtrl: ModalController, private location: Location, @@ -75,6 +82,47 @@ export class TemplateNavService extends SyncServiceBase { ]); } } + + /***************************************************************************************************** + * Handling browser navigation + ****************************************************************************************************/ + + public initializeBackButtonHandler(handler?: ICustomBackHandler) { + if (handler) { + this.setCustomBackHandler(handler); + } + if (!this.popStateListener) { + this.popStateListener = this.onPopState.bind(this); + window.addEventListener("popstate", this.popStateListener); + } + } + + public destroyBackButtonHandler() { + if (this.popStateListener) { + window.removeEventListener("popstate", this.popStateListener); + this.popStateListener = null; + } + this.customBackHandler = null; + } + + private setCustomBackHandler(handler: ICustomBackHandler) { + this.customBackHandler = handler; + } + + private onPopState(event: PopStateEvent) { + if (this.ignorePopState) { + this.ignorePopState = false; + return; + } + if (this.customBackHandler) { + this.customBackHandler(); + // ignore popstate event for the programmatic forward navigation + // this.ignorePopState = true; + // this.location.forward(); + } + // this.location.back(); + } + /***************************************************************************************************** * Nav Actions ****************************************************************************************************/ From 62e7d8044291edd92d50932f7cf7b598447e7960 Mon Sep 17 00:00:00 2001 From: Johnny McQuade Date: Tue, 3 Dec 2024 16:46:10 +0000 Subject: [PATCH 2/5] chore: dismiss top nav-stack on back action --- .../feature/nav-stack/nav-stack.service.ts | 23 ++++++++----------- .../template/services/template-nav.service.ts | 10 +++----- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/app/feature/nav-stack/nav-stack.service.ts b/src/app/feature/nav-stack/nav-stack.service.ts index 6f572b7bf..d4ce86d1e 100644 --- a/src/app/feature/nav-stack/nav-stack.service.ts +++ b/src/app/feature/nav-stack/nav-stack.service.ts @@ -18,7 +18,6 @@ export class NavStackService extends SyncServiceBase { ) { super("navStack"); // NB: Actions are registered in nav-stack module - // setInterval(() => console.log("history state", history.state), 1000); } /** @@ -27,16 +26,15 @@ export class NavStackService extends SyncServiceBase { */ public async pushNavStack(navStackConfig: INavStackConfig) { const modal = await this.createNavStackModal(navStackConfig); - console.log("modal id", modal.id); - // add a history entry so that the page can be navigated back to - history.pushState({ modalId: modal.id }, ""); await this.presentAndTrackModal(modal); return modal; } public async closeAllNavStacks() { - await Promise.all(this.openNavStacks.map(async (navStack) => await navStack.dismiss())); - console.log("openNavStacks", this.openNavStacks); + // Close nav-stacks in reverse order + for (let index = this.openNavStacks.length - 1; index >= 0; index--) { + await this.closeNavStack(index); + } } public async closeTopNavStack() { @@ -67,10 +65,12 @@ export class NavStackService extends SyncServiceBase { const index = this.getNavStackIndex(modal); if (index === -1) return; this.removeNavStackFromArray(index); - // this.removeNavStackHistoryState(modal); + this.removeNavStackHistoryState(modal); }); - await modal.present(); this.addNavStackToArray(modal); + // add a history entry so that we can navigate back on dismissal without changing page + history.pushState({ modalId: modal.id }, ""); + await modal.present(); } private getNavStackIndex(modalElement: HTMLIonModalElement) { @@ -84,17 +84,13 @@ export class NavStackService extends SyncServiceBase { private async dismissNavStackModal(modal: NavStackModal) { await modal.dismiss(); - this.removeNavStackHistoryState(modal); } private removeNavStackHistoryState(modal: NavStackModal) { const modalId = modal.id; - console.log("**modalId", modalId); - console.log("**history state", history.state); - console.log("**history state modalId", history.state?.modalId); // If we pushed a state for this modal, go back if (history.state?.modalId === modalId) { - console.log("going back"); + this.templateNavService.suppressPopState = true; history.back(); } } @@ -108,7 +104,6 @@ export class NavStackService extends SyncServiceBase { private removeNavStackFromArray(index: number) { this.openNavStacks.splice(index, 1); - console.log("openNavStacks", this.openNavStacks); if (this.openNavStacks.length === 0) { this.templateNavService.destroyBackButtonHandler(); } diff --git a/src/app/shared/components/template/services/template-nav.service.ts b/src/app/shared/components/template/services/template-nav.service.ts index 047999708..6d23b12a5 100644 --- a/src/app/shared/components/template/services/template-nav.service.ts +++ b/src/app/shared/components/template/services/template-nav.service.ts @@ -29,7 +29,7 @@ export class TemplateNavService extends SyncServiceBase { // Custom function to handle browser's back button press customBackHandler: ICustomBackHandler | null = null; popStateListener: ((event: PopStateEvent) => void) | null = null; - ignorePopState: boolean = false; + public suppressPopState: boolean = false; constructor( private modalCtrl: ModalController, @@ -110,17 +110,13 @@ export class TemplateNavService extends SyncServiceBase { } private onPopState(event: PopStateEvent) { - if (this.ignorePopState) { - this.ignorePopState = false; + if (this.suppressPopState) { + this.suppressPopState = false; return; } if (this.customBackHandler) { this.customBackHandler(); - // ignore popstate event for the programmatic forward navigation - // this.ignorePopState = true; - // this.location.forward(); } - // this.location.back(); } /***************************************************************************************************** From 9ac3fb2969f0d542cd08f81827e1e5c7c0a4531f Mon Sep 17 00:00:00 2001 From: Johnny McQuade Date: Wed, 4 Dec 2024 15:54:26 +0000 Subject: [PATCH 3/5] chore: code tidy --- .../feature/nav-stack/nav-stack.service.ts | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/app/feature/nav-stack/nav-stack.service.ts b/src/app/feature/nav-stack/nav-stack.service.ts index d4ce86d1e..923030018 100644 --- a/src/app/feature/nav-stack/nav-stack.service.ts +++ b/src/app/feature/nav-stack/nav-stack.service.ts @@ -11,6 +11,7 @@ interface NavStackModal extends HTMLIonModalElement {} }) export class NavStackService extends SyncServiceBase { private openNavStacks: HTMLIonModalElement[] = []; + private readonly MAX_NAV_STACKS = 10; constructor( private modalCtrl: ModalController, @@ -25,6 +26,10 @@ export class NavStackService extends SyncServiceBase { * Await and remove from openNavStacks array on dismiss */ public async pushNavStack(navStackConfig: INavStackConfig) { + if (this.openNavStacks.length >= this.MAX_NAV_STACKS) { + console.warn(`[NAV STACK] Maximum number of nav stacks reached: ${this.MAX_NAV_STACKS}`); + return null; + } const modal = await this.createNavStackModal(navStackConfig); await this.presentAndTrackModal(modal); return modal; @@ -60,36 +65,41 @@ export class NavStackService extends SyncServiceBase { modal.setAttribute("data-nav-stack-index", navStackIndex.toString()); modal.style.setProperty("--nav-stack-index", navStackIndex.toString()); - // Remove array entry whenever modal is dismissed - modal.onWillDismiss().then(() => { - const index = this.getNavStackIndex(modal); - if (index === -1) return; - this.removeNavStackFromArray(index); - this.removeNavStackHistoryState(modal); - }); + // Handle nav stack dismissal here (whether programmatically from service or from nav-stack component) + modal.onWillDismiss().then(() => this.handleNavStackDismissal(modal)); + this.addNavStackToArray(modal); // add a history entry so that we can navigate back on dismissal without changing page history.pushState({ modalId: modal.id }, ""); await modal.present(); } + private handleNavStackDismissal(modal: NavStackModal) { + const index = this.getNavStackIndex(modal); + if (index === -1) return; + this.removeNavStackFromArray(index); + this.removeNavStackHistoryState(modal); + } + private getNavStackIndex(modalElement: HTMLIonModalElement) { return this.openNavStacks.indexOf(modalElement); } + /** + * Programmiatcally dismiss a nav-stack. Handling removing from openNavStacks array is done elsewhere + * to handle both programmatic dismissal and dismissal from nav-stack component (e.g. via close button) + */ private async closeNavStack(index: number) { - await this.dismissNavStackModal(this.openNavStacks[index]); - this.openNavStacks.splice(index, 1); - } - - private async dismissNavStackModal(modal: NavStackModal) { - await modal.dismiss(); + const modal = this.openNavStacks[index]; + if (modal) { + await modal.dismiss(); + } } private removeNavStackHistoryState(modal: NavStackModal) { const modalId = modal.id; - // If we pushed a state for this modal, go back if (history.state?.modalId === modalId) { + // Temporarily suppress handling `popstate` events for the navigation this.templateNavService.suppressPopState = true; history.back(); } From 6b0994cdccfd79ea8cb18aefa6a44dbb4b028732 Mon Sep 17 00:00:00 2001 From: chrismclarke Date: Fri, 27 Dec 2024 10:52:15 -0800 Subject: [PATCH 4/5] feat: nav stack back native --- .../nav-stack/nav-stack-back.service.ts | 43 +++++++++++++++ src/app/feature/nav-stack/nav-stack.module.ts | 8 ++- .../nav-stack/nav-stack.service.spec.ts | 14 ++--- .../feature/nav-stack/nav-stack.service.ts | 54 ++++++------------- .../template/services/template-nav.service.ts | 44 --------------- 5 files changed, 72 insertions(+), 91 deletions(-) create mode 100644 src/app/feature/nav-stack/nav-stack-back.service.ts diff --git a/src/app/feature/nav-stack/nav-stack-back.service.ts b/src/app/feature/nav-stack/nav-stack-back.service.ts new file mode 100644 index 000000000..306f3b717 --- /dev/null +++ b/src/app/feature/nav-stack/nav-stack-back.service.ts @@ -0,0 +1,43 @@ +import { computed, effect, Injectable } from "@angular/core"; +import { NavStackService } from "./nav-stack.service"; +import { App } from "@capacitor/app"; +import { Capacitor, PluginListenerHandle } from "@capacitor/core"; + +@Injectable({ providedIn: "root" }) +/** + * Utility service to help manage intercepting back button presses when working with nav stacks + * Currently just supports hardware back button press on android, used to dismiss top nav stack + */ +export class NavStackBackService { + /** Track whether navStacks are currently open or not to enable back interception */ + private navStacksOpen = computed(() => this.navStackService.openNavStacks().length > 0); + + private backButtonListener: PluginListenerHandle; + + constructor(private navStackService: NavStackService) { + effect(async () => { + const platform = Capacitor.getPlatform(); + if (platform !== "android") return; + + if (this.navStacksOpen()) { + await this.addBackButtonListener(); + } else { + await this.removeBackButtonListener(); + } + }); + } + + private async addBackButtonListener() { + const listener = await App.addListener("backButton", async (e) => { + await this.navStackService.closeTopNavStack(); + }); + this.backButtonListener = listener; + } + + private async removeBackButtonListener() { + if (this.backButtonListener) { + await this.backButtonListener.remove(); + this.backButtonListener = undefined; + } + } +} diff --git a/src/app/feature/nav-stack/nav-stack.module.ts b/src/app/feature/nav-stack/nav-stack.module.ts index 6bef7e4de..671d616c9 100644 --- a/src/app/feature/nav-stack/nav-stack.module.ts +++ b/src/app/feature/nav-stack/nav-stack.module.ts @@ -7,13 +7,19 @@ import { TemplateComponentsModule } from "../../shared/components/template/templ import { TemplateActionRegistry } from "src/app/shared/components/template/services/instance/template-action.registry"; import { NavStackService } from "./nav-stack.service"; import { NavStackActionFactory } from "./nav-stack.actions"; +import { NavStackBackService } from "./nav-stack-back.service"; @NgModule({ declarations: [NavStackComponent], imports: [CommonModule, IonicModule, TemplateComponentModule, TemplateComponentsModule], }) export class NavStackModule { - constructor(templateActionRegistry: TemplateActionRegistry, navStackService: NavStackService) { + constructor( + templateActionRegistry: TemplateActionRegistry, + navStackService: NavStackService, + // include navStackBack service to enable back button management + navStackBackService: NavStackBackService + ) { const { nav_stack } = new NavStackActionFactory(navStackService); templateActionRegistry.register({ nav_stack }); } diff --git a/src/app/feature/nav-stack/nav-stack.service.spec.ts b/src/app/feature/nav-stack/nav-stack.service.spec.ts index e5faf2d30..1fdf6e62b 100644 --- a/src/app/feature/nav-stack/nav-stack.service.spec.ts +++ b/src/app/feature/nav-stack/nav-stack.service.spec.ts @@ -68,7 +68,7 @@ describe("NavStackService", () => { const modalSpy = await pushNavStack(); expect(modalSpy.present).toHaveBeenCalled(); - expect(service["openNavStacks"].length).toEqual(1); + expect(service.openNavStacks().length).toEqual(1); }); it("tracks stack index as attributes", async () => { @@ -82,17 +82,17 @@ describe("NavStackService", () => { const modalSpy1 = await pushNavStack(); const modalSpy2 = await pushNavStack(); - expect(service["openNavStacks"].length).toEqual(2); + expect(service.openNavStacks().length).toEqual(2); expect(modalSpy1.getAttribute("data-nav-stack-index")).toEqual("0"); expect(modalSpy2.getAttribute("data-nav-stack-index")).toEqual("1"); }); - it("should remove the modal from service['openNavStacks'] on dismissal", async () => { + it("should remove the modal from service.openNavStacks on dismissal", async () => { const modalSpy = await pushNavStack(); await service.closeTopNavStack(); expect(modalSpy.dismiss).toHaveBeenCalled(); - expect(service["openNavStacks"].length).toBe(0); + expect(service.openNavStacks().length).toBe(0); }); it("should close the top modal in the stack", async () => { @@ -103,8 +103,8 @@ describe("NavStackService", () => { expect(modalSpy1.dismiss).not.toHaveBeenCalled(); expect(modalSpy2.dismiss).toHaveBeenCalled(); - expect(service["openNavStacks"].length).toBe(1); - expect(service["openNavStacks"][0]).toBe(modalSpy1); + expect(service.openNavStacks().length).toBe(1); + expect(service.openNavStacks()[0]).toBe(modalSpy1); }); it("should close all modals in the stack", async () => { @@ -115,6 +115,6 @@ describe("NavStackService", () => { expect(modalSpy1.dismiss).toHaveBeenCalled(); expect(modalSpy2.dismiss).toHaveBeenCalled(); - expect(service["openNavStacks"].length).toBe(0); + expect(service.openNavStacks().length).toBe(0); }); }); diff --git a/src/app/feature/nav-stack/nav-stack.service.ts b/src/app/feature/nav-stack/nav-stack.service.ts index 923030018..1f2397f65 100644 --- a/src/app/feature/nav-stack/nav-stack.service.ts +++ b/src/app/feature/nav-stack/nav-stack.service.ts @@ -1,8 +1,7 @@ -import { Injectable } from "@angular/core"; +import { Injectable, signal } from "@angular/core"; import { ModalController } from "@ionic/angular"; import { INavStackConfig, NavStackComponent } from "./components/nav-stack/nav-stack.component"; import { SyncServiceBase } from "src/app/shared/services/syncService.base"; -import { TemplateNavService } from "src/app/shared/components/template/services/template-nav.service"; interface NavStackModal extends HTMLIonModalElement {} @@ -10,13 +9,10 @@ interface NavStackModal extends HTMLIonModalElement {} providedIn: "root", }) export class NavStackService extends SyncServiceBase { - private openNavStacks: HTMLIonModalElement[] = []; + public openNavStacks = signal([]); private readonly MAX_NAV_STACKS = 10; - constructor( - private modalCtrl: ModalController, - private templateNavService: TemplateNavService - ) { + constructor(private modalCtrl: ModalController) { super("navStack"); // NB: Actions are registered in nav-stack module } @@ -26,7 +22,7 @@ export class NavStackService extends SyncServiceBase { * Await and remove from openNavStacks array on dismiss */ public async pushNavStack(navStackConfig: INavStackConfig) { - if (this.openNavStacks.length >= this.MAX_NAV_STACKS) { + if (this.openNavStacks().length >= this.MAX_NAV_STACKS) { console.warn(`[NAV STACK] Maximum number of nav stacks reached: ${this.MAX_NAV_STACKS}`); return null; } @@ -37,14 +33,14 @@ export class NavStackService extends SyncServiceBase { public async closeAllNavStacks() { // Close nav-stacks in reverse order - for (let index = this.openNavStacks.length - 1; index >= 0; index--) { + for (let index = this.openNavStacks().length - 1; index >= 0; index--) { await this.closeNavStack(index); } } public async closeTopNavStack() { - if (this.openNavStacks.length === 0) return; - await this.closeNavStack(this.openNavStacks.length - 1); + if (this.openNavStacks().length === 0) return; + await this.closeNavStack(this.openNavStacks().length - 1); } /** @@ -61,7 +57,7 @@ export class NavStackService extends SyncServiceBase { } private async presentAndTrackModal(modal: NavStackModal) { - const navStackIndex = this.openNavStacks.length; + const navStackIndex = this.openNavStacks().length; modal.setAttribute("data-nav-stack-index", navStackIndex.toString()); modal.style.setProperty("--nav-stack-index", navStackIndex.toString()); @@ -69,8 +65,6 @@ export class NavStackService extends SyncServiceBase { modal.onWillDismiss().then(() => this.handleNavStackDismissal(modal)); this.addNavStackToArray(modal); - // add a history entry so that we can navigate back on dismissal without changing page - history.pushState({ modalId: modal.id }, ""); await modal.present(); } @@ -78,48 +72,30 @@ export class NavStackService extends SyncServiceBase { const index = this.getNavStackIndex(modal); if (index === -1) return; this.removeNavStackFromArray(index); - this.removeNavStackHistoryState(modal); } private getNavStackIndex(modalElement: HTMLIonModalElement) { - return this.openNavStacks.indexOf(modalElement); + return this.openNavStacks().indexOf(modalElement); } /** - * Programmiatcally dismiss a nav-stack. Handling removing from openNavStacks array is done elsewhere + * Programmatically dismiss a nav-stack. Handling removing from openNavStacks array is done elsewhere * to handle both programmatic dismissal and dismissal from nav-stack component (e.g. via close button) */ private async closeNavStack(index: number) { - const modal = this.openNavStacks[index]; + const modal = this.openNavStacks()[index]; if (modal) { await modal.dismiss(); } } - private removeNavStackHistoryState(modal: NavStackModal) { - const modalId = modal.id; - if (history.state?.modalId === modalId) { - // Temporarily suppress handling `popstate` events for the navigation - this.templateNavService.suppressPopState = true; - history.back(); - } - } - private addNavStackToArray(modal: NavStackModal) { - if (this.openNavStacks.length === 0) { - this.setCustomBackHandler(); - } - this.openNavStacks.push(modal); + // use array destructure to create new object + this.openNavStacks.update((stacks) => [...stacks, modal]); } private removeNavStackFromArray(index: number) { - this.openNavStacks.splice(index, 1); - if (this.openNavStacks.length === 0) { - this.templateNavService.destroyBackButtonHandler(); - } - } - - private setCustomBackHandler() { - this.templateNavService.initializeBackButtonHandler(() => this.closeTopNavStack()); + // use filter instead of splice to avoid modifying original object + this.openNavStacks.update((stacks) => stacks.filter((v, i) => i !== index)); } } diff --git a/src/app/shared/components/template/services/template-nav.service.ts b/src/app/shared/components/template/services/template-nav.service.ts index 944f43f0a..0b509786d 100644 --- a/src/app/shared/components/template/services/template-nav.service.ts +++ b/src/app/shared/components/template/services/template-nav.service.ts @@ -17,8 +17,6 @@ import { TemplateActionRegistry } from "./instance/template-action.registry"; const SHOW_DEBUG_LOGS = false; const log = SHOW_DEBUG_LOGS ? console.log : () => null; -type ICustomBackHandler = () => any; - @Injectable({ providedIn: "root", }) @@ -27,11 +25,6 @@ type ICustomBackHandler = () => any; * ... */ export class TemplateNavService extends SyncServiceBase { - // Custom function to handle browser's back button press - customBackHandler: ICustomBackHandler | null = null; - popStateListener: ((event: PopStateEvent) => void) | null = null; - public suppressPopState: boolean = false; - constructor( private modalCtrl: ModalController, private location: Location, @@ -85,43 +78,6 @@ export class TemplateNavService extends SyncServiceBase { ]); } } - - /***************************************************************************************************** - * Handling browser navigation - ****************************************************************************************************/ - - public initializeBackButtonHandler(handler?: ICustomBackHandler) { - if (handler) { - this.setCustomBackHandler(handler); - } - if (!this.popStateListener) { - this.popStateListener = this.onPopState.bind(this); - window.addEventListener("popstate", this.popStateListener); - } - } - - public destroyBackButtonHandler() { - if (this.popStateListener) { - window.removeEventListener("popstate", this.popStateListener); - this.popStateListener = null; - } - this.customBackHandler = null; - } - - private setCustomBackHandler(handler: ICustomBackHandler) { - this.customBackHandler = handler; - } - - private onPopState(event: PopStateEvent) { - if (this.suppressPopState) { - this.suppressPopState = false; - return; - } - if (this.customBackHandler) { - this.customBackHandler(); - } - } - /***************************************************************************************************** * Nav Actions ****************************************************************************************************/ From 1b40fc3beb5fefb65405f4d1f34c7ce3dc048ced Mon Sep 17 00:00:00 2001 From: Johnny McQuade Date: Mon, 30 Dec 2024 10:48:55 +0000 Subject: [PATCH 5/5] chore: 'nav_stack: close_all' closes all nav-stacks simultaneously --- src/app/feature/nav-stack/nav-stack.service.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/app/feature/nav-stack/nav-stack.service.ts b/src/app/feature/nav-stack/nav-stack.service.ts index 1f2397f65..2405bc467 100644 --- a/src/app/feature/nav-stack/nav-stack.service.ts +++ b/src/app/feature/nav-stack/nav-stack.service.ts @@ -31,11 +31,8 @@ export class NavStackService extends SyncServiceBase { return modal; } - public async closeAllNavStacks() { - // Close nav-stacks in reverse order - for (let index = this.openNavStacks().length - 1; index >= 0; index--) { - await this.closeNavStack(index); - } + public closeAllNavStacks() { + return Promise.all(this.openNavStacks().map((navStack) => navStack.dismiss())); } public async closeTopNavStack() {