Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/analytics/analytics.module.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import { NgModule, Optional, NgZone, InjectionToken, ModuleWithProviders, APP_INITIALIZER, Injector } from '@angular/core';
import { Analytics as FirebaseAnalytics } from 'firebase/analytics';
import { ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VERSION, ɵisAnalyticsSupportedFactory } from '@angular/fire';
import { ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VERSION } from '@angular/fire';
import { Analytics, ANALYTICS_PROVIDER_NAME, AnalyticsInstances } from './analytics';
import { FirebaseApps, FirebaseApp } from '@angular/fire/app';
import { registerVersion } from 'firebase/app';
import { ScreenTrackingService } from './screen-tracking.service';
import { UserTrackingService } from './user-tracking.service';
import { isAnalyticsSupportedFactory } from './is-analytics-supported-factory';

export const PROVIDED_ANALYTICS_INSTANCES = new InjectionToken<Analytics[]>('angularfire2.analytics-instances');

export function defaultAnalyticsInstanceFactory(provided: FirebaseAnalytics[]|undefined, defaultApp: FirebaseApp) {
if (!ɵisAnalyticsSupportedFactory.sync()) { return null; }
if (!isAnalyticsSupportedFactory.sync()) { return null; }
const defaultAnalytics = ɵgetDefaultInstanceOf<FirebaseAnalytics>(ANALYTICS_PROVIDER_NAME, provided, defaultApp);
return defaultAnalytics && new Analytics(defaultAnalytics);
}

export function analyticsInstanceFactory(fn: (injector: Injector) => FirebaseAnalytics) {
return (zone: NgZone, injector: Injector) => {
if (!ɵisAnalyticsSupportedFactory.sync()) { return null; }
if (!isAnalyticsSupportedFactory.sync()) { return null; }
const analytics = zone.runOutsideAngular(() => fn(injector));
return new Analytics(analytics);
};
Expand Down Expand Up @@ -45,7 +46,7 @@ const DEFAULT_ANALYTICS_INSTANCE_PROVIDER = {
ANALYTICS_INSTANCES_PROVIDER,
{
provide: APP_INITIALIZER,
useValue: ɵisAnalyticsSupportedFactory.async,
useValue: isAnalyticsSupportedFactory.async,
multi: true,
}
]
Expand Down
19 changes: 19 additions & 0 deletions src/analytics/is-analytics-supported-factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ɵisSupportedError } from '@angular/fire';
import { isSupported } from 'firebase/analytics';

const isAnalyticsSupportedValueSymbol = '__angularfire_symbol__analyticsIsSupportedValue';
const isAnalyticsSupportedPromiseSymbol = '__angularfire_symbol__analyticsIsSupported';

globalThis[isAnalyticsSupportedPromiseSymbol] ||= isSupported().then(it =>
globalThis[isAnalyticsSupportedValueSymbol] = it
).catch(() =>
globalThis[isAnalyticsSupportedValueSymbol] = false
);
export const isAnalyticsSupportedFactory = {
async: () => globalThis[isAnalyticsSupportedPromiseSymbol],
sync: () => {
const ret = globalThis[isAnalyticsSupportedValueSymbol];
if (ret === undefined) { throw new Error(ɵisSupportedError('Analytics')); }
return ret;
}
};
5 changes: 3 additions & 2 deletions src/analytics/overrides.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ɵisAnalyticsSupportedFactory } from '@angular/fire';
import { isAnalyticsSupportedFactory } from './is-analytics-supported-factory';

export const isSupported = isAnalyticsSupportedFactory.async;

export const isSupported = ɵisAnalyticsSupportedFactory.async;
57 changes: 1 addition & 56 deletions src/core.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,14 @@
import { Version } from '@angular/core';
import { FirebaseApp, getApps } from 'firebase/app';
import { ComponentContainer } from '@firebase/component';
import { isSupported as isRemoteConfigSupported } from 'firebase/remote-config';
import { isSupported as isMessagingSupported } from 'firebase/messaging';
import { isSupported as isAnalyticsSupported } from 'firebase/analytics';

export const VERSION = new Version('ANGULARFIRE2_VERSION');

const isAnalyticsSupportedValueSymbol = '__angularfire_symbol__analyticsIsSupportedValue';
const isAnalyticsSupportedPromiseSymbol = '__angularfire_symbol__analyticsIsSupported';
const isRemoteConfigSupportedValueSymbol = '__angularfire_symbol__remoteConfigIsSupportedValue';
const isRemoteConfigSupportedPromiseSymbol = '__angularfire_symbol__remoteConfigIsSupported';
const isMessagingSupportedValueSymbol = '__angularfire_symbol__messagingIsSupportedValue';
const isMessagingSupportedPromiseSymbol = '__angularfire_symbol__messagingIsSupported';

