11import { ComponentFactoryResolver , ComponentRef , Injectable , Injector , Type , ViewContainerRef } from '@angular/core' ;
2+ import type { BottomSheetOptions as MaterialBottomSheetOptions } from '@nativescript-community/ui-material-bottomsheet' ;
23import { AppHostView , DetachedLoader , once } from '@nativescript/angular' ;
3- import { ProxyViewContainer } from '@nativescript/core' ;
4+ import { LayoutBase , ProxyViewContainer , View } from '@nativescript/core' ;
45import { Observable , Subject } from 'rxjs' ;
56import { filter , first , map } from 'rxjs/operators' ;
6- import { BottomSheetOptions as MaterialBottomSheetOptions } from '@nativescript-community/ui-material-bottomsheet' ; // ViewWithBottomSheetBase
77
8- export type BaseShowBottomSheetOptions = Pick < MaterialBottomSheetOptions , Exclude < keyof MaterialBottomSheetOptions , 'closeCallback' | 'view' > > ;
8+ export type BaseShowBottomSheetOptions = Omit < MaterialBottomSheetOptions , 'closeCallback' | 'view' > ;
99
1010export interface BottomSheetOptions extends BaseShowBottomSheetOptions {
1111 viewContainerRef ?: ViewContainerRef ;
1212}
1313
1414export class BottomSheetParams {
15- context : any ;
16- closeCallback : ( ...args ) => void ;
17-
18- constructor ( context , closeCallback ) {
19- this . context = context ;
20- this . closeCallback = closeCallback ;
21- }
15+ public constructor ( public readonly context : any , public readonly closeCallback : ( ...args ) => void ) { }
2216}
2317
18+ type ViewWithDialogRoot = View & { _ngDialogRoot ?: View } ;
19+
2420@Injectable ( {
2521 providedIn : 'root'
2622} )
2723export class BottomSheetService {
24+ private readonly results$ = new Subject < { sheetId : number ; result : any } > ( ) ;
25+
2826 private detachedLoader : ComponentRef < DetachedLoader > ;
29- private componentView : any ; //ViewWithBottomSheetBase;
30- private subject$ : Subject < { requestId : number ; result : any } > = new Subject ( ) ;
31- private currentId = 0 ;
3227
33- show < T = any > ( type : Type < any > , options : BottomSheetOptions ) : Observable < T > {
28+ private componentView : View ;
29+
30+ private nextSheetId = 0 ;
31+
32+ public show < T = any > ( type : Type < any > , options : BottomSheetOptions ) : Observable < T > {
3433 return this . showWithCloseCallback ( type , options ) . observable ;
3534 }
3635
37- showWithCloseCallback < T = any > ( type : Type < any > , options : BottomSheetOptions ) : { observable : Observable < T > ; closeCallback : ( ) => void } {
36+ public showWithCloseCallback < T = any > ( type : Type < any > , options : BottomSheetOptions ) : { observable : Observable < T > ; closeCallback : ( ) => void } {
3837 if ( ! options . viewContainerRef ) {
3938 throw new Error ( 'No viewContainerRef: Make sure you pass viewContainerRef in BottomSheetOptions.' ) ;
4039 }
41- this . currentId ++ ;
42- const requestId = this . currentId ;
40+
41+ const sheetId = this . nextSheetId ++ ;
4342 const parentView = this . getParentView ( options . viewContainerRef ) ;
4443 const factoryResolver = this . getFactoryResolver ( options . viewContainerRef ) ;
45- const bottomSheetParams = this . getBottomSheetParams ( options . context , requestId ) ;
44+ const bottomSheetParams = this . getBottomSheetParams ( options . context , sheetId ) ;
4645
4746 this . detachedLoader = this . createDetachedLoader ( factoryResolver , bottomSheetParams , options . viewContainerRef ) ;
4847
49- this . loadComponent ( type ) . then ( componentView => {
48+ this . loadComponent ( type ) . then ( ( componentView ) => {
5049 parentView . showBottomSheet ( {
5150 ...options ,
5251 ...bottomSheetParams ,
@@ -55,17 +54,17 @@ export class BottomSheetService {
5554 } ) ;
5655
5756 return {
58- observable : this . subject $. pipe (
59- filter ( item => item && item . requestId === requestId ) ,
60- map ( item => item . result ) ,
57+ observable : this . results $. pipe (
58+ filter ( ( item ) => item && item . sheetId === sheetId ) ,
59+ map ( ( item ) => item . result ) ,
6160 first ( )
6261 ) ,
6362 closeCallback : bottomSheetParams . closeCallback
6463 } ;
6564 }
6665
67- private getParentView ( viewContainerRef : ViewContainerRef ) : any { //ViewWithBottomSheetBase {
68- let parentView = viewContainerRef . element . nativeElement ;
66+ private getParentView ( viewContainerRef : ViewContainerRef ) : View {
67+ let parentView = viewContainerRef . element . nativeElement as View ;
6968
7069 if ( parentView instanceof AppHostView && parentView . ngAppRoot ) {
7170 parentView = parentView . ngAppRoot ;
@@ -74,8 +73,8 @@ export class BottomSheetService {
7473 // _ngDialogRoot is the first child of the previously detached proxy.
7574 // It should have 'viewController' (iOS) or '_dialogFragment' (Android) available for
7675 // presenting future bottomSheets views.
77- if ( parentView . _ngDialogRoot ) {
78- parentView = parentView . _ngDialogRoot ;
76+ if ( ( parentView as ViewWithDialogRoot ) . _ngDialogRoot ) {
77+ parentView = ( parentView as ViewWithDialogRoot ) . _ngDialogRoot ;
7978 }
8079
8180 return parentView ;
@@ -87,7 +86,7 @@ export class BottomSheetService {
8786 return componentContainer . injector . get ( ComponentFactoryResolver ) ;
8887 }
8988
90- private createChildInjector ( bottomSheetParams : BottomSheetParams , containerRef : ViewContainerRef ) {
89+ private createChildInjector ( bottomSheetParams : BottomSheetParams , containerRef : ViewContainerRef ) : Injector {
9190 return Injector . create ( {
9291 providers : [
9392 {
@@ -99,15 +98,16 @@ export class BottomSheetService {
9998 } ) ;
10099 }
101100
102- private getBottomSheetParams ( context : any , requestId : number ) {
103- const closeCallback = once ( args => {
104- this . subject $. next ( { result : args , requestId } ) ;
101+ private getBottomSheetParams ( context : any , sheetId : number ) : BottomSheetParams {
102+ const closeCallback = once ( ( args ) => {
103+ this . results $. next ( { result : args , sheetId } ) ;
105104
106105 if ( ! this . componentView ) {
107106 return ;
108107 }
109108
110109 this . componentView . closeBottomSheet ( ) ;
110+
111111 this . detachedLoader . instance . detectChanges ( ) ;
112112 this . detachedLoader . destroy ( ) ;
113113 } ) ;
@@ -122,7 +122,7 @@ export class BottomSheetService {
122122 return viewContainerRef . createComponent ( detachedLoaderFactory , 0 , childInjector , null ) ;
123123 }
124124
125- private async loadComponent ( type : Type < any > ) : Promise < any > { //ViewWithBottomSheetBase > {
125+ private async loadComponent ( type : Type < any > ) : Promise < View > {
126126 try {
127127 const componentRef = await this . detachedLoader . instance . loadComponent ( type ) ;
128128 const detachedProxy = componentRef . location . nativeElement as ProxyViewContainer ;
@@ -131,16 +131,17 @@ export class BottomSheetService {
131131 throw new Error ( 'BottomSheet content has more than one root view.' ) ;
132132 }
133133
134- this . componentView = detachedProxy . getChildAt ( 0 ) as any ; //ViewWithBottomSheetBase ;
134+ this . componentView = detachedProxy . getChildAt ( 0 ) ;
135135
136- if ( this . componentView . parent ) {
137- ( this . componentView . parent ) . _ngDialogRoot = this . componentView ;
138- ( this . componentView . parent ) . removeChild ( this . componentView ) ;
136+ if ( this . componentView . parent instanceof LayoutBase ) {
137+ ( this . componentView . parent as ViewWithDialogRoot ) . _ngDialogRoot = this . componentView ;
138+ this . componentView . parent . removeChild ( this . componentView ) ;
139139 }
140140
141141 return this . componentView ;
142- } catch ( e ) {
143- console . error ( e ) ;
142+ } catch ( err ) {
143+ console . error ( err ) ;
144+
144145 return null ;
145146 }
146147 }
0 commit comments