Procházet zdrojové kódy

Update local notifications on iOS

Sebastián Katzer před 11 roky
rodič
revize
9258d9095f

+ 2 - 0
src/ios/APPLocalNotification.h

@@ -28,6 +28,8 @@
 - (void) deviceready:(CDVInvokedUrlCommand*)command;
 // Schedule a new notification
 - (void) add:(CDVInvokedUrlCommand*)command;
+// Update a notification
+- (void) update:(CDVInvokedUrlCommand*)command;
 // Cancel a given notification
 - (void) cancel:(CDVInvokedUrlCommand*)command;
 // Cancel all currently scheduled notifications

+ 58 - 7
src/ios/APPLocalNotification.m

@@ -72,7 +72,7 @@
     NSArray* notifications = command.arguments;
 
     [self.commandDelegate runInBackground:^{
-        for (NSMutableDictionary* options in notifications) {
+        for (NSDictionary* options in notifications) {
             UILocalNotification* notification;
 
             notification = [[UILocalNotification alloc]
@@ -90,6 +90,39 @@
     }];
 }
 
+/**
+ * Update a set of notifications.
+ *
+ * @param properties
+ *      A dict of properties for each notification
+ */
+- (void) update:(CDVInvokedUrlCommand*)command
+{
+    NSArray* notifications = command.arguments;
+
+    [self.commandDelegate runInBackground:^{
+        for (NSDictionary* options in notifications) {
+            NSString* id = [options objectForKey:@"id"];
+            UILocalNotification* notification;
+
+            notification = [[UIApplication sharedApplication]
+                            scheduledLocalNotificationWithId:id];
+
+            if (!notification)
+                continue;
+
+            [self updateLocalNotification:[notification copy]
+                              withOptions:options];
+
+            if (notifications.count > 1) {
+                [NSThread sleepForTimeInterval:0.01];
+            }
+        }
+
+        [self execCallback:command];
+    }];
+}
+
 /**
  * Cancel a set of notifications.
  *
@@ -335,14 +368,29 @@
      scheduleLocalNotification:notification];
 }
 
+/**
+ * Update the local notification.
+ */
+- (void) updateLocalNotification:(UILocalNotification*)notification
+                     withOptions:(NSDictionary*)newOptions
+{
+    NSMutableDictionary* options = [notification.userInfo mutableCopy];
+
+    [options addEntriesFromDictionary:newOptions];
+    [options setObject:[NSDate date] forKey:@"updatedAt"];
+
+    notification = [[UILocalNotification alloc]
+                    initWithOptions:options];
+
+    [self scheduleLocalNotification:notification];
+
+}
+
 /**
  * Cancel the local notification.
  */
 - (void) cancelLocalNotification:(UILocalNotification*)notification
 {
-    if (!notification)
-        return;
-
     [[UIApplication sharedApplication]
      cancelLocalNotification:notification];
 
@@ -392,7 +440,7 @@
 
     for (UILocalNotification* notification in notifications)
     {
-        if (notification && notification.repeatInterval == NSCalendarUnitEra
+        if (notification && [notification isRepeating]
             && notification.timeIntervalSinceFireDate > seconds)
         {
             [self cancelLocalNotification:notification];
@@ -412,8 +460,11 @@
 {
     UILocalNotification* notification = [localNotification object];
 
+    if ([notification wasUpdated])
+        return;
+
     BOOL autoCancel = notification.options.autoCancel;
-    NSTimeInterval timeInterval = notification.timeIntervalSinceFireDate;
+    NSTimeInterval timeInterval = [notification timeIntervalSinceFireDate];
 
     NSString* event = (timeInterval <= 1 && deviceready) ? @"trigger" : @"click";
 
@@ -551,7 +602,7 @@
     if (notification) {
         NSString* id = notification.options.id;
         NSString* json = notification.options.json;
-        NSString* args = [notification.options encodeToJSON];
+        NSString* args = [notification encodeToJSON];
 
         params = [NSString stringWithFormat:
                   @"\"%@\",\"%@\",\\'%@\\',JSON.parse(\\'%@\\')",

+ 0 - 2
src/ios/APPLocalNotificationOptions.h

@@ -33,8 +33,6 @@
 @property (readonly, getter=repeatInterval) NSCalendarUnit repeatInterval;
 @property (readonly, getter=userInfo) NSDictionary* userInfo;
 
-// Encode the user info dict to JSON
-- (NSString*) encodeToJSON;
 // If it's a repeating notification
 - (BOOL) isRepeating;
 

+ 0 - 22
src/ios/APPLocalNotificationOptions.m

@@ -212,28 +212,6 @@
     return dict;
 }
 
-/**
- * Encode the user info dict to JSON.
- */
-- (NSString*) encodeToJSON
-{
-    NSString* json;
-    NSData* data;
-    NSMutableDictionary* obj = [dict mutableCopy];
-
-    [obj removeObjectForKey:@"json"];
-
-    data = [NSJSONSerialization dataWithJSONObject:obj
-                                           options:NSJSONWritingPrettyPrinted
-                                             error:Nil];
-
-    json = [[NSString alloc] initWithData:data
-                                 encoding:NSUTF8StringEncoding];
-
-    return [json stringByReplacingOccurrencesOfString:@"\n"
-                                           withString:@""];
-}
-
 /**
  * If it's a repeating notification.
  */

+ 4 - 0
src/ios/UILocalNotification+APPLocalNotification.h

@@ -33,7 +33,11 @@
 - (BOOL) wasInThePast;
 // If the notification was already triggered
 - (BOOL) wasTriggered;
+// If the notification was updated
+- (BOOL) wasUpdated;
 // If it's a repeating notification
 - (BOOL) isRepeating;
+// Encode the user info dict to JSON
+- (NSString*) encodeToJSON;
 
 @end

+ 45 - 2
src/ios/UILocalNotification+APPLocalNotification.m

@@ -28,7 +28,7 @@ static char optionsKey;
 @implementation UILocalNotification (APPLocalNotification)
 
 #pragma mark -
-#pragma mark Init methods
+#pragma mark Init
 
 /**
  * Initialize a local notification with the given options when calling on JS side:
@@ -59,6 +59,10 @@ static char optionsKey;
     self.repeatInterval = options.repeatInterval;
     self.alertBody = options.alertBody;
     self.soundName = options.soundName;
+
+    if ([self wasInThePast]) {
+        self.fireDate = [NSDate date];
+    }
 }
 
 #pragma mark -
@@ -129,7 +133,7 @@ static char optionsKey;
     NSDate* now      = [NSDate date];
     NSDate* fireDate = self.options.fireDate;
 
-    int timespan     = [now timeIntervalSinceDate:fireDate];
+    int timespan = [now timeIntervalSinceDate:fireDate];
 
     if ([self isRepeating]) {
         timespan = timespan % [self repeatIntervalInSeconds];
@@ -159,6 +163,22 @@ static char optionsKey;
     return isLaterThanOrEqualTo;
 }
 
+/**
+ * If the notification was updated.
+ */
+- (BOOL) wasUpdated
+{
+    NSDate* now       = [NSDate date];
+    NSDate* updatedAt = [self.userInfo objectForKey:@"updatedAt"];
+
+    if (updatedAt == NULL)
+        return NO;
+
+    int timespan = [now timeIntervalSinceDate:updatedAt];
+
+    return timespan < 1;
+}
+
 /**
  * If it's a repeating notification.
  */
@@ -167,4 +187,27 @@ static char optionsKey;
     return [self.options isRepeating];
 }
 
+/**
+ * Encode the user info dict to JSON.
+ */
+- (NSString*) encodeToJSON
+{
+    NSString* json;
+    NSData* data;
+    NSMutableDictionary* obj = [self.userInfo mutableCopy];
+
+    [obj removeObjectForKey:@"json"];
+    [obj removeObjectForKey:@"updatedAt"];
+
+    data = [NSJSONSerialization dataWithJSONObject:obj
+                                           options:NSJSONWritingPrettyPrinted
+                                             error:Nil];
+
+    json = [[NSString alloc] initWithData:data
+                                 encoding:NSUTF8StringEncoding];
+
+    return [json stringByReplacingOccurrencesOfString:@"\n"
+                                           withString:@""];
+}
+
 @end

+ 14 - 6
www/local-notification.js

@@ -98,20 +98,20 @@ exports.setDefaults = function (newDefaults) {
 /**
  * Add a new entry to the registry
  *
- * @param {Object} props
+ * @param {Object} opts
  *      The notification properties
  * @param {Function} callback
  *      A function to be called after the notification has been canceled
  * @param {Object?} scope
  *      The scope for the callback function
  */
-exports.add = function (props, callback, scope) {
+exports.add = function (opts, callback, scope) {
     this.registerPermission(function(granted) {
 
         if (!granted)
             return;
 
-        var notifications = Array.isArray(props) ? props : [props];
+        var notifications = Array.isArray(opts) ? opts : [opts];
 
         for (var i = 0; i < notifications.length; i++) {
             var properties = notifications[i];
@@ -125,7 +125,7 @@ exports.add = function (props, callback, scope) {
 };
 
 /**
- * Update existing notification specified by ID in options.
+ * Update existing notifications specified by IDs in options.
  *
  * @param {Object} options
  *      The notification properties to update
@@ -134,8 +134,16 @@ exports.add = function (props, callback, scope) {
  * @param {Object?} scope
  *      The scope for the callback function
  */
-exports.update = function (options, callback, scope) {
-    this.exec('update', options, callback, scope);
+exports.update = function (opts, callback, scope) {
+    var notifications = Array.isArray(opts) ? opts : [opts];
+
+    for (var i = 0; i < notifications.length; i++) {
+        var properties = notifications[i];
+
+        this.convertProperties(properties);
+    }
+
+    this.exec('update', notifications, callback, scope);
 };
 
 /**