289 lines
15 KiB
JavaScript
289 lines
15 KiB
JavaScript
import { ɵgetAllInstancesOf, ɵisAnalyticsSupportedFactory, ɵzoneWrap, VERSION, ɵgetDefaultInstanceOf, ɵAngularFireSchedulers } from '@angular/fire';
|
|
import { timer, from, of } from 'rxjs';
|
|
import { concatMap, distinct, filter, switchMap, map, groupBy, mergeMap, distinctUntilChanged, startWith, pairwise } from 'rxjs/operators';
|
|
import * as i0 from '@angular/core';
|
|
import { Injectable, Optional, InjectionToken, APP_INITIALIZER, NgModule, NgZone, Injector } from '@angular/core';
|
|
import { FirebaseApp, FirebaseApps } from '@angular/fire/app';
|
|
import { registerVersion } from 'firebase/app';
|
|
import { __awaiter } from 'tslib';
|
|
import * as i1$1 from '@angular/router';
|
|
import { ActivationEnd, ɵEmptyOutletComponent } from '@angular/router';
|
|
import * as i2 from '@angular/platform-browser';
|
|
import { getAnalytics as getAnalytics$1, initializeAnalytics as initializeAnalytics$1, logEvent as logEvent$1, setAnalyticsCollectionEnabled as setAnalyticsCollectionEnabled$1, setCurrentScreen as setCurrentScreen$1, settings as settings$1, setUserId as setUserId$1, setUserProperties as setUserProperties$1 } from 'firebase/analytics';
|
|
export * from 'firebase/analytics';
|
|
import * as i1 from '@angular/fire/auth';
|
|
import { authState } from '@angular/fire/auth';
|
|
|
|
class Analytics {
|
|
constructor(analytics) {
|
|
return analytics;
|
|
}
|
|
}
|
|
const ANALYTICS_PROVIDER_NAME = 'analytics';
|
|
class AnalyticsInstances {
|
|
constructor() {
|
|
return ɵgetAllInstancesOf(ANALYTICS_PROVIDER_NAME);
|
|
}
|
|
}
|
|
const analyticInstance$ = timer(0, 300).pipe(concatMap(() => from(ɵgetAllInstancesOf(ANALYTICS_PROVIDER_NAME))), distinct());
|
|
|
|
const isSupported = ɵisAnalyticsSupportedFactory.async;
|
|
|
|
// DO NOT MODIFY, this file is autogenerated by tools/build.ts
|
|
const getAnalytics = ɵzoneWrap(getAnalytics$1, true);
|
|
const initializeAnalytics = ɵzoneWrap(initializeAnalytics$1, true);
|
|
const logEvent = ɵzoneWrap(logEvent$1, true);
|
|
const setAnalyticsCollectionEnabled = ɵzoneWrap(setAnalyticsCollectionEnabled$1, true);
|
|
const setCurrentScreen = ɵzoneWrap(setCurrentScreen$1, true);
|
|
const settings = ɵzoneWrap(settings$1, true);
|
|
const setUserId = ɵzoneWrap(setUserId$1, true);
|
|
const setUserProperties = ɵzoneWrap(setUserProperties$1, true);
|
|
|
|
class UserTrackingService {
|
|
constructor(auth, zone, injector) {
|
|
this.disposables = [];
|
|
registerVersion('angularfire', VERSION.full, 'user-tracking');
|
|
let resolveInitialized;
|
|
this.initialized = zone.runOutsideAngular(() => new Promise(resolve => { resolveInitialized = resolve; }));
|
|
// The APP_INITIALIZER that is making isSupported() sync for the sake of convenient DI
|
|
// may not be done when services are initialized. Guard the functionality by first ensuring
|
|
// that the (global) promise has resolved, then get Analytics from the injector.
|
|
isSupported().then(() => {
|
|
const analytics = injector.get(Analytics);
|
|
if (analytics) {
|
|
this.disposables = [
|
|
// TODO add credential tracking back in
|
|
authState(auth).subscribe(user => {
|
|
setUserId(analytics, user === null || user === void 0 ? void 0 : user.uid);
|
|
resolveInitialized();
|
|
}),
|
|
];
|
|
}
|
|
else {
|
|
resolveInitialized();
|
|
}
|
|
});
|
|
}
|
|
ngOnDestroy() {
|
|
this.disposables.forEach(it => it.unsubscribe());
|
|
}
|
|
}
|
|
UserTrackingService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: UserTrackingService, deps: [{ token: i1.Auth }, { token: i0.NgZone }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
UserTrackingService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: UserTrackingService });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: UserTrackingService, decorators: [{
|
|
type: Injectable
|
|
}], ctorParameters: function () { return [{ type: i1.Auth }, { type: i0.NgZone }, { type: i0.Injector }]; } });
|
|
|
|
const FIREBASE_EVENT_ORIGIN_KEY = 'firebase_event_origin';
|
|
const FIREBASE_PREVIOUS_SCREEN_CLASS_KEY = 'firebase_previous_class';
|
|
const FIREBASE_PREVIOUS_SCREEN_INSTANCE_ID_KEY = 'firebase_previous_id';
|
|
const FIREBASE_PREVIOUS_SCREEN_NAME_KEY = 'firebase_previous_screen';
|
|
const FIREBASE_SCREEN_CLASS_KEY = 'firebase_screen_class';
|
|
const FIREBASE_SCREEN_INSTANCE_ID_KEY = 'firebase_screen_id';
|
|
const FIREBASE_SCREEN_NAME_KEY = 'firebase_screen';
|
|
const OUTLET_KEY = 'outlet';
|
|
const PAGE_PATH_KEY = 'page_path';
|
|
const PAGE_TITLE_KEY = 'page_title';
|
|
const SCREEN_CLASS_KEY = 'screen_class';
|
|
const SCREEN_NAME_KEY = 'screen_name';
|
|
const SCREEN_VIEW_EVENT = 'screen_view';
|
|
const EVENT_ORIGIN_AUTO = 'auto';
|
|
const SCREEN_INSTANCE_DELIMITER = '#';
|
|
// this is an INT64 in iOS/Android but use INT32 cause javascript
|
|
let nextScreenInstanceID = Math.floor(Math.random() * (Math.pow(2, 32) - 1)) - Math.pow(2, 31);
|
|
const knownScreenInstanceIDs = {};
|
|
const getScreenInstanceID = (params) => {
|
|
// unique the screen class against the outlet name
|
|
const screenInstanceKey = [
|
|
params[SCREEN_CLASS_KEY],
|
|
params[OUTLET_KEY]
|
|
].join(SCREEN_INSTANCE_DELIMITER);
|
|
if (knownScreenInstanceIDs.hasOwnProperty(screenInstanceKey)) {
|
|
return knownScreenInstanceIDs[screenInstanceKey];
|
|
}
|
|
else {
|
|
const ret = nextScreenInstanceID++;
|
|
knownScreenInstanceIDs[screenInstanceKey] = ret;
|
|
return ret;
|
|
}
|
|
};
|
|
const ɵscreenViewEvent = (router, title, componentFactoryResolver) => {
|
|
const activationEndEvents = router.events.pipe(filter(e => e instanceof ActivationEnd));
|
|
return activationEndEvents.pipe(switchMap(activationEnd => {
|
|
var _a;
|
|
// router parseUrl is having trouble with outlets when they're empty
|
|
// e.g, /asdf/1(bob://sally:asdf), so put another slash in when empty
|
|
const urlTree = router.parseUrl(router.url.replace(/(?:\().+(?:\))/g, a => a.replace('://', ':///')));
|
|
const pagePath = ((_a = urlTree.root.children[activationEnd.snapshot.outlet]) === null || _a === void 0 ? void 0 : _a.toString()) || '';
|
|
const actualSnapshot = router.routerState.root.children.map(it => it).find(it => it.outlet === activationEnd.snapshot.outlet);
|
|
if (!actualSnapshot) {
|
|
return of(null);
|
|
}
|
|
let actualDeep = actualSnapshot;
|
|
while (actualDeep.firstChild) {
|
|
actualDeep = actualDeep.firstChild;
|
|
}
|
|
const screenName = actualDeep.pathFromRoot.map(s => { var _a; return (_a = s.routeConfig) === null || _a === void 0 ? void 0 : _a.path; }).filter(it => it).join('/') || '/';
|
|
const params = {
|
|
[SCREEN_NAME_KEY]: screenName,
|
|
[PAGE_PATH_KEY]: `/${pagePath}`,
|
|
[FIREBASE_EVENT_ORIGIN_KEY]: EVENT_ORIGIN_AUTO,
|
|
[FIREBASE_SCREEN_NAME_KEY]: screenName,
|
|
[OUTLET_KEY]: activationEnd.snapshot.outlet
|
|
};
|
|
if (title) {
|
|
params[PAGE_TITLE_KEY] = title.getTitle();
|
|
}
|
|
let component = actualSnapshot.component;
|
|
if (component) {
|
|
if (component === ɵEmptyOutletComponent) {
|
|
let deepSnapshot = activationEnd.snapshot;
|
|
// TODO when might there be mutple children, different outlets? explore
|
|
while (deepSnapshot.firstChild) {
|
|
deepSnapshot = deepSnapshot.firstChild;
|
|
}
|
|
component = deepSnapshot.component;
|
|
}
|
|
}
|
|
else {
|
|
component = activationEnd.snapshot.component;
|
|
}
|
|
if (typeof component === 'string') {
|
|
return of(Object.assign(Object.assign({}, params), { [SCREEN_CLASS_KEY]: component }));
|
|
}
|
|
else if (component) {
|
|
const componentFactory = componentFactoryResolver.resolveComponentFactory(component);
|
|
return of(Object.assign(Object.assign({}, params), { [SCREEN_CLASS_KEY]: componentFactory.selector }));
|
|
}
|
|
// lazy loads cause extra activations, ignore
|
|
return of(null);
|
|
}), filter(it => !!it), map(params => (Object.assign({ [FIREBASE_SCREEN_CLASS_KEY]: params[SCREEN_CLASS_KEY], [FIREBASE_SCREEN_INSTANCE_ID_KEY]: getScreenInstanceID(params) }, params))), groupBy(it => it[OUTLET_KEY]), mergeMap(it => it.pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)), startWith(undefined), pairwise(), map(([prior, current]) => prior ? Object.assign({ [FIREBASE_PREVIOUS_SCREEN_CLASS_KEY]: prior[SCREEN_CLASS_KEY], [FIREBASE_PREVIOUS_SCREEN_NAME_KEY]: prior[SCREEN_NAME_KEY], [FIREBASE_PREVIOUS_SCREEN_INSTANCE_ID_KEY]: prior[FIREBASE_SCREEN_INSTANCE_ID_KEY] }, current) : current))));
|
|
};
|
|
class ScreenTrackingService {
|
|
constructor(router, title, componentFactoryResolver, zone, userTrackingService, injector) {
|
|
registerVersion('angularfire', VERSION.full, 'screen-tracking');
|
|
// The APP_INITIALIZER that is making isSupported() sync for the sake of convenient DI
|
|
// may not be done when services are initialized. Guard the functionality by first ensuring
|
|
// that the (global) promise has resolved, then get Analytics from the injector.
|
|
isSupported().then(() => {
|
|
const analytics = injector.get(Analytics);
|
|
if (!router || !analytics) {
|
|
return;
|
|
}
|
|
zone.runOutsideAngular(() => {
|
|
this.disposable = ɵscreenViewEvent(router, title, componentFactoryResolver).pipe(switchMap((params) => __awaiter(this, void 0, void 0, function* () {
|
|
if (userTrackingService) {
|
|
yield userTrackingService.initialized;
|
|
}
|
|
return logEvent(analytics, SCREEN_VIEW_EVENT, params);
|
|
}))).subscribe();
|
|
});
|
|
});
|
|
}
|
|
ngOnDestroy() {
|
|
if (this.disposable) {
|
|
this.disposable.unsubscribe();
|
|
}
|
|
}
|
|
}
|
|
ScreenTrackingService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: ScreenTrackingService, deps: [{ token: i1$1.Router, optional: true }, { token: i2.Title, optional: true }, { token: i0.ComponentFactoryResolver }, { token: i0.NgZone }, { token: UserTrackingService, optional: true }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
ScreenTrackingService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: ScreenTrackingService });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: ScreenTrackingService, decorators: [{
|
|
type: Injectable
|
|
}], ctorParameters: function () { return [{ type: i1$1.Router, decorators: [{
|
|
type: Optional
|
|
}] }, { type: i2.Title, decorators: [{
|
|
type: Optional
|
|
}] }, { type: i0.ComponentFactoryResolver }, { type: i0.NgZone }, { type: UserTrackingService, decorators: [{
|
|
type: Optional
|
|
}] }, { type: i0.Injector }]; } });
|
|
|
|
const PROVIDED_ANALYTICS_INSTANCES = new InjectionToken('angularfire2.analytics-instances');
|
|
function defaultAnalyticsInstanceFactory(provided, defaultApp) {
|
|
if (!ɵisAnalyticsSupportedFactory.sync()) {
|
|
return null;
|
|
}
|
|
const defaultAnalytics = ɵgetDefaultInstanceOf(ANALYTICS_PROVIDER_NAME, provided, defaultApp);
|
|
return defaultAnalytics && new Analytics(defaultAnalytics);
|
|
}
|
|
function analyticsInstanceFactory(fn) {
|
|
return (zone, injector) => {
|
|
if (!ɵisAnalyticsSupportedFactory.sync()) {
|
|
return null;
|
|
}
|
|
const analytics = zone.runOutsideAngular(() => fn(injector));
|
|
return new Analytics(analytics);
|
|
};
|
|
}
|
|
const ANALYTICS_INSTANCES_PROVIDER = {
|
|
provide: AnalyticsInstances,
|
|
deps: [
|
|
[new Optional(), PROVIDED_ANALYTICS_INSTANCES],
|
|
]
|
|
};
|
|
const DEFAULT_ANALYTICS_INSTANCE_PROVIDER = {
|
|
provide: Analytics,
|
|
useFactory: defaultAnalyticsInstanceFactory,
|
|
deps: [
|
|
[new Optional(), PROVIDED_ANALYTICS_INSTANCES],
|
|
FirebaseApp,
|
|
]
|
|
};
|
|
class AnalyticsModule {
|
|
constructor(_screenTrackingService, _userTrackingService) {
|
|
registerVersion('angularfire', VERSION.full, 'analytics');
|
|
}
|
|
}
|
|
AnalyticsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: AnalyticsModule, deps: [{ token: ScreenTrackingService, optional: true }, { token: UserTrackingService, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
|
|
AnalyticsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: AnalyticsModule });
|
|
AnalyticsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: AnalyticsModule, providers: [
|
|
DEFAULT_ANALYTICS_INSTANCE_PROVIDER,
|
|
ANALYTICS_INSTANCES_PROVIDER,
|
|
{
|
|
provide: APP_INITIALIZER,
|
|
useValue: ɵisAnalyticsSupportedFactory.async,
|
|
multi: true,
|
|
}
|
|
] });
|
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: AnalyticsModule, decorators: [{
|
|
type: NgModule,
|
|
args: [{
|
|
providers: [
|
|
DEFAULT_ANALYTICS_INSTANCE_PROVIDER,
|
|
ANALYTICS_INSTANCES_PROVIDER,
|
|
{
|
|
provide: APP_INITIALIZER,
|
|
useValue: ɵisAnalyticsSupportedFactory.async,
|
|
multi: true,
|
|
}
|
|
]
|
|
}]
|
|
}], ctorParameters: function () { return [{ type: ScreenTrackingService, decorators: [{
|
|
type: Optional
|
|
}] }, { type: UserTrackingService, decorators: [{
|
|
type: Optional
|
|
}] }]; } });
|
|
function provideAnalytics(fn, ...deps) {
|
|
return {
|
|
ngModule: AnalyticsModule,
|
|
providers: [{
|
|
provide: PROVIDED_ANALYTICS_INSTANCES,
|
|
useFactory: analyticsInstanceFactory(fn),
|
|
multi: true,
|
|
deps: [
|
|
NgZone,
|
|
Injector,
|
|
ɵAngularFireSchedulers,
|
|
FirebaseApps,
|
|
...deps,
|
|
]
|
|
}]
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Generated bundle index. Do not edit.
|
|
*/
|
|
|
|
export { Analytics, AnalyticsInstances, AnalyticsModule, ScreenTrackingService, UserTrackingService, analyticInstance$, getAnalytics, initializeAnalytics, isSupported, logEvent, provideAnalytics, setAnalyticsCollectionEnabled, setCurrentScreen, setUserId, setUserProperties, settings, ɵscreenViewEvent };
|
|
//# sourceMappingURL=angular-fire-analytics.js.map
|