globalThis[isAnalyticsSupportedPromiseSymbol] ||= isAnalyticsSupported().then(it =>
globalThis[isAnalyticsSupportedValueSymbol] = it
).catch(() =>
globalThis[isAnalyticsSupportedValueSymbol] = false
);

globalThis[isMessagingSupportedPromiseSymbol] ||= isMessagingSupported().then(it =>
globalThis[isMessagingSupportedValueSymbol] = it
).catch(() =>
globalThis[isMessagingSupportedValueSymbol] = false
);

globalThis[isRemoteConfigSupportedPromiseSymbol] ||= isRemoteConfigSupported().then(it =>
globalThis[isRemoteConfigSupportedValueSymbol] = it
).catch(() =>
globalThis[isRemoteConfigSupportedValueSymbol] = false
);

const isSupportedError = (module: string) =>
export const ɵisSupportedError = (module: string) =>
`The APP_INITIALIZER that is "making" isSupported() sync for the sake of convenient DI has not resolved in this
context. Rather than injecting ${module} in the constructor, first ensure that ${module} is supported by calling
\`await isSupported()\`, then retrieve the instance from the injector manually \`injector.get(${module})\`.`;

export const ɵisMessagingSupportedFactory = {
async: () => globalThis[isMessagingSupportedPromiseSymbol],
sync: () => {
const ret = globalThis[isMessagingSupportedValueSymbol];
if (ret === undefined) { throw new Error(isSupportedError('Messaging')); }
return ret;
}
};

export const ɵisRemoteConfigSupportedFactory = {
async: () => globalThis[isRemoteConfigSupportedPromiseSymbol],
sync: () => {
const ret = globalThis[isRemoteConfigSupportedValueSymbol];
if (ret === undefined) { throw new Error(isSupportedError('RemoteConfig')); }
return ret;
}
};

export const ɵisAnalyticsSupportedFactory = {
async: () => globalThis[isAnalyticsSupportedPromiseSymbol],
sync: () => {
const ret = globalThis[isAnalyticsSupportedValueSymbol];
if (ret === undefined) { throw new Error(isSupportedError('Analytics')); }
return ret;
}
};

// TODO is there a better way to get at the internal types?
interface FirebaseAppWithContainer extends FirebaseApp {
container: ComponentContainer;
Expand Down
20 changes: 20 additions & 0 deletions src/messaging/is-messaging-supported-factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ɵisSupportedError } from '@angular/fire';
import { isSupported } from 'firebase/messaging';

const isMessagingSupportedPromiseSymbol = '__angularfire_symbol__messagingIsSupported';
const isMessagingSupportedValueSymbol = '__angularfire_symbol__messagingIsSupportedValue';

globalThis[isMessagingSupportedPromiseSymbol] ||= isSupported().then(it =>
globalThis[isMessagingSupportedValueSymbol] = it
).catch(() =>
globalThis[isMessagingSupportedValueSymbol] = false
);

export const isMessagingSupportedFactory = {
async: () => globalThis[isMessagingSupportedPromiseSymbol],
sync: () => {
const ret = globalThis[isMessagingSupportedValueSymbol];
if (ret === undefined) { throw new Error(ɵisSupportedError('Messaging')); }
return ret;
}
};
9 changes: 5 additions & 4 deletions src/messaging/messaging.module.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { NgModule, Optional, NgZone, InjectionToken, ModuleWithProviders, Injector, APP_INITIALIZER } from '@angular/core';
import { Messaging as FirebaseMessaging } from 'firebase/messaging';
import { ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VERSION, ɵisMessagingSupportedFactory } from '@angular/fire';
import { ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VERSION } from '@angular/fire';
import { Messaging, MessagingInstances, MESSAGING_PROVIDER_NAME } from './messaging';
import { FirebaseApps, FirebaseApp } from '@angular/fire/app';
import { registerVersion } from 'firebase/app';
import { isMessagingSupportedFactory } from './is-messaging-supported-factory';

const PROVIDED_MESSAGING_INSTANCES = new InjectionToken<Messaging[]>('angularfire2.messaging-instances');

export function defaultMessagingInstanceFactory(provided: FirebaseMessaging[]|undefined, defaultApp: FirebaseApp) {
if (!ɵisMessagingSupportedFactory.sync()) { return null; }
if (!isMessagingSupportedFactory.sync()) { return null; }
const defaultMessaging = ɵgetDefaultInstanceOf<FirebaseMessaging>(MESSAGING_PROVIDER_NAME, provided, defaultApp);
return defaultMessaging && new Messaging(defaultMessaging);
}

