diff --git a/src/core/pushnotifications/pushnotifications.module.ts b/src/core/pushnotifications/pushnotifications.module.ts index d804e4270..a907ab8ac 100644 --- a/src/core/pushnotifications/pushnotifications.module.ts +++ b/src/core/pushnotifications/pushnotifications.module.ts @@ -87,6 +87,12 @@ export class CorePushNotificationsModule { pushNotificationsProvider.notificationClicked(notification); }); + // Listen for local notification dismissed events. + localNotificationsProvider.registerObserver('clear', CorePushNotificationsProvider.COMPONENT, (notification: any) => { + // Log notification dismissed event. + pushNotificationsProvider.logEvent('moodle_notification_dismiss', notification, true); + }); + // Allow migrating the table from the old app to the new schema. updateManager.registerAppTableMigration({ name: 'mma_pushnotifications_badge', diff --git a/src/providers/local-notifications.ts b/src/providers/local-notifications.ts index 036803306..5417b5ff3 100644 --- a/src/providers/local-notifications.ts +++ b/src/providers/local-notifications.ts @@ -102,6 +102,10 @@ export class CoreLocalNotificationsProvider { }; protected triggerSubscription: Subscription; protected clickSubscription: Subscription; + protected clearSubscription: Subscription; + protected cancelSubscription: Subscription; + protected addSubscription: Subscription; + protected updateSubscription: Subscription; constructor(logger: CoreLoggerProvider, private localNotifications: LocalNotifications, private platform: Platform, private appProvider: CoreAppProvider, private utils: CoreUtilsProvider, private configProvider: CoreConfigProvider, @@ -113,16 +117,31 @@ export class CoreLocalNotificationsProvider { this.appDB.createTablesFromSchema(this.tablesSchema); platform.ready().then(() => { + // Listen to events. this.triggerSubscription = localNotifications.on('trigger').subscribe((notification: ILocalNotification) => { this.trigger(notification); + + this.handleEvent('trigger', notification); }); this.clickSubscription = localNotifications.on('click').subscribe((notification: ILocalNotification) => { - if (notification && notification.data) { - this.logger.debug('Notification clicked: ', notification.data); + this.handleEvent('click', notification); + }); - this.notifyClick(notification.data); - } + this.clearSubscription = localNotifications.on('clear').subscribe((notification: ILocalNotification) => { + this.handleEvent('clear', notification); + }); + + this.cancelSubscription = localNotifications.on('cancel').subscribe((notification: ILocalNotification) => { + this.handleEvent('cancel', notification); + }); + + this.addSubscription = localNotifications.on('add').subscribe((notification: ILocalNotification) => { + this.handleEvent('add', notification); + }); + + this.updateSubscription = localNotifications.on('update').subscribe((notification: ILocalNotification) => { + this.handleEvent('update', notification); }); // Create the default channel for local notifications. @@ -290,6 +309,20 @@ export class CoreLocalNotificationsProvider { }); } + /** + * Handle an event triggered by the local notifications plugin. + * + * @param {string} eventName Name of the event. + * @param {any} notification Notification. + */ + protected handleEvent(eventName: string, notification: any): void { + if (notification && notification.data) { + this.logger.debug('Notification event: ' + eventName + '. Data:', notification.data); + + this.notifyEvent(eventName, notification.data); + } + } + /** * Returns whether local notifications plugin is installed. * @@ -328,12 +361,22 @@ export class CoreLocalNotificationsProvider { * @param {any} data Data received by the notification. */ notifyClick(data: any): void { + this.notifyEvent('click', data); + } + + /** + * Notify a certain event to observers. Only the observers with the same component as the notification will be notified. + * + * @param {string} eventName Name of the event to notify. + * @param {any} data Data received by the notification. + */ + notifyEvent(eventName: string, data: any): void { // Execute the code in the Angular zone, so change detection doesn't stop working. this.zone.run(() => { const component = data.component; if (component) { - if (this.observables[component]) { - this.observables[component].next(data); + if (this.observables[eventName] && this.observables[eventName][component]) { + this.observables[eventName][component].next(data); } } }); @@ -385,18 +428,34 @@ export class CoreLocalNotificationsProvider { * @return {any} Object with an "off" property to stop listening for clicks. */ registerClick(component: string, callback: Function): any { - this.logger.debug(`Register observer '${component}' for notification click.`); + return this.registerObserver('click', component, callback); + } - if (typeof this.observables[component] == 'undefined') { - // No observable for this component, create a new one. - this.observables[component] = new Subject(); + /** + * Register an observer to be notified when a certain event is fired for a notification belonging to a certain component. + * + * @param {string} eventName Name of the event to listen to. + * @param {string} component Component to listen notifications for. + * @param {Function} callback Function to call with the data received by the notification. + * @return {any} Object with an "off" property to stop listening for events. + */ + registerObserver(eventName: string, component: string, callback: Function): any { + this.logger.debug(`Register observer '${component}' for event '${eventName}'.`); + + if (typeof this.observables[eventName] == 'undefined') { + this.observables[eventName] = {}; } - this.observables[component].subscribe(callback); + if (typeof this.observables[eventName][component] == 'undefined') { + // No observable for this component, create a new one. + this.observables[eventName][component] = new Subject(); + } + + this.observables[eventName][component].subscribe(callback); return { off: (): void => { - this.observables[component].unsubscribe(callback); + this.observables[eventName][component].unsubscribe(callback); } }; }