react-native-push-signal 0.1.6 → 0.1.7
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/LICENSE +1 -1
- package/PushSignal.podspec +2 -12
- package/README.md +1 -3
- package/README.ru.md +1 -3
- package/android/build.gradle +1 -62
- package/android/consumer-rules.pro +3 -3
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/com/pushsignal/PushModels.kt +15 -0
- package/android/src/main/java/com/{margelo/nitro/pushsignal → pushsignal}/PushSignalCenter.kt +2 -3
- package/android/src/main/java/com/{margelo/nitro/pushsignal → pushsignal}/PushSignalInitProvider.kt +1 -1
- package/android/src/main/java/com/{margelo/nitro/pushsignal → pushsignal}/PushSignalMessagingService.kt +1 -1
- package/android/src/main/java/com/pushsignal/PushSignalModule.kt +88 -0
- package/android/src/main/java/com/pushsignal/PushSignalPackage.kt +30 -0
- package/ios/PushSignal.h +4 -0
- package/ios/PushSignal.mm +57 -0
- package/ios/PushSignalCenter.h +26 -0
- package/ios/PushSignalCenter.m +608 -0
- package/ios/PushSignalLaunchStore.m +3 -14
- package/lib/module/NativePushSignal.js +5 -0
- package/lib/module/NativePushSignal.js.map +1 -0
- package/lib/module/pushSignal.native.js +33 -7
- package/lib/module/pushSignal.native.js.map +1 -1
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/src/NativePushSignal.d.ts +22 -0
- package/lib/typescript/src/NativePushSignal.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/pushSignal.d.ts +1 -1
- package/lib/typescript/src/pushSignal.d.ts.map +1 -1
- package/lib/typescript/src/pushSignal.native.d.ts +1 -1
- package/lib/typescript/src/pushSignal.native.d.ts.map +1 -1
- package/lib/typescript/src/{PushSignal.nitro.d.ts → types.d.ts} +2 -12
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +14 -19
- package/src/NativePushSignal.ts +25 -0
- package/src/index.tsx +1 -1
- package/src/pushSignal.native.tsx +54 -11
- package/src/pushSignal.tsx +1 -1
- package/src/types.ts +25 -0
- package/android/CMakeLists.txt +0 -24
- package/android/src/main/cpp/cpp-adapter.cpp +0 -11
- package/android/src/main/java/com/margelo/nitro/pushsignal/PushSignal.kt +0 -38
- package/android/src/main/java/com/margelo/nitro/pushsignal/PushSignalPackage.kt +0 -22
- package/ios/PushSignal.swift +0 -29
- package/ios/PushSignalCenter.swift +0 -604
- package/lib/module/PushSignal.nitro.js +0 -4
- package/lib/module/PushSignal.nitro.js.map +0 -1
- package/lib/typescript/src/PushSignal.nitro.d.ts.map +0 -1
- package/nitro.json +0 -23
- package/nitrogen/generated/android/c++/JAndroidFirebaseConfig.hpp +0 -70
- package/nitrogen/generated/android/c++/JFunc_void_PushMessage.hpp +0 -80
- package/nitrogen/generated/android/c++/JHybridPushSignalSpec.cpp +0 -114
- package/nitrogen/generated/android/c++/JHybridPushSignalSpec.hpp +0 -66
- package/nitrogen/generated/android/c++/JPushCredentials.hpp +0 -70
- package/nitrogen/generated/android/c++/JPushEnvironment.hpp +0 -58
- package/nitrogen/generated/android/c++/JPushMessage.hpp +0 -84
- package/nitrogen/generated/android/c++/JPushPlatform.hpp +0 -58
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/AndroidFirebaseConfig.kt +0 -66
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/Func_void_PushMessage.kt +0 -78
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/HybridPushSignalSpec.kt +0 -79
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushCredentials.kt +0 -61
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushEnvironment.kt +0 -23
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushMessage.kt +0 -66
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushPlatform.kt +0 -23
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/pushsignalOnLoad.kt +0 -35
- package/nitrogen/generated/android/pushsignal+autolinking.cmake +0 -81
- package/nitrogen/generated/android/pushsignal+autolinking.gradle +0 -27
- package/nitrogen/generated/android/pushsignalOnLoad.cpp +0 -56
- package/nitrogen/generated/android/pushsignalOnLoad.hpp +0 -34
- package/nitrogen/generated/ios/PushSignal+autolinking.rb +0 -62
- package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Bridge.cpp +0 -65
- package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Bridge.hpp +0 -254
- package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Umbrella.hpp +0 -63
- package/nitrogen/generated/ios/PushSignalAutolinking.mm +0 -33
- package/nitrogen/generated/ios/PushSignalAutolinking.swift +0 -26
- package/nitrogen/generated/ios/c++/HybridPushSignalSpecSwift.cpp +0 -11
- package/nitrogen/generated/ios/c++/HybridPushSignalSpecSwift.hpp +0 -120
- package/nitrogen/generated/ios/swift/AndroidFirebaseConfig.swift +0 -96
- package/nitrogen/generated/ios/swift/Func_void.swift +0 -46
- package/nitrogen/generated/ios/swift/Func_void_PushCredentials.swift +0 -46
- package/nitrogen/generated/ios/swift/Func_void_PushMessage.swift +0 -46
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +0 -46
- package/nitrogen/generated/ios/swift/HybridPushSignalSpec.swift +0 -58
- package/nitrogen/generated/ios/swift/HybridPushSignalSpec_cxx.swift +0 -196
- package/nitrogen/generated/ios/swift/PushCredentials.swift +0 -45
- package/nitrogen/generated/ios/swift/PushEnvironment.swift +0 -40
- package/nitrogen/generated/ios/swift/PushMessage.swift +0 -97
- package/nitrogen/generated/ios/swift/PushPlatform.swift +0 -40
- package/nitrogen/generated/shared/c++/AndroidFirebaseConfig.hpp +0 -96
- package/nitrogen/generated/shared/c++/HybridPushSignalSpec.cpp +0 -24
- package/nitrogen/generated/shared/c++/HybridPushSignalSpec.hpp +0 -74
- package/nitrogen/generated/shared/c++/PushCredentials.hpp +0 -97
- package/nitrogen/generated/shared/c++/PushEnvironment.hpp +0 -76
- package/nitrogen/generated/shared/c++/PushMessage.hpp +0 -97
- package/nitrogen/generated/shared/c++/PushPlatform.hpp +0 -76
- package/src/PushSignal.nitro.ts +0 -39
|
@@ -1,604 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
import NitroModules
|
|
3
|
-
import ObjectiveC
|
|
4
|
-
import UIKit
|
|
5
|
-
import UserNotifications
|
|
6
|
-
|
|
7
|
-
@objc(PushSignalCenter)
|
|
8
|
-
final class PushSignalCenter: NSObject, UNUserNotificationCenterDelegate {
|
|
9
|
-
@objc static let shared = PushSignalCenter()
|
|
10
|
-
|
|
11
|
-
@objc static func bootstrap(launchOptions: [AnyHashable: Any]?) {
|
|
12
|
-
shared.pendingLaunchOptions = launchOptions
|
|
13
|
-
shared.install()
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/// Called from ObjC `+load` / launch notifications so the UNUserNotificationCenter
|
|
17
|
-
/// delegate is set before the app finishes launching. If this happens after JS loads,
|
|
18
|
-
/// iOS never calls `willPresent` and foreground pushes never reach JS.
|
|
19
|
-
@objc static func installEarly() {
|
|
20
|
-
shared.install()
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
private let lock = NSLock()
|
|
24
|
-
private var didInstall = false
|
|
25
|
-
private var didSwizzleAppDelegate = false
|
|
26
|
-
private var didSwizzleNotificationCenter = false
|
|
27
|
-
private var deviceToken: String?
|
|
28
|
-
private var registrationError: Error?
|
|
29
|
-
private var tokenWaiters: [(Result<String, Error>) -> Void] = []
|
|
30
|
-
private var pendingPress: PushMessage?
|
|
31
|
-
private var pendingMessages: [PushMessage] = []
|
|
32
|
-
private var pendingLaunchOptions: [AnyHashable: Any]?
|
|
33
|
-
private var didCaptureLaunchNotification = false
|
|
34
|
-
private var recentMessageIds: [String: Date] = [:]
|
|
35
|
-
private weak var forwardingDelegate: UNUserNotificationCenterDelegate?
|
|
36
|
-
|
|
37
|
-
var onMessage: ((PushMessage) -> Void)? {
|
|
38
|
-
didSet {
|
|
39
|
-
flushPendingMessages()
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
var onNotificationPress: ((PushMessage) -> Void)? {
|
|
43
|
-
didSet {
|
|
44
|
-
flushPendingPress()
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
func install() {
|
|
49
|
-
if Thread.isMainThread {
|
|
50
|
-
installOnMain()
|
|
51
|
-
} else {
|
|
52
|
-
DispatchQueue.main.async {
|
|
53
|
-
self.installOnMain()
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
private func installOnMain() {
|
|
59
|
-
swizzleNotificationCenterDelegateIfNeeded()
|
|
60
|
-
|
|
61
|
-
guard !didInstall else {
|
|
62
|
-
UNUserNotificationCenter.current().delegate = self
|
|
63
|
-
swizzleAppDelegate()
|
|
64
|
-
captureLaunchNotificationIfNeeded()
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
didInstall = true
|
|
69
|
-
UNUserNotificationCenter.current().delegate = self
|
|
70
|
-
swizzleAppDelegate()
|
|
71
|
-
captureLaunchNotificationIfNeeded()
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
func rememberForwardingDelegate(_ delegate: UNUserNotificationCenterDelegate?) {
|
|
75
|
-
if let delegate, delegate !== self {
|
|
76
|
-
forwardingDelegate = delegate
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
func fetchCredentials() async throws -> PushCredentials {
|
|
81
|
-
await MainActor.run {
|
|
82
|
-
self.installOnMain()
|
|
83
|
-
UIApplication.shared.registerForRemoteNotifications()
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
let token = try await waitForToken()
|
|
87
|
-
return PushCredentials(
|
|
88
|
-
platform: .ios,
|
|
89
|
-
token: token,
|
|
90
|
-
environment: currentEnvironment()
|
|
91
|
-
)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
func handleDeviceToken(_ deviceToken: Data) {
|
|
95
|
-
let token = deviceToken.map { String(format: "%02x", $0) }.joined()
|
|
96
|
-
finishRegistration(result: .success(token))
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
func handleRegistrationError(_ error: Error) {
|
|
100
|
-
finishRegistration(result: .failure(error))
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
@objc func userNotificationCenter(
|
|
104
|
-
_ center: UNUserNotificationCenter,
|
|
105
|
-
willPresent notification: UNNotification,
|
|
106
|
-
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
|
|
107
|
-
) {
|
|
108
|
-
deliverMessage(Self.message(from: notification))
|
|
109
|
-
forwardWillPresent(
|
|
110
|
-
center,
|
|
111
|
-
notification: notification,
|
|
112
|
-
ourOptions: Self.foregroundPresentationOptions,
|
|
113
|
-
completionHandler: completionHandler
|
|
114
|
-
)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
@objc func userNotificationCenter(
|
|
118
|
-
_ center: UNUserNotificationCenter,
|
|
119
|
-
didReceive response: UNNotificationResponse,
|
|
120
|
-
withCompletionHandler completionHandler: @escaping () -> Void
|
|
121
|
-
) {
|
|
122
|
-
emitPress(Self.message(from: response.notification))
|
|
123
|
-
if forwardingDelegate?.responds(
|
|
124
|
-
to: #selector(UNUserNotificationCenterDelegate.userNotificationCenter(_:didReceive:withCompletionHandler:))
|
|
125
|
-
) == true {
|
|
126
|
-
forwardingDelegate?.userNotificationCenter?(center, didReceive: response, withCompletionHandler: completionHandler)
|
|
127
|
-
} else {
|
|
128
|
-
completionHandler()
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
private func waitForToken() async throws -> String {
|
|
133
|
-
if let deviceToken {
|
|
134
|
-
return deviceToken
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if let registrationError {
|
|
138
|
-
throw registrationError
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return try await withCheckedThrowingContinuation { continuation in
|
|
142
|
-
var didResume = false
|
|
143
|
-
let finish: (Result<String, Error>) -> Void = { result in
|
|
144
|
-
guard !didResume else {
|
|
145
|
-
return
|
|
146
|
-
}
|
|
147
|
-
didResume = true
|
|
148
|
-
continuation.resume(with: result)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
lock.lock()
|
|
152
|
-
if let deviceToken {
|
|
153
|
-
lock.unlock()
|
|
154
|
-
finish(.success(deviceToken))
|
|
155
|
-
return
|
|
156
|
-
}
|
|
157
|
-
if let registrationError {
|
|
158
|
-
lock.unlock()
|
|
159
|
-
finish(.failure(registrationError))
|
|
160
|
-
return
|
|
161
|
-
}
|
|
162
|
-
tokenWaiters.append(finish)
|
|
163
|
-
lock.unlock()
|
|
164
|
-
|
|
165
|
-
DispatchQueue.main.asyncAfter(deadline: .now() + 20) {
|
|
166
|
-
let timeout = NSError(
|
|
167
|
-
domain: "PushSignal",
|
|
168
|
-
code: 1,
|
|
169
|
-
userInfo: [
|
|
170
|
-
NSLocalizedDescriptionKey:
|
|
171
|
-
"APNs registration timed out. Use a physical iOS device and enable the Push Notifications capability.",
|
|
172
|
-
]
|
|
173
|
-
)
|
|
174
|
-
PushSignalCenter.shared.finishRegistration(result: .failure(timeout))
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
private func finishRegistration(result: Result<String, Error>) {
|
|
180
|
-
lock.lock()
|
|
181
|
-
switch result {
|
|
182
|
-
case let .success(token):
|
|
183
|
-
deviceToken = token
|
|
184
|
-
registrationError = nil
|
|
185
|
-
case let .failure(error):
|
|
186
|
-
if deviceToken == nil {
|
|
187
|
-
registrationError = error
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
let waiters = tokenWaiters
|
|
191
|
-
tokenWaiters.removeAll()
|
|
192
|
-
lock.unlock()
|
|
193
|
-
|
|
194
|
-
waiters.forEach { $0(result) }
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
private func synchronized<T>(_ body: () -> T) -> T {
|
|
198
|
-
lock.lock()
|
|
199
|
-
defer { lock.unlock() }
|
|
200
|
-
return body()
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
private func deliverMessage(_ message: PushMessage) {
|
|
204
|
-
guard shouldEmit(message) else {
|
|
205
|
-
return
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
let callback = synchronized { onMessage }
|
|
209
|
-
guard let callback else {
|
|
210
|
-
synchronized { pendingMessages.append(message) }
|
|
211
|
-
return
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
emitToJs(callback, message: message)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
private func emitToJs(
|
|
218
|
-
_ callback: @escaping (PushMessage) -> Void,
|
|
219
|
-
message: PushMessage
|
|
220
|
-
) {
|
|
221
|
-
DispatchQueue.main.async {
|
|
222
|
-
callback(message)
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
private func flushPendingMessages() {
|
|
227
|
-
DispatchQueue.main.async {
|
|
228
|
-
let callback = self.synchronized { self.onMessage }
|
|
229
|
-
let queued = self.synchronized { () -> [PushMessage] in
|
|
230
|
-
let messages = self.pendingMessages
|
|
231
|
-
self.pendingMessages.removeAll()
|
|
232
|
-
return messages
|
|
233
|
-
}
|
|
234
|
-
guard let callback, !queued.isEmpty else {
|
|
235
|
-
return
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
for message in queued {
|
|
239
|
-
self.emitToJs(callback, message: message)
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
private func shouldEmit(_ message: PushMessage) -> Bool {
|
|
245
|
-
let key = message.id ?? "\(message.title ?? "")|\(message.body ?? "")"
|
|
246
|
-
return synchronized {
|
|
247
|
-
let now = Date()
|
|
248
|
-
recentMessageIds = recentMessageIds.filter { now.timeIntervalSince($0.value) < 5 }
|
|
249
|
-
if let last = recentMessageIds[key], now.timeIntervalSince(last) < 2 {
|
|
250
|
-
return false
|
|
251
|
-
}
|
|
252
|
-
recentMessageIds[key] = now
|
|
253
|
-
return true
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
private func forwardWillPresent(
|
|
258
|
-
_ center: UNUserNotificationCenter,
|
|
259
|
-
notification: UNNotification,
|
|
260
|
-
ourOptions: UNNotificationPresentationOptions,
|
|
261
|
-
completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
|
|
262
|
-
) {
|
|
263
|
-
let selector = #selector(
|
|
264
|
-
UNUserNotificationCenterDelegate.userNotificationCenter(_:willPresent:withCompletionHandler:)
|
|
265
|
-
)
|
|
266
|
-
guard let forwardingDelegate, forwardingDelegate.responds(to: selector) else {
|
|
267
|
-
completionHandler(ourOptions)
|
|
268
|
-
return
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
forwardingDelegate.userNotificationCenter?(
|
|
272
|
-
center,
|
|
273
|
-
willPresent: notification,
|
|
274
|
-
withCompletionHandler: { (forwarded: Int) in
|
|
275
|
-
// ObjC optional-protocol bridging exposes options as Int here.
|
|
276
|
-
let forwardedOptions = UNNotificationPresentationOptions(rawValue: UInt(forwarded))
|
|
277
|
-
completionHandler(ourOptions.union(forwardedOptions))
|
|
278
|
-
}
|
|
279
|
-
)
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
private static var foregroundPresentationOptions: UNNotificationPresentationOptions {
|
|
283
|
-
if #available(iOS 14.0, *) {
|
|
284
|
-
return [.banner, .list, .sound, .badge]
|
|
285
|
-
}
|
|
286
|
-
return [.alert, .sound, .badge]
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
private func emitPress(_ message: PushMessage) {
|
|
290
|
-
DispatchQueue.main.async {
|
|
291
|
-
if let onNotificationPress = self.onNotificationPress {
|
|
292
|
-
onNotificationPress(message)
|
|
293
|
-
} else {
|
|
294
|
-
self.pendingPress = message
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
private func flushPendingPress() {
|
|
300
|
-
DispatchQueue.main.async {
|
|
301
|
-
guard let pendingPress = self.pendingPress, let onNotificationPress = self.onNotificationPress else {
|
|
302
|
-
return
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
self.pendingPress = nil
|
|
306
|
-
onNotificationPress(pendingPress)
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
private func captureLaunchNotificationIfNeeded() {
|
|
311
|
-
guard !didCaptureLaunchNotification else {
|
|
312
|
-
return
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
if pendingLaunchOptions == nil {
|
|
316
|
-
pendingLaunchOptions = PushSignalCopyLaunchOptions() as? [AnyHashable: Any]
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
let launchOptions = pendingLaunchOptions
|
|
320
|
-
guard let launchOptions else {
|
|
321
|
-
return
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
didCaptureLaunchNotification = true
|
|
325
|
-
|
|
326
|
-
let key = UIApplication.LaunchOptionsKey.remoteNotification
|
|
327
|
-
let payload = launchOptions[key] as? [AnyHashable: Any]
|
|
328
|
-
?? launchOptions[key.rawValue] as? [AnyHashable: Any]
|
|
329
|
-
guard let payload else {
|
|
330
|
-
return
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
emitPress(Self.message(from: payload, fallbackId: "launch"))
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
private func currentEnvironment() -> PushEnvironment {
|
|
337
|
-
if let environment = Self.apsEnvironment() {
|
|
338
|
-
return environment
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
#if DEBUG
|
|
342
|
-
return .sandbox
|
|
343
|
-
#else
|
|
344
|
-
return .production
|
|
345
|
-
#endif
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
private static func apsEnvironment() -> PushEnvironment? {
|
|
349
|
-
guard let url = Bundle.main.url(forResource: "embedded", withExtension: "mobileprovision"),
|
|
350
|
-
let data = try? Data(contentsOf: url),
|
|
351
|
-
let contents = String(data: data, encoding: .ascii),
|
|
352
|
-
let regex = try? NSRegularExpression(
|
|
353
|
-
pattern: "<key>aps-environment</key>\\s*<string>(\\w+)</string>"
|
|
354
|
-
)
|
|
355
|
-
else {
|
|
356
|
-
return nil
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
let range = NSRange(contents.startIndex..<contents.endIndex, in: contents)
|
|
360
|
-
guard let match = regex.firstMatch(in: contents, range: range),
|
|
361
|
-
let valueRange = Range(match.range(at: 1), in: contents)
|
|
362
|
-
else {
|
|
363
|
-
return nil
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
switch contents[valueRange] {
|
|
367
|
-
case "development":
|
|
368
|
-
return .sandbox
|
|
369
|
-
case "production":
|
|
370
|
-
return .production
|
|
371
|
-
default:
|
|
372
|
-
return nil
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
private static func message(from notification: UNNotification) -> PushMessage {
|
|
377
|
-
let content = notification.request.content
|
|
378
|
-
return message(
|
|
379
|
-
from: content.userInfo,
|
|
380
|
-
fallbackId: notification.request.identifier,
|
|
381
|
-
title: content.title.isEmpty ? nil : content.title,
|
|
382
|
-
body: content.body.isEmpty ? nil : content.body
|
|
383
|
-
)
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
private static func message(
|
|
387
|
-
from userInfo: [AnyHashable: Any],
|
|
388
|
-
fallbackId: String? = nil,
|
|
389
|
-
title: String? = nil,
|
|
390
|
-
body: String? = nil
|
|
391
|
-
) -> PushMessage {
|
|
392
|
-
let aps = userInfo["aps"] as? [AnyHashable: Any]
|
|
393
|
-
let alert = aps?["alert"]
|
|
394
|
-
var resolvedTitle = title
|
|
395
|
-
var resolvedBody = body
|
|
396
|
-
|
|
397
|
-
if let alertText = alert as? String {
|
|
398
|
-
resolvedBody = resolvedBody ?? alertText
|
|
399
|
-
} else if let alertDict = alert as? [AnyHashable: Any] {
|
|
400
|
-
resolvedTitle = resolvedTitle ?? stringify(alertDict["title"])
|
|
401
|
-
resolvedBody = resolvedBody ?? stringify(alertDict["body"])
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
var data: [String: String] = [:]
|
|
405
|
-
for (key, value) in userInfo {
|
|
406
|
-
let stringKey = String(describing: key)
|
|
407
|
-
if stringKey == "aps" {
|
|
408
|
-
continue
|
|
409
|
-
}
|
|
410
|
-
if let stringValue = stringify(value) {
|
|
411
|
-
data[stringKey] = stringValue
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
return PushMessage(
|
|
416
|
-
id: stringify(userInfo["gcm.message_id"]) ?? fallbackId,
|
|
417
|
-
title: resolvedTitle,
|
|
418
|
-
body: resolvedBody,
|
|
419
|
-
data: data
|
|
420
|
-
)
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
private static func stringify(_ value: Any?) -> String? {
|
|
424
|
-
guard let value else {
|
|
425
|
-
return nil
|
|
426
|
-
}
|
|
427
|
-
if let value = value as? String {
|
|
428
|
-
return value
|
|
429
|
-
}
|
|
430
|
-
if let value = value as? NSNumber {
|
|
431
|
-
return value.stringValue
|
|
432
|
-
}
|
|
433
|
-
if JSONSerialization.isValidJSONObject(value),
|
|
434
|
-
let data = try? JSONSerialization.data(withJSONObject: value),
|
|
435
|
-
let json = String(data: data, encoding: .utf8)
|
|
436
|
-
{
|
|
437
|
-
return json
|
|
438
|
-
}
|
|
439
|
-
return String(describing: value)
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
private func swizzleAppDelegate() {
|
|
443
|
-
guard !didSwizzleAppDelegate else {
|
|
444
|
-
return
|
|
445
|
-
}
|
|
446
|
-
guard let appDelegate = UIApplication.shared.delegate else {
|
|
447
|
-
return
|
|
448
|
-
}
|
|
449
|
-
didSwizzleAppDelegate = true
|
|
450
|
-
|
|
451
|
-
let target: AnyClass = type(of: appDelegate)
|
|
452
|
-
let source: AnyClass = PushSignalAppDelegateHook.self
|
|
453
|
-
|
|
454
|
-
swizzle(
|
|
455
|
-
target: target,
|
|
456
|
-
original: #selector(UIApplicationDelegate.application(_:didRegisterForRemoteNotificationsWithDeviceToken:)),
|
|
457
|
-
replacement: #selector(PushSignalAppDelegateHook.pushSignal_application(_:didRegisterForRemoteNotificationsWithDeviceToken:)),
|
|
458
|
-
source: source
|
|
459
|
-
)
|
|
460
|
-
swizzle(
|
|
461
|
-
target: target,
|
|
462
|
-
original: #selector(UIApplicationDelegate.application(_:didFailToRegisterForRemoteNotificationsWithError:)),
|
|
463
|
-
replacement: #selector(PushSignalAppDelegateHook.pushSignal_application(_:didFailToRegisterForRemoteNotificationsWithError:)),
|
|
464
|
-
source: source
|
|
465
|
-
)
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
private func swizzleNotificationCenterDelegateIfNeeded() {
|
|
469
|
-
guard !didSwizzleNotificationCenter else {
|
|
470
|
-
return
|
|
471
|
-
}
|
|
472
|
-
didSwizzleNotificationCenter = true
|
|
473
|
-
|
|
474
|
-
let target: AnyClass = UNUserNotificationCenter.self
|
|
475
|
-
let original = #selector(setter: UNUserNotificationCenter.delegate)
|
|
476
|
-
let replacement = #selector(UNUserNotificationCenter.pushSignal_setDelegate(_:))
|
|
477
|
-
|
|
478
|
-
guard let originalMethod = class_getInstanceMethod(target, original),
|
|
479
|
-
let replacementMethod = class_getInstanceMethod(target, replacement)
|
|
480
|
-
else {
|
|
481
|
-
return
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
method_exchangeImplementations(originalMethod, replacementMethod)
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
private func swizzle(target: AnyClass, original: Selector, replacement: Selector, source: AnyClass) {
|
|
488
|
-
guard let replacementMethod = class_getInstanceMethod(source, replacement) else {
|
|
489
|
-
return
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
let replacementImp = method_getImplementation(replacementMethod)
|
|
493
|
-
let types = method_getTypeEncoding(replacementMethod)
|
|
494
|
-
let superMethod = class_getSuperclass(target).flatMap { class_getInstanceMethod($0, original) }
|
|
495
|
-
|
|
496
|
-
// No implementation on this class yet — install ours and keep superclass under `replacement`.
|
|
497
|
-
if class_addMethod(target, original, replacementImp, types) {
|
|
498
|
-
if let superMethod {
|
|
499
|
-
class_addMethod(
|
|
500
|
-
target,
|
|
501
|
-
replacement,
|
|
502
|
-
method_getImplementation(superMethod),
|
|
503
|
-
method_getTypeEncoding(superMethod)
|
|
504
|
-
)
|
|
505
|
-
}
|
|
506
|
-
return
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
guard class_addMethod(target, replacement, replacementImp, types),
|
|
510
|
-
let originalMethod = class_getInstanceMethod(target, original),
|
|
511
|
-
let addedReplacement = class_getInstanceMethod(target, replacement)
|
|
512
|
-
else {
|
|
513
|
-
return
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
method_exchangeImplementations(originalMethod, addedReplacement)
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
private final class PushSignalAppDelegateHook: NSObject {
|
|
521
|
-
@objc func pushSignal_application(
|
|
522
|
-
_ application: UIApplication,
|
|
523
|
-
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
|
|
524
|
-
) {
|
|
525
|
-
PushSignalCenter.shared.handleDeviceToken(deviceToken)
|
|
526
|
-
forwardToOriginal(
|
|
527
|
-
hooked: #selector(
|
|
528
|
-
UIApplicationDelegate.application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
|
|
529
|
-
),
|
|
530
|
-
original: #selector(
|
|
531
|
-
PushSignalAppDelegateHook.pushSignal_application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
|
|
532
|
-
),
|
|
533
|
-
application: application,
|
|
534
|
-
deviceToken: deviceToken
|
|
535
|
-
)
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
@objc func pushSignal_application(
|
|
539
|
-
_ application: UIApplication,
|
|
540
|
-
didFailToRegisterForRemoteNotificationsWithError error: Error
|
|
541
|
-
) {
|
|
542
|
-
PushSignalCenter.shared.handleRegistrationError(error)
|
|
543
|
-
forwardToOriginal(
|
|
544
|
-
hooked: #selector(
|
|
545
|
-
UIApplicationDelegate.application(_:didFailToRegisterForRemoteNotificationsWithError:)
|
|
546
|
-
),
|
|
547
|
-
original: #selector(
|
|
548
|
-
PushSignalAppDelegateHook.pushSignal_application(_:didFailToRegisterForRemoteNotificationsWithError:)
|
|
549
|
-
),
|
|
550
|
-
application: application,
|
|
551
|
-
error: error as NSError
|
|
552
|
-
)
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
private func forwardToOriginal(
|
|
556
|
-
hooked: Selector,
|
|
557
|
-
original: Selector,
|
|
558
|
-
application: UIApplication,
|
|
559
|
-
deviceToken: Data
|
|
560
|
-
) {
|
|
561
|
-
guard responds(to: original),
|
|
562
|
-
let cls = object_getClass(self),
|
|
563
|
-
let originalImp = class_getMethodImplementation(cls, original),
|
|
564
|
-
let hookedImp = class_getMethodImplementation(cls, hooked),
|
|
565
|
-
originalImp != hookedImp
|
|
566
|
-
else {
|
|
567
|
-
return
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
typealias Fn = @convention(c) (Any, Selector, UIApplication, Data) -> Void
|
|
571
|
-
unsafeBitCast(originalImp, to: Fn.self)(self, original, application, deviceToken)
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
private func forwardToOriginal(
|
|
575
|
-
hooked: Selector,
|
|
576
|
-
original: Selector,
|
|
577
|
-
application: UIApplication,
|
|
578
|
-
error: NSError
|
|
579
|
-
) {
|
|
580
|
-
guard responds(to: original),
|
|
581
|
-
let cls = object_getClass(self),
|
|
582
|
-
let originalImp = class_getMethodImplementation(cls, original),
|
|
583
|
-
let hookedImp = class_getMethodImplementation(cls, hooked),
|
|
584
|
-
originalImp != hookedImp
|
|
585
|
-
else {
|
|
586
|
-
return
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
typealias Fn = @convention(c) (Any, Selector, UIApplication, NSError) -> Void
|
|
590
|
-
unsafeBitCast(originalImp, to: Fn.self)(self, original, application, error)
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
extension UNUserNotificationCenter {
|
|
595
|
-
@objc func pushSignal_setDelegate(_ delegate: UNUserNotificationCenterDelegate?) {
|
|
596
|
-
if let delegate, delegate is PushSignalCenter {
|
|
597
|
-
pushSignal_setDelegate(delegate)
|
|
598
|
-
return
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
PushSignalCenter.shared.rememberForwardingDelegate(delegate)
|
|
602
|
-
pushSignal_setDelegate(PushSignalCenter.shared)
|
|
603
|
-
}
|
|
604
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../src","sources":["PushSignal.nitro.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PushSignal.nitro.d.ts","sourceRoot":"","sources":["../../../src/PushSignal.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D,8FAA8F;AAC9F,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,YAAY,CAAC;AAChD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,YAAY,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,MAAM,iBAAiB,GAAG,CAC9B,OAAO,EAAE,WAAW,KACjB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,UAAW,SAAQ,YAAY,CAAC;IAC/C,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;CACnB,CAAC;IACA,UAAU,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3C,YAAY,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI,CAAC;IAC7D,sBAAsB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI,CAAC;CACxE"}
|
package/nitro.json
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"cxxNamespace": ["pushsignal"],
|
|
3
|
-
"ios": {
|
|
4
|
-
"iosModuleName": "PushSignal"
|
|
5
|
-
},
|
|
6
|
-
"android": {
|
|
7
|
-
"androidNamespace": ["pushsignal"],
|
|
8
|
-
"androidCxxLibName": "pushsignal"
|
|
9
|
-
},
|
|
10
|
-
"autolinking": {
|
|
11
|
-
"PushSignal": {
|
|
12
|
-
"ios": {
|
|
13
|
-
"language": "swift",
|
|
14
|
-
"implementationClassName": "PushSignal"
|
|
15
|
-
},
|
|
16
|
-
"android": {
|
|
17
|
-
"language": "kotlin",
|
|
18
|
-
"implementationClassName": "PushSignal"
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
"ignorePaths": ["node_modules"]
|
|
23
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
///
|
|
2
|
-
/// JAndroidFirebaseConfig.hpp
|
|
3
|
-
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
-
/// https://github.com/mrousavy/nitro
|
|
5
|
-
/// Copyright © Marc Rousavy @ Margelo
|
|
6
|
-
///
|
|
7
|
-
|
|
8
|
-
#pragma once
|
|
9
|
-
|
|
10
|
-
#include <fbjni/fbjni.h>
|
|
11
|
-
#include "AndroidFirebaseConfig.hpp"
|
|
12
|
-
|
|
13
|
-
#include <optional>
|
|
14
|
-
#include <string>
|
|
15
|
-
|
|
16
|
-
namespace margelo::nitro::pushsignal {
|
|
17
|
-
|
|
18
|
-
using namespace facebook;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* The C++ JNI bridge between the C++ struct "AndroidFirebaseConfig" and the Kotlin data class "AndroidFirebaseConfig".
|
|
22
|
-
*/
|
|
23
|
-
struct JAndroidFirebaseConfig final: public jni::JavaClass<JAndroidFirebaseConfig> {
|
|
24
|
-
public:
|
|
25
|
-
static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/pushsignal/AndroidFirebaseConfig;";
|
|
26
|
-
|
|
27
|
-
public:
|
|
28
|
-
/**
|
|
29
|
-
* Convert this Java/Kotlin-based struct to the C++ struct AndroidFirebaseConfig by copying all values to C++.
|
|
30
|
-
*/
|
|
31
|
-
[[maybe_unused]]
|
|
32
|
-
[[nodiscard]]
|
|
33
|
-
AndroidFirebaseConfig toCpp() const {
|
|
34
|
-
static const auto clazz = javaClassStatic();
|
|
35
|
-
static const auto fieldProject_id = clazz->getField<jni::JString>("project_id");
|
|
36
|
-
jni::local_ref<jni::JString> project_id = this->getFieldValue(fieldProject_id);
|
|
37
|
-
static const auto fieldMobilesdk_app_id = clazz->getField<jni::JString>("mobilesdk_app_id");
|
|
38
|
-
jni::local_ref<jni::JString> mobilesdk_app_id = this->getFieldValue(fieldMobilesdk_app_id);
|
|
39
|
-
static const auto fieldCurrent_key = clazz->getField<jni::JString>("current_key");
|
|
40
|
-
jni::local_ref<jni::JString> current_key = this->getFieldValue(fieldCurrent_key);
|
|
41
|
-
static const auto fieldProject_number = clazz->getField<jni::JString>("project_number");
|
|
42
|
-
jni::local_ref<jni::JString> project_number = this->getFieldValue(fieldProject_number);
|
|
43
|
-
return AndroidFirebaseConfig(
|
|
44
|
-
project_id != nullptr ? std::make_optional(project_id->toStdString()) : std::nullopt,
|
|
45
|
-
mobilesdk_app_id != nullptr ? std::make_optional(mobilesdk_app_id->toStdString()) : std::nullopt,
|
|
46
|
-
current_key != nullptr ? std::make_optional(current_key->toStdString()) : std::nullopt,
|
|
47
|
-
project_number != nullptr ? std::make_optional(project_number->toStdString()) : std::nullopt
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
public:
|
|
52
|
-
/**
|
|
53
|
-
* Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.
|
|
54
|
-
*/
|
|
55
|
-
[[maybe_unused]]
|
|
56
|
-
static jni::local_ref<JAndroidFirebaseConfig::javaobject> fromCpp(const AndroidFirebaseConfig& value) {
|
|
57
|
-
using JSignature = JAndroidFirebaseConfig(jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JString>);
|
|
58
|
-
static const auto clazz = javaClassStatic();
|
|
59
|
-
static const auto create = clazz->getStaticMethod<JSignature>("fromCpp");
|
|
60
|
-
return create(
|
|
61
|
-
clazz,
|
|
62
|
-
value.project_id.has_value() ? jni::make_jstring(value.project_id.value()) : nullptr,
|
|
63
|
-
value.mobilesdk_app_id.has_value() ? jni::make_jstring(value.mobilesdk_app_id.value()) : nullptr,
|
|
64
|
-
value.current_key.has_value() ? jni::make_jstring(value.current_key.value()) : nullptr,
|
|
65
|
-
value.project_number.has_value() ? jni::make_jstring(value.project_number.value()) : nullptr
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
} // namespace margelo::nitro::pushsignal
|