export function messagingInstanceFactory(fn: (injector: Injector) => FirebaseMessaging) {
return (zone: NgZone, injector: Injector) => {
if (!ɵisMessagingSupportedFactory.sync()) { return null; }
if (!isMessagingSupportedFactory.sync()) { return null; }
const messaging = zone.runOutsideAngular(() => fn(injector));
return new Messaging(messaging);
};
Expand Down Expand Up @@ -43,7 +44,7 @@ const DEFAULT_MESSAGING_INSTANCE_PROVIDER = {
MESSAGING_INSTANCES_PROVIDER,
{
provide: APP_INITIALIZER,
useValue: ɵisMessagingSupportedFactory.async,
useValue: isMessagingSupportedFactory.async,
multi: true,
},
]
Expand Down
4 changes: 2 additions & 2 deletions src/messaging/overrides.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { ɵisMessagingSupportedFactory } from '@angular/fire';
import { isMessagingSupportedFactory } from './is-messaging-supported-factory';

export const isSupported = ɵisMessagingSupportedFactory.async;
export const isSupported = isMessagingSupportedFactory.async;
20 changes: 20 additions & 0 deletions src/remote-config/is-remote-config-supported-factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { isSupported } from 'firebase/remote-config';
import { ɵisSupportedError } from '@angular/fire';

const isRemoteConfigSupportedValueSymbol = '__angularfire_symbol__remoteConfigIsSupportedValue';
const isRemoteConfigSupportedPromiseSymbol = '__angularfire_symbol__remoteConfigIsSupported';

globalThis[isRemoteConfigSupportedPromiseSymbol] ||= isSupported().then(it =>
globalThis[isRemoteConfigSupportedValueSymbol] = it
).catch(() =>
globalThis[isRemoteConfigSupportedValueSymbol] = false
);

export const isRemoteConfigSupportedFactory = {
async: () => globalThis[isRemoteConfigSupportedPromiseSymbol],
sync: () => {
const ret = globalThis[isRemoteConfigSupportedValueSymbol];
if (ret === undefined) { throw new Error(ɵisSupportedError('RemoteConfig')); }
return ret;
}
};
4 changes: 2 additions & 2 deletions src/remote-config/overrides.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { ɵisRemoteConfigSupportedFactory } from '@angular/fire';
import { isRemoteConfigSupportedFactory } from './is-remote-config-supported-factory';

export const isSupported = ɵisRemoteConfigSupportedFactory.async;
export const isSupported = isRemoteConfigSupportedFactory.async;
9 changes: 5 additions & 4 deletions src/remote-config/remote-config.module.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import { NgModule, Optional, NgZone, InjectionToken, ModuleWithProviders, Injector, APP_INITIALIZER } from '@angular/core';
import { RemoteConfig as FirebaseRemoteConfig } from 'firebase/remote-config';
import { ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VERSION, ɵisRemoteConfigSupportedFactory } from '@angular/fire';
import { ɵgetDefaultInstanceOf, ɵAngularFireSchedulers, VERSION } from '@angular/fire';
import { RemoteConfig, RemoteConfigInstances, REMOTE_CONFIG_PROVIDER_NAME } from './remote-config';
import { FirebaseApps, FirebaseApp } from '@angular/fire/app';
import { registerVersion } from 'firebase/app';
import { isRemoteConfigSupportedFactory } from './is-remote-config-supported-factory';

export const PROVIDED_REMOTE_CONFIG_INSTANCES = new InjectionToken<RemoteConfig[]>('angularfire2.remote-config-instances');

export function defaultRemoteConfigInstanceFactory(
provided: FirebaseRemoteConfig[]|undefined,
defaultApp: FirebaseApp,
) {
if (!ɵisRemoteConfigSupportedFactory.sync()) { return null; }
if (!isRemoteConfigSupportedFactory.sync()) { return null; }
const defaultRemoteConfig = ɵgetDefaultInstanceOf<FirebaseRemoteConfig>(REMOTE_CONFIG_PROVIDER_NAME, provided, defaultApp);
return defaultRemoteConfig && new RemoteConfig(defaultRemoteConfig);
}

export function remoteConfigInstanceFactory(fn: (injector: Injector) => FirebaseRemoteConfig) {
return (zone: NgZone, injector: Injector) => {
if (!ɵisRemoteConfigSupportedFactory.sync()) { return null; }
if (!isRemoteConfigSupportedFactory.sync()) { return null; }
const remoteConfig = zone.runOutsideAngular(() => fn(injector));
return new RemoteConfig(remoteConfig);
};
Expand Down Expand Up @@ -46,7 +47,7 @@ const DEFAULT_REMOTE_CONFIG_INSTANCE_PROVIDER = {
REMOTE_CONFIG_INSTANCES_PROVIDER,
{
provide: APP_INITIALIZER,
useValue: ɵisRemoteConfigSupportedFactory.async,
useValue: isRemoteConfigSupportedFactory.async,
multi: true,
},
]
Expand Down