Skip to content

Commit 05c840b

Browse files
committed
Cleaning things up, beyond docs ready for release
1 parent d47dc3f commit 05c840b

File tree

4 files changed

+48
-31
lines changed

4 files changed

+48
-31
lines changed

src/analytics/analytics.service.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { Injectable, Optional, NgZone, OnDestroy, ComponentFactoryResolver, Inject, PLATFORM_ID, Injector, NgModuleFactory } from '@angular/core';
2-
import { Subscription, from, Observable, empty, of } from 'rxjs';
2+
import { Subscription, from, Observable, of } from 'rxjs';
33
import { filter, withLatestFrom, switchMap, map, tap, pairwise, startWith, groupBy, mergeMap } from 'rxjs/operators';
44
import { Router, NavigationEnd, ActivationEnd, ROUTES } from '@angular/router';
55
import { runOutsideAngular } from '@angular/fire';
66
import { AngularFireAnalytics, DEBUG_MODE } from './analytics';
77
import { User } from 'firebase/app';
88
import { Title } from '@angular/platform-browser';
9-
import { isPlatformBrowser } from '@angular/common';
9+
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
1010

1111
const FIREBASE_EVENT_ORIGIN_KEY = 'firebase_event_origin';
1212
const FIREBASE_PREVIOUS_SCREEN_CLASS_KEY = 'firebase_previous_class';
@@ -101,7 +101,7 @@ export class ScreenTrackingService implements OnDestroy {
101101
const declarations = [].concat.apply([], (lazyModule[ANNOTATIONS] || []).map((f:any) => f.declarations));
102102
const selectors = [].concat.apply([], declarations.map((c:any) => (c[ANNOTATIONS] || []).map((f:any) => f.selector)));
103103
// should I just be grabbing the selector like this or should i match against the route component?
104-
// const routerModule = lazyModule.ngInjectorDef.imports.find(i => !!i.ngModule);
104+
// const routerModule = lazyModule.ngInjectorDef.imports.find(i => i.ngModule && ....);
105105
// const route = routerModule.providers[0].find(p => p.provide == ROUTES).useValue[0];
106106
return {...params, [SCREEN_CLASS_KEY]: selectors[0] || DEFAULT_SCREEN_CLASS};
107107
}
@@ -157,15 +157,21 @@ export class UserTrackingService implements OnDestroy {
157157
// TODO a user properties injector
158158
constructor(
159159
analytics: AngularFireAnalytics,
160-
zone: NgZone
160+
zone: NgZone,
161+
@Inject(PLATFORM_ID) platformId:Object
161162
) {
162-
this.disposable = from(analytics.app).pipe(
163-
// TODO can I hook into auth being loaded...
164-
map(app => app.auth()),
165-
switchMap(auth => auth ? new Observable<User>(auth.onAuthStateChanged.bind(auth)) : empty()),
166-
switchMap(user => analytics.setUserId(user ? user.uid : null!)),
167-
runOutsideAngular(zone)
168-
).subscribe();
163+
if (!isPlatformServer(platformId)) {
164+
zone.runOutsideAngular(() => {
165+
// @ts-ignore zap the import in the UMD
166+
this.disposable = from(import('firebase/auth')).pipe(
167+
switchMap(() => analytics.app),
168+
map(app => app.auth()),
169+
switchMap(auth => new Observable<User|null>(auth.onAuthStateChanged.bind(auth))),
170+
switchMap(user => analytics.setUserId(user ? user.uid : null!)),
171+
runOutsideAngular(zone)
172+
).subscribe();
173+
});
174+
}
169175
}
170176

171177
ngOnDestroy() {

src/analytics/analytics.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export class AngularFireAnalytics {
8989
if (analyticsCollectionEnabled === false) { analytics.setAnalyticsCollectionEnabled(false) }
9090
}),
9191
runOutsideAngular(zone),
92-
shareReplay(1)
92+
shareReplay({ bufferSize: 1, refCount: false }),
9393
);
9494

