fix(service-worker): Fix public api guard typing (#25860)
PR Close #25860
This commit is contained in:
parent
10618752e6
commit
4a01ada291
|
@ -52,8 +52,6 @@ interface StatusEvent {
|
|||
error?: string;
|
||||
}
|
||||
|
||||
export interface NotificationObject extends NotificationOptions { title: string; }
|
||||
|
||||
|
||||
function errorObservable(message: string): Observable<any> {
|
||||
return defer(() => throwError(new Error(message)));
|
||||
|
|
|
@ -10,7 +10,7 @@ import {Injectable} from '@angular/core';
|
|||
import {NEVER, Observable, Subject, merge} from 'rxjs';
|
||||
import {map, switchMap, take} from 'rxjs/operators';
|
||||
|
||||
import {ERR_SW_NOT_SUPPORTED, NgswCommChannel, NotificationObject, PushEvent} from './low_level';
|
||||
import {ERR_SW_NOT_SUPPORTED, NgswCommChannel, PushEvent} from './low_level';
|
||||
|
||||
|
||||
/**
|
||||
|
@ -30,14 +30,16 @@ export class SwPush {
|
|||
* interacted with.
|
||||
* If no action was used the action property will be an empty string `''`.
|
||||
*
|
||||
* Note that the `notification` property is __not__ a
|
||||
* [Notification](https://developer.mozilla.org/en-US/docs/Web/API/Notification) but rather a
|
||||
* Note that the `notification` property is **not** a
|
||||
* [Notification](https://developer.mozilla.org/en-US/docs/Web/API/Notification) object but rather
|
||||
* a
|
||||
* [NotificationOptions](https://notifications.spec.whatwg.org/#dictdef-notificationoptions)
|
||||
* object that also includes the notification `title`.
|
||||
* object that also includes the `title` of the
|
||||
* [Notification](https://developer.mozilla.org/en-US/docs/Web/API/Notification) object.
|
||||
*/
|
||||
readonly messagesClicked: Observable < {
|
||||
readonly notificationClicks: Observable < {
|
||||
action: string;
|
||||
notification: NotificationObject
|
||||
notification: NotificationOptions&{ title: string }
|
||||
}
|
||||
> ;
|
||||
|
||||
|
@ -61,14 +63,14 @@ export class SwPush {
|
|||
constructor(private sw: NgswCommChannel) {
|
||||
if (!sw.isEnabled) {
|
||||
this.messages = NEVER;
|
||||
this.messagesClicked = NEVER;
|
||||
this.notificationClicks = NEVER;
|
||||
this.subscription = NEVER;
|
||||
return;
|
||||
}
|
||||
|
||||
this.messages = this.sw.eventsOfType<PushEvent>('PUSH').pipe(map(message => message.data));
|
||||
|
||||
this.messagesClicked =
|
||||
this.notificationClicks =
|
||||
this.sw.eventsOfType('NOTIFICATION_CLICK').pipe(map((message: any) => message.data));
|
||||
|
||||
this.pushManager = this.sw.registration.pipe(map(registration => registration.pushManager));
|
||||
|
|
|
@ -304,13 +304,13 @@ import {async_fit, async_it} from './async';
|
|||
});
|
||||
});
|
||||
|
||||
describe('messagesClicked', () => {
|
||||
describe('notificationClicks', () => {
|
||||
it('receives notification clicked messages', () => {
|
||||
const sendMessage = (type: string, action: string) =>
|
||||
mock.sendMessage({type, data: {action}});
|
||||
|
||||
const receivedMessages: string[] = [];
|
||||
push.messagesClicked.subscribe(
|
||||
push.notificationClicks.subscribe(
|
||||
(msg: {action: string}) => receivedMessages.push(msg.action));
|
||||
|
||||
sendMessage('NOTIFICATION_CLICK', 'this was a click');
|
||||
|
@ -388,7 +388,7 @@ import {async_fit, async_it} from './async';
|
|||
|
||||
it('does not crash on subscription to observables', () => {
|
||||
push.messages.toPromise().catch(err => fail(err));
|
||||
push.messagesClicked.toPromise().catch(err => fail(err));
|
||||
push.notificationClicks.toPromise().catch(err => fail(err));
|
||||
push.subscription.toPromise().catch(err => fail(err));
|
||||
});
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ const serverUpdate =
|
|||
scope.clients.getMock('default') !.queue.subscribe(msg => { mock.sendMessage(msg); });
|
||||
|
||||
mock.messages.subscribe(msg => { scope.handleMessage(msg, 'default'); });
|
||||
mock.messagesClicked.subscribe(msg => { scope.handleMessage(msg, 'default'); });
|
||||
mock.notificationClicks.subscribe(msg => { scope.handleMessage(msg, 'default'); });
|
||||
|
||||
mock.setupSw();
|
||||
reg = mock.mockRegistration !;
|
||||
|
@ -135,7 +135,7 @@ const serverUpdate =
|
|||
scope.updateServerState(serverUpdate);
|
||||
|
||||
const gotNotificationClick = (async() => {
|
||||
const event: any = await obsToSinglePromise(push.messagesClicked);
|
||||
const event: any = await obsToSinglePromise(push.notificationClicks);
|
||||
expect(event.action).toEqual('clicked');
|
||||
expect(event.notification.title).toEqual('This is a test');
|
||||
})();
|
||||
|
|
|
@ -28,7 +28,7 @@ export class MockServiceWorkerContainer {
|
|||
mockRegistration: MockServiceWorkerRegistration|null = null;
|
||||
controller: MockServiceWorker|null = null;
|
||||
messages = new Subject();
|
||||
messagesClicked = new Subject();
|
||||
notificationClicks = new Subject();
|
||||
|
||||
addEventListener(event: 'controllerchange'|'message', handler: Function) {
|
||||
if (event === 'controllerchange') {
|
||||
|
|
|
@ -29,13 +29,9 @@ const IDLE_THRESHOLD = 5000;
|
|||
|
||||
const SUPPORTED_CONFIG_VERSION = 1;
|
||||
|
||||
const NOTIFICATION_OPTION_NAMES = [
|
||||
'actions', 'badge', 'body', 'dir', 'icon', 'lang', 'renotify', 'requireInteraction', 'tag',
|
||||
'vibrate', 'data'
|
||||
];
|
||||
const NOTIFICATION_CLICK_OPTION_NAMES = [
|
||||
'actions', 'badge', 'title', 'body', 'dir', 'icon', 'image', 'lang', 'renotify',
|
||||
'requireInteraction', 'tag', 'timestamp', 'vibrate', 'data'
|
||||
const NOTIFICATION_OPTION_NAMES: (keyof Notification)[] = [
|
||||
'actions', 'badge', 'body', 'data', 'dir', 'icon', 'image', 'lang', 'renotify',
|
||||
'requireInteraction', 'silent', 'tag', 'timestamp', 'title', 'vibrate'
|
||||
];
|
||||
|
||||
interface LatestEntry {
|
||||
|
@ -312,10 +308,9 @@ export class Driver implements Debuggable, UpdateSource {
|
|||
private async handleClick(notification: Notification, action?: string): Promise<void> {
|
||||
notification.close();
|
||||
|
||||
const desc = notification as any;
|
||||
let options: {[key: string]: string | undefined} = {};
|
||||
NOTIFICATION_CLICK_OPTION_NAMES.filter(name => desc.hasOwnProperty(name))
|
||||
.forEach(name => options[name] = desc[name]);
|
||||
const options: {-readonly[K in keyof Notification]?: Notification[K]} = {};
|
||||
NOTIFICATION_OPTION_NAMES.filter(name => name in notification)
|
||||
.forEach(name => options[name] = notification[name]);
|
||||
|
||||
await this.broadcast({
|
||||
type: 'NOTIFICATION_CLICK',
|
||||
|
|
|
@ -576,7 +576,7 @@ const manifestUpdateHash = sha1(JSON.stringify(manifestUpdate));
|
|||
});
|
||||
expect(scope.notifications).toEqual([{
|
||||
title: 'This is a test',
|
||||
options: {body: 'Test body'},
|
||||
options: {title: 'This is a test', body: 'Test body'},
|
||||
}]);
|
||||
expect(scope.clients.getMock('default') !.messages).toEqual([{
|
||||
type: 'PUSH',
|
||||
|
|
|
@ -8,7 +8,12 @@ export declare class ServiceWorkerModule {
|
|||
export declare class SwPush {
|
||||
readonly isEnabled: boolean;
|
||||
readonly messages: Observable<object>;
|
||||
readonly messagesClicked: Observable<{ action: string; notification: NotificationObject }>;
|
||||
readonly notificationClicks: Observable<{
|
||||
action: string;
|
||||
notification: NotificationOptions & {
|
||||
title: string;
|
||||
};
|
||||
}>;
|
||||
readonly subscription: Observable<PushSubscription | null>;
|
||||
constructor(sw: NgswCommChannel);
|
||||
requestSubscription(options: {
|
||||
|
|
Loading…
Reference in New Issue