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' ;
5- import { filter , first , map } from 'rxjs/operators' ;
6- import { BottomSheetOptions as MaterialBottomSheetOptions } from '@nativescript-community/ui-material-bottomsheet' ; // ViewWithBottomSheetBase
76
8- export type BaseShowBottomSheetOptions = Pick < MaterialBottomSheetOptions , Exclude < keyof MaterialBottomSheetOptions , 'closeCallback' | 'view' > > ;
7+ export type BaseShowBottomSheetOptions = Omit < MaterialBottomSheetOptions , 'closeCallback' | 'view' > ;
98
109export interface BottomSheetOptions extends BaseShowBottomSheetOptions {
1110 viewContainerRef ?: ViewContainerRef ;
1211}
1312
1413export class BottomSheetParams {
15- context : any ;
16- closeCallback : ( ... args ) => void ;
14+ public constructor ( public readonly context : any , public readonly closeCallback : ( ... args ) => void ) { }
15+ }
1716
18- constructor ( context , closeCallback ) {
19- this . context = context ;
20- this . closeCallback = closeCallback ;
21- }
17+ type ViewWithDialogRoot = View & { _ngDialogRoot ?: View } ;
18+
19+ interface SheetRef < TResult = unknown > {
20+ detachedLoader ?: ComponentRef < DetachedLoader > ;
21+ componentView ?: View ;
22+ result : Subject < TResult > ;
2223}
2324
2425@Injectable ( {
2526 providedIn : 'root'
2627} )
2728export class BottomSheetService {
28- private detachedLoader : ComponentRef < DetachedLoader > ;
29- private componentView : any ; //ViewWithBottomSheetBase;
30- private subject$ : Subject < { requestId : number ; result : any } > = new Subject ( ) ;
31- private currentId = 0 ;
32-
33- show < T = any > ( type : Type < any > , options : BottomSheetOptions ) : Observable < T > {
29+ public show < TResult = any > ( type : Type < any > , options : BottomSheetOptions ) : Observable < TResult > {
3430 return this . showWithCloseCallback ( type , options ) . observable ;
3531 }
3632
37- showWithCloseCallback < T = any > ( type : Type < any > , options : BottomSheetOptions ) : { observable : Observable < T > ; closeCallback : ( ) => void } {
33+ public showWithCloseCallback < TResult = any > ( type : Type < any > , options : BottomSheetOptions ) : { observable : Observable < TResult > ; closeCallback : ( ) => void } {
3834 if ( ! options . viewContainerRef ) {
3935 throw new Error ( 'No viewContainerRef: Make sure you pass viewContainerRef in BottomSheetOptions.' ) ;
4036 }
41- this . currentId ++ ;
42- const requestId = this . currentId ;
37+
38+ const sheetRef : SheetRef < TResult > = {
39+ result : new Subject ( )
40+ } ;
41+
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 , sheetRef ) ;
4645
47- this . detachedLoader = this . createDetachedLoader ( factoryResolver , bottomSheetParams , options . viewContainerRef ) ;
46+ sheetRef . detachedLoader = this . createDetachedLoader ( factoryResolver , bottomSheetParams , options . viewContainerRef ) ;
4847
49- this . loadComponent ( type ) . then ( componentView => {
48+ this . loadComponent ( type , sheetRef ) . then ( ( componentView ) => {
5049 parentView . showBottomSheet ( {
5150 ...options ,
5251 ...bottomSheetParams ,
@@ -55,17 +54,13 @@ export class BottomSheetService {
5554 } ) ;
5655
5756 return {
58- observable : this . subject$ . pipe (
59- filter ( item => item && item . requestId === requestId ) ,
60- map ( item => item . result ) ,
61- first ( )
62- ) ,
57+ observable : sheetRef . result ,
6358 closeCallback : bottomSheetParams . closeCallback
6459 } ;
6560 }
6661
67- private getParentView ( viewContainerRef : ViewContainerRef ) : any { //ViewWithBottomSheetBase {
68- let parentView = viewContainerRef . element . nativeElement ;
62+ private getParentView ( viewContainerRef : ViewContainerRef ) : View {
63+ let parentView = viewContainerRef . element . nativeElement as View ;
6964
7065 if ( parentView instanceof AppHostView && parentView . ngAppRoot ) {
7166 parentView = parentView . ngAppRoot ;
@@ -74,8 +69,8 @@ export class BottomSheetService {
7469 // _ngDialogRoot is the first child of the previously detached proxy.
7570 // It should have 'viewController' (iOS) or '_dialogFragment' (Android) available for
7671 // presenting future bottomSheets views.
77- if ( parentView . _ngDialogRoot ) {
78- parentView = parentView . _ngDialogRoot ;
72+ if ( ( parentView as ViewWithDialogRoot ) . _ngDialogRoot ) {
73+ parentView = ( parentView as ViewWithDialogRoot ) . _ngDialogRoot ;
7974 }
8075
8176 return parentView ;
@@ -87,7 +82,7 @@ export class BottomSheetService {
8782 return componentContainer . injector . get ( ComponentFactoryResolver ) ;
8883 }
8984
90- private createChildInjector ( bottomSheetParams : BottomSheetParams , containerRef : ViewContainerRef ) {
85+ private createChildInjector ( bottomSheetParams : BottomSheetParams , containerRef : ViewContainerRef ) : Injector {
9186 return Injector . create ( {
9287 providers : [
9388 {
@@ -99,17 +94,21 @@ export class BottomSheetService {
9994 } ) ;
10095 }
10196
102- private getBottomSheetParams ( context : any , requestId : number ) {
103- const closeCallback = once ( args => {
104- this . subject$ . next ( { result : args , requestId } ) ;
97+ private getBottomSheetParams ( context : any , sheetRef : SheetRef ) : BottomSheetParams {
98+ const closeCallback = once ( ( args ) => {
99+ const { result, componentView, detachedLoader } = sheetRef ;
100+
101+ result . next ( args ) ;
102+ result . complete ( ) ;
105103
106- if ( ! this . componentView ) {
107- return ;
104+ if ( componentView ) {
105+ componentView . closeBottomSheet ( ) ;
108106 }
109107
110- this . componentView . closeBottomSheet ( ) ;
111- this . detachedLoader . instance . detectChanges ( ) ;
112- this . detachedLoader . destroy ( ) ;
108+ if ( detachedLoader ) {
109+ detachedLoader . instance . detectChanges ( ) ;
110+ detachedLoader . destroy ( ) ;
111+ }
113112 } ) ;
114113
115114 return new BottomSheetParams ( context , closeCallback ) ;
@@ -122,25 +121,26 @@ export class BottomSheetService {
122121 return viewContainerRef . createComponent ( detachedLoaderFactory , 0 , childInjector , null ) ;
123122 }
124123
125- private async loadComponent ( type : Type < any > ) : Promise < any > { //ViewWithBottomSheetBase > {
124+ private async loadComponent ( type : Type < any > , sheetRef : SheetRef ) : Promise < View > {
126125 try {
127- const componentRef = await this . detachedLoader . instance . loadComponent ( type ) ;
126+ const componentRef = await sheetRef . detachedLoader . instance . loadComponent ( type ) ;
128127 const detachedProxy = componentRef . location . nativeElement as ProxyViewContainer ;
129128
130129 if ( detachedProxy . getChildrenCount ( ) > 1 ) {
131130 throw new Error ( 'BottomSheet content has more than one root view.' ) ;
132131 }
133132
134- this . componentView = detachedProxy . getChildAt ( 0 ) as any ; //ViewWithBottomSheetBase ;
133+ sheetRef . componentView = detachedProxy . getChildAt ( 0 ) ;
135134
136- if ( this . componentView . parent ) {
137- ( this . componentView . parent ) . _ngDialogRoot = this . componentView ;
138- ( this . componentView . parent ) . removeChild ( this . componentView ) ;
135+ if ( sheetRef . componentView . parent instanceof LayoutBase ) {
136+ ( sheetRef . componentView . parent as ViewWithDialogRoot ) . _ngDialogRoot = sheetRef . componentView ;
137+ sheetRef . componentView . parent . removeChild ( sheetRef . componentView ) ;
139138 }
140139
141- return this . componentView ;
142- } catch ( e ) {
143- console . error ( e ) ;
140+ return sheetRef . componentView ;
141+ } catch ( err ) {
142+ console . error ( err ) ;
143+
144144 return null ;
145145 }
146146 }
0 commit comments