cordova-plugin-local-notifications-continued 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.github/FUNDING.yml +1 -0
  2. package/.github/ISSUE_TEMPLATE/report_issue.yml +126 -0
  3. package/CHANGELOG.md +358 -0
  4. package/LICENSE +202 -0
  5. package/README.md +1531 -0
  6. package/images/android-actions-with-input-clicked.png +0 -0
  7. package/images/android-actions-with-input-not-clicked.png +0 -0
  8. package/images/android-actions.png +0 -0
  9. package/images/android-alarms-and-reminders-in-app-settings.png +0 -0
  10. package/images/android-alarms-and-reminders-setting.png +0 -0
  11. package/images/android-app-hibernation-notification.png +0 -0
  12. package/images/android-app-hibernation-settings-android-12.png +0 -0
  13. package/images/android-app-hibernation-settings-android-13-14.png +0 -0
  14. package/images/android-app-hibernation-settings-android-15.png +0 -0
  15. package/images/android-attachments-image-folded.png +0 -0
  16. package/images/android-attachments-image-unfolded.png +0 -0
  17. package/images/android-chat.png +0 -0
  18. package/images/android-icon.svg +19 -0
  19. package/images/android-inbox.png +0 -0
  20. package/images/android-notification-example.png +0 -0
  21. package/images/android-progress.png +0 -0
  22. package/images/android-request-permission.png +0 -0
  23. package/images/android-stack.png +0 -0
  24. package/images/apple-icon.svg +1 -0
  25. package/images/cordova-app-notified-logo.png +0 -0
  26. package/images/ios-actions-with-input.png +0 -0
  27. package/images/ios-actions.png +0 -0
  28. package/images/ios-attachments-image-folded.png +0 -0
  29. package/images/ios-attachments-image-unfolded.png +0 -0
  30. package/images/ios-notification.png +0 -0
  31. package/images/ios-request-permission.png +0 -0
  32. package/images/logo.png +0 -0
  33. package/package.json +53 -0
  34. package/plugin.xml +266 -0
  35. package/src/android/ClickActivity.java +72 -0
  36. package/src/android/LocalNotification.java +779 -0
  37. package/src/android/Manager.java +327 -0
  38. package/src/android/Notification.java +844 -0
  39. package/src/android/Options.java +956 -0
  40. package/src/android/OptionsTrigger.java +104 -0
  41. package/src/android/action/Action.java +214 -0
  42. package/src/android/action/ActionGroup.java +135 -0
  43. package/src/android/build/localnotification.gradle +29 -0
  44. package/src/android/receiver/ClearReceiver.java +61 -0
  45. package/src/android/receiver/RestoreReceiver.java +70 -0
  46. package/src/android/receiver/TriggerReceiver.java +70 -0
  47. package/src/android/trigger/TriggerHandler.java +195 -0
  48. package/src/android/trigger/TriggerHandlerAt.java +63 -0
  49. package/src/android/trigger/TriggerHandlerEvery.java +257 -0
  50. package/src/android/trigger/TriggerHandlerIn.java +69 -0
  51. package/src/android/util/AssetUtil.java +385 -0
  52. package/src/android/util/CallbackContextUtil.java +88 -0
  53. package/src/android/util/PluginFileProvider.java +34 -0
  54. package/src/android/xml/shared_files_provider_paths.xml +38 -0
  55. package/src/ios/APPLocalNotification.h +56 -0
  56. package/src/ios/APPLocalNotification.m +650 -0
  57. package/src/ios/APPNotificationCategory.h +28 -0
  58. package/src/ios/APPNotificationCategory.m +107 -0
  59. package/src/ios/APPNotificationContent.h +32 -0
  60. package/src/ios/APPNotificationContent.m +122 -0
  61. package/src/ios/APPNotificationOptions.h +42 -0
  62. package/src/ios/APPNotificationOptions.m +689 -0
  63. package/src/ios/UNNotificationRequest+APPLocalNotification.h +32 -0
  64. package/src/ios/UNNotificationRequest+APPLocalNotification.m +100 -0
  65. package/src/ios/UNUserNotificationCenter+APPLocalNotification.h +60 -0
  66. package/src/ios/UNUserNotificationCenter+APPLocalNotification.m +344 -0
  67. package/www/local-notification.js +1104 -0
