Commit 6540f331 by Sebastián Katzer

Add sample for actions

parent 008a0ec0
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
// Request permission to show notifications // Request permission to show notifications
- (void) request:(CDVInvokedUrlCommand*)command; - (void) request:(CDVInvokedUrlCommand*)command;
// Register/update an action group
- (void) registerCategory:(CDVInvokedUrlCommand*)command;
// Schedule notifications // Schedule notifications
- (void) schedule:(CDVInvokedUrlCommand*)command; - (void) schedule:(CDVInvokedUrlCommand*)command;
//// Update set of notifications //// Update set of notifications
......
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
// NSNumber* id = [options objectForKey:@"id"]; // NSNumber* id = [options objectForKey:@"id"];
// UNNotificationRequest* notification; // UNNotificationRequest* notification;
// //
// notification = [self.center getNotificationWithId:id]; // notification = [_center getNotificationWithId:id];
// //
// if (!notification) // if (!notification)
// continue; // continue;
...@@ -119,7 +119,7 @@ ...@@ -119,7 +119,7 @@
// NSNumber* id = [options objectForKey:@"id"]; // NSNumber* id = [options objectForKey:@"id"];
// UILocalNotification* notification; // UILocalNotification* notification;
// //
// notification = [self.app localNotificationWithId:id]; // notification = [_app localNotificationWithId:id];
// //
// if (!notification) // if (!notification)
// continue; // continue;
...@@ -151,16 +151,16 @@ ...@@ -151,16 +151,16 @@
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
for (NSNumber* id in command.arguments) { for (NSNumber* id in command.arguments) {
UNNotificationRequest* notification; UNNotificationRequest* notification;
notification = [self.center getNotificationWithId:id]; notification = [_center getNotificationWithId:id];
if (!notification) if (!notification)
continue; continue;
[self.center clearNotification:notification]; [_center clearNotification:notification];
[self fireEvent:@"clear" notification:notification]; [self fireEvent:@"clear" notification:notification];
} }
[self execCallback:command]; [self execCallback:command];
}]; }];
} }
...@@ -173,8 +173,8 @@ ...@@ -173,8 +173,8 @@
- (void) clearAll:(CDVInvokedUrlCommand*)command - (void) clearAll:(CDVInvokedUrlCommand*)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
[self.center clearAllNotifications]; [_center clearAllNotifications];
[self.app setApplicationIconBadgeNumber:0]; [_app setApplicationIconBadgeNumber:0];
[self fireEvent:@"clearall"]; [self fireEvent:@"clearall"];
[self execCallback:command]; [self execCallback:command];
}]; }];
...@@ -192,13 +192,13 @@ ...@@ -192,13 +192,13 @@
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
for (NSNumber* id in command.arguments) { for (NSNumber* id in command.arguments) {
UNNotificationRequest* notification; UNNotificationRequest* notification;
notification = [self.center getNotificationWithId:id]; notification = [_center getNotificationWithId:id];
if (!notification) if (!notification)
continue; continue;
[self.center cancelNotification:notification]; [_center cancelNotification:notification];
[self fireEvent:@"cancel" notification:notification]; [self fireEvent:@"cancel" notification:notification];
} }
...@@ -214,8 +214,8 @@ ...@@ -214,8 +214,8 @@
- (void) cancelAll:(CDVInvokedUrlCommand*)command - (void) cancelAll:(CDVInvokedUrlCommand*)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
[self.center cancelAllNotifications]; [_center cancelAllNotifications];
[self.app setApplicationIconBadgeNumber:0]; [_app setApplicationIconBadgeNumber:0];
[self fireEvent:@"cancelall"]; [self fireEvent:@"cancelall"];
[self execCallback:command]; [self execCallback:command];
}]; }];
...@@ -321,12 +321,12 @@ ...@@ -321,12 +321,12 @@
byType:(APPNotificationType)type; byType:(APPNotificationType)type;
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
NSArray* ids = [self.center getNotificationIdsByType:type]; NSArray* ids = [_center getNotificationIdsByType:type];
CDVPluginResult* result; CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:ids]; messageAsArray:ids];
[self.commandDelegate sendPluginResult:result [self.commandDelegate sendPluginResult:result
callbackId:command.callbackId]; callbackId:command.callbackId];
}]; }];
...@@ -383,11 +383,11 @@ ...@@ -383,11 +383,11 @@
NSArray* notifications; NSArray* notifications;
notifications = [_center getNotificationOptionsByType:type andId:ids]; notifications = [_center getNotificationOptionsByType:type andId:ids];
CDVPluginResult* result; CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:[notifications firstObject]]; messageAsDictionary:[notifications firstObject]];
[self.commandDelegate sendPluginResult:result [self.commandDelegate sendPluginResult:result
callbackId:command.callbackId]; callbackId:command.callbackId];
}]; }];
...@@ -497,11 +497,30 @@ ...@@ -497,11 +497,30 @@
UNAuthorizationOptions options = UNAuthorizationOptions options =
(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert); (UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert);
[self.center requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError* e) { [_center requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError* e) {
[self check:command]; [self check:command];
}]; }];
} }
/**
* Register/update an action group.
*
* @return [ Void ]
*/
- (void) registerCategory:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
NSDictionary* options = command.arguments[0];
APPNotificationContent* notification;
notification = [[APPNotificationContent alloc]
initWithOptions:options];
[_center addNotificationCategory:notification.category];
[self execCallback:command];
}];
}
#pragma mark - #pragma mark -
#pragma mark Private #pragma mark Private
...@@ -513,6 +532,8 @@ ...@@ -513,6 +532,8 @@
__weak APPLocalNotification* weakSelf = self; __weak APPLocalNotification* weakSelf = self;
UNNotificationRequest* request = notification.request; UNNotificationRequest* request = notification.request;
[_center addNotificationCategory:notification.category];
[_center addNotificationRequest:request withCompletionHandler:^(NSError* e) { [_center addNotificationRequest:request withCompletionHandler:^(NSError* e) {
__strong APPLocalNotification* strongSelf = weakSelf; __strong APPLocalNotification* strongSelf = weakSelf;
[strongSelf fireEvent:@"add" notification:request]; [strongSelf fireEvent:@"add" notification:request];
......
...@@ -30,5 +30,6 @@ ...@@ -30,5 +30,6 @@
- (id) initWithOptions:(NSDictionary*)dict; - (id) initWithOptions:(NSDictionary*)dict;
- (APPNotificationOptions*) options; - (APPNotificationOptions*) options;
- (UNNotificationRequest*) request; - (UNNotificationRequest*) request;
- (UNNotificationCategory*) category;
@end @end
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#import "APPNotificationContent.h" #import "APPNotificationContent.h"
#import "APPNotificationOptions.h" #import "APPNotificationOptions.h"
#import "UNUserNotificationCenter+APPLocalNotification.h"
#import <objc/runtime.h> #import <objc/runtime.h>
@import UserNotifications; @import UserNotifications;
...@@ -67,7 +66,7 @@ static char optionsKey; ...@@ -67,7 +66,7 @@ static char optionsKey;
self.sound = options.sound; self.sound = options.sound;
self.badge = options.badge; self.badge = options.badge;
self.attachments = options.attachments; self.attachments = options.attachments;
self.categoryIdentifier = kAPPGeneralCategory; self.categoryIdentifier = options.categoryId;
} }
#pragma mark - #pragma mark -
...@@ -107,6 +106,25 @@ static char optionsKey; ...@@ -107,6 +106,25 @@ static char optionsKey;
trigger:opts.trigger]; trigger:opts.trigger];
} }
/**
* The category for the notification with all the actions.
*
* @return [ UNNotificationCategory* ]
*/
- (UNNotificationCategory*) category
{
NSString* categoryId = self.categoryIdentifier;
NSArray* actions = self.options.actions;
if (!actions.count)
return NULL;
return [UNNotificationCategory categoryWithIdentifier:categoryId
actions:actions
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
}
#pragma mark - #pragma mark -
#pragma mark Private #pragma mark Private
......
...@@ -27,13 +27,15 @@ ...@@ -27,13 +27,15 @@
@property (readonly, getter=id) NSNumber* id; @property (readonly, getter=id) NSNumber* id;
@property (readonly, getter=identifier) NSString* identifier; @property (readonly, getter=identifier) NSString* identifier;
@property (readonly, getter=categoryId) NSString* categoryId;
@property (readonly, getter=title) NSString* title; @property (readonly, getter=title) NSString* title;
@property (readonly, getter=subtitle) NSString* subtitle; @property (readonly, getter=subtitle) NSString* subtitle;
@property (readonly, getter=badge) NSNumber* badge; @property (readonly, getter=badge) NSNumber* badge;
@property (readonly, getter=text) NSString* text; @property (readonly, getter=text) NSString* text;
@property (readonly, getter=sound) UNNotificationSound* sound; @property (readonly, getter=sound) UNNotificationSound* sound;
@property (readonly, getter=attachments) NSArray<UNNotificationAttachment *> * attachments;
@property (readonly, getter=userInfo) NSDictionary* userInfo; @property (readonly, getter=userInfo) NSDictionary* userInfo;
@property (readonly, getter=actions) NSArray<UNNotificationAction *> * actions;
@property (readonly, getter=attachments) NSArray<UNNotificationAttachment *> * attachments;
- (id) initWithDict:(NSDictionary*)dict; - (id) initWithDict:(NSDictionary*)dict;
- (UNNotificationTrigger*) trigger; - (UNNotificationTrigger*) trigger;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
*/ */
#import "APPNotificationOptions.h" #import "APPNotificationOptions.h"
#import "UNUserNotificationCenter+APPLocalNotification.h"
@import UserNotifications; @import UserNotifications;
...@@ -51,6 +52,8 @@ ...@@ -51,6 +52,8 @@
self = [self init]; self = [self init];
self.dict = dictionary; self.dict = dictionary;
[self actions];
return self; return self;
} }
...@@ -119,7 +122,21 @@ ...@@ -119,7 +122,21 @@
*/ */
- (NSNumber*) badge - (NSNumber*) badge
{ {
return [NSNumber numberWithInt:[[dict objectForKey:@"badge"] intValue]]; id value = [dict objectForKey:@"badge"];
return (value == NULL) ? NULL : [NSNumber numberWithInt:[value intValue]];
}
/**
* The category of the notification.
*
* @return [ NSString* ]
*/
- (NSString*) categoryId
{
NSString* value = [dict objectForKey:@"actionGroupId"];
return value.length ? value : kAPPGeneralCategory;
} }
/** /**
...@@ -148,19 +165,12 @@ ...@@ -148,19 +165,12 @@
return [UNNotificationSound soundNamed:file]; return [UNNotificationSound soundNamed:file];
} }
/** /**
* The date when to fire the notification. * Additional content to attach.
* *
* @return [ NSDate* ] * @return [ UNNotificationSound* ]
*/ */
- (NSDate*) fireDate
{
double timestamp = [[dict objectForKey:@"at"]
doubleValue];
return [NSDate dateWithTimeIntervalSince1970:timestamp];
}
- (NSArray<UNNotificationAttachment *> *) attachments - (NSArray<UNNotificationAttachment *> *) attachments
{ {
NSArray* paths = [dict objectForKey:@"attachments"]; NSArray* paths = [dict objectForKey:@"attachments"];
...@@ -186,6 +196,47 @@ ...@@ -186,6 +196,47 @@
return attachments; return attachments;
} }
/**
* Additional actions for the notification.
*
* @return [ NSArray* ]
*/
- (NSArray<UNNotificationAction *> *) actions
{
NSArray* items = [dict objectForKey:@"actions"];
NSMutableArray* actions = [[NSMutableArray alloc] init];
if (!items)
return actions;
for (NSDictionary* item in items) {
NSString* id = [item objectForKey:@"id"];
NSString* title = [item objectForKey:@"title"];
UNNotificationActionOptions options = UNNotificationActionOptionNone;
if ([[item objectForKey:@"launch"] boolValue]) {
options = UNNotificationActionOptionForeground;
}
if ([[item objectForKey:@"ui"] isEqualToString:@"decline"]) {
options = options | UNNotificationActionOptionDestructive;
}
if ([[item objectForKey:@"needsAuth"] boolValue]) {
options = options | UNNotificationActionOptionAuthenticationRequired;
}
UNNotificationAction* action;
action = [UNNotificationAction actionWithIdentifier:id
title:title
options:options];
[actions addObject:action];
}
return actions;
}
#pragma mark - #pragma mark -
#pragma mark Public #pragma mark Public
...@@ -224,6 +275,19 @@ ...@@ -224,6 +275,19 @@
#pragma mark Private #pragma mark Private
/** /**
* The date when to fire the notification.
*
* @return [ NSDate* ]
*/
- (NSDate*) triggerDate
{
double timestamp = [[dict objectForKey:@"at"]
doubleValue];
return [NSDate dateWithTimeIntervalSince1970:timestamp];
}
/**
* If the notification shall be repeating. * If the notification shall be repeating.
* *
* @return [ BOOL ] * @return [ BOOL ]
...@@ -299,7 +363,7 @@ ...@@ -299,7 +363,7 @@
initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *date = [cal components:[self repeatInterval] NSDateComponents *date = [cal components:[self repeatInterval]
fromDate:[self fireDate]]; fromDate:[self triggerDate]];
date.timeZone = [NSTimeZone defaultTimeZone]; date.timeZone = [NSTimeZone defaultTimeZone];
...@@ -333,7 +397,7 @@ ...@@ -333,7 +397,7 @@
*/ */
- (double) timeInterval - (double) timeInterval
{ {
return MAX(0.01f, [self.fireDate timeIntervalSinceDate:[NSDate date]]); return MAX(0.01f, [self.triggerDate timeIntervalSinceDate:[NSDate date]]);
} }
/** /**
...@@ -464,10 +528,6 @@ ...@@ -464,10 +528,6 @@
{ {
return [self urlForAsset:path]; return [self urlForAsset:path];
} }
else if ([path hasPrefix:@"app://"])
{
return [self urlForAppInternalPath:path];
}
else if ([path hasPrefix:@"base64:"]) else if ([path hasPrefix:@"base64:"])
{ {
return [self urlFromBase64:path]; return [self urlFromBase64:path];
...@@ -515,7 +575,7 @@ ...@@ -515,7 +575,7 @@
{ {
NSFileManager* fm = [NSFileManager defaultManager]; NSFileManager* fm = [NSFileManager defaultManager];
NSBundle* mainBundle = [NSBundle mainBundle]; NSBundle* mainBundle = [NSBundle mainBundle];
NSString* bundlePath = [mainBundle bundlePath]; NSString* bundlePath = [mainBundle resourcePath];
if ([path isEqualToString:@"res://icon"]) { if ([path isEqualToString:@"res://icon"]) {
path = @"res://AppIcon60x60@3x.png"; path = @"res://AppIcon60x60@3x.png";
...@@ -561,26 +621,6 @@ ...@@ -561,26 +621,6 @@
} }
/** /**
* URL for an internal app path.
*
* @param [ NSString* ] path A relative file path from main bundle dir.
*
* @return [ NSURL* ]
*/
- (NSURL*) urlForAppInternalPath:(NSString*)path
{
NSFileManager* fm = [NSFileManager defaultManager];
NSBundle* mainBundle = [NSBundle mainBundle];
NSString* absPath = [mainBundle bundlePath];
if (![fm fileExistsAtPath:absPath]) {
NSLog(@"File not found: %@", absPath);
}
return [NSURL fileURLWithPath:absPath];
}
/**
* URL for a base64 encoded string. * URL for a base64 encoded string.
* *
* @param [ NSString* ] base64String Base64 encoded string. * @param [ NSString* ] base64String Base64 encoded string.
......
...@@ -38,7 +38,10 @@ typedef NS_ENUM(NSUInteger, APPNotificationType) { ...@@ -38,7 +38,10 @@ typedef NS_ENUM(NSUInteger, APPNotificationType) {
@property (readonly, getter=getNotifications) NSArray* localNotifications; @property (readonly, getter=getNotifications) NSArray* localNotifications;
@property (readonly, getter=getNotificationIds) NSArray* localNotificationIds; @property (readonly, getter=getNotificationIds) NSArray* localNotificationIds;
// Register general notification category to listen for dismiss actions
- (void) registerGeneralNotificationCategory; - (void) registerGeneralNotificationCategory;
// Add the specified category to the list of categories
- (void) addNotificationCategory:(UNNotificationCategory*)category;
// List of all notification IDs from given type // List of all notification IDs from given type
- (NSArray*) getNotificationIdsByType:(APPNotificationType)type; - (NSArray*) getNotificationIdsByType:(APPNotificationType)type;
......
...@@ -48,7 +48,34 @@ NSString * const kAPPGeneralCategory = @"GENERAL"; ...@@ -48,7 +48,34 @@ NSString * const kAPPGeneralCategory = @"GENERAL";
intentIdentifiers:@[] intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction]; options:UNNotificationCategoryOptionCustomDismissAction];
[self setNotificationCategories:[NSSet setWithObjects:category, nil]]; [self setNotificationCategories:[NSSet setWithObject:category]];
}
/**
* Add the specified category to the list of categories.
*
* @param [ UNNotificationCategory* ] category The category to add.
*
* @return [ Void ]
*/
- (void) addNotificationCategory:(UNNotificationCategory*)category
{
if (!category)
return;
[self getNotificationCategoriesWithCompletionHandler:^(NSSet<UNNotificationCategory *> *set) {
NSMutableSet* categories = [NSMutableSet setWithSet:set];
for (UNNotificationCategory* item in categories) {
if ([category.identifier isEqualToString:item.identifier]) {
[categories removeObject:item];
break;
}
}
[categories addObject:category];
[self setNotificationCategories:categories];
}];
} }
#pragma mark - #pragma mark -
......
...@@ -398,6 +398,21 @@ exports.getAllTriggered = function (callback, scope) { ...@@ -398,6 +398,21 @@ exports.getAllTriggered = function (callback, scope) {
}; };
/** /**
* Register an group of actions by id.
*
* @param [ String ] id The Id of the group.
* @param [ Array] actions The action config settings.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.addActionGroup = function (id, actions, callback, scope) {
var config = { actionGroupId: id, actions: actions };
this.exec('registerCategory', config, callback, scope);
};
/**
* The (platform specific) default settings. * The (platform specific) default settings.
* *
* @return [ Object ] * @return [ Object ]
......
...@@ -21,14 +21,16 @@ var exec = require('cordova/exec'), ...@@ -21,14 +21,16 @@ var exec = require('cordova/exec'),
// Default values // Default values
exports._defaults = { exports._defaults = {
text: '', id: 0,
title: '', text: '',
sound: 'res://platform_default', title: '',
badge: 0, sound: 'res://platform_default',
id: 0, badge: undefined,
data: undefined, data: undefined,
every: undefined, every: undefined,
at: undefined at: undefined,
actions: undefined,
actionGroupId: undefined
}; };
// Listener // Listener
...@@ -150,10 +152,53 @@ exports.convertProperties = function (options) { ...@@ -150,10 +152,53 @@ exports.convertProperties = function (options) {
options.data = JSON.stringify(options.data); options.data = JSON.stringify(options.data);
} }
if (options.actions) {
this.convertActions(options);
}
return options; return options;
}; };
/** /**
* Convert the passed values to their required type, modifying them
* directly for Android and passing the converted list back for iOS.
*
* @param [ Map ] options Set of custom values.
*
* @return [ Map ] Interaction object with category & actions.
*/
exports.convertActions = function (options) {
if (!options.actions)
return null;
var MAX_ACTIONS = (device.platform === 'iOS') ? 4 : 3,
actions = [];
if (options.actions.length > MAX_ACTIONS)
console.warn('Count of actions exceeded count of ' + MAX_ACTIONS);
for (var i = 0; i < options.actions.length && MAX_ACTIONS > 0; i++) {
var action = options.actions[i];
if (!action.id) {
console.warn(
'Action with title ' + action.title + ' has no id and will not be added.');
continue;
}
action.id = action.id.toString();
action.title = (action.title || action.id).toString();
actions.push(action);
MAX_ACTIONS--;
}
options.category = (options.category || 'DEFAULT_GROUP').toString();
options.actions = actions;
};
/**
* Create a callback function to get executed within a specific scope. * Create a callback function to get executed within a specific scope.
* *
* @param [ Function ] fn The function to be exec as the callback. * @param [ Function ] fn The function to be exec as the callback.
......
...@@ -278,6 +278,20 @@ exports.getAllTriggered = function (callback, scope) { ...@@ -278,6 +278,20 @@ exports.getAllTriggered = function (callback, scope) {
}; };
/** /**
* Register an group of actions by id.
*
* @param [ String ] id The Id of the group.
* @param [ Array] actions The action config settings.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.addActionGroup = function (id, actions, callback, scope) {
this.core.registerActionGroup(id, actions, callback, scope);
};
/**
* The (platform specific) default settings. * The (platform specific) default settings.
* *
* @return [ Object ] * @return [ Object ]
......
...@@ -50,6 +50,9 @@ ...@@ -50,6 +50,9 @@
<a id="sched_delayed" class="button orange">Delayed</a> <a id="sched_delayed" class="button orange">Delayed</a>
<a id="sched_interval" class="button orange">Interval</a> <a id="sched_interval" class="button orange">Interval</a>
</div> </div>
<div class="container">
<a id="sched_actions" class="button orange">Actions</a>
</div>
<h2 class="section">Update</h2> <h2 class="section">Update</h2>
<div class="container"> <div class="container">
<a id="update_text" class="button orange">Text</a> <a id="update_text" class="button orange">Text</a>
......
...@@ -57,6 +57,7 @@ var app = { ...@@ -57,6 +57,7 @@ var app = {
document.getElementById('sched_multi').onclick = app.scheduleMultiple; document.getElementById('sched_multi').onclick = app.scheduleMultiple;
document.getElementById('sched_delayed').onclick = app.scheduleDelayed; document.getElementById('sched_delayed').onclick = app.scheduleDelayed;
document.getElementById('sched_interval').onclick = app.scheduleInterval; document.getElementById('sched_interval').onclick = app.scheduleInterval;
document.getElementById('sched_actions').onclick = app.scheduleActions;
document.getElementById('clear_single').onclick = app.clearSingle; document.getElementById('clear_single').onclick = app.clearSingle;
document.getElementById('clear_multi').onclick = app.clearMulti; document.getElementById('clear_multi').onclick = app.clearMulti;
document.getElementById('clear_all').onclick = app.clearAll; document.getElementById('clear_all').onclick = app.clearAll;
...@@ -95,7 +96,6 @@ var app = { ...@@ -95,7 +96,6 @@ var app = {
text: 'Test Message 1', text: 'Test Message 1',
icon: 'http://3.bp.blogspot.com/-Qdsy-GpempY/UU_BN9LTqSI/AAAAAAAAAMA/LkwLW2yNBJ4/s1600/supersu.png', icon: 'http://3.bp.blogspot.com/-Qdsy-GpempY/UU_BN9LTqSI/AAAAAAAAAMA/LkwLW2yNBJ4/s1600/supersu.png',
smallIcon: 'res://cordova', smallIcon: 'res://cordova',
attachments: ['file://img/logo.png'],
sound: null, sound: null,
badge: 1, badge: 1,
data: { test: 1 } data: { test: 1 }
...@@ -148,6 +148,24 @@ var app = { ...@@ -148,6 +148,24 @@ var app = {
smallIcon: 'res://ic_popup_sync' smallIcon: 'res://ic_popup_sync'
}); });
}, },
// Schedule with actions
scheduleActions: function () {
cordova.plugins.notification.local.schedule({
title: 'Local Notification Plugin',
text: 'Made by appPlant from Leipzig/Germany',
attachments: ['file://img/logo.png'],
actionGroupId: 'like-dislike',
actions: [{
id: 'like',
title: 'Like',
launch: true
},{
id: 'dislike',
title: 'Dislike',
ui: 'decline'
}]
});
},
// Clear a single notification // Clear a single notification
clearSingle: function () { clearSingle: function () {
cordova.plugins.notification.local.clear(1, app.ids); cordova.plugins.notification.local.clear(1, app.ids);
......
...@@ -398,6 +398,21 @@ exports.getAllTriggered = function (callback, scope) { ...@@ -398,6 +398,21 @@ exports.getAllTriggered = function (callback, scope) {
}; };
/** /**
* Register an group of actions by id.
*
* @param [ String ] id The Id of the group.
* @param [ Array] actions The action config settings.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.addActionGroup = function (id, actions, callback, scope) {
var config = { actionGroupId: id, actions: actions };
this.exec('registerCategory', config, callback, scope);
};
/**
* The (platform specific) default settings. * The (platform specific) default settings.
* *
* @return [ Object ] * @return [ Object ]
......
...@@ -21,14 +21,16 @@ var exec = require('cordova/exec'), ...@@ -21,14 +21,16 @@ var exec = require('cordova/exec'),
// Default values // Default values
exports._defaults = { exports._defaults = {
text: '', id: 0,
title: '', text: '',
sound: 'res://platform_default', title: '',
badge: 0, sound: 'res://platform_default',
id: 0, badge: undefined,
data: undefined, data: undefined,
every: undefined, every: undefined,
at: undefined at: undefined,
actions: undefined,
actionGroupId: undefined
}; };
// Listener // Listener
...@@ -150,10 +152,53 @@ exports.convertProperties = function (options) { ...@@ -150,10 +152,53 @@ exports.convertProperties = function (options) {
options.data = JSON.stringify(options.data); options.data = JSON.stringify(options.data);
} }
if (options.actions) {
this.convertActions(options);
}
return options; return options;
}; };
/** /**
* Convert the passed values to their required type, modifying them
* directly for Android and passing the converted list back for iOS.
*
* @param [ Map ] options Set of custom values.
*
* @return [ Map ] Interaction object with category & actions.
*/
exports.convertActions = function (options) {
if (!options.actions)
return null;
var MAX_ACTIONS = (device.platform === 'iOS') ? 4 : 3,
actions = [];
if (options.actions.length > MAX_ACTIONS)
console.warn('Count of actions exceeded count of ' + MAX_ACTIONS);
for (var i = 0; i < options.actions.length && MAX_ACTIONS > 0; i++) {
var action = options.actions[i];
if (!action.id) {
console.warn(
'Action with title ' + action.title + ' has no id and will not be added.');
continue;
}
action.id = action.id.toString();
action.title = (action.title || action.id).toString();
actions.push(action);
MAX_ACTIONS--;
}
options.category = (options.category || 'DEFAULT_GROUP').toString();
options.actions = actions;
};
/**
* Create a callback function to get executed within a specific scope. * Create a callback function to get executed within a specific scope.
* *
* @param [ Function ] fn The function to be exec as the callback. * @param [ Function ] fn The function to be exec as the callback.
......
...@@ -278,6 +278,20 @@ exports.getAllTriggered = function (callback, scope) { ...@@ -278,6 +278,20 @@ exports.getAllTriggered = function (callback, scope) {
}; };
/** /**
* Register an group of actions by id.
*
* @param [ String ] id The Id of the group.
* @param [ Array] actions The action config settings.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.addActionGroup = function (id, actions, callback, scope) {
this.core.registerActionGroup(id, actions, callback, scope);
};
/**
* The (platform specific) default settings. * The (platform specific) default settings.
* *
* @return [ Object ] * @return [ Object ]
......
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
// Request permission to show notifications // Request permission to show notifications
- (void) request:(CDVInvokedUrlCommand*)command; - (void) request:(CDVInvokedUrlCommand*)command;
// Register/update an action group
- (void) registerCategory:(CDVInvokedUrlCommand*)command;
// Schedule notifications // Schedule notifications
- (void) schedule:(CDVInvokedUrlCommand*)command; - (void) schedule:(CDVInvokedUrlCommand*)command;
//// Update set of notifications //// Update set of notifications
......
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
// NSNumber* id = [options objectForKey:@"id"]; // NSNumber* id = [options objectForKey:@"id"];
// UNNotificationRequest* notification; // UNNotificationRequest* notification;
// //
// notification = [self.center getNotificationWithId:id]; // notification = [_center getNotificationWithId:id];
// //
// if (!notification) // if (!notification)
// continue; // continue;
...@@ -119,7 +119,7 @@ ...@@ -119,7 +119,7 @@
// NSNumber* id = [options objectForKey:@"id"]; // NSNumber* id = [options objectForKey:@"id"];
// UILocalNotification* notification; // UILocalNotification* notification;
// //
// notification = [self.app localNotificationWithId:id]; // notification = [_app localNotificationWithId:id];
// //
// if (!notification) // if (!notification)
// continue; // continue;
...@@ -151,16 +151,16 @@ ...@@ -151,16 +151,16 @@
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
for (NSNumber* id in command.arguments) { for (NSNumber* id in command.arguments) {
UNNotificationRequest* notification; UNNotificationRequest* notification;
notification = [self.center getNotificationWithId:id]; notification = [_center getNotificationWithId:id];
if (!notification) if (!notification)
continue; continue;
[self.center clearNotification:notification]; [_center clearNotification:notification];
[self fireEvent:@"clear" notification:notification]; [self fireEvent:@"clear" notification:notification];
} }
[self execCallback:command]; [self execCallback:command];
}]; }];
} }
...@@ -173,8 +173,8 @@ ...@@ -173,8 +173,8 @@
- (void) clearAll:(CDVInvokedUrlCommand*)command - (void) clearAll:(CDVInvokedUrlCommand*)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
[self.center clearAllNotifications]; [_center clearAllNotifications];
[self.app setApplicationIconBadgeNumber:0]; [_app setApplicationIconBadgeNumber:0];
[self fireEvent:@"clearall"]; [self fireEvent:@"clearall"];
[self execCallback:command]; [self execCallback:command];
}]; }];
...@@ -192,13 +192,13 @@ ...@@ -192,13 +192,13 @@
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
for (NSNumber* id in command.arguments) { for (NSNumber* id in command.arguments) {
UNNotificationRequest* notification; UNNotificationRequest* notification;
notification = [self.center getNotificationWithId:id]; notification = [_center getNotificationWithId:id];
if (!notification) if (!notification)
continue; continue;
[self.center cancelNotification:notification]; [_center cancelNotification:notification];
[self fireEvent:@"cancel" notification:notification]; [self fireEvent:@"cancel" notification:notification];
} }
...@@ -214,8 +214,8 @@ ...@@ -214,8 +214,8 @@
- (void) cancelAll:(CDVInvokedUrlCommand*)command - (void) cancelAll:(CDVInvokedUrlCommand*)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
[self.center cancelAllNotifications]; [_center cancelAllNotifications];
[self.app setApplicationIconBadgeNumber:0]; [_app setApplicationIconBadgeNumber:0];
[self fireEvent:@"cancelall"]; [self fireEvent:@"cancelall"];
[self execCallback:command]; [self execCallback:command];
}]; }];
...@@ -321,12 +321,12 @@ ...@@ -321,12 +321,12 @@
byType:(APPNotificationType)type; byType:(APPNotificationType)type;
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
NSArray* ids = [self.center getNotificationIdsByType:type]; NSArray* ids = [_center getNotificationIdsByType:type];
CDVPluginResult* result; CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:ids]; messageAsArray:ids];
[self.commandDelegate sendPluginResult:result [self.commandDelegate sendPluginResult:result
callbackId:command.callbackId]; callbackId:command.callbackId];
}]; }];
...@@ -383,11 +383,11 @@ ...@@ -383,11 +383,11 @@
NSArray* notifications; NSArray* notifications;
notifications = [_center getNotificationOptionsByType:type andId:ids]; notifications = [_center getNotificationOptionsByType:type andId:ids];
CDVPluginResult* result; CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:[notifications firstObject]]; messageAsDictionary:[notifications firstObject]];
[self.commandDelegate sendPluginResult:result [self.commandDelegate sendPluginResult:result
callbackId:command.callbackId]; callbackId:command.callbackId];
}]; }];
...@@ -497,11 +497,30 @@ ...@@ -497,11 +497,30 @@
UNAuthorizationOptions options = UNAuthorizationOptions options =
(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert); (UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert);
[self.center requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError* e) { [_center requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError* e) {
[self check:command]; [self check:command];
}]; }];
} }
/**
* Register/update an action group.
*
* @return [ Void ]
*/
- (void) registerCategory:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
NSDictionary* options = command.arguments[0];
APPNotificationContent* notification;
notification = [[APPNotificationContent alloc]
initWithOptions:options];
[_center addNotificationCategory:notification.category];
[self execCallback:command];
}];
}
#pragma mark - #pragma mark -
#pragma mark Private #pragma mark Private
...@@ -513,6 +532,8 @@ ...@@ -513,6 +532,8 @@
__weak APPLocalNotification* weakSelf = self; __weak APPLocalNotification* weakSelf = self;
UNNotificationRequest* request = notification.request; UNNotificationRequest* request = notification.request;
[_center addNotificationCategory:notification.category];
[_center addNotificationRequest:request withCompletionHandler:^(NSError* e) { [_center addNotificationRequest:request withCompletionHandler:^(NSError* e) {
__strong APPLocalNotification* strongSelf = weakSelf; __strong APPLocalNotification* strongSelf = weakSelf;
[strongSelf fireEvent:@"add" notification:request]; [strongSelf fireEvent:@"add" notification:request];
......
...@@ -30,5 +30,6 @@ ...@@ -30,5 +30,6 @@
- (id) initWithOptions:(NSDictionary*)dict; - (id) initWithOptions:(NSDictionary*)dict;
- (APPNotificationOptions*) options; - (APPNotificationOptions*) options;
- (UNNotificationRequest*) request; - (UNNotificationRequest*) request;
- (UNNotificationCategory*) category;
@end @end
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#import "APPNotificationContent.h" #import "APPNotificationContent.h"
#import "APPNotificationOptions.h" #import "APPNotificationOptions.h"
#import "UNUserNotificationCenter+APPLocalNotification.h"
#import <objc/runtime.h> #import <objc/runtime.h>
@import UserNotifications; @import UserNotifications;
...@@ -67,7 +66,7 @@ static char optionsKey; ...@@ -67,7 +66,7 @@ static char optionsKey;
self.sound = options.sound; self.sound = options.sound;
self.badge = options.badge; self.badge = options.badge;
self.attachments = options.attachments; self.attachments = options.attachments;
self.categoryIdentifier = kAPPGeneralCategory; self.categoryIdentifier = options.categoryId;
} }
#pragma mark - #pragma mark -
...@@ -107,6 +106,25 @@ static char optionsKey; ...@@ -107,6 +106,25 @@ static char optionsKey;
trigger:opts.trigger]; trigger:opts.trigger];
} }
/**
* The category for the notification with all the actions.
*
* @return [ UNNotificationCategory* ]
*/
- (UNNotificationCategory*) category
{
NSString* categoryId = self.categoryIdentifier;
NSArray* actions = self.options.actions;
if (!actions.count)
return NULL;
return [UNNotificationCategory categoryWithIdentifier:categoryId
actions:actions
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
}
#pragma mark - #pragma mark -
#pragma mark Private #pragma mark Private
......
...@@ -27,13 +27,15 @@ ...@@ -27,13 +27,15 @@
@property (readonly, getter=id) NSNumber* id; @property (readonly, getter=id) NSNumber* id;
@property (readonly, getter=identifier) NSString* identifier; @property (readonly, getter=identifier) NSString* identifier;
@property (readonly, getter=categoryId) NSString* categoryId;
@property (readonly, getter=title) NSString* title; @property (readonly, getter=title) NSString* title;
@property (readonly, getter=subtitle) NSString* subtitle; @property (readonly, getter=subtitle) NSString* subtitle;
@property (readonly, getter=badge) NSNumber* badge; @property (readonly, getter=badge) NSNumber* badge;
@property (readonly, getter=text) NSString* text; @property (readonly, getter=text) NSString* text;
@property (readonly, getter=sound) UNNotificationSound* sound; @property (readonly, getter=sound) UNNotificationSound* sound;
@property (readonly, getter=attachments) NSArray<UNNotificationAttachment *> * attachments;
@property (readonly, getter=userInfo) NSDictionary* userInfo; @property (readonly, getter=userInfo) NSDictionary* userInfo;
@property (readonly, getter=actions) NSArray<UNNotificationAction *> * actions;
@property (readonly, getter=attachments) NSArray<UNNotificationAttachment *> * attachments;
- (id) initWithDict:(NSDictionary*)dict; - (id) initWithDict:(NSDictionary*)dict;
- (UNNotificationTrigger*) trigger; - (UNNotificationTrigger*) trigger;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
*/ */
#import "APPNotificationOptions.h" #import "APPNotificationOptions.h"
#import "UNUserNotificationCenter+APPLocalNotification.h"
@import UserNotifications; @import UserNotifications;
...@@ -51,6 +52,8 @@ ...@@ -51,6 +52,8 @@
self = [self init]; self = [self init];
self.dict = dictionary; self.dict = dictionary;
[self actions];
return self; return self;
} }
...@@ -119,7 +122,21 @@ ...@@ -119,7 +122,21 @@
*/ */
- (NSNumber*) badge - (NSNumber*) badge
{ {
return [NSNumber numberWithInt:[[dict objectForKey:@"badge"] intValue]]; id value = [dict objectForKey:@"badge"];
return (value == NULL) ? NULL : [NSNumber numberWithInt:[value intValue]];
}
/**
* The category of the notification.
*
* @return [ NSString* ]
*/
- (NSString*) categoryId
{
NSString* value = [dict objectForKey:@"actionGroupId"];
return value.length ? value : kAPPGeneralCategory;
} }
/** /**
...@@ -148,19 +165,12 @@ ...@@ -148,19 +165,12 @@
return [UNNotificationSound soundNamed:file]; return [UNNotificationSound soundNamed:file];
} }
/** /**
* The date when to fire the notification. * Additional content to attach.
* *
* @return [ NSDate* ] * @return [ UNNotificationSound* ]
*/ */
- (NSDate*) fireDate
{
double timestamp = [[dict objectForKey:@"at"]
doubleValue];
return [NSDate dateWithTimeIntervalSince1970:timestamp];
}
- (NSArray<UNNotificationAttachment *> *) attachments - (NSArray<UNNotificationAttachment *> *) attachments
{ {
NSArray* paths = [dict objectForKey:@"attachments"]; NSArray* paths = [dict objectForKey:@"attachments"];
...@@ -186,6 +196,47 @@ ...@@ -186,6 +196,47 @@
return attachments; return attachments;
} }
/**
* Additional actions for the notification.
*
* @return [ NSArray* ]
*/
- (NSArray<UNNotificationAction *> *) actions
{
NSArray* items = [dict objectForKey:@"actions"];
NSMutableArray* actions = [[NSMutableArray alloc] init];
if (!items)
return actions;
for (NSDictionary* item in items) {
NSString* id = [item objectForKey:@"id"];
NSString* title = [item objectForKey:@"title"];
UNNotificationActionOptions options = UNNotificationActionOptionNone;
if ([[item objectForKey:@"launch"] boolValue]) {
options = UNNotificationActionOptionForeground;
}
if ([[item objectForKey:@"ui"] isEqualToString:@"decline"]) {
options = options | UNNotificationActionOptionDestructive;
}
if ([[item objectForKey:@"needsAuth"] boolValue]) {
options = options | UNNotificationActionOptionAuthenticationRequired;
}
UNNotificationAction* action;
action = [UNNotificationAction actionWithIdentifier:id
title:title
options:options];
[actions addObject:action];
}
return actions;
}
#pragma mark - #pragma mark -
#pragma mark Public #pragma mark Public
...@@ -224,6 +275,19 @@ ...@@ -224,6 +275,19 @@
#pragma mark Private #pragma mark Private
/** /**
* The date when to fire the notification.
*
* @return [ NSDate* ]
*/
- (NSDate*) triggerDate
{
double timestamp = [[dict objectForKey:@"at"]
doubleValue];
return [NSDate dateWithTimeIntervalSince1970:timestamp];
}
/**
* If the notification shall be repeating. * If the notification shall be repeating.
* *
* @return [ BOOL ] * @return [ BOOL ]
...@@ -299,7 +363,7 @@ ...@@ -299,7 +363,7 @@
initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *date = [cal components:[self repeatInterval] NSDateComponents *date = [cal components:[self repeatInterval]
fromDate:[self fireDate]]; fromDate:[self triggerDate]];
date.timeZone = [NSTimeZone defaultTimeZone]; date.timeZone = [NSTimeZone defaultTimeZone];
...@@ -333,7 +397,7 @@ ...@@ -333,7 +397,7 @@
*/ */
- (double) timeInterval - (double) timeInterval
{ {
return MAX(0.01f, [self.fireDate timeIntervalSinceDate:[NSDate date]]); return MAX(0.01f, [self.triggerDate timeIntervalSinceDate:[NSDate date]]);
} }
/** /**
...@@ -464,10 +528,6 @@ ...@@ -464,10 +528,6 @@
{ {
return [self urlForAsset:path]; return [self urlForAsset:path];
} }
else if ([path hasPrefix:@"app://"])
{
return [self urlForAppInternalPath:path];
}
else if ([path hasPrefix:@"base64:"]) else if ([path hasPrefix:@"base64:"])
{ {
return [self urlFromBase64:path]; return [self urlFromBase64:path];
...@@ -515,7 +575,7 @@ ...@@ -515,7 +575,7 @@
{ {
NSFileManager* fm = [NSFileManager defaultManager]; NSFileManager* fm = [NSFileManager defaultManager];
NSBundle* mainBundle = [NSBundle mainBundle]; NSBundle* mainBundle = [NSBundle mainBundle];
NSString* bundlePath = [mainBundle bundlePath]; NSString* bundlePath = [mainBundle resourcePath];
if ([path isEqualToString:@"res://icon"]) { if ([path isEqualToString:@"res://icon"]) {
path = @"res://AppIcon60x60@3x.png"; path = @"res://AppIcon60x60@3x.png";
...@@ -561,26 +621,6 @@ ...@@ -561,26 +621,6 @@
} }
/** /**
* URL for an internal app path.
*
* @param [ NSString* ] path A relative file path from main bundle dir.
*
* @return [ NSURL* ]
*/
- (NSURL*) urlForAppInternalPath:(NSString*)path
{
NSFileManager* fm = [NSFileManager defaultManager];
NSBundle* mainBundle = [NSBundle mainBundle];
NSString* absPath = [mainBundle bundlePath];
if (![fm fileExistsAtPath:absPath]) {
NSLog(@"File not found: %@", absPath);
}
return [NSURL fileURLWithPath:absPath];
}
/**
* URL for a base64 encoded string. * URL for a base64 encoded string.
* *
* @param [ NSString* ] base64String Base64 encoded string. * @param [ NSString* ] base64String Base64 encoded string.
......
...@@ -38,7 +38,10 @@ typedef NS_ENUM(NSUInteger, APPNotificationType) { ...@@ -38,7 +38,10 @@ typedef NS_ENUM(NSUInteger, APPNotificationType) {
@property (readonly, getter=getNotifications) NSArray* localNotifications; @property (readonly, getter=getNotifications) NSArray* localNotifications;
@property (readonly, getter=getNotificationIds) NSArray* localNotificationIds; @property (readonly, getter=getNotificationIds) NSArray* localNotificationIds;
// Register general notification category to listen for dismiss actions
- (void) registerGeneralNotificationCategory; - (void) registerGeneralNotificationCategory;
// Add the specified category to the list of categories
- (void) addNotificationCategory:(UNNotificationCategory*)category;
// List of all notification IDs from given type // List of all notification IDs from given type
- (NSArray*) getNotificationIdsByType:(APPNotificationType)type; - (NSArray*) getNotificationIdsByType:(APPNotificationType)type;
......
...@@ -48,7 +48,34 @@ NSString * const kAPPGeneralCategory = @"GENERAL"; ...@@ -48,7 +48,34 @@ NSString * const kAPPGeneralCategory = @"GENERAL";
intentIdentifiers:@[] intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction]; options:UNNotificationCategoryOptionCustomDismissAction];
[self setNotificationCategories:[NSSet setWithObjects:category, nil]]; [self setNotificationCategories:[NSSet setWithObject:category]];
}
/**
* Add the specified category to the list of categories.
*
* @param [ UNNotificationCategory* ] category The category to add.
*
* @return [ Void ]
*/
- (void) addNotificationCategory:(UNNotificationCategory*)category
{
if (!category)
return;
[self getNotificationCategoriesWithCompletionHandler:^(NSSet<UNNotificationCategory *> *set) {
NSMutableSet* categories = [NSMutableSet setWithSet:set];
for (UNNotificationCategory* item in categories) {
if ([category.identifier isEqualToString:item.identifier]) {
[categories removeObject:item];
break;
}
}
[categories addObject:category];
[self setNotificationCategories:categories];
}];
} }
#pragma mark - #pragma mark -
......
...@@ -397,6 +397,21 @@ exports.getAllTriggered = function (callback, scope) { ...@@ -397,6 +397,21 @@ exports.getAllTriggered = function (callback, scope) {
}; };
/** /**
* Register an group of actions by id.
*
* @param [ String ] id The Id of the group.
* @param [ Array] actions The action config settings.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.addActionGroup = function (id, actions, callback, scope) {
var config = { actionGroupId: id, actions: actions };
this.exec('registerCategory', config, callback, scope);
};
/**
* The (platform specific) default settings. * The (platform specific) default settings.
* *
* @return [ Object ] * @return [ Object ]
......
...@@ -20,14 +20,16 @@ var exec = require('cordova/exec'), ...@@ -20,14 +20,16 @@ var exec = require('cordova/exec'),
// Default values // Default values
exports._defaults = { exports._defaults = {
text: '', id: 0,
title: '', text: '',
sound: 'res://platform_default', title: '',
badge: 0, sound: 'res://platform_default',
id: 0, badge: undefined,
data: undefined, data: undefined,
every: undefined, every: undefined,
at: undefined at: undefined,
actions: undefined,
actionGroupId: undefined
}; };
// Listener // Listener
...@@ -149,10 +151,53 @@ exports.convertProperties = function (options) { ...@@ -149,10 +151,53 @@ exports.convertProperties = function (options) {
options.data = JSON.stringify(options.data); options.data = JSON.stringify(options.data);
} }
if (options.actions) {
this.convertActions(options);
}
return options; return options;
}; };
/** /**
* Convert the passed values to their required type, modifying them
* directly for Android and passing the converted list back for iOS.
*
* @param [ Map ] options Set of custom values.
*
* @return [ Map ] Interaction object with category & actions.
*/
exports.convertActions = function (options) {
if (!options.actions)
return null;
var MAX_ACTIONS = (device.platform === 'iOS') ? 4 : 3,
actions = [];
if (options.actions.length > MAX_ACTIONS)
console.warn('Count of actions exceeded count of ' + MAX_ACTIONS);
for (var i = 0; i < options.actions.length && MAX_ACTIONS > 0; i++) {
var action = options.actions[i];
if (!action.id) {
console.warn(
'Action with title ' + action.title + ' has no id and will not be added.');
continue;
}
action.id = action.id.toString();
action.title = (action.title || action.id).toString();
actions.push(action);
MAX_ACTIONS--;
}
options.category = (options.category || 'DEFAULT_GROUP').toString();
options.actions = actions;
};
/**
* Create a callback function to get executed within a specific scope. * Create a callback function to get executed within a specific scope.
* *
* @param [ Function ] fn The function to be exec as the callback. * @param [ Function ] fn The function to be exec as the callback.
......
...@@ -277,6 +277,20 @@ exports.getAllTriggered = function (callback, scope) { ...@@ -277,6 +277,20 @@ exports.getAllTriggered = function (callback, scope) {
}; };
/** /**
* Register an group of actions by id.
*
* @param [ String ] id The Id of the group.
* @param [ Array] actions The action config settings.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.addActionGroup = function (id, actions, callback, scope) {
this.core.registerActionGroup(id, actions, callback, scope);
};
/**
* The (platform specific) default settings. * The (platform specific) default settings.
* *
* @return [ Object ] * @return [ Object ]
......
...@@ -50,6 +50,9 @@ ...@@ -50,6 +50,9 @@
<a id="sched_delayed" class="button orange">Delayed</a> <a id="sched_delayed" class="button orange">Delayed</a>
<a id="sched_interval" class="button orange">Interval</a> <a id="sched_interval" class="button orange">Interval</a>
</div> </div>
<div class="container">
<a id="sched_actions" class="button orange">Actions</a>
</div>
<h2 class="section">Update</h2> <h2 class="section">Update</h2>
<div class="container"> <div class="container">
<a id="update_text" class="button orange">Text</a> <a id="update_text" class="button orange">Text</a>
......
...@@ -57,6 +57,7 @@ var app = { ...@@ -57,6 +57,7 @@ var app = {
document.getElementById('sched_multi').onclick = app.scheduleMultiple; document.getElementById('sched_multi').onclick = app.scheduleMultiple;
document.getElementById('sched_delayed').onclick = app.scheduleDelayed; document.getElementById('sched_delayed').onclick = app.scheduleDelayed;
document.getElementById('sched_interval').onclick = app.scheduleInterval; document.getElementById('sched_interval').onclick = app.scheduleInterval;
document.getElementById('sched_actions').onclick = app.scheduleActions;
document.getElementById('clear_single').onclick = app.clearSingle; document.getElementById('clear_single').onclick = app.clearSingle;
document.getElementById('clear_multi').onclick = app.clearMulti; document.getElementById('clear_multi').onclick = app.clearMulti;
document.getElementById('clear_all').onclick = app.clearAll; document.getElementById('clear_all').onclick = app.clearAll;
...@@ -95,7 +96,6 @@ var app = { ...@@ -95,7 +96,6 @@ var app = {
text: 'Test Message 1', text: 'Test Message 1',
icon: 'http://3.bp.blogspot.com/-Qdsy-GpempY/UU_BN9LTqSI/AAAAAAAAAMA/LkwLW2yNBJ4/s1600/supersu.png', icon: 'http://3.bp.blogspot.com/-Qdsy-GpempY/UU_BN9LTqSI/AAAAAAAAAMA/LkwLW2yNBJ4/s1600/supersu.png',
smallIcon: 'res://cordova', smallIcon: 'res://cordova',
attachments: ['file://img/logo.png'],
sound: null, sound: null,
badge: 1, badge: 1,
data: { test: 1 } data: { test: 1 }
...@@ -148,6 +148,24 @@ var app = { ...@@ -148,6 +148,24 @@ var app = {
smallIcon: 'res://ic_popup_sync' smallIcon: 'res://ic_popup_sync'
}); });
}, },
// Schedule with actions
scheduleActions: function () {
cordova.plugins.notification.local.schedule({
title: 'Local Notification Plugin',
text: 'Made by appPlant from Leipzig/Germany',
attachments: ['file://img/logo.png'],
actionGroupId: 'like-dislike',
actions: [{
id: 'like',
title: 'Like',
launch: true
},{
id: 'dislike',
title: 'Dislike',
ui: 'decline'
}]
});
},
// Clear a single notification // Clear a single notification
clearSingle: function () { clearSingle: function () {
cordova.plugins.notification.local.clear(1, app.ids); cordova.plugins.notification.local.clear(1, app.ids);
......
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