9595
return ɵlazySDKProxy(this, analytics, zone);

src/core/angularfire2.ts

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,24 @@ export const runInZone = (zone: NgZone) => <T>(obs$: Observable<T>): Observable<
8080
{ [K in PromiseReturningFunctionPropertyNames<T> ]: (...args: Parameters<T[K]>) => ReturnType<T[K]> };
8181
*/
8282

83-
export const ɵlazySDKProxy = (klass: any, observable: Observable<any>, zone: NgZone) => new Proxy(klass, {
84-
get: (_, name) => zone.runOutsideAngular(() =>
85-
klass[name] || new Proxy(() =>
86-
observable.toPromise().then(mod => {
83+
// DEBUG quick debugger function for inline logging that typescript doesn't complain about
84+
// wrote it for debugging the ɵlazySDKProxy, commenting out for now; should consider exposing a
85+
// verbose mode for AngularFire in a future release that uses something like this in multiple places
86+
// usage: () => log('something') || returnValue
87+
// const log = (...args: any[]): false => { console.log(...args); return false }
88+
89+
// The problem here are things like ngOnDestroy are missing, then triggering the service
90+
// rather than dig too far; I'm capturing these as I go.
91+
const noopFunctions = ['ngOnDestroy'];
92+
93+
// INVESTIGATE should we make the Proxy revokable and do some cleanup?
94+
// right now it's fairly simple but I'm sure this will grow in complexity
95+
export const ɵlazySDKProxy = (klass: any, observable: Observable<any>, zone: NgZone) => {
96+
return new Proxy(klass, {
97+
get: (_, name:string) => zone.runOutsideAngular(() => {
98+
if (klass[name]) { return klass[name] }
99+
if (noopFunctions.includes(name)) { return () => {} }
100+
let promise = observable.toPromise().then(mod => {
87101
const ret = mod && mod[name];
88102
// TODO move to proper type guards
89103
if (typeof ret == 'function') {
@@ -93,15 +107,14 @@ export const ɵlazySDKProxy = (klass: any, observable: Observable<any>, zone: Ng
93107
} else {
94108
return zone.run(() => ret);
95109
}
96-
}), {
97-
get: (self, name) => {
98-
const ret = self();
99-
// TODO proxy so we can have apply?
100-
return ret && ret[name] || (() => {});
101-
},
102-
// TODO handle callbacks as transparently as I can
103-
apply: (self, _, args) => self().then(it => it && it(...args))
104-
}
105-
)
106-
)
107-
});
110+
});
111+
// recurse the proxy
112+
return new Proxy(() => undefined, {
113+
get: (_, name) => promise[name],
114+
// TODO handle callbacks as transparently as I can
115+
apply: (self, _, args) => promise.then(it => it && it(...args))
116+
}
117+
)
118+
})
119+
})
120+
};

src/remote-config/remote-config.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export const REMOTE_CONFIG_SETTINGS = new InjectionToken<remoteConfig.Settings>(
1010
export const DEFAULT_CONFIG = new InjectionToken<ConfigTemplate>('angularfire2.remoteConfig.defaultConfig');
1111

1212
import { FirebaseRemoteConfig, _firebaseAppFactory, runOutsideAngular } from '@angular/fire';
13-
import { isPlatformServer } from '@angular/common';
1413

1514
// SEMVER: once we move to Typescript 3.6 use `PromiseProxy<remoteConfig.RemoteConfig>` rather than hardcoding
1615
type RemoteConfigProxy = {
@@ -127,8 +126,7 @@ export class AngularFireRemoteConfig {
127126
this.booleans = proxyAll(this.parameters, 'booleans');
128127
this.numbers = proxyAll(this.parameters, 'numbers');
129128

130-
// TODO fix the proxy for server
131-
return isPlatformServer(platformId) ? this : ɵlazySDKProxy(this, remoteConfig$, zone);
129+
return ɵlazySDKProxy(this, loadedRemoteConfig$, zone);
132130
}
133131

134132
}

0 commit comments

Comments
 (0)