@@ -0,0 +1,689 @@
1
+ /*
2
+ * Apache 2.0 License
3
+ *
4
+ * Copyright (c) Sebastian Katzer 2017
5
+ *
6
+ * This file contains Original Code and/or Modifications of Original Code
7
+ * as defined in and that are subject to the Apache License
8
+ * Version 2.0 (the 'License'). You may not use this file except in
9
+ * compliance with the License. Please obtain a copy of the License at
10
+ * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11
+ * file.
12
+ *
13
+ * The Original Code and all software distributed under the License are
14
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18
+ * Please see the License for the specific language governing rights and
19
+ * limitations under the License.
20
+ */
21
+
22
+ #import "APPNotificationOptions.h"
23
+ #import "UNUserNotificationCenter+APPLocalNotification.h"
24
+
25
+ @import CoreLocation;
26
+ @import UserNotifications;
27
+
28
+ // Maps these crap where Sunday is the 1st day of the week
29
+ static NSInteger WEEKDAYS[8] = { 0, 2, 3, 4, 5, 6, 7, 1 };
30
+
31
+ @interface APPNotificationOptions ()
32
+
33
+ // The dictionary which contains all notification properties
34
+ @property(nonatomic, retain) NSDictionary* dict;
35
+
36
+ @end
37
+
38
+ @implementation APPNotificationOptions : NSObject
39
+
40
+ @synthesize dict;
41
+
42
+ #pragma mark -
43
+ #pragma mark Initialization
44
+
45
+ /**
46
+ * Initialize by using the given property values.
47
+ * @param dictionary A key-value property map.
48
+ * @return [ APPNotificationOptions ]
49
+ */
50
+ - (id) initWithDict:(NSDictionary*)dictionary
51
+ {
52
+ self = [self init];
53
+ self.dict = dictionary;
54
+ return self;
55
+ }
56
+
57
+ #pragma mark -
58
+ #pragma mark Properties
59
+
60
+ /**
61
+ * The ID for the notification.
62
+ *
63
+ * @return [ NSNumber* ]
64
+ */
65
+ - (NSNumber*) id
66
+ {
67
+ NSInteger id = [dict[@"id"] integerValue];
68
+
69
+ return [NSNumber numberWithInteger:id];
70
+ }
71
+
72
+ /**
73
+ * The ID for the notification.
74
+ *
75
+ * @return [ NSString* ]
76
+ */
77
+ - (NSString*) identifier
78
+ {
79
+ return [NSString stringWithFormat:@"%@", self.id];
80
+ }
81
+
82
+ /**
83
+ * The title for the notification.
84
+ *
85
+ * @return [ NSString* ]
86
+ */
87
+ - (NSString*) title
88
+ {
89
+ return dict[@"title"];
90
+ }
91
+
92
+ /**
93
+ * The subtitle for the notification.
94
+ *
95
+ * @return [ NSString* ]
96
+ */
97
+ - (NSString*) subtitle
98
+ {
99
+ NSArray *parts = [self.title componentsSeparatedByString:@"\n"];
100
+
101
+ return parts.count < 2 ? @"" : [parts objectAtIndex:1];
102
+ }
103
+
104
+ /**
105
+ * The text for the notification.
106
+ *
107
+ * @return [ NSString* ]
108
+ */
109
+ - (NSString*) text
110
+ {
111
+ return dict[@"text"];
112
+ }
113
+
114
+ /**
115
+ * Don't show a notification, make no sound, no vibration, when app is in foreground
116
+ *
117
+ * @return [ BOOL ]
118
+ */
119
+ - (BOOL) silent
120
+ {
121
+ return [dict[@"silent"] boolValue];
122
+ }
123
+
124
+ /**
125
+ * Show notification in foreground.
126
+ *
127
+ * @return [ BOOL ]
128
+ */
129
+ - (BOOL) iOSForeground
130
+ {
131
+ return [dict[@"iOSForeground"] boolValue];
132
+ }
133
+
134
+ /**
135
+ * The badge number for the notification.
136
+ * 0 removes the badge, -1 don't changes the badge
137
+ *
138
+ * @return [ int ]
139
+ */
140
+ - (int) badgeNumber
141
+ {
142
+ return [dict[@"badgeNumber"] intValue];
143
+ }
144
+
145
+ /**
146
+ * The category of the notification.
147
+ *
148
+ * @return [ NSString* ]
149
+ */
150
+ - (NSString*) actionGroupId
151
+ {
152
+ id actions = dict[@"actions"];
153
+
154
+ return ([actions isKindOfClass:NSString.class]) ? actions : kAPPGeneralCategory;
155
+ }
156
+
157
+ /**
158
+ * The sound file for the notification.
159
+ *
160
+ * @return [ UNNotificationSound* ]
161
+ */
162
+ - (UNNotificationSound*) sound
163
+ {
164
+ NSString* soundPath = dict[@"sound"];
165
+
166
+ if (soundPath == NULL || [soundPath length] == 0 ) return NULL;
167
+
168
+ if ([soundPath isEqualToString:@"default"]) {
169
+ return [UNNotificationSound defaultSound];
170
+ }
171
+
172
+ // Change file:// to www/ for assets
173
+ if ([soundPath hasPrefix:@"file://"]) {
174
+ soundPath = [self soundPathForAsset:soundPath];
175
+
176
+ // Gets the file name from the path
177
+ } else if ([soundPath hasPrefix:@"res:"]) {
178
+ soundPath = [self soundNameForResource:soundPath];
179
+ }
180
+
181
+ return [UNNotificationSound soundNamed:soundPath];
182
+ }
183
+
184
+
185
+ /**
186
+ * Additional content to attach.
187
+ *
188
+ * @return [ UNNotificationSound* ]
189
+ */
190
+ - (NSArray<UNNotificationAttachment *> *) attachments
191
+ {
192
+ NSArray* attachmentsPaths = dict[@"attachments"];
193
+ NSMutableArray* attachments = [[NSMutableArray alloc] init];
194
+
195
+ if (!attachmentsPaths) return attachments;
196
+
197
+ for (NSString* path in attachmentsPaths) {
198
+ UNNotificationAttachment* attachment = [UNNotificationAttachment attachmentWithIdentifier:path
199
+ URL:[self urlForAttachmentPath:path]
200
+ options:NULL
201
+ error:NULL];
202
+
203
+ if (attachment) {
204
+ [attachments addObject:attachment];
205
+ }
206
+ }
207
+
208
+ return attachments;
209
+ }
210
+
211
+ #pragma mark -
212
+ #pragma mark Public
213
+
214
+ /**
215
+ * Specify how and when to trigger the notification.
216
+ *
217
+ * @return [ UNNotificationTrigger* ]
218
+ */
219
+ - (UNNotificationTrigger*) trigger
220
+ {
221
+ NSString* type = [self valueForTriggerOption:@"type"];
222
+
223
+ if ([type isEqualToString:@"location"]) return [self triggerWithRegion];
224
+ if (![type isEqualToString:@"calendar"]) NSLog(@"Unknown type: %@", type);
225
+ if ([self isRepeating]) return [self repeatingTrigger];
226
+
227
+ return [self nonRepeatingTrigger];
228
+ }
229
+
230
+ /**
231
+ * The notification's user info dict.
232
+ *
233
+ * @return [ NSDictionary* ]
234
+ */
235
+ - (NSDictionary*) userInfo
236
+ {
237
+ if (dict[@"updatedAt"]) {
238
+ NSMutableDictionary* data = [dict mutableCopy];
239
+
240
+ [data removeObjectForKey:@"updatedAt"];
241
+
242
+ return data;
243
+ }
244
+
245
+ return dict;
246
+ }
247
+
248
+ #pragma mark -
249
+ #pragma mark Private
250
+
251
+ - (id) valueForTriggerOption:(NSString*)key
252
+ {
253
+ return dict[@"trigger"][key];
254
+ }
255
+
256
+ /**
257
+ * The date when to fire the notification.
258
+ *
259
+ * @return [ NSDate* ]
260
+ */
261
+ - (NSDate*) triggerDate
262
+ {
263
+ double timestamp = [[self valueForTriggerOption:@"at"] doubleValue];
264
+
265
+ return [NSDate dateWithTimeIntervalSince1970:(timestamp / 1000)];
266
+ }
267
+
268
+ /**
269
+ * If the notification shall be repeating.
270
+ *
271
+ * @return [ BOOL ]
272
+ */
273
+ - (BOOL) isRepeating
274
+ {
275
+ id every = [self valueForTriggerOption:@"every"];
276
+
277
+ if ([every isKindOfClass:NSString.class])
278
+ return ((NSString*) every).length > 0;
279
+
280
+ if ([every isKindOfClass:NSDictionary.class])
281
+ return ((NSDictionary*) every).count > 0;
282
+
283
+ return every > 0;
284
+ }
285
+
286
+ /**
287
+ * Non repeating trigger.
288
+ *
289
+ * @return [ UNTimeIntervalNotificationTrigger* ]
290
+ */
291
+ - (UNNotificationTrigger*) nonRepeatingTrigger
292
+ {
293
+ if ([self valueForTriggerOption:@"at"]) {
294
+ return [self triggerWithDateMatchingComponents:NO];
295
+ }
296
+
297
+ return [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:[self timeInterval] repeats:NO];
298
+ }
299
+
300
+ /**
301
+ * Repeating trigger.
302
+ *
303
+ * @return [ UNNotificationTrigger* ]
304
+ */
305
+ - (UNNotificationTrigger*) repeatingTrigger
306
+ {
307
+ id every = [self valueForTriggerOption:@"every"];
308
+
309
+ if ([every isKindOfClass:NSString.class])
310
+ return [self triggerWithDateMatchingComponents:YES];
311
+
312
+ if ([every isKindOfClass:NSDictionary.class])
313
+ return [self triggerWithCustomDateMatchingComponents];
314
+
315
+ return [self triggerWithTimeInterval];
316
+ }
317
+
318
+ /**
319
+ * A trigger based on a calendar time defined by the user.
320
+ *
321
+ * @return [ UNTimeIntervalNotificationTrigger* ]
322
+ */
323
+ - (UNTimeIntervalNotificationTrigger*) triggerWithTimeInterval
324
+ {
325
+ double seconds = [self convertTicksToSeconds:[[self valueForTriggerOption:@"every"] doubleValue]
326
+ unit:[self valueForTriggerOption:@"unit"]];
327
+
328
+ if (seconds < 60) {
329
+ NSLog(@"time interval must be at least 60 sec if repeating");
330
+ seconds = 60;
331
+ }
332
+
333
+ return [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:seconds
334
+ repeats:YES];
335
+ }
336
+
337
+ /**
338
+ * A repeating trigger based on a calendar time intervals defined by the plugin.
339
+ *
340
+ * @return [ UNCalendarNotificationTrigger* ]
341
+ */
342
+ - (UNCalendarNotificationTrigger*) triggerWithDateMatchingComponents:(BOOL)repeats
343
+ {
344
+ NSDateComponents *date = [[self calendarWithMondayAsFirstDay] components:[self repeatInterval]
345
+ fromDate:[self triggerDate]];
346
+
347
+ date.timeZone = [NSTimeZone defaultTimeZone];
348
+
349
+ return [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:date
350
+ repeats:repeats];
351
+ }
352
+
353
+ /**
354
+ * A repeating trigger based on a calendar time intervals defined by the user.
355
+ *
356
+ * @return [ UNCalendarNotificationTrigger* ]
357
+ */
358
+ - (UNCalendarNotificationTrigger*) triggerWithCustomDateMatchingComponents
359
+ {
360
+ NSDateComponents *date = [self customDateComponents];
361
+ date.calendar = [self calendarWithMondayAsFirstDay];
362
+ date.timeZone = [NSTimeZone defaultTimeZone];
363
+
364
+ return [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:date
365
+ repeats:YES];
366
+ }
367
+
368
+ /**
369
+ * A repeating trigger based on a location region.
370
+ *
371
+ * @return [ UNLocationNotificationTrigger* ]
372
+ */
373
+ - (UNLocationNotificationTrigger*) triggerWithRegion
374
+ {
375
+ NSArray* center = [self valueForTriggerOption:@"center"];
376
+ double radius = [[self valueForTriggerOption:@"radius"] doubleValue];
377
+ BOOL single = [[self valueForTriggerOption:@"single"] boolValue];
378
+
379
+ CLLocationCoordinate2D coord =
380
+ CLLocationCoordinate2DMake([center[0] doubleValue], [center[1] doubleValue]);
381
+
382
+ CLCircularRegion* region =
383
+ [[CLCircularRegion alloc] initWithCenter:coord
384
+ radius:radius
385
+ identifier:self.identifier];
386
+
387
+ region.notifyOnEntry = [[self valueForTriggerOption:@"notifyOnEntry"] boolValue];
388
+ region.notifyOnExit = [[self valueForTriggerOption:@"notifyOnExit"] boolValue];
389
+
390
+ return [UNLocationNotificationTrigger triggerWithRegion:region
391
+ repeats:!single];
392
+ }
393
+
394
+ /**
395
+ * The time interval between the next fire date and now.
396
+ *
397
+ * @return [ double ]
398
+ */
399
+ - (double) timeInterval
400
+ {
401
+ double ticks = [[self valueForTriggerOption:@"in"] doubleValue];
402
+ NSString* unit = [self valueForTriggerOption:@"unit"];
403
+ double seconds = [self convertTicksToSeconds:ticks unit:unit];
404
+
405
+ return MAX(0.01f, seconds);
406
+ }
407
+
408
+ /**
409
+ * The repeat interval for the notification.
410
+ *
411
+ * @return [ NSCalendarUnit ]
412
+ */
413
+ - (NSCalendarUnit) repeatInterval
414
+ {
415
+ NSString* interval = [self valueForTriggerOption:@"every"];
416
+ NSCalendarUnit units = NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
417
+
418
+ if ([interval isEqualToString:@"minute"])
419
+ return NSCalendarUnitSecond;
420
+
421
+ if ([interval isEqualToString:@"hour"])
422
+ return NSCalendarUnitMinute|NSCalendarUnitSecond;
423
+
424
+ if ([interval isEqualToString:@"day"])
425
+ return NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
426
+
427
+ if ([interval isEqualToString:@"week"])
428
+ return NSCalendarUnitWeekday|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
429
+
430
+ if ([interval isEqualToString:@"month"])
431
+ return NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
432
+
433
+ if ([interval isEqualToString:@"year"])
434
+ return NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
435
+
436
+ return units;
437
+ }
438
+
439
+ /**
440
+ * The repeat interval for the notification.
441
+ *
442
+ * @return [ NSDateComponents* ]
443
+ */
444
+ - (NSDateComponents*) customDateComponents
445
+ {
446
+ NSDateComponents* date = [[NSDateComponents alloc] init];
447
+ NSDictionary* every = [self valueForTriggerOption:@"every"];
448
+
449
+ date.second = 0;
450
+
451
+ for (NSString* key in every) {
452
+ long value = [[every valueForKey:key] longValue];
453
+
454
+ if ([key isEqualToString:@"minute"]) {
455
+ date.minute = value;
456
+ } else
457
+ if ([key isEqualToString:@"hour"]) {
458
+ date.hour = value;
459
+ } else
460
+ if ([key isEqualToString:@"day"]) {
461
+ date.day = value;
462
+ } else
463
+ if ([key isEqualToString:@"weekday"]) {
464
+ date.weekday = WEEKDAYS[value];
465
+ } else
466
+ if ([key isEqualToString:@"weekdayOrdinal"]) {
467
+ date.weekdayOrdinal = value;
468
+ } else
469
+ if ([key isEqualToString:@"week"]) {
470
+ date.weekOfYear = value;
471
+ } else
472
+ if ([key isEqualToString:@"weekOfMonth"]) {
473
+ date.weekOfMonth = value;
474
+ } else
475
+ if ([key isEqualToString:@"month"]) {
476
+ date.month = value;
477
+ } else
478
+ if ([key isEqualToString:@"quarter"]) {
479
+ date.quarter = value;
480
+ } else
481
+ if ([key isEqualToString:@"year"]) {
482
+ date.year = value;
483
+ }
484
+ }
485
+
486
+ return date;
487
+ }
488
+
489
+ /**
490
+ * Converts file:// to www/ for assets.
491
+ * @param path A relative assets file path.
492
+ * @return [ NSString* ]
493
+ */
494
+ - (NSString*) soundPathForAsset:(NSString*)path
495
+ {
496
+ return [path stringByReplacingOccurrencesOfString:@"file://" withString:@"www/"];
497
+ }
498
+
499
+ /**
500
+ * Convert a ressource path to an valid sound name attribute.
501
+ * @param path A relative ressource file path.
502
+ * @return [ NSString* ]
503
+ */
504
+ - (NSString*) soundNameForResource:(NSString*)path
505
+ {
506
+ return [path pathComponents].lastObject;
507
+ }
508
+
509
+ /**
510
+ * URL for the specified attachment path.
511
+ * @param path Absolute/relative path or a base64 data.
512
+ * @return [ NSURL* ]
513
+ */
514
+ - (NSURL*) urlForAttachmentPath:(NSString*)path
515
+ {
516
+ if ([path hasPrefix:@"file:///"]) return [self urlForFile:path];
517
+ if ([path hasPrefix:@"res:"]) return [self urlForResource:path];
518
+ if ([path hasPrefix:@"www"] || [path hasPrefix:@"file://"]) return [self urlForAsset:path];
519
+ if ([path hasPrefix:@"base64:"]) return [self urlFromBase64:path];
520
+
521
+ if (![[NSFileManager defaultManager] fileExistsAtPath:path]) NSLog(@"File not found: %@", path);
522
+
523
+ return [NSURL fileURLWithPath:path];
524
+ }
525
+
526
+ /**
527
+ * URL to an absolute file path.
528
+ * @return [ NSURL* ]
529
+ */
530
+ - (NSURL*) urlForFile:(NSString*)absoluteFilePath
531
+ {
532
+ absoluteFilePath = [absoluteFilePath stringByReplacingOccurrencesOfString:@"file://" withString:@""];
533
+
534
+ if (![[NSFileManager defaultManager] fileExistsAtPath:absoluteFilePath]) {
535
+ NSLog(@"File not found: %@", absoluteFilePath);
536
+ }
537
+
538
+ return [NSURL fileURLWithPath:absoluteFilePath];
539
+ }
540
+
541
+ /**
542
+ * URL to a resource file.
543
+ * @param path A relative file path.
544
+ * @return [ NSURL* ]
545
+ */
546
+ - (NSURL*) urlForResource:(NSString*)path
547
+ {
548
+ if ([path isEqualToString:@"res://icon"]) path = @"res://AppIcon60x60@3x.png";
549
+
550
+ NSString* absPath = [path stringByReplacingOccurrencesOfString:@"res:/"
551
+ withString:@""];
552
+
553
+ absPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:absPath];
554
+
555
+ if (![[NSFileManager defaultManager] fileExistsAtPath:absPath]) NSLog(@"File not found: %@", absPath);
556
+
557
+ return [NSURL fileURLWithPath:absPath];
558
+ }
559
+
560
+ /**
561
+ * URL to an asset file.
562
+ * @param path A relative www file path.
563
+ * @return [ NSURL* ]
564
+ */
565
+ - (NSURL*) urlForAsset:(NSString*)path
566
+ {
567
+ NSString *absoluteAssetPath = [NSString stringWithFormat:@"%@/%@",
568
+ [[NSBundle mainBundle] bundlePath],
569
+ [path stringByReplacingOccurrencesOfString:@"file://"
570
+ withString:@"www/"]];
571
+
572
+ if (![[NSFileManager defaultManager] fileExistsAtPath:absoluteAssetPath]) {
573
+ NSLog(@"File not found: %@", absoluteAssetPath);
574
+ }
575
+
576
+ return [NSURL fileURLWithPath:absoluteAssetPath];
577
+ }
578
+
579
+ /**
580
+ * URL for a base64 encoded string.
581
+ * @param base64String Base64 encoded string.
582
+ * @return [ NSURL* ]
583
+ */
584
+ - (NSURL*) urlFromBase64:(NSString*)base64String
585
+ {
586
+ NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^base64:[^/]+.."
587
+ options:NSRegularExpressionCaseInsensitive
588
+ error:Nil];
589
+
590
+ NSString *dataString = [regex stringByReplacingMatchesInString:base64String
591
+ options:0
592
+ range:NSMakeRange(0, [base64String length])
593
+ withTemplate:@""];
594
+
595
+ NSData* data = [[NSData alloc] initWithBase64EncodedString:dataString
596
+ options:0];
597
+
598
+
599
+ return [self urlForData:data withFileName:[self basenameFromAttachmentPath:base64String]];
600
+ }
601
+
602
+ /**
603
+ * Extract the attachments basename.
604
+ * @param path The file path or base64 data.
605
+ * @return [ NSString* ]
606
+ */
607
+ - (NSString*) basenameFromAttachmentPath:(NSString*)path
608
+ {
609
+ if ([path hasPrefix:@"base64:"]) {
610
+ NSString* pathWithoutPrefix = [path stringByReplacingOccurrencesOfString:@"base64:"
611
+ withString:@""];
612
+
613
+ return [pathWithoutPrefix substringToIndex:[pathWithoutPrefix rangeOfString:@"//"].location];
614
+ }
615
+
616
+ return path;
617
+ }
618
+
619
+ /**
620
+ * Write the data into a temp file.
621
+ * @param data The data to save to file.
622
+ * @param filename The name of the file.
623
+ * @return [ NSURL* ]
624
+ */
625
+ - (NSURL*) urlForData:(NSData*)data withFileName:(NSString*) filename
626
+ {
627
+ [[NSFileManager defaultManager] createDirectoryAtPath:NSTemporaryDirectory()
628
+ withIntermediateDirectories:YES
629
+ attributes:NULL
630
+ error:NULL];
631
+
632
+ NSString* absPath = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
633
+
634
+ if (![[NSFileManager defaultManager] fileExistsAtPath:absPath]) NSLog(@"File not found: %@", absPath);
635
+
636
+ NSURL* url = [NSURL fileURLWithPath:absPath];
637
+ [data writeToURL:url atomically:NO];
638
+
639
+ return url;
640
+ }
641
+
642
+ /**
643
+ * Convert the amount of ticks into seconds.
644
+ * @param ticks The amount of ticks.
645
+ * @param unit The unit of the ticks (minute, hour, day, ...)
646
+ * @return [ double ] Amount of ticks in seconds.
647
+ */
648
+ - (double) convertTicksToSeconds:(double)ticks unit:(NSString*)unit
649
+ {
650
+ if ([unit isEqualToString:@"second"]) {
651
+ return ticks;
652
+ } else if ([unit isEqualToString:@"minute"]) {
653
+ return ticks * 60;
654
+ } else if ([unit isEqualToString:@"hour"]) {
655
+ return ticks * 60 * 60;
656
+ } else if ([unit isEqualToString:@"day"]) {
657
+ return ticks * 60 * 60 * 24;
658
+ } else if ([unit isEqualToString:@"week"]) {
659
+ return ticks * 60 * 60 * 24 * 7;
660
+ } else if ([unit isEqualToString:@"month"]) {
661
+ return ticks * 60 * 60 * 24 * 30.438;
662
+ } else if ([unit isEqualToString:@"quarter"]) {
663
+ return ticks * 60 * 60 * 24 * 91.313;
664
+ } else if ([unit isEqualToString:@"year"]) {
665
+ return ticks * 60 * 60 * 24 * 365;
666
+ }
667
+
668
+ return 0;
669
+ }
670
+
671
+ /**
672
+ * Instance if a calendar where the monday is the first day of the week.
673
+ * @return [ NSCalendar* ]
674
+ */
675
+ - (NSCalendar*) calendarWithMondayAsFirstDay
676
+ {
677
+ NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
678
+ calendar.firstWeekday = 2;
679
+ calendar.minimumDaysInFirstWeek = 1;
680
+ return calendar;
681
+ }
682
+
683
+ /**
684
+ * String representation of this Object
685
+ */
686
+ - (NSString *)description {
687
+ return [NSString stringWithFormat: @"%@", dict];
688
+ }
689
+ @end
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Apache 2.0 License
3
+ *
4
+ * Copyright (c) Sebastian Katzer 2017
5
+ *
6
+ * This file contains Original Code and/or Modifications of Original Code
7
+ * as defined in and that are subject to the Apache License
8
+ * Version 2.0 (the 'License'). You may not use this file except in
9
+ * compliance with the License. Please obtain a copy of the License at
10
+ * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11
+ * file.
12
+ *
13
+ * The Original Code and all software distributed under the License are
14
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18
+ * Please see the License for the specific language governing rights and
19
+ * limitations under the License.
20
+ */
21
+
22
+ #import "APPNotificationOptions.h"
23
+
24
+ @import UserNotifications;
25
+
26
+ @interface UNNotificationRequest (APPLocalNotification)
27
+
28
+ - (APPNotificationOptions*) options;
29
+ - (BOOL) wasUpdated;
30
+ - (NSString*) encodeToJSON;
31
+
32
+ @end