@trycourier/courier-react-native 1.0.8 → 2.0.0-beta0
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/README.md +16 -416
- package/android/build.gradle +48 -83
- package/android/src/main/AndroidManifest.xml +0 -1
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/java/com/courierreactnative/CourierReactNativeActivity.kt +10 -10
- package/android/src/main/java/com/courierreactnative/CourierReactNativeModule.kt +146 -139
- package/android/src/main/java/com/courierreactnative/CourierReactNativePackage.kt +1 -3
- package/android/src/main/java/com/courierreactnative/CourierReactNativeViewManager.kt +43 -0
- package/courier-react-native.podspec +12 -4
- package/ios/CourierReactNative-Bridging-Header.h +0 -1
- package/ios/CourierReactNative.xcodeproj/project.pbxproj +4 -4
- package/ios/CourierReactNative.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
- package/ios/CourierReactNativeModule.m +48 -0
- package/ios/{CourierReactNative.swift → CourierReactNativeModule.swift} +167 -48
- package/ios/CourierReactNativeViewManager.m +15 -0
- package/ios/CourierReactNativeViewManager.swift +348 -0
- package/lib/commonjs/index.js +68 -215
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/CourierInboxListener.js +26 -0
- package/lib/commonjs/models/CourierInboxListener.js.map +1 -0
- package/lib/commonjs/models/CourierInboxTheme.js +2 -0
- package/lib/commonjs/models/CourierInboxTheme.js.map +1 -0
- package/lib/commonjs/models/InboxAction.js +2 -0
- package/lib/commonjs/models/InboxAction.js.map +1 -0
- package/lib/commonjs/models/InboxMessage.js +6 -0
- package/lib/commonjs/models/InboxMessage.js.map +1 -0
- package/lib/commonjs/views/CourierInboxView.js +53 -0
- package/lib/commonjs/views/CourierInboxView.js.map +1 -0
- package/lib/module/index.js +62 -214
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/CourierInboxListener.js +18 -0
- package/lib/module/models/CourierInboxListener.js.map +1 -0
- package/lib/module/models/CourierInboxTheme.js +2 -0
- package/lib/module/models/CourierInboxTheme.js.map +1 -0
- package/lib/module/models/InboxAction.js +2 -0
- package/lib/module/models/InboxAction.js.map +1 -0
- package/lib/module/models/InboxMessage.js +2 -0
- package/lib/module/models/InboxMessage.js.map +1 -0
- package/lib/module/views/CourierInboxView.js +45 -0
- package/lib/module/views/CourierInboxView.js.map +1 -0
- package/lib/typescript/index.d.ts +34 -94
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/models/CourierInboxListener.d.ts +9 -0
- package/lib/typescript/models/CourierInboxListener.d.ts.map +1 -0
- package/lib/typescript/models/CourierInboxTheme.d.ts +34 -0
- package/lib/typescript/models/CourierInboxTheme.d.ts.map +1 -0
- package/lib/typescript/models/InboxAction.d.ts +8 -0
- package/lib/typescript/models/InboxAction.d.ts.map +1 -0
- package/lib/typescript/models/InboxMessage.d.ts +18 -0
- package/lib/typescript/models/InboxMessage.d.ts.map +1 -0
- package/lib/typescript/views/CourierInboxView.d.ts +16 -0
- package/lib/typescript/views/CourierInboxView.d.ts.map +1 -0
- package/package.json +61 -44
- package/src/index.tsx +188 -0
- package/src/models/CourierInboxListener.tsx +25 -0
- package/src/models/CourierInboxTheme.tsx +30 -0
- package/src/models/InboxAction.tsx +5 -0
- package/src/models/InboxMessage.tsx +16 -0
- package/src/views/CourierInboxView.tsx +85 -0
- package/android/.gradle/7.1/dependencies-accessors/dependencies-accessors.lock +0 -0
- package/android/.gradle/7.1/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/7.1/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/7.1/fileChanges/last-build.bin +0 -0
- package/android/.gradle/7.1/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/7.1/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/7.1/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
- package/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
- package/android/.gradle/checksums/checksums.lock +0 -0
- package/android/.gradle/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/.idea/compiler.xml +0 -6
- package/android/.idea/gradle.xml +0 -17
- package/android/.idea/jarRepositories.xml +0 -35
- package/android/.idea/misc.xml +0 -10
- package/android/.idea/vcs.xml +0 -6
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +0 -5
- package/android/gradlew +0 -185
- package/android/gradlew.bat +0 -89
- package/android/local.properties +0 -8
- package/android/src/main/java/com/courierreactnative/NotificationPermissionStatus.kt +0 -6
- package/ios/CourierReactNative.m +0 -53
- package/ios/CourierReactNativeDelegate.h +0 -20
- package/ios/CourierReactNativeDelegate.m +0 -125
- package/src/index.ts +0 -341
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import Courier_iOS
|
|
2
2
|
|
|
3
|
-
@objc(
|
|
4
|
-
class
|
|
3
|
+
@objc(CourierReactNativeModule)
|
|
4
|
+
class CourierReactNativeModule: RCTEventEmitter {
|
|
5
5
|
|
|
6
6
|
private static let COURIER_ERROR_TAG = "Courier iOS SDK Error"
|
|
7
7
|
internal static let COURIER_PUSH_NOTIFICATION_CLICKED_EVENT = "pushNotificationClicked"
|
|
8
8
|
internal static let COURIER_PUSH_NOTIFICATION_DELIVERED_EVENT = "pushNotificationDelivered"
|
|
9
9
|
private static let COURIER_PUSH_NOTIFICATION_DEBUG_LOG_EVENT = "courierDebugEvent"
|
|
10
10
|
|
|
11
|
+
class InboxEvents {
|
|
12
|
+
internal static let INITIAL_LOADING = "inboxInitialLoad"
|
|
13
|
+
internal static let ERROR = "inboxError"
|
|
14
|
+
internal static let MESSAGES_CHANGED = "inboxMessagesChanged"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
private var inboxListeners = [String: CourierInboxListener]()
|
|
18
|
+
|
|
11
19
|
private var hasListeners = false
|
|
12
20
|
|
|
13
21
|
private var lastClickedMessage: [AnyHashable: Any]? = nil
|
|
@@ -35,7 +43,10 @@ class CourierReactNative: RCTEventEmitter {
|
|
|
35
43
|
|
|
36
44
|
// setup listeners
|
|
37
45
|
Courier.shared.logListener = { log in
|
|
38
|
-
self.sendEvent(
|
|
46
|
+
self.sendEvent(
|
|
47
|
+
withName: CourierReactNativeModule.COURIER_PUSH_NOTIFICATION_DEBUG_LOG_EVENT,
|
|
48
|
+
body: log
|
|
49
|
+
)
|
|
39
50
|
}
|
|
40
51
|
|
|
41
52
|
}
|
|
@@ -52,14 +63,14 @@ class CourierReactNative: RCTEventEmitter {
|
|
|
52
63
|
notificationCenter.addObserver(
|
|
53
64
|
self,
|
|
54
65
|
selector: #selector(pushNotificationClicked),
|
|
55
|
-
name: Notification.Name(rawValue:
|
|
66
|
+
name: Notification.Name(rawValue: CourierReactNativeModule.COURIER_PUSH_NOTIFICATION_CLICKED_EVENT),
|
|
56
67
|
object: nil
|
|
57
68
|
)
|
|
58
69
|
|
|
59
70
|
notificationCenter.addObserver(
|
|
60
71
|
self,
|
|
61
72
|
selector: #selector(pushNotificationDelivered),
|
|
62
|
-
name: Notification.Name(rawValue:
|
|
73
|
+
name: Notification.Name(rawValue: CourierReactNativeModule.COURIER_PUSH_NOTIFICATION_DELIVERED_EVENT),
|
|
63
74
|
object: nil
|
|
64
75
|
)
|
|
65
76
|
|
|
@@ -86,7 +97,7 @@ class CourierReactNative: RCTEventEmitter {
|
|
|
86
97
|
|
|
87
98
|
lastClickedMessage = notification.userInfo
|
|
88
99
|
sendMessage(
|
|
89
|
-
name:
|
|
100
|
+
name: CourierReactNativeModule.COURIER_PUSH_NOTIFICATION_CLICKED_EVENT,
|
|
90
101
|
message: lastClickedMessage
|
|
91
102
|
)
|
|
92
103
|
|
|
@@ -95,7 +106,7 @@ class CourierReactNative: RCTEventEmitter {
|
|
|
95
106
|
@objc private func pushNotificationDelivered(notification: Notification) {
|
|
96
107
|
|
|
97
108
|
sendMessage(
|
|
98
|
-
name:
|
|
109
|
+
name: CourierReactNativeModule.COURIER_PUSH_NOTIFICATION_DELIVERED_EVENT,
|
|
99
110
|
message: notification.userInfo
|
|
100
111
|
)
|
|
101
112
|
|
|
@@ -104,28 +115,12 @@ class CourierReactNative: RCTEventEmitter {
|
|
|
104
115
|
@objc func registerPushNotificationClickedOnKilledState() {
|
|
105
116
|
|
|
106
117
|
sendMessage(
|
|
107
|
-
name:
|
|
118
|
+
name: CourierReactNativeModule.COURIER_PUSH_NOTIFICATION_CLICKED_EVENT,
|
|
108
119
|
message: lastClickedMessage
|
|
109
120
|
)
|
|
110
121
|
|
|
111
122
|
}
|
|
112
|
-
|
|
113
|
-
@objc(signIn: accessToken: withResolver: withRejecter:)
|
|
114
|
-
func signIn(userId: NSString, accessToken: NSString, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
115
|
-
|
|
116
|
-
Courier.shared.signIn(
|
|
117
|
-
accessToken: accessToken as String,
|
|
118
|
-
userId: userId as String,
|
|
119
|
-
onSuccess: {
|
|
120
|
-
resolve(nil)
|
|
121
|
-
},
|
|
122
|
-
onFailure: { error in
|
|
123
|
-
reject(String(describing: error), CourierReactNative.COURIER_ERROR_TAG, nil)
|
|
124
|
-
}
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
123
|
+
|
|
129
124
|
@objc(getNotificationPermissionStatus: withRejecter:)
|
|
130
125
|
func getNotificationPermissionStatus(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
131
126
|
|
|
@@ -144,6 +139,23 @@ class CourierReactNative: RCTEventEmitter {
|
|
|
144
139
|
|
|
145
140
|
}
|
|
146
141
|
|
|
142
|
+
@objc(signIn: withClientKey: withUserId: withResolver: withRejecter:)
|
|
143
|
+
func signIn(accessToken: NSString, clientKey: NSString?, userId: NSString, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
144
|
+
|
|
145
|
+
Courier.shared.signIn(
|
|
146
|
+
accessToken: accessToken as String,
|
|
147
|
+
clientKey: clientKey as? String,
|
|
148
|
+
userId: userId as String,
|
|
149
|
+
onSuccess: {
|
|
150
|
+
resolve(nil)
|
|
151
|
+
},
|
|
152
|
+
onFailure: { error in
|
|
153
|
+
reject(String(describing: error), CourierReactNativeModule.COURIER_ERROR_TAG, nil)
|
|
154
|
+
}
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
}
|
|
158
|
+
|
|
147
159
|
@objc(signOut: withRejecter:)
|
|
148
160
|
func signOut(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
149
161
|
|
|
@@ -152,7 +164,7 @@ class CourierReactNative: RCTEventEmitter {
|
|
|
152
164
|
resolve(nil)
|
|
153
165
|
},
|
|
154
166
|
onFailure: { error in
|
|
155
|
-
reject(String(describing: error),
|
|
167
|
+
reject(String(describing: error), CourierReactNativeModule.COURIER_ERROR_TAG, nil)
|
|
156
168
|
}
|
|
157
169
|
)
|
|
158
170
|
|
|
@@ -183,7 +195,7 @@ class CourierReactNative: RCTEventEmitter {
|
|
|
183
195
|
resolve(nil)
|
|
184
196
|
},
|
|
185
197
|
onFailure: { error in
|
|
186
|
-
reject(String(describing: error),
|
|
198
|
+
reject(String(describing: error), CourierReactNativeModule.COURIER_ERROR_TAG, nil)
|
|
187
199
|
}
|
|
188
200
|
)
|
|
189
201
|
|
|
@@ -197,28 +209,27 @@ class CourierReactNative: RCTEventEmitter {
|
|
|
197
209
|
|
|
198
210
|
}
|
|
199
211
|
|
|
200
|
-
@objc(sendPush: withUserId: withTitle: withBody: withProviders:
|
|
201
|
-
func sendPush(authKey: NSString, userId: NSString, title: NSString, body: NSString, providers: NSArray,
|
|
212
|
+
@objc(sendPush: withUserId: withTitle: withBody: withProviders: withResolver: withRejecter:)
|
|
213
|
+
func sendPush(authKey: NSString, userId: NSString, title: NSString, body: NSString, providers: NSArray, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
202
214
|
|
|
203
215
|
guard let courierProviders = providers as? [String] else {
|
|
204
|
-
reject("No provider supported",
|
|
216
|
+
reject("No provider supported", CourierReactNativeModule.COURIER_ERROR_TAG, nil)
|
|
205
217
|
return
|
|
206
218
|
}
|
|
207
219
|
|
|
208
|
-
Courier.shared.sendPush(
|
|
209
|
-
authKey: authKey as String,
|
|
210
|
-
userId: userId as String,
|
|
211
|
-
title: title as String,
|
|
212
|
-
message: body as String,
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
)
|
|
220
|
+
// Courier.shared.sendPush(
|
|
221
|
+
// authKey: authKey as String,
|
|
222
|
+
// userId: userId as String,
|
|
223
|
+
// title: title as String,
|
|
224
|
+
// message: body as String,
|
|
225
|
+
// providers: courierProviders,
|
|
226
|
+
// onSuccess: { requestId in
|
|
227
|
+
// resolve(requestId)
|
|
228
|
+
// },
|
|
229
|
+
// onFailure: { error in
|
|
230
|
+
// reject(String(describing: error), CourierReactNative.COURIER_ERROR_TAG, nil)
|
|
231
|
+
// }
|
|
232
|
+
// )
|
|
222
233
|
|
|
223
234
|
}
|
|
224
235
|
|
|
@@ -235,21 +246,129 @@ class CourierReactNative: RCTEventEmitter {
|
|
|
235
246
|
}
|
|
236
247
|
|
|
237
248
|
@objc(setDebugMode: withResolver: withRejecter:)
|
|
238
|
-
func setDebugMode(isDebugging: Bool,resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
249
|
+
func setDebugMode(isDebugging: Bool, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
239
250
|
|
|
240
251
|
Courier.shared.isDebugging = isDebugging
|
|
241
252
|
resolve(Courier.shared.isDebugging)
|
|
242
253
|
|
|
243
254
|
}
|
|
255
|
+
|
|
256
|
+
@objc(readMessage: withResolver: withRejecter:)
|
|
257
|
+
func readMessage(messageId: NSString, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
258
|
+
|
|
259
|
+
Courier.shared.readMessage(
|
|
260
|
+
messageId: messageId as String,
|
|
261
|
+
onSuccess: {
|
|
262
|
+
resolve(nil)
|
|
263
|
+
},
|
|
264
|
+
onFailure: { error in
|
|
265
|
+
reject(String(describing: error), CourierReactNativeModule.COURIER_ERROR_TAG, nil)
|
|
266
|
+
}
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
@objc(unreadMessage: withResolver: withRejecter:)
|
|
272
|
+
func unreadMessage(messageId: NSString, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
273
|
+
|
|
274
|
+
Courier.shared.unreadMessage(
|
|
275
|
+
messageId: messageId as String,
|
|
276
|
+
onSuccess: {
|
|
277
|
+
resolve(nil)
|
|
278
|
+
},
|
|
279
|
+
onFailure: { error in
|
|
280
|
+
reject(String(describing: error), CourierReactNativeModule.COURIER_ERROR_TAG, nil)
|
|
281
|
+
}
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
@objc(readAllInboxMessages: withRejecter:)
|
|
287
|
+
func readAllInboxMessages(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
288
|
+
|
|
289
|
+
Courier.shared.readAllInboxMessages(
|
|
290
|
+
onSuccess: {
|
|
291
|
+
resolve(nil)
|
|
292
|
+
},
|
|
293
|
+
onFailure: { error in
|
|
294
|
+
reject(String(describing: error), CourierReactNativeModule.COURIER_ERROR_TAG, nil)
|
|
295
|
+
}
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
@objc(addInboxListener:)
|
|
301
|
+
func addInboxListener(listenerId: NSString?) -> String {
|
|
302
|
+
|
|
303
|
+
let listener = Courier.shared.addInboxListener(
|
|
304
|
+
onInitialLoad: { [weak self] in
|
|
305
|
+
self?.sendEvent(
|
|
306
|
+
withName: CourierReactNativeModule.InboxEvents.INITIAL_LOADING,
|
|
307
|
+
body: nil
|
|
308
|
+
)
|
|
309
|
+
},
|
|
310
|
+
onError: { [weak self] error in
|
|
311
|
+
self?.sendEvent(
|
|
312
|
+
withName: CourierReactNativeModule.InboxEvents.ERROR,
|
|
313
|
+
body: String(describing: error)
|
|
314
|
+
)
|
|
315
|
+
},
|
|
316
|
+
onMessagesChanged: { [weak self] messages, unreadMessageCount, totalMessageCount, canPaginate in
|
|
317
|
+
|
|
318
|
+
let json: [String: Any] = [
|
|
319
|
+
"messages": messages.map { $0.toDictionary() },
|
|
320
|
+
"unreadMessageCount": unreadMessageCount,
|
|
321
|
+
"totalMessageCount": totalMessageCount,
|
|
322
|
+
"canPaginate": canPaginate
|
|
323
|
+
]
|
|
324
|
+
|
|
325
|
+
self?.sendEvent(
|
|
326
|
+
withName: CourierReactNativeModule.InboxEvents.MESSAGES_CHANGED,
|
|
327
|
+
body: json
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
}
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
// Create an id and add the listener to the dictionary
|
|
334
|
+
let id = UUID().uuidString
|
|
335
|
+
inboxListeners[id] = listener
|
|
336
|
+
|
|
337
|
+
return id
|
|
338
|
+
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
@objc(removeInboxListener:)
|
|
342
|
+
func removeInboxListener(listenerId: NSString) -> String {
|
|
343
|
+
|
|
344
|
+
let id = listenerId as String
|
|
345
|
+
|
|
346
|
+
// Remove the listener
|
|
347
|
+
let listener = inboxListeners[id]
|
|
348
|
+
listener?.remove()
|
|
349
|
+
|
|
350
|
+
// Remove from dictionary
|
|
351
|
+
inboxListeners.removeValue(forKey: id)
|
|
352
|
+
|
|
353
|
+
return id
|
|
354
|
+
|
|
355
|
+
}
|
|
244
356
|
|
|
245
357
|
override func supportedEvents() -> [String]! {
|
|
246
358
|
return [
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
359
|
+
CourierReactNativeModule.COURIER_PUSH_NOTIFICATION_CLICKED_EVENT,
|
|
360
|
+
CourierReactNativeModule.COURIER_PUSH_NOTIFICATION_DELIVERED_EVENT,
|
|
361
|
+
CourierReactNativeModule.COURIER_PUSH_NOTIFICATION_DEBUG_LOG_EVENT,
|
|
362
|
+
CourierReactNativeModule.InboxEvents.INITIAL_LOADING,
|
|
363
|
+
CourierReactNativeModule.InboxEvents.ERROR,
|
|
364
|
+
CourierReactNativeModule.InboxEvents.MESSAGES_CHANGED
|
|
250
365
|
]
|
|
251
366
|
}
|
|
252
367
|
|
|
368
|
+
@objc override static func requiresMainQueueSetup() -> Bool {
|
|
369
|
+
return true
|
|
370
|
+
}
|
|
371
|
+
|
|
253
372
|
}
|
|
254
373
|
|
|
255
374
|
extension [AnyHashable: Any] {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#import <React/RCTViewManager.h>
|
|
2
|
+
|
|
3
|
+
@interface RCT_EXTERN_MODULE(CourierReactNativeViewManager, RCTViewManager)
|
|
4
|
+
|
|
5
|
+
RCT_EXPORT_VIEW_PROPERTY(lightTheme, NSDictionary)
|
|
6
|
+
|
|
7
|
+
RCT_EXPORT_VIEW_PROPERTY(darkTheme, NSDictionary)
|
|
8
|
+
|
|
9
|
+
RCT_EXPORT_VIEW_PROPERTY(onClickInboxMessageAtIndex, RCTBubblingEventBlock)
|
|
10
|
+
|
|
11
|
+
RCT_EXPORT_VIEW_PROPERTY(onClickInboxActionForMessageAtIndex, RCTBubblingEventBlock)
|
|
12
|
+
|
|
13
|
+
RCT_EXPORT_VIEW_PROPERTY(onScrollInbox, RCTBubblingEventBlock)
|
|
14
|
+
|
|
15
|
+
@end
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import Courier_iOS
|
|
2
|
+
|
|
3
|
+
@objc(CourierReactNativeViewManager)
|
|
4
|
+
class CourierReactNativeViewManager: RCTViewManager {
|
|
5
|
+
|
|
6
|
+
override func view() -> (CourierReactNativeView) {
|
|
7
|
+
return CourierReactNativeView()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@objc override static func requiresMainQueueSetup() -> Bool {
|
|
11
|
+
return true
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class CourierReactNativeView : UIView {
|
|
17
|
+
|
|
18
|
+
@objc var lightTheme: NSDictionary? = [:] {
|
|
19
|
+
didSet {
|
|
20
|
+
refreshInbox()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@objc var darkTheme: NSDictionary? = [:] {
|
|
25
|
+
didSet {
|
|
26
|
+
refreshInbox()
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@objc var onClickInboxMessageAtIndex: RCTBubblingEventBlock? = nil
|
|
31
|
+
|
|
32
|
+
@objc var onClickInboxActionForMessageAtIndex: RCTBubblingEventBlock? = nil
|
|
33
|
+
|
|
34
|
+
@objc var onScrollInbox: RCTBubblingEventBlock? = nil
|
|
35
|
+
|
|
36
|
+
override init(frame: CGRect) {
|
|
37
|
+
super.init(frame: frame)
|
|
38
|
+
refreshInbox()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
required init?(coder: NSCoder) {
|
|
42
|
+
super.init(coder: coder)
|
|
43
|
+
refreshInbox()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private func refreshInbox() {
|
|
47
|
+
|
|
48
|
+
subviews.forEach { $0.removeFromSuperview() }
|
|
49
|
+
|
|
50
|
+
// Create the view
|
|
51
|
+
let courierInbox = CourierInbox(
|
|
52
|
+
lightTheme: dictionaryToTheme(dictionary: lightTheme) ?? .defaultLight,
|
|
53
|
+
darkTheme: dictionaryToTheme(dictionary: darkTheme) ?? .defaultDark,
|
|
54
|
+
didClickInboxMessageAtIndex: { [weak self] message, index in
|
|
55
|
+
self?.onClickInboxMessageAtIndex?([
|
|
56
|
+
"message" : message.toDictionary(),
|
|
57
|
+
"index" : index
|
|
58
|
+
])
|
|
59
|
+
},
|
|
60
|
+
didClickInboxActionForMessageAtIndex: { [weak self] action, message, index in
|
|
61
|
+
self?.onClickInboxActionForMessageAtIndex?([
|
|
62
|
+
"action" : action.toDictionary(),
|
|
63
|
+
"message" : message.toDictionary(),
|
|
64
|
+
"index" : index
|
|
65
|
+
])
|
|
66
|
+
},
|
|
67
|
+
didScrollInbox: { [weak self] scrollView in
|
|
68
|
+
self?.onScrollInbox?([
|
|
69
|
+
"contentOffset" : [
|
|
70
|
+
"y": scrollView.contentOffset.y,
|
|
71
|
+
"x": scrollView.contentOffset.x
|
|
72
|
+
]
|
|
73
|
+
])
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
// Add the view to your UI
|
|
78
|
+
courierInbox.translatesAutoresizingMaskIntoConstraints = false
|
|
79
|
+
addSubview(courierInbox)
|
|
80
|
+
|
|
81
|
+
// Constrain the view how you'd like
|
|
82
|
+
NSLayoutConstraint.activate([
|
|
83
|
+
courierInbox.topAnchor.constraint(equalTo: topAnchor),
|
|
84
|
+
courierInbox.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
85
|
+
courierInbox.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
86
|
+
courierInbox.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
87
|
+
])
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
func dictionaryToTheme(dictionary: NSDictionary?) -> CourierInboxTheme? {
|
|
92
|
+
|
|
93
|
+
guard let dict = dictionary else {
|
|
94
|
+
return nil
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// iOS Theme
|
|
98
|
+
let iOS = dict["iOS"] as? [String : Any]
|
|
99
|
+
let messageAnimationStyle = iOS?["messageAnimationStyle"] as? String
|
|
100
|
+
let cellStyles = iOS?["cellStyles"] as? [String : Any]
|
|
101
|
+
|
|
102
|
+
// Unread
|
|
103
|
+
let unreadIndicatorBarColor = dict["unreadIndicatorBarColor"] as? String
|
|
104
|
+
|
|
105
|
+
// Loading
|
|
106
|
+
let loadingIndicatorColor = dict["loadingIndicatorColor"] as? String
|
|
107
|
+
|
|
108
|
+
// Title
|
|
109
|
+
let titleFont = dict["titleFont"] as? [String : Any]
|
|
110
|
+
|
|
111
|
+
// Time
|
|
112
|
+
let timeFont = dict["timeFont"] as? [String : Any]
|
|
113
|
+
|
|
114
|
+
// Body
|
|
115
|
+
let bodyFont = dict["bodyFont"] as? [String : Any]
|
|
116
|
+
|
|
117
|
+
// Detail
|
|
118
|
+
let detailTitleFont = dict["detailTitleFont"] as? [String : Any]
|
|
119
|
+
|
|
120
|
+
// Detail
|
|
121
|
+
let buttonStyles = dict["buttonStyles"] as? [String : Any]
|
|
122
|
+
|
|
123
|
+
return CourierInboxTheme(
|
|
124
|
+
messageAnimationStyle: messageAnimationStyle?.toRowAnimation() ?? .left,
|
|
125
|
+
unreadIndicatorBarColor: unreadIndicatorBarColor?.toColor(),
|
|
126
|
+
loadingIndicatorColor: loadingIndicatorColor?.toColor(),
|
|
127
|
+
titleFont: dictionaryToFont(
|
|
128
|
+
dictionary: titleFont,
|
|
129
|
+
defaultFont: UIFont.boldSystemFont(ofSize: UIFont.labelFontSize),
|
|
130
|
+
defaultColor: .label
|
|
131
|
+
),
|
|
132
|
+
timeFont: dictionaryToFont(
|
|
133
|
+
dictionary: timeFont,
|
|
134
|
+
defaultFont: UIFont.systemFont(ofSize: UIFont.labelFontSize),
|
|
135
|
+
defaultColor: .placeholderText
|
|
136
|
+
),
|
|
137
|
+
bodyFont: dictionaryToFont(
|
|
138
|
+
dictionary: bodyFont,
|
|
139
|
+
defaultFont: UIFont.systemFont(ofSize: UIFont.labelFontSize),
|
|
140
|
+
defaultColor: .label
|
|
141
|
+
),
|
|
142
|
+
detailTitleFont: dictionaryToFont(
|
|
143
|
+
dictionary: detailTitleFont,
|
|
144
|
+
defaultFont: UIFont.systemFont(ofSize: UIFont.labelFontSize),
|
|
145
|
+
defaultColor: .label
|
|
146
|
+
),
|
|
147
|
+
buttonStyles: dictionaryToButtonStyles(
|
|
148
|
+
dictionary: buttonStyles
|
|
149
|
+
),
|
|
150
|
+
cellStyles: dictionaryToCellStyles(
|
|
151
|
+
dictionary: cellStyles
|
|
152
|
+
)
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
func dictionaryToFont(dictionary: [String : Any]?, defaultFont: UIFont, defaultColor: UIColor) -> CourierInboxFont {
|
|
158
|
+
|
|
159
|
+
guard let dict = dictionary else {
|
|
160
|
+
return CourierInboxFont(
|
|
161
|
+
font: defaultFont,
|
|
162
|
+
color: defaultColor
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let family = dict["family"] as? String ?? defaultFont.familyName
|
|
167
|
+
let size = dict["size"] as? CGFloat ?? defaultFont.pointSize
|
|
168
|
+
let color = dict["color"] as? String
|
|
169
|
+
|
|
170
|
+
return CourierInboxFont(
|
|
171
|
+
font: UIFont(name: family, size: size) ?? defaultFont,
|
|
172
|
+
color: color?.toColor() ?? defaultColor
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
func dictionaryToButtonStyles(dictionary: [String : Any]?) -> CourierInboxButtonStyles {
|
|
178
|
+
|
|
179
|
+
guard let dict = dictionary else {
|
|
180
|
+
return CourierInboxButtonStyles()
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
let font = dict["font"] as? [String : Any]
|
|
184
|
+
let backgroundColor = dict["backgroundColor"] as? String
|
|
185
|
+
let cornerRadius = dict["cornerRadius"] as? CGFloat
|
|
186
|
+
|
|
187
|
+
return CourierInboxButtonStyles(
|
|
188
|
+
font: dictionaryToFont(
|
|
189
|
+
dictionary: font,
|
|
190
|
+
defaultFont: UIFont.systemFont(ofSize: UIFont.labelFontSize),
|
|
191
|
+
defaultColor: .white
|
|
192
|
+
),
|
|
193
|
+
backgroundColor: backgroundColor?.toColor(),
|
|
194
|
+
cornerRadius: cornerRadius ?? 8
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
func dictionaryToCellStyles(dictionary: [String : Any]?) -> CourierInboxCellStyles {
|
|
200
|
+
|
|
201
|
+
guard let dict = dictionary else {
|
|
202
|
+
return CourierInboxCellStyles()
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
let separatorStyle = dict["separatorStyle"] as? String
|
|
206
|
+
let separatorColor = dict["separatorColor"] as? String
|
|
207
|
+
let selectionStyle = dict["selectionStyle"] as? String
|
|
208
|
+
|
|
209
|
+
let insets = dict["separatorInsets"] as? [String : Any]
|
|
210
|
+
let top = insets?["top"] as? CGFloat
|
|
211
|
+
let left = insets?["left"] as? CGFloat
|
|
212
|
+
let right = insets?["right"] as? CGFloat
|
|
213
|
+
let bottom = insets?["bottom"] as? CGFloat
|
|
214
|
+
let separatorInsets = UIEdgeInsets(top: top ?? 0, left: left ?? 0, bottom: bottom ?? 0, right: right ?? 0)
|
|
215
|
+
|
|
216
|
+
return CourierInboxCellStyles(
|
|
217
|
+
separatorStyle: separatorStyle?.toSeparatorStyle() ?? .singleLine,
|
|
218
|
+
separatorInsets: separatorInsets,
|
|
219
|
+
separatorColor: separatorColor?.toColor(),
|
|
220
|
+
selectionStyle: selectionStyle?.toSelectionStyle() ?? .default
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
internal extension InboxMessage {
|
|
228
|
+
|
|
229
|
+
@objc func toDictionary() -> NSDictionary {
|
|
230
|
+
|
|
231
|
+
let dictionary: [String: Any?] = [
|
|
232
|
+
"messageId": messageId,
|
|
233
|
+
"title": title,
|
|
234
|
+
"body": body,
|
|
235
|
+
"preview": preview,
|
|
236
|
+
"created": created,
|
|
237
|
+
"actions": actions?.map { $0.toDictionary() },
|
|
238
|
+
"data": data,
|
|
239
|
+
"read": isRead,
|
|
240
|
+
"opened": isOpened,
|
|
241
|
+
"archived": isArchived
|
|
242
|
+
]
|
|
243
|
+
|
|
244
|
+
let mutableDictionary = NSMutableDictionary()
|
|
245
|
+
for (key, value) in dictionary {
|
|
246
|
+
if let unwrappedValue = value {
|
|
247
|
+
mutableDictionary[key] = unwrappedValue
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return mutableDictionary
|
|
252
|
+
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
internal extension InboxAction {
|
|
258
|
+
|
|
259
|
+
@objc func toDictionary() -> NSDictionary {
|
|
260
|
+
|
|
261
|
+
let dictionary: [String: Any?] = [
|
|
262
|
+
"content": content,
|
|
263
|
+
"href": href,
|
|
264
|
+
"data": data
|
|
265
|
+
]
|
|
266
|
+
|
|
267
|
+
let mutableDictionary = NSMutableDictionary()
|
|
268
|
+
for (key, value) in dictionary {
|
|
269
|
+
if let unwrappedValue = value {
|
|
270
|
+
mutableDictionary[key] = unwrappedValue
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return mutableDictionary
|
|
275
|
+
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
internal extension String {
|
|
281
|
+
|
|
282
|
+
func toRowAnimation() -> UITableView.RowAnimation {
|
|
283
|
+
|
|
284
|
+
switch self.lowercased() {
|
|
285
|
+
case "fade": return .fade
|
|
286
|
+
case "right": return .right
|
|
287
|
+
case "left": return .left
|
|
288
|
+
case "top": return .top
|
|
289
|
+
case "bottom": return .bottom
|
|
290
|
+
case "none": return .none
|
|
291
|
+
case "middle": return .middle
|
|
292
|
+
case "automatic":
|
|
293
|
+
if #available(iOS 11.0, *) {
|
|
294
|
+
return .automatic
|
|
295
|
+
} else {
|
|
296
|
+
return .fade
|
|
297
|
+
}
|
|
298
|
+
default: return .fade
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
func toSeparatorStyle() -> UITableViewCell.SeparatorStyle {
|
|
304
|
+
|
|
305
|
+
switch self.lowercased() {
|
|
306
|
+
case "none": return .none
|
|
307
|
+
case "singleLine": return .singleLine
|
|
308
|
+
case "singleLineEtched": return .singleLineEtched
|
|
309
|
+
default: return .singleLine
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
func toSelectionStyle() -> UITableViewCell.SelectionStyle? {
|
|
315
|
+
|
|
316
|
+
switch self.lowercased() {
|
|
317
|
+
case "none": return .none
|
|
318
|
+
case "blue": return .blue
|
|
319
|
+
case "gray": return .gray
|
|
320
|
+
case "default": return .default
|
|
321
|
+
default: return .default
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
func toColor() -> UIColor? {
|
|
327
|
+
|
|
328
|
+
var hexSanitized = trimmingCharacters(in: .whitespacesAndNewlines)
|
|
329
|
+
hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "")
|
|
330
|
+
|
|
331
|
+
var rgb: UInt64 = 0
|
|
332
|
+
|
|
333
|
+
Scanner(string: hexSanitized).scanHexInt64(&rgb)
|
|
334
|
+
|
|
335
|
+
guard hexSanitized.count == 6 else {
|
|
336
|
+
return nil
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return UIColor(
|
|
340
|
+
red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0,
|
|
341
|
+
green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0,
|
|
342
|
+
blue: CGFloat(rgb & 0x0000FF) / 255.0,
|
|
343
|
+
alpha: 1.0
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
}
|