From abb50e5fd20f9852d2033be25c585ba9741c6dbc Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Tue, 13 Sep 2022 09:33:48 -0300 Subject: [PATCH] fix: modal beforeClosed and afterClosed consistency between platforms --- .../angular/src/lib/cdk/dialog/dialog-ref.ts | 11 ++++++++--- .../src/lib/cdk/dialog/native-modal-ref.ts | 18 +++++++++++------- .../src/lib/legacy/directives/dialogs.ts | 4 ++-- .../lib/legacy/router/ns-location-strategy.ts | 2 ++ 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/packages/angular/src/lib/cdk/dialog/dialog-ref.ts b/packages/angular/src/lib/cdk/dialog/dialog-ref.ts index 042c8a8..5121319 100644 --- a/packages/angular/src/lib/cdk/dialog/dialog-ref.ts +++ b/packages/angular/src/lib/cdk/dialog/dialog-ref.ts @@ -61,13 +61,14 @@ export class NativeDialogRef { .subscribe(() => { clearTimeout(this._closeFallbackTimeout); this._finishDialogClose(); + this._afterClosed.next(this._result); + this._afterClosed.complete(); }); _nativeModalRef.onDismiss.subscribe(() => { this._beforeClosed.next(this._result); this._beforeClosed.complete(); - this._afterClosed.next(this._result); - this._afterClosed.complete(); + this.componentInstance = null!; _nativeModalRef.dispose(); }); @@ -98,7 +99,11 @@ export class NativeDialogRef { // amount of time plus 100ms. We don't need to run this outside the NgZone, because for the // vast majority of cases the timeout will have been cleared before it has the chance to fire. this._closeFallbackTimeout = setTimeout( - () => this._finishDialogClose(), + () => { + this._finishDialogClose(); + this._afterClosed.next(this._result); + this._afterClosed.complete(); + }, //event.totalTime + 100); 100 ); diff --git a/packages/angular/src/lib/cdk/dialog/native-modal-ref.ts b/packages/angular/src/lib/cdk/dialog/native-modal-ref.ts index ee575ab..4807ac1 100644 --- a/packages/angular/src/lib/cdk/dialog/native-modal-ref.ts +++ b/packages/angular/src/lib/cdk/dialog/native-modal-ref.ts @@ -22,6 +22,7 @@ export class NativeModalRef { modalViewRef: NgViewRef; private _closeCallback: () => void; + private _isDismissed = false; constructor(private _config: NativeDialogConfig, private _injector: Injector, @Optional() private location?: NSLocationStrategy) { let parentView = this._config.viewContainerRef?.element.nativeElement || Application.getRootView(); @@ -38,10 +39,12 @@ export class NativeModalRef { } this.parentView = parentView; - this._closeCallback = once(() => { + this._closeCallback = once(async () => { this.stateChanged.next({ state: 'closing' }); - this.modalViewRef.firstNativeLikeView?.closeModal(); - this.location?._closeModalNavigation(); + if (!this._isDismissed) { + this.modalViewRef.firstNativeLikeView?.closeModal(); + } + await this.location?._closeModalNavigation(); // this.detachedLoaderRef?.destroy(); if (this.modalViewRef?.firstNativeLikeView.isLoaded) { fromEvent(this.modalViewRef.firstNativeLikeView, 'unloaded') @@ -81,8 +84,8 @@ export class NativeModalRef { this.parentView.showModal(this.modalViewRef.firstNativeLikeView, { context: null, ...userOptions, - closeCallback: () => { - this.location?._closeModalNavigation(); + closeCallback: async () => { + await this.location?._closeModalNavigation(); this.onDismiss.next(); this.onDismiss.complete(); }, @@ -113,8 +116,9 @@ export class NativeModalRef { this.parentView.showModal(this.modalViewRef.firstNativeLikeView, { context: null, ...userOptions, - closeCallback: () => { - this.location?._closeModalNavigation(); + closeCallback: async () => { + this._isDismissed = true; + this._closeCallback(); // close callback can only be called once, so we call it here to setup the exit events this.onDismiss.next(); this.onDismiss.complete(); }, diff --git a/packages/angular/src/lib/legacy/directives/dialogs.ts b/packages/angular/src/lib/legacy/directives/dialogs.ts index 49ad112..7542731 100644 --- a/packages/angular/src/lib/legacy/directives/dialogs.ts +++ b/packages/angular/src/lib/legacy/directives/dialogs.ts @@ -123,7 +123,7 @@ export class ModalDialogService { let detachedLoaderRef: ComponentRef; let portalOutlet: NativeScriptDomPortalOutlet; - const closeCallback = once((...args) => { + const closeCallback = once(async (...args) => { options.doneCallback.apply(undefined, args); if (componentViewRef) { componentViewRef.firstNativeLikeView.closeModal(); @@ -131,7 +131,7 @@ export class ModalDialogService { if (this._closed$) { this._closed$.next(params); } - this.location._closeModalNavigation(); + await this.location._closeModalNavigation(); if (detachedLoaderRef || portalOutlet) { this.zone.run(() => { portalOutlet?.dispose(); diff --git a/packages/angular/src/lib/legacy/router/ns-location-strategy.ts b/packages/angular/src/lib/legacy/router/ns-location-strategy.ts index 00d3f77..dcfee1d 100644 --- a/packages/angular/src/lib/legacy/router/ns-location-strategy.ts +++ b/packages/angular/src/lib/legacy/router/ns-location-strategy.ts @@ -354,6 +354,8 @@ export class NSLocationStrategy extends LocationStrategy { this.currentOutlet = outlet; this.currentOutlet.showingModal = false; this.callPopState(this.currentOutlet.peekState(), false); + // this is needed because angular does a setTimeout on onPopState, so if we don't do this we might end up with inconsistent state + return new Promise((resolve) => setTimeout(resolve, 0)); } }