Skip to content

Commit cf304b8

Browse files
committed
refactor(bottomsheet): reformat/modernize angular service
1 parent 3db3c7b commit cf304b8

File tree

1 file changed

+38
-37
lines changed

1 file changed

+38
-37
lines changed

src/bottomsheet/angular/bottomsheet.service.ts

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,51 @@
11
import { ComponentFactoryResolver, ComponentRef, Injectable, Injector, Type, ViewContainerRef } from '@angular/core';
2+
import type { BottomSheetOptions as MaterialBottomSheetOptions } from '@nativescript-community/ui-material-bottomsheet';
23
import { AppHostView, DetachedLoader, once } from '@nativescript/angular';
3-
import { ProxyViewContainer } from '@nativescript/core';
4+
import { LayoutBase, ProxyViewContainer, View } from '@nativescript/core';
45
import { Observable, Subject } from 'rxjs';
56
import { 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

1010
export interface BottomSheetOptions extends BaseShowBottomSheetOptions {
1111
viewContainerRef?: ViewContainerRef;
1212
}
1313

1414
export 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
})
2723
export 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

Comments
 (0)