@radhya/mach-push-react-native 0.1.2 → 0.1.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.
- package/ios/MachPush.swift +28 -13
- package/ios/MachPushAppDelegateInterceptor.m +83 -28
- package/package.json +1 -1
package/ios/MachPush.swift
CHANGED
|
@@ -5,8 +5,13 @@ import UserNotifications
|
|
|
5
5
|
|
|
6
6
|
@objc(MachPush)
|
|
7
7
|
final class MachPush: RCTEventEmitter {
|
|
8
|
-
private
|
|
9
|
-
|
|
8
|
+
private struct PendingNativeTokenRequest {
|
|
9
|
+
let id: UUID
|
|
10
|
+
let resolve: RCTPromiseResolveBlock
|
|
11
|
+
let reject: RCTPromiseRejectBlock
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private var nativeTokenRequests: [PendingNativeTokenRequest] = []
|
|
10
15
|
private var hasEventListeners = false
|
|
11
16
|
|
|
12
17
|
override init() {
|
|
@@ -108,11 +113,23 @@ final class MachPush: RCTEventEmitter {
|
|
|
108
113
|
resolve(token)
|
|
109
114
|
return
|
|
110
115
|
}
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
let request = PendingNativeTokenRequest(id: UUID(), resolve: resolve, reject: reject)
|
|
117
|
+
nativeTokenRequests.append(request)
|
|
113
118
|
DispatchQueue.main.async {
|
|
114
119
|
UIApplication.shared.registerForRemoteNotifications()
|
|
115
120
|
}
|
|
121
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 20) { [weak self] in
|
|
122
|
+
guard let self else { return }
|
|
123
|
+
guard let index = self.nativeTokenRequests.firstIndex(where: { $0.id == request.id }) else {
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
let pending = self.nativeTokenRequests.remove(at: index)
|
|
127
|
+
pending.reject(
|
|
128
|
+
"MACH_PUSH_APNS_TOKEN_TIMEOUT",
|
|
129
|
+
"Timed out waiting for an APNs device token. Confirm the iOS build has the Push Notifications capability / aps-environment entitlement and that the app is installed on a physical device.",
|
|
130
|
+
nil
|
|
131
|
+
)
|
|
132
|
+
}
|
|
116
133
|
}
|
|
117
134
|
|
|
118
135
|
@objc(getDeviceInfo:rejecter:)
|
|
@@ -162,19 +179,17 @@ final class MachPush: RCTEventEmitter {
|
|
|
162
179
|
|
|
163
180
|
@objc private func didRegisterToken(_ notification: Notification) {
|
|
164
181
|
guard let token = notification.userInfo?["token"] as? String else { return }
|
|
165
|
-
let
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
resolvers.forEach { $0(token) }
|
|
182
|
+
let requests = nativeTokenRequests
|
|
183
|
+
nativeTokenRequests.removeAll()
|
|
184
|
+
requests.forEach { $0.resolve(token) }
|
|
169
185
|
}
|
|
170
186
|
|
|
171
187
|
@objc private func didFailRegistration(_ notification: Notification) {
|
|
172
188
|
let error = notification.userInfo?["error"] as? NSError
|
|
173
|
-
let
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
$0(
|
|
189
|
+
let requests = nativeTokenRequests
|
|
190
|
+
nativeTokenRequests.removeAll()
|
|
191
|
+
requests.forEach {
|
|
192
|
+
$0.reject(
|
|
178
193
|
"MACH_PUSH_REGISTRATION",
|
|
179
194
|
error?.localizedDescription ?? "APNs registration failed.",
|
|
180
195
|
error
|
|
@@ -5,20 +5,75 @@
|
|
|
5
5
|
NSString * const MachPushDidRegisterTokenNotification = @"MachPushDidRegisterTokenNotification";
|
|
6
6
|
NSString * const MachPushDidFailRegistrationNotification = @"MachPushDidFailRegistrationNotification";
|
|
7
7
|
|
|
8
|
+
static void MachPushPostDeviceToken(NSData *deviceToken) {
|
|
9
|
+
const unsigned char *bytes = deviceToken.bytes;
|
|
10
|
+
NSMutableString *token = [NSMutableString stringWithCapacity:deviceToken.length * 2];
|
|
11
|
+
for (NSUInteger index = 0; index < deviceToken.length; index++) {
|
|
12
|
+
[token appendFormat:@"%02x", bytes[index]];
|
|
13
|
+
}
|
|
14
|
+
[[NSUserDefaults standardUserDefaults] setObject:token forKey:@"mach.push.nativeToken"];
|
|
15
|
+
[[NSNotificationCenter defaultCenter]
|
|
16
|
+
postNotificationName:MachPushDidRegisterTokenNotification
|
|
17
|
+
object:nil
|
|
18
|
+
userInfo:@{ @"token": token }];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static void MachPushPostRegistrationError(NSError *error) {
|
|
22
|
+
[[NSNotificationCenter defaultCenter]
|
|
23
|
+
postNotificationName:MachPushDidFailRegistrationNotification
|
|
24
|
+
object:nil
|
|
25
|
+
userInfo:@{ @"error": error }];
|
|
26
|
+
}
|
|
27
|
+
|
|
8
28
|
static BOOL MachPushSwizzle(Class cls, SEL original, SEL replacement) {
|
|
9
|
-
Method replacementMethod = class_getInstanceMethod(
|
|
29
|
+
Method replacementMethod = class_getInstanceMethod([NSObject class], replacement);
|
|
10
30
|
if (!replacementMethod) return NO;
|
|
11
31
|
Method originalMethod = class_getInstanceMethod(cls, original);
|
|
12
32
|
if (!originalMethod) {
|
|
13
33
|
class_addMethod(cls, original, method_getImplementation(replacementMethod), method_getTypeEncoding(replacementMethod));
|
|
14
34
|
return NO;
|
|
15
35
|
}
|
|
16
|
-
|
|
36
|
+
|
|
37
|
+
// Copy the original implementation onto the concrete app delegate class so
|
|
38
|
+
// `[self mach_application:...]` reliably reaches the app/Expo handler even
|
|
39
|
+
// when the original method is inherited from a Swift superclass.
|
|
40
|
+
class_addMethod(
|
|
41
|
+
cls,
|
|
42
|
+
replacement,
|
|
43
|
+
method_getImplementation(originalMethod),
|
|
44
|
+
method_getTypeEncoding(originalMethod)
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
Method concreteOriginal = class_getInstanceMethod(cls, original);
|
|
48
|
+
Method concreteReplacement = class_getInstanceMethod(cls, replacement);
|
|
49
|
+
if (!concreteOriginal || !concreteReplacement) return NO;
|
|
50
|
+
method_exchangeImplementations(concreteOriginal, concreteReplacement);
|
|
17
51
|
return YES;
|
|
18
52
|
}
|
|
19
53
|
|
|
20
54
|
static BOOL MachPushHadRegisterHandler = NO;
|
|
21
55
|
static BOOL MachPushHadFailureHandler = NO;
|
|
56
|
+
static Class MachPushInstalledDelegateClass = Nil;
|
|
57
|
+
|
|
58
|
+
static void MachPushInstallInterceptorIfNeeded(void) {
|
|
59
|
+
if (MachPushInstalledDelegateClass) return;
|
|
60
|
+
|
|
61
|
+
id<UIApplicationDelegate> delegate = UIApplication.sharedApplication.delegate;
|
|
62
|
+
Class appDelegateClass = delegate ? object_getClass(delegate) : NSClassFromString(@"AppDelegate");
|
|
63
|
+
if (!appDelegateClass) return;
|
|
64
|
+
|
|
65
|
+
MachPushHadRegisterHandler = MachPushSwizzle(
|
|
66
|
+
appDelegateClass,
|
|
67
|
+
@selector(application:didRegisterForRemoteNotificationsWithDeviceToken:),
|
|
68
|
+
@selector(mach_application:didRegisterForRemoteNotificationsWithDeviceToken:)
|
|
69
|
+
);
|
|
70
|
+
MachPushHadFailureHandler = MachPushSwizzle(
|
|
71
|
+
appDelegateClass,
|
|
72
|
+
@selector(application:didFailToRegisterForRemoteNotificationsWithError:),
|
|
73
|
+
@selector(mach_application:didFailToRegisterForRemoteNotificationsWithError:)
|
|
74
|
+
);
|
|
75
|
+
MachPushInstalledDelegateClass = appDelegateClass;
|
|
76
|
+
}
|
|
22
77
|
|
|
23
78
|
@interface NSObject (MachPushAppDelegateInterceptor)
|
|
24
79
|
@end
|
|
@@ -27,33 +82,36 @@ static BOOL MachPushHadFailureHandler = NO;
|
|
|
27
82
|
|
|
28
83
|
+ (void)load {
|
|
29
84
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
)
|
|
85
|
+
MachPushInstallInterceptorIfNeeded();
|
|
86
|
+
[[NSNotificationCenter defaultCenter]
|
|
87
|
+
addObserverForName:UIApplicationDidFinishLaunchingNotification
|
|
88
|
+
object:nil
|
|
89
|
+
queue:[NSOperationQueue mainQueue]
|
|
90
|
+
usingBlock:^(__unused NSNotification *note) {
|
|
91
|
+
MachPushInstallInterceptorIfNeeded();
|
|
92
|
+
}];
|
|
93
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
94
|
+
MachPushInstallInterceptorIfNeeded();
|
|
95
|
+
});
|
|
96
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
97
|
+
MachPushInstallInterceptorIfNeeded();
|
|
98
|
+
});
|
|
42
99
|
});
|
|
43
100
|
}
|
|
44
101
|
|
|
102
|
+
- (void)application:(UIApplication *)application
|
|
103
|
+
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
|
|
104
|
+
MachPushPostDeviceToken(deviceToken);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
- (void)application:(UIApplication *)application
|
|
108
|
+
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
|
|
109
|
+
MachPushPostRegistrationError(error);
|
|
110
|
+
}
|
|
111
|
+
|
|
45
112
|
- (void)mach_application:(UIApplication *)application
|
|
46
113
|
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
|
|
47
|
-
|
|
48
|
-
NSMutableString *token = [NSMutableString stringWithCapacity:deviceToken.length * 2];
|
|
49
|
-
for (NSUInteger index = 0; index < deviceToken.length; index++) {
|
|
50
|
-
[token appendFormat:@"%02x", bytes[index]];
|
|
51
|
-
}
|
|
52
|
-
[[NSUserDefaults standardUserDefaults] setObject:token forKey:@"mach.push.nativeToken"];
|
|
53
|
-
[[NSNotificationCenter defaultCenter]
|
|
54
|
-
postNotificationName:MachPushDidRegisterTokenNotification
|
|
55
|
-
object:nil
|
|
56
|
-
userInfo:@{ @"token": token }];
|
|
114
|
+
MachPushPostDeviceToken(deviceToken);
|
|
57
115
|
if (MachPushHadRegisterHandler) {
|
|
58
116
|
[self mach_application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
|
|
59
117
|
}
|
|
@@ -61,10 +119,7 @@ static BOOL MachPushHadFailureHandler = NO;
|
|
|
61
119
|
|
|
62
120
|
- (void)mach_application:(UIApplication *)application
|
|
63
121
|
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
|
|
64
|
-
|
|
65
|
-
postNotificationName:MachPushDidFailRegistrationNotification
|
|
66
|
-
object:nil
|
|
67
|
-
userInfo:@{ @"error": error }];
|
|
122
|
+
MachPushPostRegistrationError(error);
|
|
68
123
|
if (MachPushHadFailureHandler) {
|
|
69
124
|
[self mach_application:application didFailToRegisterForRemoteNotificationsWithError:error];
|
|
70
125
|
}
|