Skip to content

Commit d945614

Browse files
jamesdanielsdavideast
authored andcommitted
feat(fcm): Lazy messaging, for compatibility with SSR (#1827)
1 parent 9f34be8 commit d945614

File tree

5 files changed

+53
-45
lines changed

5 files changed

+53
-45
lines changed

src/core/angularfire2.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,16 @@ export class FirebaseZoneScheduler {
3535
});
3636
});
3737
}
38+
}
39+
40+
export const runOutsideAngular = (zone: NgZone) => <T>(obs$: Observable<T>): Observable<T> => {
41+
return new Observable<T>(subscriber => {
42+
return zone.runOutsideAngular(() => {
43+
return obs$.subscribe(
44+
value => zone.run(() => subscriber.next(value)),
45+
error => zone.run(() => subscriber.error(error)),
46+
() => zone.run(() => subscriber.complete()),
47+
);
48+
});
49+
});
3850
}

src/messaging/messaging.module.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { NgModule } from '@angular/core';
2-
import { AngularFireModule, FirebaseApp } from 'angularfire2';
32
import { AngularFireMessaging } from './messaging';
4-
import 'firebase/messaging';
53

64
@NgModule({
75
providers: [ AngularFireMessaging ]

src/messaging/messaging.ts

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import { Injectable, Inject, Optional, NgZone, PLATFORM_ID } from '@angular/core';
22
import { isPlatformBrowser } from '@angular/common';
33
import { messaging } from 'firebase';
4-
import { requestPermission } from './observable/request-permission';
54
import { Observable, empty, from, of, throwError } from 'rxjs';
6-
import { mergeMap, catchError } from 'rxjs/operators';
7-
import { FirebaseOptions, FirebaseAppConfig } from 'angularfire2';
5+
import { mergeMap, catchError, map, switchMap, concat, defaultIfEmpty } from 'rxjs/operators';
6+
import { FirebaseOptions, FirebaseAppConfig, runOutsideAngular } from 'angularfire2';
87
import { FirebaseOptionsToken, FirebaseNameOrConfigToken, _firebaseAppFactory, FirebaseZoneScheduler } from 'angularfire2';
98

109
@Injectable()
1110
export class AngularFireMessaging {
12-
messaging: messaging.Messaging;
11+
messaging: Observable<messaging.Messaging>;
1312
requestPermission: Observable<void>;
1413
getToken: Observable<string|null>;
1514
tokenChanges: Observable<string|null>;
@@ -23,52 +22,58 @@ export class AngularFireMessaging {
2322
@Inject(PLATFORM_ID) platformId: Object,
2423
zone: NgZone
2524
) {
26-
const scheduler = new FirebaseZoneScheduler(zone, platformId);
27-
this.messaging = zone.runOutsideAngular(() => {
28-
const app = _firebaseAppFactory(options, nameOrConfig);
29-
return app.messaging();
30-
});
3125

3226
if (isPlatformBrowser(platformId)) {
3327

34-
this.requestPermission = scheduler.runOutsideAngular(
35-
requestPermission(this.messaging)
36-
);
37-
38-
this.getToken = scheduler.runOutsideAngular(
39-
from(this.messaging.getToken())
40-
);
41-
42-
this.tokenChanges = scheduler.runOutsideAngular(
43-
new Observable(subscriber => {
44-
this.messaging.getToken().then(t => subscriber.next(t));
45-
this.messaging.onTokenRefresh(subscriber.next);
46-
})
47-
);
28+
const requireMessaging = from(require('firebase/messaging'));
4829

49-
this.messages = scheduler.runOutsideAngular(
50-
new Observable(subscriber => {
51-
this.messaging.onMessage(subscriber.next);
52-
})
30+
this.messaging = requireMessaging.pipe(
31+
map(() => _firebaseAppFactory(options, nameOrConfig)),
32+
map(app => app.messaging()),
33+
runOutsideAngular(zone)
5334
);
5435

55-
this.requestToken = this.requestPermission.pipe(
56-
catchError(() => of(null)),
57-
mergeMap(() => this.tokenChanges),
36+
this.requestPermission = this.messaging.pipe(
37+
switchMap(messaging => messaging.requestPermission()),
38+
runOutsideAngular(zone)
5839
);
5940

6041
} else {
6142

43+
this.messaging = empty();
6244
this.requestPermission = throwError('Not available on server platform.');
63-
this.getToken = of(null);
64-
this.tokenChanges = of(null);
65-
this.messages = empty();
66-
this.requestToken = of(null);
6745

6846
}
6947

70-
this.deleteToken = (token: string) => scheduler.runOutsideAngular(
71-
from(this.messaging.deleteToken(token))
48+
this.getToken = this.messaging.pipe(
49+
switchMap(messaging => messaging.getToken()),
50+
defaultIfEmpty(null),
51+
runOutsideAngular(zone)
52+
);
53+
54+
const tokenChanges = this.messaging.pipe(
55+
switchMap(messaging => new Observable(messaging.onTokenRefresh)),
56+
runOutsideAngular(zone)
57+
);
58+
59+
this.tokenChanges = this.getToken.pipe(
60+
concat(tokenChanges)
61+
);
62+
63+
this.messages = this.messaging.pipe(
64+
switchMap(messaging => new Observable(messaging.onMessage)),
65+
runOutsideAngular(zone)
66+
);
67+
68+
this.requestToken = this.requestPermission.pipe(
69+
catchError(() => of(null)),
70+
mergeMap(() => this.tokenChanges)
71+
);
72+
73+
this.deleteToken = (token: string) => this.messaging.pipe(
74+
switchMap(messaging => messaging.deleteToken(token)),
75+
defaultIfEmpty(false),
76+
runOutsideAngular(zone)
7277
);
7378
}
7479

src/messaging/observable/request-permission.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

src/messaging/public_api.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
export * from './observable/request-permission';
21
export * from './messaging';
32
export * from './messaging.module';

0 commit comments

Comments
 (0)