2017-09-28 16:18:12 -07:00
|
|
|
/**
|
|
|
|
|
* @license
|
|
|
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
|
*/
|
|
|
|
|
|
2017-10-16 18:08:41 +08:00
|
|
|
import {Injectable} from '@angular/core';
|
2018-02-27 17:06:06 -05:00
|
|
|
import {NEVER, Observable, Subject, merge} from 'rxjs';
|
|
|
|
|
import {map, switchMap, take} from 'rxjs/operators';
|
2017-09-28 16:18:12 -07:00
|
|
|
|
2017-11-30 08:22:41 -08:00
|
|
|
import {ERR_SW_NOT_SUPPORTED, NgswCommChannel} from './low_level';
|
|
|
|
|
|
2017-09-28 16:18:12 -07:00
|
|
|
|
2018-02-27 17:06:06 -05:00
|
|
|
|
2017-09-28 16:18:12 -07:00
|
|
|
/**
|
|
|
|
|
* Subscribe and listen to push notifications from the Service Worker.
|
|
|
|
|
*
|
|
|
|
|
* @experimental
|
|
|
|
|
*/
|
2017-10-16 18:08:41 +08:00
|
|
|
@Injectable()
|
2017-09-28 16:18:12 -07:00
|
|
|
export class SwPush {
|
|
|
|
|
readonly messages: Observable<object>;
|
|
|
|
|
readonly subscription: Observable<PushSubscription|null>;
|
|
|
|
|
|
|
|
|
|
private pushManager: Observable<PushManager>;
|
|
|
|
|
private subscriptionChanges: Subject<PushSubscription|null> =
|
|
|
|
|
new Subject<PushSubscription|null>();
|
|
|
|
|
|
|
|
|
|
constructor(private sw: NgswCommChannel) {
|
2017-11-30 08:22:41 -08:00
|
|
|
if (!sw.isEnabled) {
|
2018-02-27 17:06:06 -05:00
|
|
|
this.messages = NEVER;
|
|
|
|
|
this.subscription = NEVER;
|
2017-11-30 08:22:41 -08:00
|
|
|
return;
|
|
|
|
|
}
|
2018-02-27 17:06:06 -05:00
|
|
|
this.messages = this.sw.eventsOfType('PUSH').pipe(map((message: any) => message.data));
|
2017-09-28 16:18:12 -07:00
|
|
|
|
2018-02-27 17:06:06 -05:00
|
|
|
this.pushManager = this.sw.registration.pipe(
|
|
|
|
|
map((registration: ServiceWorkerRegistration) => { return registration.pushManager; }));
|
2017-09-28 16:18:12 -07:00
|
|
|
|
2018-02-27 17:06:06 -05:00
|
|
|
const workerDrivenSubscriptions = this.pushManager.pipe(
|
|
|
|
|
switchMap((pm: PushManager) => pm.getSubscription().then(sub => { return sub; })));
|
|
|
|
|
this.subscription = merge(workerDrivenSubscriptions, this.subscriptionChanges);
|
2017-09-28 16:18:12 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-30 08:22:41 -08:00
|
|
|
/**
|
|
|
|
|
* Returns true if the Service Worker is enabled (supported by the browser and enabled via
|
|
|
|
|
* ServiceWorkerModule).
|
|
|
|
|
*/
|
|
|
|
|
get isEnabled(): boolean { return this.sw.isEnabled; }
|
|
|
|
|
|
2017-09-28 16:18:12 -07:00
|
|
|
requestSubscription(options: {serverPublicKey: string}): Promise<PushSubscription> {
|
2017-11-30 08:22:41 -08:00
|
|
|
if (!this.sw.isEnabled) {
|
|
|
|
|
return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED));
|
|
|
|
|
}
|
2017-09-28 16:18:12 -07:00
|
|
|
const pushOptions: PushSubscriptionOptionsInit = {userVisibleOnly: true};
|
|
|
|
|
let key = atob(options.serverPublicKey.replace(/_/g, '/').replace(/-/g, '+'));
|
|
|
|
|
let applicationServerKey = new Uint8Array(new ArrayBuffer(key.length));
|
|
|
|
|
for (let i = 0; i < key.length; i++) {
|
|
|
|
|
applicationServerKey[i] = key.charCodeAt(i);
|
|
|
|
|
}
|
|
|
|
|
pushOptions.applicationServerKey = applicationServerKey;
|
2018-02-27 17:06:06 -05:00
|
|
|
|
|
|
|
|
return this.pushManager.pipe(switchMap((pm: PushManager) => pm.subscribe(pushOptions)), take(1))
|
|
|
|
|
.toPromise()
|
|
|
|
|
.then(sub => {
|
|
|
|
|
this.subscriptionChanges.next(sub);
|
|
|
|
|
return sub;
|
|
|
|
|
});
|
2017-09-28 16:18:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsubscribe(): Promise<void> {
|
2017-11-30 08:22:41 -08:00
|
|
|
if (!this.sw.isEnabled) {
|
|
|
|
|
return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED));
|
|
|
|
|
}
|
2018-02-27 17:06:06 -05:00
|
|
|
const unsubscribe = this.subscription.pipe(switchMap((sub: PushSubscription | null) => {
|
2017-09-28 16:18:12 -07:00
|
|
|
if (sub !== null) {
|
|
|
|
|
return sub.unsubscribe().then(success => {
|
|
|
|
|
if (success) {
|
|
|
|
|
this.subscriptionChanges.next(null);
|
|
|
|
|
return undefined;
|
|
|
|
|
} else {
|
|
|
|
|
throw new Error('Unsubscribe failed!');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
throw new Error('Not subscribed to push notifications.');
|
|
|
|
|
}
|
2018-02-27 17:06:06 -05:00
|
|
|
}));
|
|
|
|
|
return unsubscribe.pipe(take(1)).toPromise();
|
2017-09-28 16:18:12 -07:00
|
|
|
}
|
2017-10-16 18:08:41 +08:00
|
|
|
}
|