From d0d3aaf7af63afa041e9af145267b0bb04ee729f Mon Sep 17 00:00:00 2001 From: Arjun Roychowdhury Date: Sat, 10 Oct 2015 11:28:44 -0400 Subject: Notifications now have a blop sound, also handling application badges --- .../src/windows/LocalNotificationCore.js | 436 ++++++++++++++++++++ .../src/windows/LocalNotificationProxy.js | 311 +++++++++++++++ .../src/windows/LocalNotificationUtil.js | 443 +++++++++++++++++++++ 3 files changed, 1190 insertions(+) create mode 100644 plugins/de.appplant.cordova.plugin.local-notification/src/windows/LocalNotificationCore.js create mode 100644 plugins/de.appplant.cordova.plugin.local-notification/src/windows/LocalNotificationProxy.js create mode 100644 plugins/de.appplant.cordova.plugin.local-notification/src/windows/LocalNotificationUtil.js (limited to 'plugins/de.appplant.cordova.plugin.local-notification/src/windows') diff --git a/plugins/de.appplant.cordova.plugin.local-notification/src/windows/LocalNotificationCore.js b/plugins/de.appplant.cordova.plugin.local-notification/src/windows/LocalNotificationCore.js new file mode 100644 index 00000000..f27193e1 --- /dev/null +++ b/plugins/de.appplant.cordova.plugin.local-notification/src/windows/LocalNotificationCore.js @@ -0,0 +1,436 @@ +/* + Copyright 2013-2015 appPlant UG + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +*/ + + +var proxy = require('de.appplant.cordova.plugin.local-notification.LocalNotification.Proxy'); + +var Notifications = Windows.UI.Notifications; + + +proxy.core = { + + /** + * Executes all queued events. + */ + deviceready: function () { + var plugin = cordova.plugins.notification.local, + events = this.eventQueue; + + this.isReady = true; + + for (var i = 0; i < events.length; i++) { + plugin.fireEvent.apply(plugin, events[i]); + } + + this.eventQueue = []; + }, + + /** + * Schedules new local notifications. + * + * @param {Object[]} notifications + * Array of local notifications + * @param {String} event + * 'schedule' or 'update' + */ + schedule: function (notifications) { + var triggerFn = function (notification) { + this.updateBadge(notification.badge); + this.fireEvent('trigger', notification); + }; + + for (var i = 0; i < notifications.length; i++) { + var options = notifications[i], + notification = this.build(options); + + this.cancelLocalNotification(options.id); + this.scheduleLocalNotification(notification, options); + this.scheduleBackupNotification(notification, options); + this.fireEvent('schedule', options); + this.callOnTrigger(options, triggerFn); + } + }, + + /** + * Schedules a single local notification. + * + * @param {Windows.Data.Xml.Dom.XmlDocument} notification + * The local notification + * @param {Object} options + * Local notification properties + */ + scheduleLocalNotification: function (notification, options) { + var interval = this.getRepeatInterval(options.every), + triggerTime = new Date((options.at * 1000)), + now = new Date().getTime(), + toast; + + if (triggerTime <= now) { + triggerTime = new Date(now + 10); + } + + try { + if (interval !== 0 && interval < 360001 && interval > 59999) { + toast = new Notifications.ScheduledToastNotification( + notification, triggerTime, interval, 5); + } else { + toast = new Notifications.ScheduledToastNotification( + notification, triggerTime); + } + } catch (e) { + console.error(e); + return; + } + + toast.id = options.id; + toast.tag = 'Toast' + toast.id; + + Notifications.ToastNotificationManager + .createToastNotifier() + .addToSchedule(toast); + }, + + /** + * Schedules a backup local notification 10 years later. + * + * @param {Object} notification + * The local notification + */ + scheduleBackupNotification: function (notification, options) { + var properties = Object.create(options); + + properties.id = options.id + '-2'; + properties.at = options.at + 315360000; // 10 years later + + this.scheduleLocalNotification(notification, properties); + }, + + /** + * Updates the badge number of the active tile. + * + * @param {Number} badge + * The badge number. Zero will clean the badge. + */ + updateBadge: function (badge) { + var notifications = Windows.UI.Notifications, + type = notifications.BadgeTemplateType.badgeNumber, + xml = notifications.BadgeUpdateManager.getTemplateContent(type), + attrs = xml.getElementsByTagName('badge'), + notification = new notifications.BadgeNotification(xml); + + attrs[0].setAttribute('value', badge); + + notifications.BadgeUpdateManager.createBadgeUpdaterForApplication() + .update(notification); + }, + + /** + * Updates existing notifications specified by IDs in options. + * + * @param {Object[]} notifications + * Array of local notifications + */ + update: function (notifications) { + for (var i = 0; i < notifications.length; i++) { + var updates = notifications[i], + options = getAll(updates.id || '0')[0]; + + this.updateLocalNotification(options, updates); + this.fireEvent('update', options); + } + }, + + /** + * Updates a single local notification. + * + * @param {Object} notification + * The local notification + * @param {Object} updates + * Updated properties + */ + updateLocalNotification: function (notification, updates) { + for (var key in updates) { + notification[key] = updates[key]; + } + + this.cancelLocalNotification(notification.id); + this.scheduleLocalNotification(notification); + }, + + /** + * Clears the specified notifications. + * + * @param {int[]} ids + * List of local notification IDs + */ + clear: function (ids) { + for (var i = 0; i < ids.length; i++) { + var id = ids[i], + notification = this.getAll([id])[0]; + + this.clearLocalNotification(id); + this.fireEvent('clear', notification); + } + }, + + /** + * Clears the local notification with the given ID. + * + * @param {String} id + * Local notification ID + */ + clearLocalNotification: function (id) { + var notification = this.getAll([id])[0]; + + try { + this.getToastHistory().remove('Toast' + id); + } catch (e) {/*Only Phones support the NotificationHistory*/ } + + if (this.isRepeating(notification)) + return; + + if (this.isTriggered(id) && !this.isScheduled(id)) { + this.cancelLocalNotification(id); + } + }, + + /** + * Clears all notifications. + */ + clearAll: function () { + var ids = this.getTriggeredIds(); + + for (var i = 0; i < ids.length; i++) { + this.clearLocalNotification(ids[i]); + } + + try { + this.getToastHistory().clear(); + } catch (e) {/*Only Phones support the NotificationHistory*/ } + this.fireEvent('clearall'); + }, + + /** + * Cancels all specified notifications. + * + * @param {int[]} ids + * List of local notification IDs + */ + cancel: function (ids) { + for (var i = 0; i < ids.length; i++) { + var id = ids[i], + notification = this.getAll([id])[0]; + + this.cancelLocalNotification(ids[i]); + this.fireEvent('cancel', notification); + } + }, + + /** + * Cancels the local notification with the given ID. + * + * @param {String} id + * Local notification ID + */ + cancelLocalNotification: function (id) { + var notifier = this.getToastNotifier(), + history = this.getToastHistory(), + toasts = this.getScheduledToasts(); + + try { + history.remove('Toast' + id); + } catch (e) {/*Only Phones support the NotificationHistory*/ } + + for (var i = 0; i < toasts.length; i++) { + var toast = toasts[i]; + + if (toast.id == id || toast.id == id + '-2') { + notifier.removeFromSchedule(toast); + } + } + }, + + /** + * Cancels all notifications. + */ + cancelAll: function () { + var ids = this.getAllIds(); + + for (var i = 0; i < ids.length; i++) { + this.cancelLocalNotification(ids[i]); + } + + try { + this.getToastHistory().clear(); + } catch (e) {/*Only Phones support the NotificationHistory*/ } + this.fireEvent('cancelall'); + }, + + /** + * Checks if a notification with an ID is present. + * + * @param {int} id + * Local notification ID + */ + isPresent: function (id) { + return !!this.findToastById(id); + }, + + /** + * Checks if a notification with an ID was scheduled. + * + * @param {int} id + * Local notification ID + */ + isScheduled: function (id) { + var toast = this.findToastById(id); + + return toast && this.isToastScheduled(toast); + }, + + /** + * Checks if a notification with an ID was triggered. + * + * @param {int} id + * Local notification ID + */ + isTriggered: function (id) { + var toast = this.findToastById(id); + + return toast && this.isToastTriggered(toast); + }, + + /** + * Lists all local notification IDs. + */ + getAllIds: function () { + var toasts = this.getScheduledToasts(), + ids = []; + + for (var i = 0; i < toasts.length; i++) { + var toast = toasts[i]; + + ids.push(this.getToastId(toast)); + } + + return ids; + }, + + /** + * Lists all scheduled notification IDs. + */ + getScheduledIds: function () { + var toasts = this.getScheduledToasts(), + ids = []; + + for (var i = 0; i < toasts.length; i++) { + var toast = toasts[i]; + + if (!this.isToastScheduled(toast)) + continue; + + ids.push(this.getToastId(toast)); + } + + return ids; + }, + + /** + * Lists all scheduled notification IDs. + */ + getTriggeredIds: function () { + var toasts = this.getScheduledToasts(), + ids = []; + + for (var i = 0; i < toasts.length; i++) { + var toast = toasts[i]; + + if (!this.isToastTriggered(toast)) + continue; + + ids.push(this.getToastId(toast)); + } + + return ids; + }, + + /** + * Property list for given notifications. + * If called without IDs, all notification will be returned. + * + * @param {int[]} ids + * List of local notification IDs. + * @param {String?} type + * Local notification life cycle type + */ + getAll: function (ids, type) { + var toasts = this.getScheduledToasts(), + notifications = []; + + if (!ids || ids.length === 0) { + ids = this.getAllIds(); + } + + for (var index = 0; index < ids.length; index++) { + var id = ids[index], + toast = this.findToastById(id); + + if (!toast || type && this.getToastType(toast) != type) + continue; + + var json = toast.content.lastChild.lastChild.innerText; + + notifications.push(JSON.parse(json)); + } + + return notifications; + }, + + /** + * Property list for given notifications. + * If called without IDs, all notification will be returned. + * + * @param {int[]} ids + * List of local notification IDs + */ + getScheduled: function (ids) { + if (!ids || ids.length === 0) { + ids = this.getAllIds(); + } + + return this.getAll(ids, 'scheduled'); + }, + + /** + * Property list for given notifications. + * If called without IDs, all notification will be returned. + * + * @param {int[]} ids + * List of local notification IDs + */ + getTriggered: function (ids) { + if (!ids || ids.length === 0) { + ids = this.getAllIds(); + } + + return this.getAll(ids, 'triggered'); + }, +}; diff --git a/plugins/de.appplant.cordova.plugin.local-notification/src/windows/LocalNotificationProxy.js b/plugins/de.appplant.cordova.plugin.local-notification/src/windows/LocalNotificationProxy.js new file mode 100644 index 00000000..2f7ed3d7 --- /dev/null +++ b/plugins/de.appplant.cordova.plugin.local-notification/src/windows/LocalNotificationProxy.js @@ -0,0 +1,311 @@ +/* + Copyright 2013-2015 appPlant UG + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +*/ + +/** + * Executes all queued events. + */ +exports.deviceready = function () { + exports.core.deviceready(); +}; + +/** + * Schedule a new local notification. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {Object[]} notifications + * Array of local notifications + */ +exports.schedule = function (success, error, notifications) { + exports.core.schedule(notifications, 'schedule'); + + success(); +}; + +/** + * Update existing notifications specified by IDs in options. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {Object[]} notifications + * Array of local notifications + */ +exports.update = function (success, error, notifications) { + exports.core.update(notifications); + + success(); +}; + +/** + * Clear the specified notification. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {int[]} ids + * List of local notification IDs + */ +exports.clear = function (success, error, ids) { + exports.core.clear(ids, true); + + success(); +}; + +/** + * Clear all previously sheduled notifications. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + */ +exports.clearAll = function (success, error) { + exports.core.clearAll(); + + success(); +}; + +/** + * Cancel the specified notifications. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {int[]} ids + * List of local notification IDs + */ +exports.cancel = function (success, error, ids) { + exports.core.cancel(ids, true); + + success(); +}; + +/** + * Remove all previously registered notifications. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + */ +exports.cancelAll = function (success, error) { + exports.core.cancelAll(); + + success(); +}; + +/** + * Check if a notification with an ID is present. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {int} id + * Local notification ID + */ +exports.isPresent = function (success, error, args) { + var found = exports.core.isPresent(args[0]); + + success(found); +}; + +/** + * Check if a notification with an ID is scheduled. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {int} id + * Local notification ID + */ +exports.isScheduled = function (success, error, args) { + var found = exports.core.isScheduled(args[0]); + + success(found); +}; + +/** + * Check if a notification with an ID was triggered. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {int} id + * Local notification ID + */ +exports.isTriggered = function (success, error, args) { + var found = exports.core.isTriggered(args[0]); + + success(found); +}; + +/** + * List all local notification IDs. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + */ +exports.getAllIds = function (success, error) { + var ids = exports.core.getAllIds(); + + success(ids); +}; + +/** + * List all scheduled notification IDs. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + */ +exports.getScheduledIds = function (success, error) { + var ids = exports.core.getScheduledIds(); + + success(ids); +}; + +/** + * List all triggered notification IDs. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + */ +exports.getTriggeredIds = function (success, error) { + var ids = exports.core.getTriggeredIds(); + + success(ids); +}; + +/** + * Propertys for given notification. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {int[]} ids + * List of local notification IDs + */ +exports.getSingle = function (success, error, ids) { + var notification = exports.core.getAll(ids)[0]; + + success(notification); +}; + +/** + * Propertys for given scheduled notification. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {int[]} ids + * List of local notification IDs + */ +exports.getSingleScheduled = function (success, error, ids) { + var notification = exports.core.getScheduled(ids)[0]; + + success(notification); +}; + +/** + * Propertys for given triggered notification. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {int[]} ids + * List of local notification IDs + */ +exports.getSingleTriggered = function (success, error, ids) { + var notification = exports.core.getTriggered(ids)[0]; + + success(notification); +}; + +/** + * Property list for given notifications. + * If called without IDs, all notification will be returned. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {int[]} ids + * List of local notification IDs + */ +exports.getAll = function (success, error, ids) { + var notifications = exports.core.getAll(ids); + + success(notifications); +}; + +/** + * Property list for given triggered notifications. + * If called without IDs, all notification will be returned. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {int[]} ids + * List of local notification IDs + */ +exports.getScheduled = function (success, error, ids) { + var notifications = exports.core.getScheduled(ids); + + success(notifications); +}; + +/** + * Property list for given triggered notifications. + * If called without IDs, all notification will be returned. + * + * @param {Function} success + * Success callback + * @param {Function} error + * Error callback + * @param {int[]} ids + * List of local notification IDs + */ +exports.getTriggered = function (success, error, ids) { + var notifications = exports.core.getTriggered(ids); + + success(notifications); +}; + + +cordova.commandProxy.add('LocalNotification', exports); diff --git a/plugins/de.appplant.cordova.plugin.local-notification/src/windows/LocalNotificationUtil.js b/plugins/de.appplant.cordova.plugin.local-notification/src/windows/LocalNotificationUtil.js new file mode 100644 index 00000000..4081a0b8 --- /dev/null +++ b/plugins/de.appplant.cordova.plugin.local-notification/src/windows/LocalNotificationUtil.js @@ -0,0 +1,443 @@ +/* + Copyright 2013-2015 appPlant UG + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +*/ + + +exports = require('de.appplant.cordova.plugin.local-notification.LocalNotification.Proxy').core; + +var channel = require('cordova/channel'); + + +/*********** + * MEMBERS * + ***********/ + +// True if App is running, false if suspended +exports.isInBackground = true; + +// Indicates if the device is ready (to receive events) +exports.isReady = false; + +// Queues all events before deviceready +exports.eventQueue = []; + +/******** + * UTIL * + ********/ + +/** + * The repeating interval in milliseconds. + * + * @param {String} interval + * A number or a placeholder like `minute`. + * + * @return {Number} + * Interval in milliseconds + */ +exports.getRepeatInterval = function (every) { + + if (!every) + return 0; + + if (every == 'minute') + return 60000; + + if (every == 'hour') + return 360000; + + if (!NaN(every)) + return parseInt(every) * 60000; + + return 0; +}; + +/** + * If the notification is repeating. + * + * @param {Object} notification + * Local notification object + * + * @return Boolean + */ +exports.isRepeating = function (notification) { + return this.getRepeatInterval(notification.every) !== 0; +}; + +/** + * Parses sound file path. + * + * @param {String} path + * Relative path to sound resource + * + * @return {String} XML Tag for Sound-File + */ +exports.parseSound = function (path) { + if (!path.match(/^file/)) + return ''; + + var uri = this.parseUri(path), + audio = "