218 lines
7.1 KiB
TypeScript
218 lines
7.1 KiB
TypeScript
// (C) Copyright 2015 Moodle Pty Ltd.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import { Injectable } from '@angular/core';
|
|
import { CoreLoggerProvider } from '@providers/logger';
|
|
import { CoreSitesProvider } from '@providers/sites';
|
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
|
import { Subject } from 'rxjs';
|
|
|
|
/**
|
|
* Interface that all click handlers must implement.
|
|
*/
|
|
export interface CorePushNotificationsClickHandler {
|
|
/**
|
|
* A name to identify the handler.
|
|
*/
|
|
name: string;
|
|
|
|
/**
|
|
* Handler's priority. The highest priority is treated first.
|
|
*/
|
|
priority?: number;
|
|
|
|
/**
|
|
* Name of the feature this handler is related to.
|
|
* It will be used to check if the feature is disabled (@see CoreSite.isFeatureDisabled).
|
|
*/
|
|
featureName?: string;
|
|
|
|
/**
|
|
* Check if a notification click is handled by this handler.
|
|
*
|
|
* @param notification The notification to check.
|
|
* @return Whether the notification click is handled by this handler.
|
|
*/
|
|
handles(notification: any): boolean | Promise<boolean>;
|
|
|
|
/**
|
|
* Handle the notification click.
|
|
*
|
|
* @param notification The notification to check.
|
|
* @return Promise resolved when done.
|
|
*/
|
|
handleClick(notification: any): Promise<any>;
|
|
}
|
|
|
|
/**
|
|
* Service to handle push notifications actions to perform when clicked and received.
|
|
*/
|
|
@Injectable()
|
|
export class CorePushNotificationsDelegate {
|
|
|
|
protected logger;
|
|
protected observables: { [s: string]: Subject<any> } = {};
|
|
protected clickHandlers: { [s: string]: CorePushNotificationsClickHandler } = {};
|
|
protected counterHandlers: { [s: string]: string } = {};
|
|
|
|
constructor(loggerProvider: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider) {
|
|
this.logger = loggerProvider.getInstance('CorePushNotificationsDelegate');
|
|
this.observables['receive'] = new Subject<any>();
|
|
}
|
|
|
|
/**
|
|
* Function called when a push notification is clicked. Sends notification to handlers.
|
|
*
|
|
* @param notification Notification clicked.
|
|
* @return Promise resolved when done.
|
|
*/
|
|
clicked(notification: any): Promise<any> {
|
|
if (!notification) {
|
|
return;
|
|
}
|
|
|
|
const promises = [];
|
|
let handlers: CorePushNotificationsClickHandler[] = [];
|
|
|
|
for (const name in this.clickHandlers) {
|
|
const handler = this.clickHandlers[name];
|
|
|
|
// Check if the handler is disabled for the site.
|
|
promises.push(this.isFeatureDisabled(handler, notification.site).then((disabled) => {
|
|
if (!disabled) {
|
|
// Check if the handler handles the notification.
|
|
return Promise.resolve(handler.handles(notification)).then((handles) => {
|
|
if (handles) {
|
|
handlers.push(handler);
|
|
}
|
|
});
|
|
}
|
|
}));
|
|
}
|
|
|
|
return this.utils.allPromises(promises).catch(() => {
|
|
// Ignore errors.
|
|
}).then(() => {
|
|
// Sort by priority.
|
|
handlers = handlers.sort((a, b) => {
|
|
return a.priority <= b.priority ? 1 : -1;
|
|
});
|
|
|
|
if (handlers[0]) {
|
|
// Execute the first one.
|
|
handlers[0].handleClick(notification);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Check if a handler's feature is disabled for a certain site.
|
|
*
|
|
* @param handler Handler to check.
|
|
* @param siteId The site ID to check.
|
|
* @return Promise resolved with boolean: whether the handler feature is disabled.
|
|
*/
|
|
protected isFeatureDisabled(handler: CorePushNotificationsClickHandler, siteId: string): Promise<boolean> {
|
|
if (handler.featureName) {
|
|
// Check if the feature is disabled.
|
|
return this.sitesProvider.isFeatureDisabled(handler.featureName, siteId);
|
|
} else {
|
|
return Promise.resolve(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function called when a push notification is received in foreground (cannot tell when it's received in background).
|
|
* Sends notification to all handlers.
|
|
*
|
|
* @param notification Notification received.
|
|
*/
|
|
received(notification: any): void {
|
|
this.observables['receive'].next(notification);
|
|
}
|
|
|
|
/**
|
|
* Register a push notifications observable for a certain event. Right now, only receive is supported.
|
|
* let observer = pushNotificationsDelegate.on('receive').subscribe((notification) => {
|
|
* ...
|
|
* observer.unsuscribe();
|
|
*
|
|
* @param eventName Only receive is permitted.
|
|
* @return Observer to subscribe.
|
|
*/
|
|
on(eventName: string): Subject<any> {
|
|
if (typeof this.observables[eventName] == 'undefined') {
|
|
const eventNames = Object.keys(this.observables).join(', ');
|
|
this.logger.warn(`'${eventName}' event name is not allowed. Use one of the following: '${eventNames}'.`);
|
|
|
|
return new Subject<any>();
|
|
}
|
|
|
|
return this.observables[eventName];
|
|
}
|
|
|
|
/**
|
|
* Register a click handler.
|
|
*
|
|
* @param handler The handler to register.
|
|
* @return True if registered successfully, false otherwise.
|
|
*/
|
|
registerClickHandler(handler: CorePushNotificationsClickHandler): boolean {
|
|
if (typeof this.clickHandlers[handler.name] !== 'undefined') {
|
|
this.logger.log(`Addon '${handler.name}' already registered`);
|
|
|
|
return false;
|
|
}
|
|
|
|
this.logger.log(`Registered addon '${handler.name}'`);
|
|
this.clickHandlers[handler.name] = handler;
|
|
handler.priority = handler.priority || 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Register a push notifications handler for update badge counter.
|
|
*
|
|
* @param name Handler's name.
|
|
*/
|
|
registerCounterHandler(name: string): void {
|
|
if (typeof this.counterHandlers[name] == 'undefined') {
|
|
this.logger.debug(`Registered handler '${name}' as badge counter handler.`);
|
|
this.counterHandlers[name] = name;
|
|
} else {
|
|
this.logger.log(`Handler '${name}' as badge counter handler already registered.`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if a counter handler is present.
|
|
*
|
|
* @param name Handler's name.
|
|
* @return If handler name is present.
|
|
*/
|
|
isCounterHandlerRegistered(name: string): boolean {
|
|
return typeof this.counterHandlers[name] != 'undefined';
|
|
}
|
|
|
|
/**
|
|
* Get all counter badge handlers.
|
|
*
|
|
* @return with all the handler names.
|
|
*/
|
|
getCounterHandlers(): any {
|
|
return this.counterHandlers;
|
|
}
|
|
}
|