@ammarahmed/notifee-react-native 7.3.0
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.
- package/.gitattributes +3 -0
- package/LICENSE +44 -0
- package/README.md +131 -0
- package/RNNotifee.podspec +39 -0
- package/RNNotifeeCore.podspec +33 -0
- package/android/build.gradle +116 -0
- package/android/gradle.properties +1 -0
- package/android/libs/app/notifee/core/202108261756/core-202108261756.aar +0 -0
- package/android/libs/app/notifee/core/202108261756/core-202108261756.aar.md5 +1 -0
- package/android/libs/app/notifee/core/202108261756/core-202108261756.aar.sha1 +1 -0
- package/android/libs/app/notifee/core/202108261756/core-202108261756.aar.sha256 +1 -0
- package/android/libs/app/notifee/core/202108261756/core-202108261756.aar.sha512 +1 -0
- package/android/libs/app/notifee/core/202108261756/core-202108261756.pom +9 -0
- package/android/libs/app/notifee/core/202108261756/core-202108261756.pom.md5 +1 -0
- package/android/libs/app/notifee/core/202108261756/core-202108261756.pom.sha1 +1 -0
- package/android/libs/app/notifee/core/202108261756/core-202108261756.pom.sha256 +1 -0
- package/android/libs/app/notifee/core/202108261756/core-202108261756.pom.sha512 +1 -0
- package/android/libs/app/notifee/core/maven-metadata.xml +13 -0
- package/android/libs/app/notifee/core/maven-metadata.xml.md5 +1 -0
- package/android/libs/app/notifee/core/maven-metadata.xml.sha1 +1 -0
- package/android/libs/app/notifee/core/maven-metadata.xml.sha256 +1 -0
- package/android/libs/app/notifee/core/maven-metadata.xml.sha512 +1 -0
- package/android/lint.xml +5 -0
- package/android/proguard-rules.pro +74 -0
- package/android/settings.gradle +1 -0
- package/android/src/main/AndroidManifest.xml +12 -0
- package/android/src/main/java/io/invertase/notifee/NotifeeApiModule.java +349 -0
- package/android/src/main/java/io/invertase/notifee/NotifeeEventSubscriber.java +118 -0
- package/android/src/main/java/io/invertase/notifee/NotifeeInitProvider.java +55 -0
- package/android/src/main/java/io/invertase/notifee/NotifeePackage.java +30 -0
- package/android/src/main/java/io/invertase/notifee/NotifeeReactUtils.java +244 -0
- package/app.plugin.js +1 -0
- package/dist/NotifeeApiModule.d.ts +53 -0
- package/dist/NotifeeApiModule.js +607 -0
- package/dist/NotifeeApiModule.js.map +1 -0
- package/dist/NotifeeJSEventEmitter.d.ts +3 -0
- package/dist/NotifeeJSEventEmitter.js +14 -0
- package/dist/NotifeeJSEventEmitter.js.map +1 -0
- package/dist/NotifeeNativeError.d.ts +15 -0
- package/dist/NotifeeNativeError.js +61 -0
- package/dist/NotifeeNativeError.js.map +1 -0
- package/dist/NotifeeNativeModule.d.ts +14 -0
- package/dist/NotifeeNativeModule.js +43 -0
- package/dist/NotifeeNativeModule.js.map +1 -0
- package/dist/NotifeeNativeModule.web.d.ts +12 -0
- package/dist/NotifeeNativeModule.web.js +19 -0
- package/dist/NotifeeNativeModule.web.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/types/Library.d.ts +21 -0
- package/dist/types/Library.js +6 -0
- package/dist/types/Library.js.map +1 -0
- package/dist/types/Module.d.ts +572 -0
- package/dist/types/Module.js +6 -0
- package/dist/types/Module.js.map +1 -0
- package/dist/types/Notification.d.ts +450 -0
- package/dist/types/Notification.js +105 -0
- package/dist/types/Notification.js.map +1 -0
- package/dist/types/NotificationAndroid.d.ts +1276 -0
- package/dist/types/NotificationAndroid.js +380 -0
- package/dist/types/NotificationAndroid.js.map +1 -0
- package/dist/types/NotificationIOS.d.ts +537 -0
- package/dist/types/NotificationIOS.js +92 -0
- package/dist/types/NotificationIOS.js.map +1 -0
- package/dist/types/NotificationWeb.d.ts +5 -0
- package/dist/types/NotificationWeb.js +3 -0
- package/dist/types/NotificationWeb.js.map +1 -0
- package/dist/types/PowerManagerInfo.d.ts +36 -0
- package/dist/types/PowerManagerInfo.js +6 -0
- package/dist/types/PowerManagerInfo.js.map +1 -0
- package/dist/types/Trigger.d.ts +108 -0
- package/dist/types/Trigger.js +39 -0
- package/dist/types/Trigger.js.map +1 -0
- package/dist/utils/id.d.ts +1 -0
- package/dist/utils/id.js +16 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/index.d.ts +16 -0
- package/dist/utils/index.js +52 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/validate.d.ts +15 -0
- package/dist/utils/validate.js +93 -0
- package/dist/utils/validate.js.map +1 -0
- package/dist/validators/iosCommunicationInfo/validateIOSCommunicationInfo.d.ts +2 -0
- package/dist/validators/iosCommunicationInfo/validateIOSCommunicationInfo.js +39 -0
- package/dist/validators/iosCommunicationInfo/validateIOSCommunicationInfo.js.map +1 -0
- package/dist/validators/iosCommunicationInfo/validateIOSCommunicationInfoPerson.d.ts +2 -0
- package/dist/validators/iosCommunicationInfo/validateIOSCommunicationInfoPerson.js +27 -0
- package/dist/validators/iosCommunicationInfo/validateIOSCommunicationInfoPerson.js.map +1 -0
- package/dist/validators/validate.d.ts +25 -0
- package/dist/validators/validate.js +75 -0
- package/dist/validators/validate.js.map +1 -0
- package/dist/validators/validateAndroidAction.d.ts +2 -0
- package/dist/validators/validateAndroidAction.js +52 -0
- package/dist/validators/validateAndroidAction.js.map +1 -0
- package/dist/validators/validateAndroidChannel.d.ts +2 -0
- package/dist/validators/validateAndroidChannel.js +155 -0
- package/dist/validators/validateAndroidChannel.js.map +1 -0
- package/dist/validators/validateAndroidChannelGroup.d.ts +2 -0
- package/dist/validators/validateAndroidChannelGroup.js +42 -0
- package/dist/validators/validateAndroidChannelGroup.js.map +1 -0
- package/dist/validators/validateAndroidFullScreenAction.d.ts +2 -0
- package/dist/validators/validateAndroidFullScreenAction.js +50 -0
- package/dist/validators/validateAndroidFullScreenAction.js.map +1 -0
- package/dist/validators/validateAndroidInput.d.ts +2 -0
- package/dist/validators/validateAndroidInput.js +54 -0
- package/dist/validators/validateAndroidInput.js.map +1 -0
- package/dist/validators/validateAndroidNotification.d.ts +2 -0
- package/dist/validators/validateAndroidNotification.js +529 -0
- package/dist/validators/validateAndroidNotification.js.map +1 -0
- package/dist/validators/validateAndroidPressAction.d.ts +2 -0
- package/dist/validators/validateAndroidPressAction.js +50 -0
- package/dist/validators/validateAndroidPressAction.js.map +1 -0
- package/dist/validators/validateAndroidStyle.d.ts +22 -0
- package/dist/validators/validateAndroidStyle.js +231 -0
- package/dist/validators/validateAndroidStyle.js.map +1 -0
- package/dist/validators/validateIOSAttachment.d.ts +6 -0
- package/dist/validators/validateIOSAttachment.js +102 -0
- package/dist/validators/validateIOSAttachment.js.map +1 -0
- package/dist/validators/validateIOSCategory.d.ts +2 -0
- package/dist/validators/validateIOSCategory.js +124 -0
- package/dist/validators/validateIOSCategory.js.map +1 -0
- package/dist/validators/validateIOSCategoryAction.d.ts +2 -0
- package/dist/validators/validateIOSCategoryAction.js +59 -0
- package/dist/validators/validateIOSCategoryAction.js.map +1 -0
- package/dist/validators/validateIOSInput.d.ts +2 -0
- package/dist/validators/validateIOSInput.js +32 -0
- package/dist/validators/validateIOSInput.js.map +1 -0
- package/dist/validators/validateIOSNotification.d.ts +2 -0
- package/dist/validators/validateIOSNotification.js +211 -0
- package/dist/validators/validateIOSNotification.js.map +1 -0
- package/dist/validators/validateIOSPermissions.d.ts +2 -0
- package/dist/validators/validateIOSPermissions.js +62 -0
- package/dist/validators/validateIOSPermissions.js.map +1 -0
- package/dist/validators/validateNotification.d.ts +11 -0
- package/dist/validators/validateNotification.js +129 -0
- package/dist/validators/validateNotification.js.map +1 -0
- package/dist/validators/validateTrigger.d.ts +2 -0
- package/dist/validators/validateTrigger.js +104 -0
- package/dist/validators/validateTrigger.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js.map +1 -0
- package/ios/NotifeeCore/Info.plist +22 -0
- package/ios/NotifeeCore/NotifeeCore+NSNotificationCenter.h +28 -0
- package/ios/NotifeeCore/NotifeeCore+NSNotificationCenter.m +72 -0
- package/ios/NotifeeCore/NotifeeCore+NSURLSession.h +25 -0
- package/ios/NotifeeCore/NotifeeCore+NSURLSession.m +55 -0
- package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.h +37 -0
- package/ios/NotifeeCore/NotifeeCore+UNUserNotificationCenter.m +242 -0
- package/ios/NotifeeCore/NotifeeCore.h +118 -0
- package/ios/NotifeeCore/NotifeeCore.m +784 -0
- package/ios/NotifeeCore/NotifeeCoreDelegateHolder.h +34 -0
- package/ios/NotifeeCore/NotifeeCoreDelegateHolder.m +70 -0
- package/ios/NotifeeCore/NotifeeCoreDownloadDelegate.h +39 -0
- package/ios/NotifeeCore/NotifeeCoreDownloadDelegate.m +68 -0
- package/ios/NotifeeCore/NotifeeCoreExtensionHelper.h +38 -0
- package/ios/NotifeeCore/NotifeeCoreExtensionHelper.m +224 -0
- package/ios/NotifeeCore/NotifeeCoreUtil.h +82 -0
- package/ios/NotifeeCore/NotifeeCoreUtil.m +793 -0
- package/ios/RNNotifee/NotifeeApiModule.h +25 -0
- package/ios/RNNotifee/NotifeeApiModule.m +371 -0
- package/ios/RNNotifee/NotifeeExtensionHelper.h +37 -0
- package/ios/RNNotifee/NotifeeExtensionHelper.m +37 -0
- package/ios/RNNotifee.xcodeproj/project.pbxproj +318 -0
- package/jest-mock.js +158 -0
- package/package.json +59 -0
- package/plugin/build/index.d.ts +3 -0
- package/plugin/build/index.js +12 -0
- package/plugin/build/index.js.map +1 -0
- package/plugin/build/withNotifeeProjectGradlePlugin.d.ts +5 -0
- package/plugin/build/withNotifeeProjectGradlePlugin.js +24 -0
- package/plugin/build/withNotifeeProjectGradlePlugin.js.map +1 -0
- package/plugin/src/index.ts +9 -0
- package/plugin/src/withNotifeeProjectGradlePlugin.ts +27 -0
- package/plugin/tsconfig.json +9 -0
- package/react-native.config.js +11 -0
- package/refresh-example.sh +71 -0
- package/src/NotifeeApiModule.ts +825 -0
- package/src/NotifeeJSEventEmitter.ts +11 -0
- package/src/NotifeeNativeError.ts +70 -0
- package/src/NotifeeNativeModule.ts +55 -0
- package/src/NotifeeNativeModule.web.ts +25 -0
- package/src/index.ts +33 -0
- package/src/types/Library.ts +28 -0
- package/src/types/Module.ts +625 -0
- package/src/types/Notification.ts +505 -0
- package/src/types/NotificationAndroid.ts +1443 -0
- package/src/types/NotificationIOS.ts +681 -0
- package/src/types/NotificationWeb.ts +5 -0
- package/src/types/PowerManagerInfo.ts +43 -0
- package/src/types/Trigger.ts +118 -0
- package/src/utils/id.ts +13 -0
- package/src/utils/index.ts +47 -0
- package/src/utils/validate.ts +92 -0
- package/src/validators/iosCommunicationInfo/validateIOSCommunicationInfo.ts +45 -0
- package/src/validators/iosCommunicationInfo/validateIOSCommunicationInfoPerson.ts +33 -0
- package/src/validators/validate.ts +85 -0
- package/src/validators/validateAndroidAction.ts +54 -0
- package/src/validators/validateAndroidChannel.ts +188 -0
- package/src/validators/validateAndroidChannelGroup.ts +49 -0
- package/src/validators/validateAndroidFullScreenAction.ts +65 -0
- package/src/validators/validateAndroidInput.ts +67 -0
- package/src/validators/validateAndroidNotification.ts +704 -0
- package/src/validators/validateAndroidPressAction.ts +65 -0
- package/src/validators/validateAndroidStyle.ts +315 -0
- package/src/validators/validateIOSAttachment.ts +136 -0
- package/src/validators/validateIOSCategory.ts +150 -0
- package/src/validators/validateIOSCategoryAction.ts +65 -0
- package/src/validators/validateIOSInput.ts +38 -0
- package/src/validators/validateIOSNotification.ts +296 -0
- package/src/validators/validateIOSPermissions.ts +78 -0
- package/src/validators/validateNotification.ts +156 -0
- package/src/validators/validateTrigger.ts +134 -0
- package/src/version.ts +2 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,793 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2016-present Invertase Limited & Contributors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this library except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#import "NotifeeCoreUtil.h"
|
|
19
|
+
#include <CoreGraphics/CGGeometry.h>
|
|
20
|
+
#import <Intents/INIntentIdentifiers.h>
|
|
21
|
+
#import <UIKit/UIKit.h>
|
|
22
|
+
#import "NotifeeCore+NSURLSession.h"
|
|
23
|
+
|
|
24
|
+
@implementation NotifeeCoreUtil
|
|
25
|
+
|
|
26
|
+
+ (NSNumber *)numberForUNNotificationSetting:(UNNotificationSetting)setting {
|
|
27
|
+
NSNumber *asNumber = @-1;
|
|
28
|
+
if (setting == UNNotificationSettingNotSupported) {
|
|
29
|
+
asNumber = @-1;
|
|
30
|
+
} else if (setting == UNNotificationSettingDisabled) {
|
|
31
|
+
asNumber = @0;
|
|
32
|
+
} else if (setting == UNNotificationSettingEnabled) {
|
|
33
|
+
asNumber = @1;
|
|
34
|
+
}
|
|
35
|
+
return asNumber;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
+ (NSMutableArray<NSDictionary *> *)notificationActionsToDictionaryArray:
|
|
39
|
+
(NSArray<UNNotificationAction *> *)notificationActions {
|
|
40
|
+
NSMutableArray<NSDictionary *> *notificationActionDicts = [[NSMutableArray alloc] init];
|
|
41
|
+
|
|
42
|
+
for (UNNotificationAction *notificationAction in notificationActions) {
|
|
43
|
+
NSMutableDictionary *notificationActionDict = [NSMutableDictionary dictionary];
|
|
44
|
+
|
|
45
|
+
notificationActionDict[@"id"] = notificationAction.identifier;
|
|
46
|
+
notificationActionDict[@"title"] = notificationAction.title;
|
|
47
|
+
|
|
48
|
+
notificationActionDict[@"destructive"] =
|
|
49
|
+
@(((notificationAction.options & UNNotificationActionOptionDestructive) != 0));
|
|
50
|
+
notificationActionDict[@"foreground"] =
|
|
51
|
+
@(((notificationAction.options & UNNotificationActionOptionForeground) != 0));
|
|
52
|
+
notificationActionDict[@"authenticationRequired"] =
|
|
53
|
+
@(((notificationAction.options & UNNotificationActionOptionAuthenticationRequired) != 0));
|
|
54
|
+
|
|
55
|
+
if ([[notificationAction class] isKindOfClass:[UNTextInputNotificationAction class]]) {
|
|
56
|
+
UNTextInputNotificationAction *notificationInputAction =
|
|
57
|
+
(UNTextInputNotificationAction *)notificationAction;
|
|
58
|
+
if ([notificationInputAction textInputButtonTitle] == nil &&
|
|
59
|
+
[notificationInputAction textInputPlaceholder] == nil) {
|
|
60
|
+
notificationActionDict[@"input"] = @(YES);
|
|
61
|
+
} else {
|
|
62
|
+
NSMutableDictionary *inputDict = [NSMutableDictionary dictionary];
|
|
63
|
+
inputDict[@"buttonText"] = [notificationInputAction textInputButtonTitle];
|
|
64
|
+
inputDict[@"placeholderText"] = [notificationInputAction textInputPlaceholder];
|
|
65
|
+
notificationActionDict[@"input"] = inputDict;
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
notificationActionDict[@"input"] = @(NO);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
[notificationActionDicts addObject:notificationActionDict];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return notificationActionDicts;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
+ (NSMutableArray<UNNotificationAction *> *)notificationActionsFromDictionaryArray:
|
|
78
|
+
(NSArray<NSDictionary *> *)actionDictionaries {
|
|
79
|
+
NSMutableArray<UNNotificationAction *> *notificationActions = [[NSMutableArray alloc] init];
|
|
80
|
+
|
|
81
|
+
for (NSDictionary *actionDictionary in actionDictionaries) {
|
|
82
|
+
UNNotificationAction *notificationAction;
|
|
83
|
+
|
|
84
|
+
NSString *id = actionDictionary[@"id"];
|
|
85
|
+
NSString *title = actionDictionary[@"title"];
|
|
86
|
+
|
|
87
|
+
UNNotificationActionOptions options = 0;
|
|
88
|
+
|
|
89
|
+
if ([actionDictionary[@"destructive"] isEqual:@(YES)]) {
|
|
90
|
+
options |= UNNotificationActionOptionDestructive;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if ([actionDictionary[@"foreground"] isEqual:@(YES)]) {
|
|
94
|
+
options |= UNNotificationActionOptionForeground;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if ([actionDictionary[@"authenticationRequired"] isEqual:@(YES)]) {
|
|
98
|
+
options |= UNNotificationActionOptionAuthenticationRequired;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (actionDictionary[@"input"] != nil &&
|
|
102
|
+
[actionDictionary[@"input"] isKindOfClass:NSDictionary.class]) {
|
|
103
|
+
NSDictionary *inputDictionary = actionDictionary[@"input"];
|
|
104
|
+
NSString *buttonText = inputDictionary[@"buttonText"];
|
|
105
|
+
NSString *placeholderText = inputDictionary[@"placeholderText"];
|
|
106
|
+
notificationAction = [UNTextInputNotificationAction actionWithIdentifier:id
|
|
107
|
+
title:title
|
|
108
|
+
options:options
|
|
109
|
+
textInputButtonTitle:buttonText
|
|
110
|
+
textInputPlaceholder:placeholderText];
|
|
111
|
+
} else if (actionDictionary[@"input"] != nil) { // BOOL
|
|
112
|
+
notificationAction = [UNTextInputNotificationAction actionWithIdentifier:id
|
|
113
|
+
title:title
|
|
114
|
+
options:options];
|
|
115
|
+
} else {
|
|
116
|
+
notificationAction = [UNNotificationAction actionWithIdentifier:id
|
|
117
|
+
title:title
|
|
118
|
+
options:options];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
[notificationActions addObject:notificationAction];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return notificationActions;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Builds the notification attachments
|
|
129
|
+
* If no attachments are resolved, an empty array will be returned
|
|
130
|
+
*
|
|
131
|
+
* @return NSArray<UNNotificationAttachment *> *
|
|
132
|
+
*/
|
|
133
|
+
+ (NSMutableArray<UNNotificationAttachment *> *)notificationAttachmentsFromDictionaryArray:
|
|
134
|
+
(NSArray<NSDictionary *> *)attachmentDictionaries {
|
|
135
|
+
NSMutableArray<UNNotificationAttachment *> *attachments = [[NSMutableArray alloc] init];
|
|
136
|
+
|
|
137
|
+
for (NSDictionary *attachmentDict in attachmentDictionaries) {
|
|
138
|
+
UNNotificationAttachment *attachment = [self attachmentFromDictionary:attachmentDict];
|
|
139
|
+
if (attachment) {
|
|
140
|
+
[attachments addObject:attachment];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return attachments;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Returns an UNNotificationAttachment from a file path or local resource
|
|
148
|
+
*
|
|
149
|
+
* @return UNNotificationAttachment or null if the attachment fails to resolve
|
|
150
|
+
*/
|
|
151
|
+
+ (UNNotificationAttachment *)attachmentFromDictionary:(NSDictionary *)attachmentDict {
|
|
152
|
+
NSString *identifier = attachmentDict[@"id"];
|
|
153
|
+
NSString *urlString = attachmentDict[@"url"];
|
|
154
|
+
NSURL *url;
|
|
155
|
+
|
|
156
|
+
if ([urlString hasPrefix:@"http://"] || [urlString hasPrefix:@"https://"]) {
|
|
157
|
+
// handle remote url by attempting to download attachement synchronously
|
|
158
|
+
url = [self downloadMediaSynchronously:urlString];
|
|
159
|
+
} else if ([urlString hasPrefix:@"/"]) {
|
|
160
|
+
// handle absolute file path
|
|
161
|
+
url = [NSURL fileURLWithPath:urlString];
|
|
162
|
+
} else {
|
|
163
|
+
// try to resolve local resource
|
|
164
|
+
url = [[NSBundle mainBundle] URLForResource:attachmentDict[@"url"] withExtension:nil];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (url) {
|
|
168
|
+
NSError *error;
|
|
169
|
+
UNNotificationAttachment *attachment = [UNNotificationAttachment
|
|
170
|
+
attachmentWithIdentifier:identifier
|
|
171
|
+
URL:url
|
|
172
|
+
options:[self attachmentOptionsFromDictionary:attachmentDict]
|
|
173
|
+
error:&error];
|
|
174
|
+
if (error != nil) {
|
|
175
|
+
NSLog(@"NotifeeCore: An error occurred whilst trying to resolve an "
|
|
176
|
+
@"attachment %@: %@",
|
|
177
|
+
attachmentDict, error);
|
|
178
|
+
return nil;
|
|
179
|
+
} else if (attachment == nil) {
|
|
180
|
+
NSLog(@"NotifeeCore: Failed resolving an attachment %@: data at URL is "
|
|
181
|
+
@"not a supported type.",
|
|
182
|
+
attachmentDict);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return attachment;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
NSLog(@"NotifeeCore: Unable to resolve url for attachment: %@", attachmentDict);
|
|
189
|
+
return nil;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/*
|
|
193
|
+
* Downloads a media file, syncronously to the NSCachesDirectory
|
|
194
|
+
*
|
|
195
|
+
* @param urlString NSString
|
|
196
|
+
* @return NSURL or nil
|
|
197
|
+
*/
|
|
198
|
+
+ (NSURL *)downloadMediaSynchronously:(NSString *)urlString {
|
|
199
|
+
NSURL *url = [NSURL URLWithString:urlString];
|
|
200
|
+
|
|
201
|
+
NSString *newCachedFileName = [self generateCachedFileName:15];
|
|
202
|
+
|
|
203
|
+
NSArray *localDirectoryPaths =
|
|
204
|
+
NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
|
205
|
+
NSString *tempDestination =
|
|
206
|
+
[localDirectoryPaths[0] stringByAppendingPathComponent:newCachedFileName];
|
|
207
|
+
|
|
208
|
+
@try {
|
|
209
|
+
NSError *error;
|
|
210
|
+
|
|
211
|
+
// Apple gives us a suggested file name which can be used to infer the file
|
|
212
|
+
// extension
|
|
213
|
+
NSString *suggestedFilename = [NotifeeCoreNSURLSession downloadItemAtURL:url
|
|
214
|
+
toFile:tempDestination
|
|
215
|
+
error:&error];
|
|
216
|
+
|
|
217
|
+
if (error) {
|
|
218
|
+
NSLog(@"NotifeeCore: Failed to download attachement with URL %@: %@", urlString, error);
|
|
219
|
+
return nil;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Rename the recently downloaded file to include its file extension
|
|
223
|
+
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
224
|
+
|
|
225
|
+
NSString *fileExtension = [NSString stringWithFormat:@".%@", [suggestedFilename pathExtension]];
|
|
226
|
+
|
|
227
|
+
if (!fileExtension || [fileExtension isEqualToString:@""]) {
|
|
228
|
+
NSLog(@"NotifeeCore: Failed to determine file extension for attachment "
|
|
229
|
+
@"with URL %@: %@",
|
|
230
|
+
urlString, error);
|
|
231
|
+
return nil;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
NSString *localFilePath =
|
|
235
|
+
[localDirectoryPaths[0] stringByAppendingPathComponent:newCachedFileName];
|
|
236
|
+
|
|
237
|
+
localFilePath = [localFilePath stringByAppendingString:fileExtension];
|
|
238
|
+
NSURL *localURL = [NSURL fileURLWithPath:localFilePath];
|
|
239
|
+
|
|
240
|
+
[fileManager moveItemAtPath:tempDestination toPath:localFilePath error:&error];
|
|
241
|
+
|
|
242
|
+
// Returns the local cached path to attachment
|
|
243
|
+
return localURL;
|
|
244
|
+
} @catch (NSException *exception) {
|
|
245
|
+
NSLog(@"NotifeeCore: An exception occured while attempting to download "
|
|
246
|
+
@"attachment with URL %@: "
|
|
247
|
+
@"%@",
|
|
248
|
+
urlString, exception);
|
|
249
|
+
return nil;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Returns a NSDictionary representation of options related to the attached file
|
|
255
|
+
*
|
|
256
|
+
* @param optionsDict NSDictionary
|
|
257
|
+
*/
|
|
258
|
+
+ (NSDictionary *)attachmentOptionsFromDictionary:(NSDictionary *)optionsDict {
|
|
259
|
+
NSMutableDictionary *options = [NSMutableDictionary new];
|
|
260
|
+
if (optionsDict[@"typeHint"] != nil) {
|
|
261
|
+
options[UNNotificationAttachmentOptionsTypeHintKey] = optionsDict[@"typeHint"];
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (optionsDict[@"thumbnailHidden"] != nil) {
|
|
265
|
+
options[UNNotificationAttachmentOptionsThumbnailHiddenKey] = optionsDict[@"thumbnailHidden"];
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (optionsDict[@"thumbnailClippingRect"] != nil) {
|
|
269
|
+
NSDictionary *area = optionsDict[@"thumbnailClippingRect"];
|
|
270
|
+
NSNumber *x = area[@"x"];
|
|
271
|
+
NSNumber *y = area[@"y"];
|
|
272
|
+
NSNumber *width = area[@"width"];
|
|
273
|
+
NSNumber *height = area[@"height"];
|
|
274
|
+
CGRect areaRect =
|
|
275
|
+
CGRectMake([x doubleValue], [y doubleValue], [width doubleValue], [height doubleValue]);
|
|
276
|
+
options[UNNotificationAttachmentOptionsThumbnailClippingRectKey] =
|
|
277
|
+
(__bridge id _Nullable)(CGRectCreateDictionaryRepresentation(areaRect));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (optionsDict[@"thumbnailTime"] != nil) {
|
|
281
|
+
options[UNNotificationAttachmentOptionsThumbnailTimeKey] = optionsDict[@"thumbnailTime"];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return options;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Returns an UNNotificationTrigger from NSDictionary representing a trigger
|
|
289
|
+
*
|
|
290
|
+
* @param triggerDict NSDictionary
|
|
291
|
+
* @return UNNotificationTrigger or null if trigger type is not recognised
|
|
292
|
+
*/
|
|
293
|
+
+ (UNNotificationTrigger *)triggerFromDictionary:(NSDictionary *)triggerDict {
|
|
294
|
+
UNNotificationTrigger *trigger;
|
|
295
|
+
NSInteger triggerType = [triggerDict[@"type"] integerValue];
|
|
296
|
+
|
|
297
|
+
if (triggerType == NotifeeCoreTriggerTypeTimestamp) {
|
|
298
|
+
trigger = [self timestampTriggerFromDictionary:triggerDict];
|
|
299
|
+
} else if (triggerType == NotifeeCoreTriggerTypeInterval) {
|
|
300
|
+
trigger = [self intervalTriggerFromDictionary:triggerDict];
|
|
301
|
+
} else {
|
|
302
|
+
NSLog(@"NotifeeCore: Failed to parse trigger with unknown trigger type: %ld",
|
|
303
|
+
(long)triggerType);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return trigger;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Returns an UNNotificationTrigger from NSDictionary representing a
|
|
311
|
+
* TimestampTrigger
|
|
312
|
+
*
|
|
313
|
+
* @param triggerDict NSDictionary
|
|
314
|
+
*/
|
|
315
|
+
+ (UNNotificationTrigger *)timestampTriggerFromDictionary:(NSDictionary *)triggerDict {
|
|
316
|
+
UNNotificationTrigger *trigger;
|
|
317
|
+
Boolean repeats = false;
|
|
318
|
+
NSCalendarUnit calendarUnit;
|
|
319
|
+
|
|
320
|
+
NSInteger repeatFrequency = [triggerDict[@"repeatFrequency"] integerValue];
|
|
321
|
+
NSNumber *timestampMillis = triggerDict[@"timestamp"];
|
|
322
|
+
|
|
323
|
+
// convert timestamp to a NSDate
|
|
324
|
+
NSInteger timestamp = [timestampMillis doubleValue] / 1000;
|
|
325
|
+
NSDate *date = [NSDate dateWithTimeIntervalSince1970:timestamp];
|
|
326
|
+
|
|
327
|
+
if (repeatFrequency != -1) {
|
|
328
|
+
repeats = true;
|
|
329
|
+
|
|
330
|
+
if (repeatFrequency == NotifeeCoreRepeatFrequencyHourly) {
|
|
331
|
+
// match by minute and second
|
|
332
|
+
calendarUnit = NSCalendarUnitMinute | NSCalendarUnitSecond;
|
|
333
|
+
} else if (repeatFrequency == NotifeeCoreRepeatFrequencyDaily) {
|
|
334
|
+
// match by hour, minute and second
|
|
335
|
+
calendarUnit = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
|
|
336
|
+
} else if (repeatFrequency == NotifeeCoreRepeatFrequencyWeekly) {
|
|
337
|
+
// match by day, hour, minute, and second
|
|
338
|
+
calendarUnit =
|
|
339
|
+
NSCalendarUnitWeekday | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
|
|
340
|
+
} else if (repeatFrequency == NotifeeCoreRepeatFrequencyMonthly) {
|
|
341
|
+
// match by day, hour, minute, and second
|
|
342
|
+
calendarUnit =
|
|
343
|
+
NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
|
|
344
|
+
} else {
|
|
345
|
+
NSLog(@"NotifeeCore: Failed to parse TimestampTrigger with unknown "
|
|
346
|
+
@"repeatFrequency: %ld",
|
|
347
|
+
(long)repeatFrequency);
|
|
348
|
+
|
|
349
|
+
return nil;
|
|
350
|
+
}
|
|
351
|
+
} else {
|
|
352
|
+
// Needs to match exactly to the second
|
|
353
|
+
calendarUnit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay |
|
|
354
|
+
NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
NSDateComponents *components = [[NSCalendar currentCalendar] components:calendarUnit
|
|
358
|
+
fromDate:date];
|
|
359
|
+
trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components
|
|
360
|
+
repeats:repeats];
|
|
361
|
+
|
|
362
|
+
return trigger;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Returns an UNNotificationTrigger from NSDictionary representing an
|
|
366
|
+
* IntervalTrigger
|
|
367
|
+
*
|
|
368
|
+
* @param triggerDict NSDictionary
|
|
369
|
+
*/
|
|
370
|
+
+ (UNNotificationTrigger *)intervalTriggerFromDictionary:(NSDictionary *)triggerDict {
|
|
371
|
+
double intervalNumber = [triggerDict[@"interval"] doubleValue];
|
|
372
|
+
NSString *timeUnit = triggerDict[@"timeUnit"];
|
|
373
|
+
|
|
374
|
+
NSTimeInterval intervalInSeconds = 0;
|
|
375
|
+
|
|
376
|
+
if ([timeUnit isEqualToString:kNotifeeCoreTimeUnitSeconds]) {
|
|
377
|
+
intervalInSeconds = intervalNumber;
|
|
378
|
+
} else if ([timeUnit isEqualToString:kNotifeeCoreTimeUnitMinutes]) {
|
|
379
|
+
// multiply by the number of seconds in 1 minute
|
|
380
|
+
intervalInSeconds = intervalNumber * 60;
|
|
381
|
+
} else if ([timeUnit isEqualToString:kNotifeeCoreTimeUnitHours]) {
|
|
382
|
+
// multiply by the number of seconds in 1 hour
|
|
383
|
+
intervalInSeconds = intervalNumber * 3600;
|
|
384
|
+
} else if ([timeUnit isEqualToString:kNotifeeCoreTimeUnitDays]) {
|
|
385
|
+
// multiply by the number of seconds in 1 day
|
|
386
|
+
intervalInSeconds = intervalNumber * 86400;
|
|
387
|
+
} else {
|
|
388
|
+
NSLog(@"NotifeeCore: Failed to parse IntervalTrigger with unknown "
|
|
389
|
+
@"timeUnit: %@",
|
|
390
|
+
timeUnit);
|
|
391
|
+
return nil;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:intervalInSeconds repeats:true];
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
+ (NSMutableArray<NSNumber *> *)intentIdentifiersFromStringArray:
|
|
398
|
+
(NSArray<NSString *> *)identifiers {
|
|
399
|
+
NSMutableArray<NSNumber *> *intentIdentifiers = [[NSMutableArray alloc] init];
|
|
400
|
+
|
|
401
|
+
for (NSString *identifier in identifiers) {
|
|
402
|
+
if ([identifier isEqualToString:INStartAudioCallIntentIdentifier]) {
|
|
403
|
+
// IOSIntentIdentifier.START_AUDIO_CALL
|
|
404
|
+
[intentIdentifiers addObject:@0];
|
|
405
|
+
} else if ([identifier isEqualToString:INStartVideoCallIntentIdentifier]) {
|
|
406
|
+
// IOSIntentIdentifier.START_VIDEO_CALL
|
|
407
|
+
[intentIdentifiers addObject:@1];
|
|
408
|
+
} else if ([identifier isEqualToString:INSearchCallHistoryIntentIdentifier]) {
|
|
409
|
+
// IOSIntentIdentifier.SEARCH_CALL_HISTORY
|
|
410
|
+
[intentIdentifiers addObject:@2];
|
|
411
|
+
} else if ([identifier isEqualToString:INSetAudioSourceInCarIntentIdentifier]) {
|
|
412
|
+
// IOSIntentIdentifier.SET_AUDIO_SOURCE_IN_CAR
|
|
413
|
+
[intentIdentifiers addObject:@3];
|
|
414
|
+
} else if ([identifier isEqualToString:INSetClimateSettingsInCarIntentIdentifier]) {
|
|
415
|
+
// IOSIntentIdentifier.SET_CLIMATE_SETTINGS_IN_CAR
|
|
416
|
+
[intentIdentifiers addObject:@4];
|
|
417
|
+
} else if ([identifier isEqualToString:INSetDefrosterSettingsInCarIntentIdentifier]) {
|
|
418
|
+
// IOSIntentIdentifier.SET_DEFROSTER_SETTINGS_IN_CAR
|
|
419
|
+
[intentIdentifiers addObject:@5];
|
|
420
|
+
} else if ([identifier isEqualToString:INSetSeatSettingsInCarIntentIdentifier]) {
|
|
421
|
+
// IOSIntentIdentifier.SET_SEAT_SETTINGS_IN_CAR
|
|
422
|
+
[intentIdentifiers addObject:@6];
|
|
423
|
+
} else if ([identifier isEqualToString:INSetProfileInCarIntentIdentifier]) {
|
|
424
|
+
// IOSIntentIdentifier.SET_PROFILE_IN_CAR
|
|
425
|
+
[intentIdentifiers addObject:@7];
|
|
426
|
+
} else if ([identifier isEqualToString:INSaveProfileInCarIntentIdentifier]) {
|
|
427
|
+
// IOSIntentIdentifier.SAVE_PROFILE_IN_CAR
|
|
428
|
+
[intentIdentifiers addObject:@8];
|
|
429
|
+
} else if ([identifier isEqualToString:INStartWorkoutIntentIdentifier]) {
|
|
430
|
+
// IOSIntentIdentifier.START_WORKOUT
|
|
431
|
+
[intentIdentifiers addObject:@9];
|
|
432
|
+
} else if ([identifier isEqualToString:INPauseWorkoutIntentIdentifier]) {
|
|
433
|
+
// IOSIntentIdentifier.PAUSE_WORKOUT
|
|
434
|
+
[intentIdentifiers addObject:@10];
|
|
435
|
+
} else if ([identifier isEqualToString:INEndWorkoutIntentIdentifier]) {
|
|
436
|
+
// IOSIntentIdentifier.END_WORKOUT
|
|
437
|
+
[intentIdentifiers addObject:@11];
|
|
438
|
+
} else if ([identifier isEqualToString:INCancelWorkoutIntentIdentifier]) {
|
|
439
|
+
// IOSIntentIdentifier.CANCEL_WORKOUT
|
|
440
|
+
[intentIdentifiers addObject:@12];
|
|
441
|
+
} else if ([identifier isEqualToString:INResumeWorkoutIntentIdentifier]) {
|
|
442
|
+
// IOSIntentIdentifier.RESUME_WORKOUT
|
|
443
|
+
[intentIdentifiers addObject:@13];
|
|
444
|
+
} else if ([identifier isEqualToString:INSetRadioStationIntentIdentifier]) {
|
|
445
|
+
// IOSIntentIdentifier.SET_RADIO_STATION
|
|
446
|
+
[intentIdentifiers addObject:@14];
|
|
447
|
+
} else if ([identifier isEqualToString:INSendMessageIntentIdentifier]) {
|
|
448
|
+
// IOSIntentIdentifier.SEND_MESSAGE
|
|
449
|
+
[intentIdentifiers addObject:@15];
|
|
450
|
+
} else if ([identifier isEqualToString:INSearchForMessagesIntentIdentifier]) {
|
|
451
|
+
// IOSIntentIdentifier.SEARCH_FOR_MESSAGES
|
|
452
|
+
[intentIdentifiers addObject:@16];
|
|
453
|
+
} else if ([identifier isEqualToString:INSetMessageAttributeIntentIdentifier]) {
|
|
454
|
+
// IOSIntentIdentifier.SET_MESSAGE_ATTRIBUTE
|
|
455
|
+
[intentIdentifiers addObject:@17];
|
|
456
|
+
} else if ([identifier isEqualToString:INSendPaymentIntentIdentifier]) {
|
|
457
|
+
// IOSIntentIdentifier.SEND_PAYMENT
|
|
458
|
+
[intentIdentifiers addObject:@18];
|
|
459
|
+
} else if ([identifier isEqualToString:INRequestPaymentIntentIdentifier]) {
|
|
460
|
+
// IOSIntentIdentifier.REQUEST_PAYMENT
|
|
461
|
+
[intentIdentifiers addObject:@19];
|
|
462
|
+
} else if ([identifier isEqualToString:INSearchForPhotosIntentIdentifier]) {
|
|
463
|
+
// IOSIntentIdentifier.SEARCH_FOR_PHOTOS
|
|
464
|
+
[intentIdentifiers addObject:@20];
|
|
465
|
+
} else if ([identifier isEqualToString:INStartPhotoPlaybackIntentIdentifier]) {
|
|
466
|
+
// IOSIntentIdentifier.START_PHOTO_PLAYBACK
|
|
467
|
+
[intentIdentifiers addObject:@21];
|
|
468
|
+
} else if ([identifier isEqualToString:INListRideOptionsIntentIdentifier]) {
|
|
469
|
+
// IOSIntentIdentifier.LIST_RIDE_OPTIONS
|
|
470
|
+
[intentIdentifiers addObject:@22];
|
|
471
|
+
} else if ([identifier isEqualToString:INRequestRideIntentIdentifier]) {
|
|
472
|
+
// IOSIntentIdentifier.REQUEST_RIDE
|
|
473
|
+
[intentIdentifiers addObject:@23];
|
|
474
|
+
} else if ([identifier isEqualToString:INGetRideStatusIntentIdentifier]) {
|
|
475
|
+
// IOSIntentIdentifier.GET_RIDE_STATUS
|
|
476
|
+
[intentIdentifiers addObject:@24];
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return intentIdentifiers;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
+ (NSMutableArray<NSString *> *)intentIdentifiersFromNumberArray:
|
|
484
|
+
(NSArray<NSNumber *> *)identifiers {
|
|
485
|
+
NSMutableArray<NSString *> *intentIdentifiers = [[NSMutableArray alloc] init];
|
|
486
|
+
|
|
487
|
+
for (NSNumber *identifier in identifiers) {
|
|
488
|
+
if ([identifier isEqualToNumber:@0]) {
|
|
489
|
+
// IOSIntentIdentifier.START_AUDIO_CALL
|
|
490
|
+
[intentIdentifiers addObject:INStartAudioCallIntentIdentifier];
|
|
491
|
+
} else if ([identifier isEqualToNumber:@1]) {
|
|
492
|
+
// IOSIntentIdentifier.START_VIDEO_CALL
|
|
493
|
+
[intentIdentifiers addObject:INStartVideoCallIntentIdentifier];
|
|
494
|
+
} else if ([identifier isEqualToNumber:@2]) {
|
|
495
|
+
// IOSIntentIdentifier.SEARCH_CALL_HISTORY
|
|
496
|
+
[intentIdentifiers addObject:INSearchCallHistoryIntentIdentifier];
|
|
497
|
+
} else if ([identifier isEqualToNumber:@3]) {
|
|
498
|
+
// IOSIntentIdentifier.SET_AUDIO_SOURCE_IN_CAR
|
|
499
|
+
[intentIdentifiers addObject:INSetAudioSourceInCarIntentIdentifier];
|
|
500
|
+
} else if ([identifier isEqualToNumber:@4]) {
|
|
501
|
+
// IOSIntentIdentifier.SET_CLIMATE_SETTINGS_IN_CAR
|
|
502
|
+
[intentIdentifiers addObject:INSetClimateSettingsInCarIntentIdentifier];
|
|
503
|
+
} else if ([identifier isEqualToNumber:@5]) {
|
|
504
|
+
// IOSIntentIdentifier.SET_DEFROSTER_SETTINGS_IN_CAR
|
|
505
|
+
[intentIdentifiers addObject:INSetDefrosterSettingsInCarIntentIdentifier];
|
|
506
|
+
} else if ([identifier isEqualToNumber:@6]) {
|
|
507
|
+
// IOSIntentIdentifier.SET_SEAT_SETTINGS_IN_CAR
|
|
508
|
+
[intentIdentifiers addObject:INSetSeatSettingsInCarIntentIdentifier];
|
|
509
|
+
} else if ([identifier isEqualToNumber:@7]) {
|
|
510
|
+
// IOSIntentIdentifier.SET_PROFILE_IN_CAR
|
|
511
|
+
[intentIdentifiers addObject:INSetProfileInCarIntentIdentifier];
|
|
512
|
+
} else if ([identifier isEqualToNumber:@8]) {
|
|
513
|
+
// IOSIntentIdentifier.SAVE_PROFILE_IN_CAR
|
|
514
|
+
[intentIdentifiers addObject:INSaveProfileInCarIntentIdentifier];
|
|
515
|
+
} else if ([identifier isEqualToNumber:@9]) {
|
|
516
|
+
// IOSIntentIdentifier.START_WORKOUT
|
|
517
|
+
[intentIdentifiers addObject:INStartWorkoutIntentIdentifier];
|
|
518
|
+
} else if ([identifier isEqualToNumber:@10]) {
|
|
519
|
+
// IOSIntentIdentifier.PAUSE_WORKOUT
|
|
520
|
+
[intentIdentifiers addObject:INPauseWorkoutIntentIdentifier];
|
|
521
|
+
} else if ([identifier isEqualToNumber:@11]) {
|
|
522
|
+
// IntentIdentifier.END_WORKOUT
|
|
523
|
+
[intentIdentifiers addObject:INEndWorkoutIntentIdentifier];
|
|
524
|
+
} else if ([identifier isEqualToNumber:@12]) {
|
|
525
|
+
// IOSIntentIdentifier.CANCEL_WORKOUT
|
|
526
|
+
[intentIdentifiers addObject:INCancelWorkoutIntentIdentifier];
|
|
527
|
+
} else if ([identifier isEqualToNumber:@13]) {
|
|
528
|
+
// IOSIntentIdentifier.RESUME_WORKOUT
|
|
529
|
+
[intentIdentifiers addObject:INResumeWorkoutIntentIdentifier];
|
|
530
|
+
} else if ([identifier isEqualToNumber:@14]) {
|
|
531
|
+
// IOSIntentIdentifier.SET_RADIO_STATION
|
|
532
|
+
[intentIdentifiers addObject:INSetRadioStationIntentIdentifier];
|
|
533
|
+
} else if ([identifier isEqualToNumber:@15]) {
|
|
534
|
+
// IOSIntentIdentifier.SEND_MESSAGE
|
|
535
|
+
[intentIdentifiers addObject:INSendMessageIntentIdentifier];
|
|
536
|
+
} else if ([identifier isEqualToNumber:@16]) {
|
|
537
|
+
// IOSIntentIdentifier.SEARCH_FOR_MESSAGES
|
|
538
|
+
[intentIdentifiers addObject:INSearchForMessagesIntentIdentifier];
|
|
539
|
+
} else if ([identifier isEqualToNumber:@17]) {
|
|
540
|
+
// IOSIntentIdentifier.SET_MESSAGE_ATTRIBUTE
|
|
541
|
+
[intentIdentifiers addObject:INSetMessageAttributeIntentIdentifier];
|
|
542
|
+
} else if ([identifier isEqualToNumber:@18]) {
|
|
543
|
+
// IOSIntentIdentifier.SEND_PAYMENT
|
|
544
|
+
[intentIdentifiers addObject:INSendPaymentIntentIdentifier];
|
|
545
|
+
} else if ([identifier isEqualToNumber:@19]) {
|
|
546
|
+
// IOSIntentIdentifier.REQUEST_PAYMENT
|
|
547
|
+
[intentIdentifiers addObject:INRequestPaymentIntentIdentifier];
|
|
548
|
+
} else if ([identifier isEqualToNumber:@20]) {
|
|
549
|
+
// IOSIntentIdentifier.SEARCH_FOR_PHOTOS
|
|
550
|
+
[intentIdentifiers addObject:INSearchForPhotosIntentIdentifier];
|
|
551
|
+
} else if ([identifier isEqualToNumber:@21]) {
|
|
552
|
+
// IOSIntentIdentifier.START_PHOTO_PLAYBACK
|
|
553
|
+
[intentIdentifiers addObject:INStartPhotoPlaybackIntentIdentifier];
|
|
554
|
+
} else if ([identifier isEqualToNumber:@22]) {
|
|
555
|
+
// IOSIntentIdentifier.LIST_RIDE_OPTIONS
|
|
556
|
+
[intentIdentifiers addObject:INListRideOptionsIntentIdentifier];
|
|
557
|
+
} else if ([identifier isEqualToNumber:@23]) {
|
|
558
|
+
// IOSIntentIdentifier.REQUEST_RIDE
|
|
559
|
+
[intentIdentifiers addObject:INRequestRideIntentIdentifier];
|
|
560
|
+
} else if ([identifier isEqualToNumber:@24]) {
|
|
561
|
+
// IOSIntentIdentifier.GET_RIDE_STATUS
|
|
562
|
+
[intentIdentifiers addObject:INGetRideStatusIntentIdentifier];
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return intentIdentifiers;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Returns timestamp in millisecons
|
|
571
|
+
*
|
|
572
|
+
* @param date NSDate
|
|
573
|
+
*/
|
|
574
|
+
+ (NSNumber *)convertToTimestamp:(NSDate *)date {
|
|
575
|
+
return [NSNumber numberWithDouble:([date timeIntervalSince1970] * 1000)];
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Parse UNNotificationRequest to NSDictionary
|
|
580
|
+
*
|
|
581
|
+
* @param request UNNotificationRequest
|
|
582
|
+
*/
|
|
583
|
+
+ (NSMutableDictionary *)parseUNNotificationRequest:(UNNotificationRequest *)request {
|
|
584
|
+
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
|
585
|
+
|
|
586
|
+
dictionary = [self parseUNNotificationContent:request.content];
|
|
587
|
+
dictionary[@"id"] = request.identifier;
|
|
588
|
+
|
|
589
|
+
NSDictionary *userInfo = request.content.userInfo;
|
|
590
|
+
|
|
591
|
+
// Check for remote details
|
|
592
|
+
if ([request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
|
|
593
|
+
NSMutableDictionary *remote = [NSMutableDictionary dictionary];
|
|
594
|
+
|
|
595
|
+
remote[@"messageId"] = userInfo[@"gcm.message_id"];
|
|
596
|
+
remote[@"senderId"] = userInfo[@"google.c.sender.id"];
|
|
597
|
+
|
|
598
|
+
if (userInfo[@"aps"] != nil) {
|
|
599
|
+
remote[@"mutableContent"] = userInfo[@"aps"][@"mutable-content"];
|
|
600
|
+
remote[@"contentAvailable"] = userInfo[@"aps"][@"content-available"];
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
dictionary[@"remote"] = remote;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
dictionary[@"data"] = [self parseDataFromUserInfo:userInfo];
|
|
607
|
+
|
|
608
|
+
return dictionary;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
+ (NSMutableDictionary *)parseDataFromUserInfo:(NSDictionary *)userInfo {
|
|
612
|
+
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
|
|
613
|
+
for (id key in userInfo) {
|
|
614
|
+
// build data dict from remaining keys but skip keys that shouldn't be included in data
|
|
615
|
+
if ([key isEqualToString:@"aps"] || [key hasPrefix:@"gcm."] || [key hasPrefix:@"google."] ||
|
|
616
|
+
// notifee or notifee_options
|
|
617
|
+
[key hasPrefix:@"notifee"] ||
|
|
618
|
+
// fcm_options
|
|
619
|
+
[key hasPrefix:@"fcm"]) {
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
data[key] = userInfo[key];
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
return data;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
+ (NSMutableDictionary *)parseUNNotificationContent:(UNNotificationContent *)content {
|
|
629
|
+
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
|
|
630
|
+
NSMutableDictionary *iosDict = [NSMutableDictionary dictionary];
|
|
631
|
+
|
|
632
|
+
dictionary[@"subtitle"] = content.subtitle;
|
|
633
|
+
dictionary[@"body"] = content.body;
|
|
634
|
+
dictionary[@"data"] = [content.userInfo mutableCopy];
|
|
635
|
+
|
|
636
|
+
// title
|
|
637
|
+
if (content.title != nil) {
|
|
638
|
+
dictionary[@"title"] = content.title;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// subtitle
|
|
642
|
+
if (content.subtitle != nil) {
|
|
643
|
+
dictionary[@"subtitle"] = content.subtitle;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// body
|
|
647
|
+
if (content.body != nil) {
|
|
648
|
+
dictionary[@"body"] = content.body;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
iosDict[@"badgeCount"] = content.badge;
|
|
652
|
+
|
|
653
|
+
// categoryId
|
|
654
|
+
if (content.categoryIdentifier != nil) {
|
|
655
|
+
iosDict[@"categoryId"] = content.categoryIdentifier;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// launchImageName
|
|
659
|
+
if (content.launchImageName != nil) {
|
|
660
|
+
iosDict[@"launchImageName"] = content.launchImageName;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// threadId
|
|
664
|
+
if (content.threadIdentifier != nil) {
|
|
665
|
+
iosDict[@"threadId"] = content.threadIdentifier;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// targetContentId
|
|
669
|
+
if (@available(iOS 13.0, macOS 10.15, macCatalyst 13.0, tvOS 13.0, watchOS 6.0, *)) {
|
|
670
|
+
if (content.targetContentIdentifier != nil) {
|
|
671
|
+
iosDict[@"targetContentId"] = content.targetContentIdentifier;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
if (content.attachments != nil) {
|
|
676
|
+
// TODO: parse attachments
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// sound
|
|
680
|
+
if (content.sound != nil) {
|
|
681
|
+
if ([content.sound isKindOfClass:[NSString class]]) {
|
|
682
|
+
iosDict[@"sound"] = content.sound;
|
|
683
|
+
} else if ([content.sound isKindOfClass:[NSDictionary class]]) {
|
|
684
|
+
NSDictionary *soundDict = content.sound;
|
|
685
|
+
NSMutableDictionary *notificationIOSSound = [[NSMutableDictionary alloc] init];
|
|
686
|
+
|
|
687
|
+
// ios.sound.name String
|
|
688
|
+
if (soundDict[@"name"] != nil) {
|
|
689
|
+
notificationIOSSound[@"name"] = soundDict[@"name"];
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// sound.critical Boolean
|
|
693
|
+
if (soundDict[@"critical"] != nil) {
|
|
694
|
+
notificationIOSSound[@"critical"] = soundDict[@"critical"];
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// ios.sound.volume Number
|
|
698
|
+
if (soundDict[@"volume"] != nil) {
|
|
699
|
+
notificationIOSSound[@"volume"] = soundDict[@"volume"];
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// ios.sound
|
|
703
|
+
iosDict[@"sound"] = notificationIOSSound;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
dictionary[@"ios"] = iosDict;
|
|
708
|
+
return dictionary;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
+ (INSendMessageIntent *)generateSenderIntentForCommunicationNotifciation:
|
|
712
|
+
(NSDictionary *)communicationInfo {
|
|
713
|
+
if (@available(iOS 15.0, *)) {
|
|
714
|
+
NSDictionary *sender = communicationInfo[@"sender"];
|
|
715
|
+
INPersonHandle *senderPersonHandle =
|
|
716
|
+
[[INPersonHandle alloc] initWithValue:sender[@"id"] type:INPersonHandleTypeUnknown];
|
|
717
|
+
|
|
718
|
+
// Parse sender's avatar
|
|
719
|
+
INImage *avatar = nil;
|
|
720
|
+
if (sender[@"avatar"] != nil) {
|
|
721
|
+
NSURL *url = [[NSURL alloc] initWithString:sender[@"avatar"]];
|
|
722
|
+
avatar = [INImage imageWithURL:url];
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
INPerson *senderPerson = [[INPerson alloc] initWithPersonHandle:senderPersonHandle
|
|
726
|
+
nameComponents:nil
|
|
727
|
+
displayName:sender[@"displayName"]
|
|
728
|
+
image:avatar
|
|
729
|
+
contactIdentifier:nil
|
|
730
|
+
customIdentifier:nil];
|
|
731
|
+
|
|
732
|
+
INSendMessageIntent *intent =
|
|
733
|
+
[[INSendMessageIntent alloc] initWithRecipients:nil
|
|
734
|
+
outgoingMessageType:INOutgoingMessageTypeOutgoingMessageText
|
|
735
|
+
content:communicationInfo[@"body"]
|
|
736
|
+
speakableGroupName:nil
|
|
737
|
+
conversationIdentifier:communicationInfo[@"conversationId"]
|
|
738
|
+
serviceName:nil
|
|
739
|
+
sender:senderPerson
|
|
740
|
+
attachments:nil];
|
|
741
|
+
|
|
742
|
+
return intent;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
return nil;
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Returns a random string using UUID
|
|
749
|
+
*
|
|
750
|
+
* @param length int
|
|
751
|
+
*/
|
|
752
|
+
+ (NSString *)generateCachedFileName:(int)length {
|
|
753
|
+
return [[NSUUID UUID] UUIDString];
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Returns a shared instance of [UIApplication sharedApplication]
|
|
758
|
+
* Needed to prevent compile errors for App extensions when calling [UIApplication
|
|
759
|
+
* sharedApplication]
|
|
760
|
+
*
|
|
761
|
+
* @return instancetype
|
|
762
|
+
*/
|
|
763
|
+
+ (nullable instancetype)notifeeUIApplication {
|
|
764
|
+
static dispatch_once_t once;
|
|
765
|
+
static NotifeeCoreUtil *sharedInstance;
|
|
766
|
+
dispatch_once(&once, ^{
|
|
767
|
+
static Class applicationClass = nil;
|
|
768
|
+
if (![self isAppExtension]) {
|
|
769
|
+
Class cls = NSClassFromString(@"UIApplication");
|
|
770
|
+
if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) {
|
|
771
|
+
applicationClass = cls;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
sharedInstance = (NotifeeCoreUtil *)[applicationClass sharedApplication];
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
return sharedInstance;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* Checks if the current application is an extension
|
|
783
|
+
*/
|
|
784
|
+
+ (BOOL)isAppExtension {
|
|
785
|
+
#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH
|
|
786
|
+
BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"];
|
|
787
|
+
return appExtension;
|
|
788
|
+
#elif TARGET_OS_OSX
|
|
789
|
+
return NO;
|
|
790
|
+
#endif
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
@end
|