Commit 1a6ebf04 by Sebastián Katzer

Initial windows support (not yet complete)

parent 5dc8b661
...@@ -199,4 +199,25 @@ ...@@ -199,4 +199,25 @@
</platform> </platform>
<!-- windows -->
<platform name="windows">
<js-module src="src/windows/LocalNotificationProxy.js" name="LocalNotification.Proxy" >
<merges target="" />
</js-module>
<js-module src="src/windows/LocalNotificationCore.js" name="LocalNotification.Proxy.Core" >
<merges target="" />
</js-module>
<js-module src="src/windows/LocalNotificationUtil.js" name="LocalNotification.Proxy.Util" >
<merges target="" />
</js-module>
<!-- Platform Hooks -->
<hook type="after_platform_add" src="scripts/windows/setToastCapable.js" />
<hook type="after_plugin_install" src="scripts/windows/setToastCapable.js" />
</platform>
</plugin> </plugin>
#!/usr/bin/env node
// This Plugin-Hook sets ToastCapable on true to allow windows-platform
// cordova apps displaing local-notifications
var fs = require('fs'),
rootdir = process.argv[2];
if (!rootdir)
return;
function replace_string_in_file (filename, to_replace, replace_with) {
var data = fs.readFileSync(filename, 'utf8'),
result;
if (data.indexOf(replace_with) > -1)
return;
result = data.replace(new RegExp(to_replace, 'g'), replace_with);
fs.writeFileSync(filename, result, 'utf8');
}
var manifests = [
'platforms/windows/package.phone.appxmanifest',
'platforms/windows/package.windows.appxmanifest',
'platforms/windows/package.windows80.appxmanifest'
];
for (var i = 0; i < manifests.length; i++) {
replace_string_in_file(manifests[i], '<m3:VisualElements ', '<m3:VisualElements ToastCapable="true" ');
}
/*
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 Notifications = Windows.UI.Notifications,
applicationData = Windows.Storage.ApplicationData.current,
localSettings = applicationData.localSettings;
exports.core = {
// Array of unactivated notifications
unactivatedIds: [],
/**
* 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.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 a single local notification.
*
* @param {Object} notification
* The local notification
* @param {Object} updates
* Updated properties
*/
updateLocalNotification: function (notification, updates) {
},
/**
* 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.getScheduledToast();
history.remove('Toast' + id);
for (var i = 0; i < toasts.length; i++) {
var toast = toasts[i];
if (toast.id == id || toast.id == id + '-2') {
notifier.removeFromSchedule(toast);
}
}
},
/**
* Clears the local notification with the given ID.
*
* @param {String} id
* Local notification ID
*/
clearLocalNotification: function (id) {
this.getToastHistory().remove('Toast' + id);
if (this.isTriggered(id) && !this.isScheduled(id)) {
this.cancelLocalNotification(id);
}
},
/**
* 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);
}
},
/**
* Clears the specified notifications.
*
* @param {int[]} ids
* List of local notification IDs
*/
clear: function (ids) {
for (var i = 0; i < ids.length; i++) {
var notification = this.getAll([id])[0];
this.clearLocalNotification(ids[i]);
this.fireEvent('clear', notification);
}
},
/**
* Clears all notifications.
*/
clearAll: function () {
var ids = this.getTriggeredIds();
for (var i = 0; i < ids.length; i++) {
this.clearLocalNotification(ids[i]);
}
this.getToastHistory().clear();
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 notification = this.getAll([id])[0];
this.cancelLocalNotification(ids[i]);
this.fireEvent('cancel', notification);
}
},
/**
* Cancels all notifications.
*/
cancelAll: function () {
var ids = this.getAllIds();
for (var i = 0; i < ids.length; i++) {
this.cancelLocalNotification(ids[i]);
}
this.getToastHistory().clear();
this.fireEvent('cancelall');
},
/**
* Checks if a notification with an ID is present.
*
* @param {int} id
* Local notification ID
*/
isPresent: function (id) {
return this.getAllIds().indexOf(id) > -1;
},
/**
* Checks if a notification with an ID was scheduled.
*
* @param {int} id
* Local notification ID
*/
isScheduled: function (id) {
return this.getScheduledIds().indexOf(id) > -1;
},
/**
* Checks if a notification with an ID was triggered.
*
* @param {int} id
* Local notification ID
*/
isTriggered: function (id) {
return this.getTriggeredIds().indexOf(id) > -1;
},
/**
* Lists all local notification IDs.
*/
getAllIds: function () {
var toasts = this.getScheduledToast(),
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.getScheduledToast(),
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.getScheduledToast(),
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.getScheduledToast(),
notifications = [];
if (ids.length === 0) {
ids = 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.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.length === 0) {
ids = this.getAllIds();
}
return this.getAll(ids, 'triggered');
},
};
/*
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 () {
};
/**
* 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);
};
/**
* 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);
};
/**
* Required for core module to access the proxy.
*/
exports.exports = function () {
return exports;
};
cordova.commandProxy.add('LocalNotification', exports);
/*
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').core;
/***********
* MEMBERS *
***********/
// True if App is running, false if suspended
exports.isInBackground = true;
/********
* 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;
};
/**
* Parses sound file path.
*
* @param {String} path
* Relative path to sound resource
*
* @return {String} URI to Sound-File
*/
exports.parseSound = function (path) {
var pkg = Windows.ApplicationModel.Package.current,
pkgId = pkg.id,
pkgName = pkgId.name;
if (!path.match(/^file/))
return;
var sound = "'ms-appx://" + pkgName + "/www/" + path.slice(6, path.length) + "'",
audio = "<audio src=" + sound + " loop='false'/>";
return audio;
};
/**
* Builds the xml payload for a local notification based on its options.
*
* @param {Object} options
* Local notification properties
*
* @return {String}
* Windows.Data.Xml.Dom.XmlDocument
*/
exports.build = function (options) {
var title = options.title,
message = options.text || '',
sound = '';
if (!title || title === '') {
title = 'Notification';
}
if (options.sound) {
sound = this.parseSound(options.sound);
}
var payload =
"<toast> " +
"<visual version='2'>" +
"<binding template='ToastText02'>" +
"<text id='2'>" + message + "</text>" +
"<text id='1'>" + title + "</text>" +
"</binding>" +
"</visual>" +
sound +
"<json>" + JSON.stringify(options) + "</json>" +
"</toast>";
var notification = new Windows.Data.Xml.Dom.XmlDocument();
try {
notification.loadXml(payload);
} catch (e) {
console.error(
'LocalNotification#schedule',
'Error loading the xml, check for invalid characters.');
}
// Launch Attribute to enable onClick event
var launchAttr = notification.createAttribute('launch'),
toastNode = notification.selectSingleNode('/toast');
launchAttr.value = options.id.toString();
toastNode.attributes.setNamedItem(launchAttr);
return notification;
};
/**
* Short-hand method for the toast notification history.
*/
exports.getToastHistory = function () {
return Windows.UI.Notifications.ToastNotificationManager.history;
};
/**
* Gets a toast notifier instance.
*
* @return Object
*/
exports.getToastNotifier = function () {
return Windows.UI.Notifications.ToastNotificationManager
.createToastNotifier();
};
/**
* List of all scheduled toast notifiers.
*
* @return Array
*/
exports.getScheduledToast = function () {
return this.getToastNotifier().getScheduledToastNotifications();
};
/**
* Gets the Id from the toast notifier.
*
* @param {Object} toast
* A toast notifier object
*
* @return String
*/
exports.getToastId = function (toast) {
var id = toast.id;
if (id.match(/-2$/))
return id.match(/^[^-]+/)[0];
return id;
};
/**
* Gets the notification life cycle type
* (scheduled or triggered)
*
* @param {Object} toast
* A toast notifier object
*
* @return String
*/
exports.getToastType = function (toast) {
return this.isToastTriggered(toast) ? 'triggered' : 'scheduled';
};
/**
* If the toast is already scheduled.
*
* @param {Object} toast
* A toast notifier object
*
* @return Boolean
*/
exports.isToastScheduled = function (toast) {
return !this.isToastTriggered(toast);
};
/**
* If the toast is already triggered.
*
* @param {Object} toast
* A toast notifier object
*
* @return Boolean
*/
exports.isToastTriggered = function (toast) {
var id = this.getToastId(toast),
notification = this.getAll(id)[0];
fireDate = new Date((notification.at) * 1000);
return fireDate <= new Date();
};
/**
* Finds the toast by it's ID.
*
* @param {String} id
* Local notification ID
*
* @param Object
*/
exports.findToastById = function (id) {
var toasts = this.getScheduledToastNotifications();
for (var i = 0; i < toasts.length; i++) {
var toast = toasts[i];
if (this.getToastId(toast) == id)
return toast;
}
return null;
};
/**
* Sets trigger event for local notification.
*
* @param {Object} notification
* Local notification object
* @param {Function} callback
* Callback function
*/
exports.callOnTrigger = function (notification, callback) {
var triggerTime = new Date((notification.at * 1000)),
interval = triggerTime - new Date();
if (interval <= 0) {
callback.call(this, notification);
return;
}
WinJS.Promise.timeout(interval).then(function () {
if (exports.isPresent(notification.id)) {
callback.call(exports, notification);
}
});
};
/**
* The application state - background or foreground.
*
* @return String
*/
exports.getApplicationState = function () {
return this.isInBackground ? 'background' : 'foreground';
};
/**
* Fires the event about a local notification.
*
* @param {String} event
* The event
* @param {Object} notification
* The notification
*/
exports.fireEvent = function (event, notification) {
var plugin = cordova.plugins.notification.local.core,
state = this.getApplicationState();
if (notification) {
plugin.fireEvent(event, notification, state);
} else {
plugin.fireEvent(event, state);
}
};
/**************
* LIFE CYCLE *
**************/
// App is running in background
document.addEventListener('pause', function () {
exports.isInBackground = true;
}, false);
// App is running in foreground
document.addEventListener('resume', function () {
exports.isInBackground = false;
}, false);
// App is running in foreground
document.addEventListener('deviceready', function () {
exports.isInBackground = false;
}, false);
...@@ -327,7 +327,7 @@ exports.getScheduled = function () { ...@@ -327,7 +327,7 @@ exports.getScheduled = function () {
}; };
/** /**
* Retrieve the properties for all scheduled notifications. * Property list for all scheduled notifications.
* *
* @param {Function} callback * @param {Function} callback
* A callback function to be called with the list * A callback function to be called with the list
...@@ -370,7 +370,7 @@ exports.getTriggered = function () { ...@@ -370,7 +370,7 @@ exports.getTriggered = function () {
}; };
/** /**
* Retrieve the properties for all triggered notifications. * Property list for all triggered notifications.
* *
* @param {Function} callback * @param {Function} callback
* A callback function to be called with the list * A callback function to be called with the list
......
...@@ -252,7 +252,7 @@ exports.getScheduled = function () { ...@@ -252,7 +252,7 @@ exports.getScheduled = function () {
}; };
/** /**
* Retrieve the properties for all scheduled notifications. * Property list for all scheduled notifications.
* *
* @param {Function} callback * @param {Function} callback
* A callback function to be called with the list * A callback function to be called with the list
...@@ -279,7 +279,7 @@ exports.getTriggered = function () { ...@@ -279,7 +279,7 @@ exports.getTriggered = function () {
}; };
/** /**
* Retrieve the properties for all triggered notifications. * Property list for all triggered notifications.
* *
* @param {Function} callback * @param {Function} callback
* A callback function to be called with the list * A callback function to be called with the list
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment