react-native-push-signal 0.1.4 → 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 +3 -11
- package/README.ru.md +3 -11
- 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 +24 -71
- 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 +6 -9
- package/lib/module/NativePushSignal.js +5 -0
- package/lib/module/NativePushSignal.js.map +1 -0
- package/lib/module/pushSignal.native.js +36 -12
- 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/types.d.ts +22 -0
- 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 +60 -22
- 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 -588
- 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 +0 -32
- 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_std__shared_ptr_Promise_std__shared_ptr_Promise_bool_____PushMessage.hpp +0 -128
- package/nitrogen/generated/android/c++/JFunc_void_PushMessage.hpp +0 -80
- package/nitrogen/generated/android/c++/JHybridPushSignalSpec.cpp +0 -115
- 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_std__shared_ptr_Promise_std__shared_ptr_Promise_bool_____PushMessage.kt +0 -78
- 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 -58
- 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 -90
- package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Bridge.hpp +0 -345
- 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_std__shared_ptr_Promise_std__shared_ptr_Promise_bool_____PushMessage.swift +0 -61
- 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_bool.swift +0 -46
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +0 -46
- package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_bool__.swift +0 -66
- package/nitrogen/generated/ios/swift/HybridPushSignalSpec.swift +0 -58
- package/nitrogen/generated/ios/swift/HybridPushSignalSpec_cxx.swift +0 -217
- 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,588 +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 didSwizzleNotificationCenter = false
|
|
26
|
-
private var deviceToken: String?
|
|
27
|
-
private var registrationError: Error?
|
|
28
|
-
private var tokenWaiters: [(Result<String, Error>) -> Void] = []
|
|
29
|
-
private var pendingPress: PushMessage?
|
|
30
|
-
private var pendingMessages: [PushMessage] = []
|
|
31
|
-
private var pendingLaunchOptions: [AnyHashable: Any]?
|
|
32
|
-
private var didCaptureLaunchNotification = false
|
|
33
|
-
private var recentMessageIds: [String: Date] = [:]
|
|
34
|
-
private weak var forwardingDelegate: UNUserNotificationCenterDelegate?
|
|
35
|
-
|
|
36
|
-
var onMessage: ((PushMessage) -> Promise<Promise<Bool>>)? {
|
|
37
|
-
didSet {
|
|
38
|
-
flushPendingMessages()
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
var onNotificationPress: ((PushMessage) -> Void)? {
|
|
42
|
-
didSet {
|
|
43
|
-
flushPendingPress()
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
func install() {
|
|
48
|
-
if Thread.isMainThread {
|
|
49
|
-
installOnMain()
|
|
50
|
-
} else {
|
|
51
|
-
DispatchQueue.main.async {
|
|
52
|
-
self.installOnMain()
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
private func installOnMain() {
|
|
58
|
-
swizzleNotificationCenterDelegateIfNeeded()
|
|
59
|
-
|
|
60
|
-
guard !didInstall else {
|
|
61
|
-
UNUserNotificationCenter.current().delegate = self
|
|
62
|
-
swizzleAppDelegate()
|
|
63
|
-
captureLaunchNotificationIfNeeded()
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
didInstall = true
|
|
68
|
-
UNUserNotificationCenter.current().delegate = self
|
|
69
|
-
swizzleAppDelegate()
|
|
70
|
-
captureLaunchNotificationIfNeeded()
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
func rememberForwardingDelegate(_ delegate: UNUserNotificationCenterDelegate?) {
|
|
74
|
-
if let delegate, delegate !== self {
|
|
75
|
-
forwardingDelegate = delegate
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
func fetchCredentials() async throws -> PushCredentials {
|
|
80
|
-
await MainActor.run {
|
|
81
|
-
self.installOnMain()
|
|
82
|
-
UIApplication.shared.registerForRemoteNotifications()
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
let token = try await waitForToken()
|
|
86
|
-
return PushCredentials(
|
|
87
|
-
platform: .ios,
|
|
88
|
-
token: token,
|
|
89
|
-
environment: currentEnvironment()
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
func handleDeviceToken(_ deviceToken: Data) {
|
|
94
|
-
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
|
|
95
|
-
finishRegistration(result: .success(token))
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
func handleRegistrationError(_ error: Error) {
|
|
99
|
-
finishRegistration(result: .failure(error))
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
@objc func userNotificationCenter(
|
|
103
|
-
_ center: UNUserNotificationCenter,
|
|
104
|
-
willPresent notification: UNNotification,
|
|
105
|
-
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
|
|
106
|
-
) {
|
|
107
|
-
let message = Self.message(from: notification)
|
|
108
|
-
Task {
|
|
109
|
-
let shouldShow = await self.deliverMessage(message)
|
|
110
|
-
let ours: UNNotificationPresentationOptions = shouldShow ? Self.foregroundPresentationOptions : []
|
|
111
|
-
await MainActor.run {
|
|
112
|
-
self.forwardWillPresent(
|
|
113
|
-
center,
|
|
114
|
-
notification: notification,
|
|
115
|
-
ourOptions: ours,
|
|
116
|
-
completionHandler: completionHandler
|
|
117
|
-
)
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
@objc func userNotificationCenter(
|
|
123
|
-
_ center: UNUserNotificationCenter,
|
|
124
|
-
didReceive response: UNNotificationResponse,
|
|
125
|
-
withCompletionHandler completionHandler: @escaping () -> Void
|
|
126
|
-
) {
|
|
127
|
-
emitPress(Self.message(from: response.notification))
|
|
128
|
-
if forwardingDelegate?.responds(
|
|
129
|
-
to: #selector(UNUserNotificationCenterDelegate.userNotificationCenter(_:didReceive:withCompletionHandler:))
|
|
130
|
-
) == true {
|
|
131
|
-
forwardingDelegate?.userNotificationCenter?(center, didReceive: response, withCompletionHandler: completionHandler)
|
|
132
|
-
} else {
|
|
133
|
-
completionHandler()
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
private func waitForToken() async throws -> String {
|
|
138
|
-
if let deviceToken {
|
|
139
|
-
return deviceToken
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if let registrationError {
|
|
143
|
-
throw registrationError
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return try await withCheckedThrowingContinuation { continuation in
|
|
147
|
-
var didResume = false
|
|
148
|
-
let finish: (Result<String, Error>) -> Void = { result in
|
|
149
|
-
guard !didResume else {
|
|
150
|
-
return
|
|
151
|
-
}
|
|
152
|
-
didResume = true
|
|
153
|
-
continuation.resume(with: result)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
lock.lock()
|
|
157
|
-
if let deviceToken {
|
|
158
|
-
lock.unlock()
|
|
159
|
-
finish(.success(deviceToken))
|
|
160
|
-
return
|
|
161
|
-
}
|
|
162
|
-
if let registrationError {
|
|
163
|
-
lock.unlock()
|
|
164
|
-
finish(.failure(registrationError))
|
|
165
|
-
return
|
|
166
|
-
}
|
|
167
|
-
tokenWaiters.append(finish)
|
|
168
|
-
lock.unlock()
|
|
169
|
-
|
|
170
|
-
DispatchQueue.main.asyncAfter(deadline: .now() + 20) {
|
|
171
|
-
let timeout = NSError(
|
|
172
|
-
domain: "PushSignal",
|
|
173
|
-
code: 1,
|
|
174
|
-
userInfo: [
|
|
175
|
-
NSLocalizedDescriptionKey:
|
|
176
|
-
"APNs registration timed out. Use a physical iOS device and enable the Push Notifications capability.",
|
|
177
|
-
]
|
|
178
|
-
)
|
|
179
|
-
PushSignalCenter.shared.finishRegistration(result: .failure(timeout))
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
private func finishRegistration(result: Result<String, Error>) {
|
|
185
|
-
lock.lock()
|
|
186
|
-
switch result {
|
|
187
|
-
case let .success(token):
|
|
188
|
-
deviceToken = token
|
|
189
|
-
registrationError = nil
|
|
190
|
-
case let .failure(error):
|
|
191
|
-
if deviceToken == nil {
|
|
192
|
-
registrationError = error
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
let waiters = tokenWaiters
|
|
196
|
-
tokenWaiters.removeAll()
|
|
197
|
-
lock.unlock()
|
|
198
|
-
|
|
199
|
-
waiters.forEach { $0(result) }
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
private func synchronized<T>(_ body: () -> T) -> T {
|
|
203
|
-
lock.lock()
|
|
204
|
-
defer { lock.unlock() }
|
|
205
|
-
return body()
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
private func deliverMessage(_ message: PushMessage) async -> Bool {
|
|
209
|
-
guard shouldEmit(message) else {
|
|
210
|
-
return false
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
let callback = synchronized { onMessage }
|
|
214
|
-
|
|
215
|
-
guard let callback else {
|
|
216
|
-
synchronized { pendingMessages.append(message) }
|
|
217
|
-
// Still show the system banner so a visible push is not swallowed
|
|
218
|
-
// before JS has subscribed.
|
|
219
|
-
return true
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return await invokeOnMessage(callback, message: message)
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
private func invokeOnMessage(
|
|
226
|
-
_ callback: @escaping (PushMessage) -> Promise<Promise<Bool>>,
|
|
227
|
-
message: PushMessage
|
|
228
|
-
) async -> Bool {
|
|
229
|
-
await withCheckedContinuation { continuation in
|
|
230
|
-
let resumeLock = NSLock()
|
|
231
|
-
var resumed = false
|
|
232
|
-
let finish: (Bool) -> Void = { value in
|
|
233
|
-
resumeLock.lock()
|
|
234
|
-
defer { resumeLock.unlock() }
|
|
235
|
-
guard !resumed else {
|
|
236
|
-
return
|
|
237
|
-
}
|
|
238
|
-
resumed = true
|
|
239
|
-
continuation.resume(returning: value)
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
DispatchQueue.main.async {
|
|
243
|
-
Task {
|
|
244
|
-
do {
|
|
245
|
-
let inner = try await callback(message).await()
|
|
246
|
-
let shouldShow = try await inner.await()
|
|
247
|
-
finish(shouldShow)
|
|
248
|
-
} catch {
|
|
249
|
-
finish(true)
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
|
255
|
-
finish(true)
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
private func flushPendingMessages() {
|
|
261
|
-
DispatchQueue.main.async {
|
|
262
|
-
let callback = self.synchronized { self.onMessage }
|
|
263
|
-
let queued = self.synchronized { () -> [PushMessage] in
|
|
264
|
-
let messages = self.pendingMessages
|
|
265
|
-
self.pendingMessages.removeAll()
|
|
266
|
-
return messages
|
|
267
|
-
}
|
|
268
|
-
guard let callback, !queued.isEmpty else {
|
|
269
|
-
return
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
for message in queued {
|
|
273
|
-
Task {
|
|
274
|
-
_ = await self.invokeOnMessage(callback, message: message)
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
private func shouldEmit(_ message: PushMessage) -> Bool {
|
|
281
|
-
let key = message.id ?? "\(message.title ?? "")|\(message.body ?? "")"
|
|
282
|
-
return synchronized {
|
|
283
|
-
let now = Date()
|
|
284
|
-
recentMessageIds = recentMessageIds.filter { now.timeIntervalSince($0.value) < 5 }
|
|
285
|
-
if let last = recentMessageIds[key], now.timeIntervalSince(last) < 2 {
|
|
286
|
-
return false
|
|
287
|
-
}
|
|
288
|
-
recentMessageIds[key] = now
|
|
289
|
-
return true
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
private func forwardWillPresent(
|
|
294
|
-
_ center: UNUserNotificationCenter,
|
|
295
|
-
notification: UNNotification,
|
|
296
|
-
ourOptions: UNNotificationPresentationOptions,
|
|
297
|
-
completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
|
|
298
|
-
) {
|
|
299
|
-
let selector = #selector(
|
|
300
|
-
UNUserNotificationCenterDelegate.userNotificationCenter(_:willPresent:withCompletionHandler:)
|
|
301
|
-
)
|
|
302
|
-
guard let forwardingDelegate, forwardingDelegate.responds(to: selector) else {
|
|
303
|
-
completionHandler(ourOptions)
|
|
304
|
-
return
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
forwardingDelegate.userNotificationCenter?(
|
|
308
|
-
center,
|
|
309
|
-
willPresent: notification,
|
|
310
|
-
withCompletionHandler: { (forwarded: UNNotificationPresentationOptions) in
|
|
311
|
-
completionHandler(ourOptions.union(forwarded))
|
|
312
|
-
}
|
|
313
|
-
)
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
private static var foregroundPresentationOptions: UNNotificationPresentationOptions {
|
|
317
|
-
if #available(iOS 14.0, *) {
|
|
318
|
-
return [.banner, .list, .sound, .badge]
|
|
319
|
-
}
|
|
320
|
-
return [.alert, .sound, .badge]
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
private func emitPress(_ message: PushMessage) {
|
|
324
|
-
DispatchQueue.main.async {
|
|
325
|
-
if let onNotificationPress = self.onNotificationPress {
|
|
326
|
-
onNotificationPress(message)
|
|
327
|
-
} else {
|
|
328
|
-
self.pendingPress = message
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
private func flushPendingPress() {
|
|
334
|
-
DispatchQueue.main.async {
|
|
335
|
-
guard let pendingPress = self.pendingPress, let onNotificationPress = self.onNotificationPress else {
|
|
336
|
-
return
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
self.pendingPress = nil
|
|
340
|
-
onNotificationPress(pendingPress)
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
private func captureLaunchNotificationIfNeeded() {
|
|
345
|
-
guard !didCaptureLaunchNotification else {
|
|
346
|
-
return
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
if pendingLaunchOptions == nil {
|
|
350
|
-
pendingLaunchOptions = PushSignalCopyLaunchOptions() as? [AnyHashable: Any]
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
let launchOptions = pendingLaunchOptions
|
|
354
|
-
guard let launchOptions else {
|
|
355
|
-
return
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
didCaptureLaunchNotification = true
|
|
359
|
-
|
|
360
|
-
let key = UIApplication.LaunchOptionsKey.remoteNotification
|
|
361
|
-
let payload = launchOptions[key] as? [AnyHashable: Any]
|
|
362
|
-
?? launchOptions[key.rawValue] as? [AnyHashable: Any]
|
|
363
|
-
guard let payload else {
|
|
364
|
-
return
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
emitPress(Self.message(from: payload, fallbackId: "launch"))
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
private func currentEnvironment() -> PushEnvironment {
|
|
371
|
-
if let environment = Self.apsEnvironment() {
|
|
372
|
-
return environment
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
#if DEBUG
|
|
376
|
-
return .sandbox
|
|
377
|
-
#else
|
|
378
|
-
return .production
|
|
379
|
-
#endif
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
private static func apsEnvironment() -> PushEnvironment? {
|
|
383
|
-
guard let url = Bundle.main.url(forResource: "embedded", withExtension: "mobileprovision"),
|
|
384
|
-
let data = try? Data(contentsOf: url),
|
|
385
|
-
let contents = String(data: data, encoding: .ascii),
|
|
386
|
-
let regex = try? NSRegularExpression(
|
|
387
|
-
pattern: "<key>aps-environment</key>\\s*<string>(\\w+)</string>"
|
|
388
|
-
)
|
|
389
|
-
else {
|
|
390
|
-
return nil
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
let range = NSRange(contents.startIndex..<contents.endIndex, in: contents)
|
|
394
|
-
guard let match = regex.firstMatch(in: contents, range: range),
|
|
395
|
-
let valueRange = Range(match.range(at: 1), in: contents)
|
|
396
|
-
else {
|
|
397
|
-
return nil
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
switch contents[valueRange] {
|
|
401
|
-
case "development":
|
|
402
|
-
return .sandbox
|
|
403
|
-
case "production":
|
|
404
|
-
return .production
|
|
405
|
-
default:
|
|
406
|
-
return nil
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
private static func message(from notification: UNNotification) -> PushMessage {
|
|
411
|
-
let content = notification.request.content
|
|
412
|
-
return message(
|
|
413
|
-
from: content.userInfo,
|
|
414
|
-
fallbackId: notification.request.identifier,
|
|
415
|
-
title: content.title.isEmpty ? nil : content.title,
|
|
416
|
-
body: content.body.isEmpty ? nil : content.body
|
|
417
|
-
)
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
private static func message(
|
|
421
|
-
from userInfo: [AnyHashable: Any],
|
|
422
|
-
fallbackId: String? = nil,
|
|
423
|
-
title: String? = nil,
|
|
424
|
-
body: String? = nil
|
|
425
|
-
) -> PushMessage {
|
|
426
|
-
let aps = userInfo["aps"] as? [AnyHashable: Any]
|
|
427
|
-
let alert = aps?["alert"]
|
|
428
|
-
var resolvedTitle = title
|
|
429
|
-
var resolvedBody = body
|
|
430
|
-
|
|
431
|
-
if let alertText = alert as? String {
|
|
432
|
-
resolvedBody = resolvedBody ?? alertText
|
|
433
|
-
} else if let alertDict = alert as? [AnyHashable: Any] {
|
|
434
|
-
resolvedTitle = resolvedTitle ?? stringify(alertDict["title"])
|
|
435
|
-
resolvedBody = resolvedBody ?? stringify(alertDict["body"])
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
var data: [String: String] = [:]
|
|
439
|
-
for (key, value) in userInfo {
|
|
440
|
-
let stringKey = String(describing: key)
|
|
441
|
-
if stringKey == "aps" {
|
|
442
|
-
continue
|
|
443
|
-
}
|
|
444
|
-
if let stringValue = stringify(value) {
|
|
445
|
-
data[stringKey] = stringValue
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
return PushMessage(
|
|
450
|
-
id: stringify(userInfo["gcm.message_id"]) ?? fallbackId,
|
|
451
|
-
title: resolvedTitle,
|
|
452
|
-
body: resolvedBody,
|
|
453
|
-
data: data
|
|
454
|
-
)
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
private static func stringify(_ value: Any?) -> String? {
|
|
458
|
-
guard let value else {
|
|
459
|
-
return nil
|
|
460
|
-
}
|
|
461
|
-
if let value = value as? String {
|
|
462
|
-
return value
|
|
463
|
-
}
|
|
464
|
-
if let value = value as? NSNumber {
|
|
465
|
-
return value.stringValue
|
|
466
|
-
}
|
|
467
|
-
if JSONSerialization.isValidJSONObject(value),
|
|
468
|
-
let data = try? JSONSerialization.data(withJSONObject: value),
|
|
469
|
-
let json = String(data: data, encoding: .utf8)
|
|
470
|
-
{
|
|
471
|
-
return json
|
|
472
|
-
}
|
|
473
|
-
return String(describing: value)
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
private func swizzleAppDelegate() {
|
|
477
|
-
guard let appDelegate = UIApplication.shared.delegate else {
|
|
478
|
-
return
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
let target: AnyClass = type(of: appDelegate)
|
|
482
|
-
let source: AnyClass = PushSignalAppDelegateHook.self
|
|
483
|
-
|
|
484
|
-
swizzle(
|
|
485
|
-
target: target,
|
|
486
|
-
original: #selector(UIApplicationDelegate.application(_:didRegisterForRemoteNotificationsWithDeviceToken:)),
|
|
487
|
-
replacement: #selector(PushSignalAppDelegateHook.pushSignal_application(_:didRegisterForRemoteNotificationsWithDeviceToken:)),
|
|
488
|
-
source: source
|
|
489
|
-
)
|
|
490
|
-
swizzle(
|
|
491
|
-
target: target,
|
|
492
|
-
original: #selector(UIApplicationDelegate.application(_:didFailToRegisterForRemoteNotificationsWithError:)),
|
|
493
|
-
replacement: #selector(PushSignalAppDelegateHook.pushSignal_application(_:didFailToRegisterForRemoteNotificationsWithError:)),
|
|
494
|
-
source: source
|
|
495
|
-
)
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
private func swizzleNotificationCenterDelegateIfNeeded() {
|
|
499
|
-
guard !didSwizzleNotificationCenter else {
|
|
500
|
-
return
|
|
501
|
-
}
|
|
502
|
-
didSwizzleNotificationCenter = true
|
|
503
|
-
|
|
504
|
-
let target: AnyClass = UNUserNotificationCenter.self
|
|
505
|
-
let original = #selector(setter: UNUserNotificationCenter.delegate)
|
|
506
|
-
let replacement = #selector(UNUserNotificationCenter.pushSignal_setDelegate(_:))
|
|
507
|
-
|
|
508
|
-
guard let originalMethod = class_getInstanceMethod(target, original),
|
|
509
|
-
let replacementMethod = class_getInstanceMethod(target, replacement)
|
|
510
|
-
else {
|
|
511
|
-
return
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
method_exchangeImplementations(originalMethod, replacementMethod)
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
private func swizzle(target: AnyClass, original: Selector, replacement: Selector, source: AnyClass) {
|
|
518
|
-
guard let replacementMethod = class_getInstanceMethod(source, replacement) else {
|
|
519
|
-
return
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
let replacementImp = method_getImplementation(replacementMethod)
|
|
523
|
-
let types = method_getTypeEncoding(replacementMethod)
|
|
524
|
-
|
|
525
|
-
if class_addMethod(target, original, replacementImp, types) {
|
|
526
|
-
return
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
guard class_addMethod(target, replacement, replacementImp, types),
|
|
530
|
-
let originalMethod = class_getInstanceMethod(target, original),
|
|
531
|
-
let addedReplacement = class_getInstanceMethod(target, replacement)
|
|
532
|
-
else {
|
|
533
|
-
return
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
method_exchangeImplementations(originalMethod, addedReplacement)
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
private final class PushSignalAppDelegateHook: NSObject {
|
|
541
|
-
@objc func pushSignal_application(
|
|
542
|
-
_ application: UIApplication,
|
|
543
|
-
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
|
|
544
|
-
) {
|
|
545
|
-
PushSignalCenter.shared.handleDeviceToken(deviceToken)
|
|
546
|
-
let selector = #selector(
|
|
547
|
-
PushSignalAppDelegateHook.pushSignal_application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
|
|
548
|
-
)
|
|
549
|
-
guard responds(to: selector),
|
|
550
|
-
let method = class_getInstanceMethod(type(of: self), selector)
|
|
551
|
-
else {
|
|
552
|
-
return
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
typealias Fn = @convention(c) (Any, Selector, UIApplication, Data) -> Void
|
|
556
|
-
unsafeBitCast(method_getImplementation(method), to: Fn.self)(self, selector, application, deviceToken)
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
@objc func pushSignal_application(
|
|
560
|
-
_ application: UIApplication,
|
|
561
|
-
didFailToRegisterForRemoteNotificationsWithError error: Error
|
|
562
|
-
) {
|
|
563
|
-
PushSignalCenter.shared.handleRegistrationError(error)
|
|
564
|
-
let selector = #selector(
|
|
565
|
-
PushSignalAppDelegateHook.pushSignal_application(_:didFailToRegisterForRemoteNotificationsWithError:)
|
|
566
|
-
)
|
|
567
|
-
guard responds(to: selector),
|
|
568
|
-
let method = class_getInstanceMethod(type(of: self), selector)
|
|
569
|
-
else {
|
|
570
|
-
return
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
typealias Fn = @convention(c) (Any, Selector, UIApplication, NSError) -> Void
|
|
574
|
-
unsafeBitCast(method_getImplementation(method), to: Fn.self)(self, selector, application, error as NSError)
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
extension UNUserNotificationCenter {
|
|
579
|
-
@objc func pushSignal_setDelegate(_ delegate: UNUserNotificationCenterDelegate?) {
|
|
580
|
-
if let delegate, delegate is PushSignalCenter {
|
|
581
|
-
pushSignal_setDelegate(delegate)
|
|
582
|
-
return
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
PushSignalCenter.shared.rememberForwardingDelegate(delegate)
|
|
586
|
-
pushSignal_setDelegate(PushSignalCenter.shared)
|
|
587
|
-
}
|
|
588
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../src","sources":["PushSignal.nitro.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { HybridObject } from 'react-native-nitro-modules';
|
|
2
|
-
/** JS/C++ name cannot be `android`: NDK defines `-DANDROID` and breaks the generated enum. */
|
|
3
|
-
export type PushPlatform = 'ios' | 'android_os';
|
|
4
|
-
export type PushEnvironment = 'sandbox' | 'production';
|
|
5
|
-
export interface PushCredentials {
|
|
6
|
-
platform: PushPlatform;
|
|
7
|
-
token: string;
|
|
8
|
-
environment?: PushEnvironment;
|
|
9
|
-
}
|
|
10
|
-
export interface PushMessage {
|
|
11
|
-
id?: string;
|
|
12
|
-
title?: string;
|
|
13
|
-
body?: string;
|
|
14
|
-
data: Record<string, string>;
|
|
15
|
-
}
|
|
16
|
-
export type OnMessageListener = (message: PushMessage) => boolean | void | Promise<boolean | void>;
|
|
17
|
-
export interface AndroidFirebaseConfig {
|
|
18
|
-
project_id?: string;
|
|
19
|
-
mobilesdk_app_id?: string;
|
|
20
|
-
current_key?: string;
|
|
21
|
-
project_number?: string;
|
|
22
|
-
}
|
|
23
|
-
export interface PushSignal extends HybridObject<{
|
|
24
|
-
ios: 'swift';
|
|
25
|
-
android: 'kotlin';
|
|
26
|
-
}> {
|
|
27
|
-
initialize(config: AndroidFirebaseConfig): Promise<void>;
|
|
28
|
-
getCredentials(): Promise<PushCredentials>;
|
|
29
|
-
setOnMessage(callback: (message: PushMessage) => Promise<boolean>): void;
|
|
30
|
-
setOnNotificationPress(callback: (message: PushMessage) => void): void;
|
|
31
|
-
}
|
|
32
|
-
//# sourceMappingURL=PushSignal.nitro.d.ts.map
|
|
@@ -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,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;AAE9C,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,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IACzE,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
|
-
}
|