react-native-move-sdk 2.13.0 → 2.14.0-1

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.
Files changed (89) hide show
  1. package/android/build.gradle.kts +42 -0
  2. package/android/gradle.properties +16 -6
  3. package/android/settings.gradle.kts +35 -0
  4. package/android/src/{main/java/in/dolph/move/sdk → legacy}/MoveSdkModule.kt +30 -195
  5. package/android/src/main/AndroidManifest.xml +1 -11
  6. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/DeviceScanner.kt +19 -21
  7. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/Mapper.kt +3 -2
  8. package/android/src/main/java/com/movesdk/MoveExtensions.kt +188 -0
  9. package/android/src/main/java/{in/dolph/move/sdk/MoveSdkRepository.kt → com/movesdk/MoveSdkConfigRepository.kt} +3 -1
  10. package/android/src/main/java/com/movesdk/MoveSdkPackage.kt +32 -0
  11. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/NativeMoveSdkWrapper.kt +201 -61
  12. package/android/src/main/java/com/movesdk/extentions/ConnectionExt.kt +52 -0
  13. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/extentions/PermissionUtils.kt +1 -1
  14. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/extentions/SharedPreferencesExt.kt +1 -1
  15. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/metadata/MetadataStorage.kt +1 -1
  16. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/metadata/MetadataStorageImpl.kt +2 -2
  17. package/android/src/main/java/com/movesdk/shared/Constants.kt +39 -0
  18. package/android/src/turbo/MoveSdkModule.kt +422 -0
  19. package/ios/MoveSdk.h +13 -0
  20. package/ios/MoveSdk.mm +717 -0
  21. package/ios/MoveSdk.swift +1022 -0
  22. package/ios/{NativeModule/MoveSdkDeviceScanner.swift → MoveSdkDeviceScanner.swift} +1 -1
  23. package/lib/commonjs/NativeMoveSdk.js +21 -0
  24. package/lib/commonjs/NativeMoveSdk.js.map +1 -0
  25. package/lib/commonjs/components/LazyMoveSdk.js +22 -41
  26. package/lib/commonjs/components/LazyMoveSdk.js.map +1 -1
  27. package/lib/commonjs/index.js +331 -25
  28. package/lib/commonjs/index.js.map +1 -1
  29. package/lib/commonjs/package.json +1 -0
  30. package/lib/module/NativeMoveSdk.js +17 -0
  31. package/lib/module/NativeMoveSdk.js.map +1 -0
  32. package/lib/module/components/LazyMoveSdk.js +15 -20
  33. package/lib/module/components/LazyMoveSdk.js.map +1 -1
  34. package/lib/module/index.js +337 -3
  35. package/lib/module/index.js.map +1 -1
  36. package/lib/module/package.json +1 -0
  37. package/lib/typescript/commonjs/example/src/App.d.ts +2 -0
  38. package/lib/typescript/commonjs/example/src/App.d.ts.map +1 -0
  39. package/lib/typescript/commonjs/package.json +1 -0
  40. package/lib/typescript/commonjs/src/NativeMoveSdk.d.ts +133 -0
  41. package/lib/typescript/commonjs/src/NativeMoveSdk.d.ts.map +1 -0
  42. package/lib/typescript/{components → commonjs/src/components}/LazyMoveSdk.d.ts +2 -1
  43. package/lib/typescript/commonjs/src/components/LazyMoveSdk.d.ts.map +1 -0
  44. package/lib/typescript/commonjs/src/index.d.ts +84 -0
  45. package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
  46. package/lib/typescript/module/example/src/App.d.ts +2 -0
  47. package/lib/typescript/module/example/src/App.d.ts.map +1 -0
  48. package/lib/typescript/module/package.json +1 -0
  49. package/lib/typescript/module/src/NativeMoveSdk.d.ts +133 -0
  50. package/lib/typescript/module/src/NativeMoveSdk.d.ts.map +1 -0
  51. package/lib/typescript/module/src/components/LazyMoveSdk.d.ts +8 -0
  52. package/lib/typescript/module/src/components/LazyMoveSdk.d.ts.map +1 -0
  53. package/lib/typescript/module/src/index.d.ts +84 -0
  54. package/lib/typescript/module/src/index.d.ts.map +1 -0
  55. package/package.json +197 -138
  56. package/react-native-move-sdk.podspec +30 -9
  57. package/src/NativeMoveSdk.ts +227 -0
  58. package/src/components/LazyMoveSdk.tsx +2 -2
  59. package/src/{MoveSdk.ts → index.tsx} +131 -199
  60. package/android/.project +0 -17
  61. package/android/build.gradle +0 -153
  62. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  63. package/android/gradle/wrapper/gradle-wrapper.properties +0 -8
  64. package/android/gradlew +0 -183
  65. package/android/gradlew.bat +0 -100
  66. package/android/src/main/java/in/dolph/move/sdk/MoveExtensions.kt +0 -72
  67. package/android/src/main/java/in/dolph/move/sdk/MoveSdkPackage.kt +0 -19
  68. package/android/src/main/java/in/dolph/move/sdk/WrapperBtConnectionsReceiver.kt +0 -99
  69. package/android/src/main/res/drawable-anydpi-v24/ic_notification.xml +0 -13
  70. package/android/src/main/res/drawable-hdpi/ic_notification.png +0 -0
  71. package/android/src/main/res/drawable-mdpi/ic_notification.png +0 -0
  72. package/android/src/main/res/drawable-xhdpi/ic_notification.png +0 -0
  73. package/android/src/main/res/drawable-xxhdpi/ic_notification.png +0 -0
  74. package/android/src/main/res/values/strings.xml +0 -9
  75. package/android/src/main/strings.xml +0 -0
  76. package/android/src/test/java/io/dolphin/move/MoveWrapperTest.kt +0 -190
  77. package/ios/MoveSdk-Bridging-Header.h +0 -3
  78. package/ios/MoveSdk.xcodeproj/project.pbxproj +0 -287
  79. package/ios/MoveSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -4
  80. package/ios/MoveSdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  81. package/ios/NativeModule/MoveSdk.h +0 -144
  82. package/ios/NativeModule/MoveSdk.swift +0 -1359
  83. package/lib/commonjs/MoveSdk.js +0 -443
  84. package/lib/commonjs/MoveSdk.js.map +0 -1
  85. package/lib/module/MoveSdk.js +0 -432
  86. package/lib/module/MoveSdk.js.map +0 -1
  87. package/lib/typescript/MoveSdk.d.ts +0 -158
  88. package/lib/typescript/index.d.ts +0 -3
  89. package/src/index.ts +0 -3
@@ -1,1359 +0,0 @@
1
- import CoreBluetooth
2
- import CoreMotion
3
- import Foundation
4
- import DolphinMoveSDK
5
-
6
- /// Move SDK Initialization singleton delegate.
7
- internal protocol MoveSDKLauncherDelegate: AnyObject {
8
- /// Send event to observer.
9
- /// - Parameters:
10
- /// - event: Event key.
11
- /// - data: Event object.
12
- func send(event: MoveSDKLauncher.Event, data: Any)
13
- }
14
-
15
- /// Type alias for error list item dict.
16
- typealias MoveSDKErrorListItem = [String: Any]
17
-
18
- /// Move SDK service identifiers.
19
- private enum ServiceName: String {
20
- /// Driving detection service.
21
- case driving = "DRIVING"
22
- /// Driving behavior subservice.
23
- case drivingBehavior = "DRIVING_BEHAVIOUR"
24
- /// Distraction free driving subservice.
25
- case distractionFreeDriving = "DISTRACTION_FREE_DRIVING"
26
- /// Device discovery subservice.
27
- case deviceDiscovery = "DEVICE_DISCOVERY"
28
- /// Walking detection service.
29
- case walking = "WALKING"
30
- /// Walking location subservice.
31
- case walkingLocation = "WALKING_LOCATION"
32
- /// Cycling detection service.
33
- case cycling = "CYCLING"
34
- /// Public transport service.
35
- case publicTransport = "PUBLIC_TRANSPORT"
36
- /// Places service.
37
- case places = "PLACES"
38
- /// Assistance call service.
39
- case assistanceCall = "ASSISTANCE_CALL"
40
- /// Points of interest service.
41
- case pointsOfInterest = "POINTS_OF_INTEREST"
42
- /// Automatic impact detection.
43
- case automaticImpactDetection = "AUTOMATIC_IMPACT_DETECTION"
44
- }
45
-
46
- /// Move SDK React Native wrapper.
47
- ///
48
- /// React Native Move SDK plugin interface.
49
- ///
50
- /// Routs through React Native calls to the Move SDK.
51
- /// This class is not guaranteed to be a singleton.
52
- @objc(RCTMoveSdk)
53
- class RCTMoveSdk: RCTEventEmitter {
54
- /// SDK thrown errors.
55
- private enum CError: String, Error {
56
- /// Invalid driving service parameters passe in `setup(...)`
57
- case transformedServices = "Unknown driving service identifier in init parameters"
58
- /// Invalid timeline parameters passe in `setup(...)`
59
- case transformedTimelineDetectionServices = "Unknown timeline service identifier in init parameters"
60
- /// Invalid walking service parameters passe in `setup(...)`
61
- case transformedWalkingServices = "Unknown walking service identifier in init parameters"
62
- /// Invalid other service parameters passe in `setup(...)`
63
- case transformedOtherServices = "Unknown other service identifier in init parameters"
64
- }
65
-
66
- /// SDK string error codes.
67
- private enum ErrorCode: String {
68
- /// SDK setup error.
69
- case setupError = "SETUP_ERROR"
70
- /// Address resolution failed.
71
- case resolveFailed = "RESOLVE_FAILED"
72
- /// Service unavailable.
73
- case serviceUnavailable = "SERVICE_UNAVAILABLE"
74
- /// Thershold reached.
75
- case thresholdReached = "THRESHOLD_REACHED"
76
- /// Geolookup error.
77
- case geocodeError = "GEOCODE_ERROR"
78
- /// SDK Authentication invalid.
79
- case authInvalid = "AUTH_INVALID"
80
- /// Initialization error.
81
- case initializationError = "INITIALIZATION_ERROR"
82
- /// Location error.
83
- case locationError = "LOCATION_ERROR"
84
- /// Network error.
85
- case networkError = "NETWORK_ERROR"
86
- /// Assistance call failed.
87
- case assistanceCallError = "ASSISTANCE_CALL_ERROR"
88
- /// Configuration error.
89
- case configurationError = "CONFIGURATION_ERROR"
90
- /// SDK uninitialized.
91
- case uninitialized = "UNINITIALIZED"
92
- }
93
-
94
- /// Motion mananger for motion permission.
95
- private let motionManager = CMMotionActivityManager()
96
- /// Audio/iBeacon device scanner.
97
- private var scanner: MoveSdkDeviceScanner?
98
- /// Bluetooth manager for permission.
99
- lazy var bluetoothManager = MoveSdkBluetoothManager()
100
-
101
- override func startObserving() {
102
- MoveSDKLauncher.shared.delegate = self
103
- }
104
-
105
- /// Wrapper for `MoveSDK.setup(auth:config:options)`.
106
- /// - Parameters:
107
- /// - contractId: Authentication user ID.
108
- /// - accessToken: Authentication user token.
109
- /// - refreshToken: Authentication refresh token.
110
- /// - productId: Authentication project ID.
111
- /// - timelineDetectionServices: List of timeline detection services.
112
- /// - drivingServices: List of driving services.
113
- /// - walkingServices: List of walking services.
114
- /// - options: Options dictionary object.
115
- /// - resolve: Resolve promise, with "OK".
116
- /// - reject: Reject promise with possible `setupError`.
117
- @objc
118
- func setup(_ contractId: String,
119
- accessToken: String,
120
- refreshToken: String,
121
- productId: Int64,
122
- timelineDetectionServices: Array<String>,
123
- drivingServices: Array<String>,
124
- walkingServices: Array<String>,
125
- options: Any,
126
- resolve: @escaping RCTPromiseResolveBlock,
127
- reject: @escaping RCTPromiseRejectBlock) {
128
-
129
- do {
130
- let sdkConfig = try convert(timelineDetectionServices: timelineDetectionServices, drivingServices: drivingServices, walkingServices: walkingServices)
131
- let auth = MoveAuth(userToken: accessToken, refreshToken: refreshToken, userID: contractId, projectID: productId)
132
- let moveOptions = convert(options: options)
133
-
134
- MoveSDKLauncher.shared.setup(auth: auth, config: sdkConfig, options: moveOptions)
135
- resolve("OK")
136
- } catch {
137
- reject(ErrorCode.setupError.rawValue, "\(error)", nil)
138
- }
139
- }
140
-
141
- /// Wrapper for `MoveSDK.setup(authCode:config:options:callback)`.
142
- /// - Parameters:
143
- /// - authCode: Authentication code.
144
- /// - timelineDetectionServices: List of timeline detection services.
145
- /// - drivingServices: List of driving services.
146
- /// - walkingServices: List of walking services.
147
- /// - options: Options dictionary object.
148
- /// - resolve: Resolve promise, with "OK".
149
- /// - reject: Reject promise with possible `setupError`.
150
- @objc
151
- func setupWithCode(_ authCode: String,
152
- timelineDetectionServices: Array<String>,
153
- drivingServices: Array<String>,
154
- walkingServices: Array<String>,
155
- options: Any,
156
- resolve: @escaping RCTPromiseResolveBlock,
157
- reject: @escaping RCTPromiseRejectBlock) {
158
-
159
- do {
160
- let sdkConfig = try convert(timelineDetectionServices: timelineDetectionServices, drivingServices: drivingServices, walkingServices: walkingServices)
161
- let moveOptions = convert(options: options)
162
-
163
- MoveSDKLauncher.shared.setup(authCode: authCode, config: sdkConfig, options: moveOptions) { result in
164
- switch result {
165
- case .success:
166
- resolve("OK")
167
- case let .networkError(error):
168
- reject(ErrorCode.networkError.rawValue, "\(error)", nil)
169
- case let .invalidCode(error):
170
- reject(ErrorCode.setupError.rawValue, "\(error)", nil)
171
- }
172
- }
173
- } catch {
174
- reject(ErrorCode.setupError.rawValue, "\(error)", nil)
175
- }
176
- }
177
-
178
- /// Wrapper for `MoveSDK.update(config:)`.
179
- /// - Parameters:
180
- /// - timelineDetectionServices: Timeline detection services strings.
181
- /// - drivingServices: Driving services strings.
182
- /// - walkingServices: Walking services strings.
183
- @objc
184
- func updateConfig(_ timelineDetectionServices: Array<String>,
185
- drivingServices: Array<String>,
186
- walkingServices: Array<String>,
187
- options: Any?) {
188
-
189
- if let sdkConfig = try? convert(timelineDetectionServices: timelineDetectionServices, drivingServices: drivingServices, walkingServices: walkingServices) {
190
- if let options {
191
- let moveOptions = convert(options: options)
192
- MoveSDK.shared.update(config: sdkConfig, options: moveOptions)
193
- } else {
194
- MoveSDK.shared.update(config: sdkConfig)
195
- }
196
- }
197
- }
198
-
199
- /// Convert service strings to config subroutine.
200
- /// - Parameters:
201
- /// - timelineDetectionServices: Timeline services strings.
202
- /// - drivingServices: Driving services strings.
203
- /// - walkingServices: Walking services strings
204
- /// - Returns: `MoveConfig` for setup.
205
- private func convert(timelineDetectionServices: Array<String>,
206
- drivingServices: Array<String>,
207
- walkingServices: Array<String>) throws -> MoveConfig {
208
-
209
- let transformedServices: [MoveConfig.DrivingService] = try drivingServices.map {
210
- switch $0 {
211
- case ServiceName.distractionFreeDriving.rawValue:
212
- return .distractionFreeDriving
213
- case ServiceName.drivingBehavior.rawValue:
214
- return .drivingBehavior
215
- case ServiceName.deviceDiscovery.rawValue:
216
- return .deviceDiscovery
217
- default:
218
- throw CError.transformedServices
219
- }
220
- }
221
-
222
- let transformedWalkingServices: [MoveConfig.WalkingService] = try walkingServices.map {
223
- if $0 == ServiceName.walkingLocation.rawValue {
224
- return .location
225
- }
226
- throw CError.transformedWalkingServices
227
- }
228
-
229
- let transformedDetectionServices: [MoveConfig.DetectionService] = try! timelineDetectionServices.map {
230
- switch $0 {
231
- case ServiceName.driving.rawValue:
232
- return .driving(transformedServices)
233
- case ServiceName.walking.rawValue:
234
- return .walking(transformedWalkingServices)
235
- case ServiceName.cycling.rawValue:
236
- return .cycling
237
- case ServiceName.publicTransport.rawValue:
238
- return .publicTransport
239
- case ServiceName.assistanceCall.rawValue:
240
- return .assistanceCall
241
- case ServiceName.pointsOfInterest.rawValue:
242
- return .pointsOfInterest
243
- case ServiceName.places.rawValue:
244
- return .places
245
- case ServiceName.automaticImpactDetection.rawValue:
246
- return .automaticImpactDetection
247
- default:
248
- throw CError.transformedTimelineDetectionServices
249
- }
250
- }
251
-
252
- return MoveConfig(detectionService: transformedDetectionServices)
253
- }
254
-
255
-
256
- /// Convert options json dict to `MoveOptions` object.
257
- /// - Returns: Converted options object.
258
- private func convert(options: Any) -> MoveOptions {
259
- let moveOptions = MoveOptions()
260
-
261
- if let opts = options as? [String: Any] {
262
- if let value = opts["motionPermissionMandatory"] as? Bool {
263
- moveOptions.motionPermissionMandatory = value
264
- }
265
-
266
- if let value = opts["backgroundLocationPermissionMandatory"] as? Bool {
267
- moveOptions.backgroundLocationPermissionMandatory = value
268
- }
269
-
270
- if let value = opts["useBackendConfig"] as? Bool {
271
- moveOptions.useBackendConfig = value
272
- }
273
-
274
- if let deviceDiscovery = opts["deviceDiscovery"] as? [String: Any] {
275
- if let value = deviceDiscovery["startDelay"] as? Double {
276
- moveOptions.deviceDiscovery.startDelay = value
277
- }
278
-
279
- if let value = deviceDiscovery["duration"] as? Double {
280
- moveOptions.deviceDiscovery.duration = value
281
- }
282
-
283
- if let value = deviceDiscovery["interval"] as? Double {
284
- moveOptions.deviceDiscovery.interval = value
285
- }
286
-
287
- if let value = deviceDiscovery["stopScanOnFirstDiscovered"] as? Bool {
288
- moveOptions.deviceDiscovery.stopScanOnFirstDiscovered = value
289
- }
290
- }
291
- }
292
-
293
- return moveOptions
294
- }
295
-
296
- /// Wrapper for `MoveSDK.getSDKState()`.
297
- /// - Parameters:
298
- /// - resolve: Resolve promise with SDK state.
299
- /// - reject: Unused.
300
- @objc
301
- func getState(
302
- _ resolve: RCTPromiseResolveBlock,
303
- rejecter reject: RCTPromiseRejectBlock
304
- ) {
305
- let value = "\(MoveSDK.shared.getSDKState())".uppercased()
306
- resolve(value)
307
- }
308
-
309
- /// Wrapper for `MoveSDK.getAuthState()`.
310
- /// - Parameters:
311
- /// - resolve: Resolve promise with auth state.
312
- /// - reject: Unused.
313
- @objc
314
- func getAuthState(
315
- _ resolve: RCTPromiseResolveBlock,
316
- rejecter reject: RCTPromiseRejectBlock
317
- ) {
318
- let value = "\(MoveSDK.shared.getAuthState())".uppercased()
319
- resolve(value)
320
- }
321
-
322
- /// Wrapper for `MoveSDK.getRegisteredDevices()`.
323
- /// - Parameters:
324
- /// - resolve: Resolve promise with list of registered devices.
325
- /// - reject: Unused.
326
- @objc
327
- func getRegisteredDevices(
328
- _ resolve: RCTPromiseResolveBlock,
329
- rejecter reject: RCTPromiseRejectBlock
330
- ) {
331
- let value = MoveSDKLauncher.shared.convert(devices: MoveSDK.shared.getRegisteredDevices())
332
- resolve(value)
333
- }
334
-
335
- /// Wrapper for `MoveSDK.isAuthValid()`.
336
- /// - Parameters:
337
- /// - resolve: Resolve promise with boolean.
338
- /// - reject: Unused.
339
- ///
340
- /// Authentication is invalid incase of `.invalid` and `.expired`.
341
- @objc
342
- func isAuthValid(
343
- _ resolve: RCTPromiseResolveBlock,
344
- rejecter reject: RCTPromiseRejectBlock
345
- ) {
346
- switch MoveSDK.shared.getAuthState() {
347
- case .invalid, .expired:
348
- resolve(false)
349
- default:
350
- resolve(true)
351
- }
352
- }
353
-
354
- /// Wrapper for `MoveSDK.getDeviceQualifier()`.
355
- /// - Parameters:
356
- /// - resolve: Resolve promise with string.
357
- /// - reject: Unused.
358
- ///
359
- /// Identifier uniquely identifying device, for when device data is transferred to a new phone.
360
- @objc
361
- func getDeviceQualifier(
362
- _ resolve: @escaping RCTPromiseResolveBlock,
363
- rejecter reject: @escaping RCTPromiseRejectBlock
364
- ) {
365
- resolve(MoveSDK.shared.getDeviceQualifier())
366
- }
367
-
368
- /// Wrapper for `MoveSDK.setAssistanceMetaData(_)`
369
- @objc
370
- func setAssistanceMetaData(_ metadata: NSString) {
371
- MoveSDK.shared.setAssistanceMetaData(metadata as String)
372
- }
373
-
374
- /// Wrapper for `MoveSDK.geocode(latitude:longitude)`.
375
- /// - Parameters:
376
- /// - resolve: Resolve promise with geolookup string.
377
- /// - reject: Reject with geocode errors.
378
- @objc
379
- func geocode(_ latitude: Double, _ longitude: Double,
380
- resolver resolve: @escaping RCTPromiseResolveBlock,
381
- rejecter reject: @escaping RCTPromiseRejectBlock
382
- ) {
383
- MoveSDK.shared.geocode(latitude: latitude, longitude: longitude) { result in
384
- switch result {
385
- case let .success(value):
386
- resolve(value)
387
- case let .failure(err):
388
- switch err {
389
- case .resolveFailed:
390
- reject(ErrorCode.resolveFailed.rawValue, nil, nil)
391
- case .serviceUnreachable:
392
- reject(ErrorCode.serviceUnavailable.rawValue, nil, nil)
393
- case .thresholdReached:
394
- reject(ErrorCode.thresholdReached.rawValue, nil, nil)
395
- }
396
- }
397
- }
398
- }
399
-
400
- /// Wrapper for `MoveSDK.updateAuth(auth)`.
401
- /// - Parameters:
402
- /// - contractId: Authentication user ID.
403
- /// - accessToken: Authentication user token.
404
- /// - refreshToken: Authentication refresh token.
405
- /// - productId: Authentication project ID.
406
- /// - resolve: Resolve promise with "OK".
407
- /// - reject: Reject with auth or configuration errors.
408
- @objc
409
- func updateAuth(
410
- _ contractId: String,
411
- accessToken: String,
412
- refreshToken: String,
413
- productId: Int64,
414
- resolver resolve: @escaping RCTPromiseResolveBlock,
415
- rejecter reject: @escaping RCTPromiseRejectBlock
416
- ) {
417
- let auth = MoveAuth(userToken: accessToken, refreshToken: refreshToken, userID: contractId, projectID: productId)
418
-
419
- MoveSDKLauncher.shared.sdk.update(auth: auth) { configurationError in
420
- if let configurationError = configurationError {
421
- switch configurationError {
422
- case .authInvalid:
423
- reject(ErrorCode.authInvalid.rawValue, nil, nil)
424
- default:
425
- reject(ErrorCode.configurationError.rawValue, nil, nil)
426
- }
427
- } else {
428
- resolve("OK")
429
- }
430
- }
431
- }
432
-
433
- /// Wrapper for `MoveSDK.getTripState()`.
434
- /// - Parameters:
435
- /// - resolve: Resolve with trip state.
436
- /// - reject: Unused.
437
- @objc
438
- func getTripState(
439
- _ resolve: RCTPromiseResolveBlock,
440
- rejecter reject: RCTPromiseRejectBlock
441
- ) {
442
- let value = "\(MoveSDK.shared.getTripState())".uppercased()
443
- resolve(value)
444
- }
445
-
446
- /// Wrapper for `MoveSDK.getServiceWarnings()`.
447
- /// - Parameters:
448
- /// - resolve: Resolve with serialized service warnings object.
449
- /// - reject: Unused.
450
- @objc
451
- func getWarnings(
452
- _ resolve: RCTPromiseResolveBlock,
453
- rejecter reject: RCTPromiseRejectBlock
454
- ) {
455
- resolve(MoveSDKLauncher.shared.getServiceWarnings())
456
- }
457
-
458
- /// Wrapper for `MoveSDK.getServiceFailures()`.
459
- /// - Parameters:
460
- /// - resolve: Resolve with serialized service failures object.
461
- /// - reject: Unused.
462
- @objc
463
- func getErrors(
464
- _ resolve: RCTPromiseResolveBlock,
465
- rejecter reject: RCTPromiseRejectBlock
466
- ) {
467
- resolve(MoveSDKLauncher.shared.getServiceFailures())
468
- }
469
-
470
- /// Wrapper for `MoveSDK.startAutomaticDetection()`.
471
- @objc
472
- func startAutomaticDetection(
473
- _ resolve: RCTPromiseResolveBlock,
474
- rejecter reject: RCTPromiseRejectBlock
475
- ) {
476
- if MoveSDK.shared.startAutomaticDetection() {
477
- resolve(true)
478
- } else {
479
- resolve(false)
480
- }
481
- }
482
-
483
- /// Wrapper for `MoveSDK.setLiveLocationTag(:)`.
484
- @objc
485
- func setLiveLocationTag(_ tag: String?,
486
- resolver resolve: RCTPromiseResolveBlock,
487
- rejecter reject: RCTPromiseRejectBlock
488
- ) {
489
- if MoveSDK.shared.setLiveLocationTag(tag) {
490
- resolve(true)
491
- } else {
492
- resolve(false)
493
- }
494
- }
495
-
496
- /// Wrapper for `MoveSDK.startTrip(metadata:)`.
497
- @objc
498
- func startTrip(_ metadata: Any?,
499
- resolver resolve: RCTPromiseResolveBlock,
500
- rejecter reject: RCTPromiseRejectBlock) {
501
- let data = metadata as? [String: String] ?? [:]
502
- if MoveSDK.shared.startTrip(metadata: data) {
503
- resolve(true)
504
- } else {
505
- resolve(false)
506
- }
507
- }
508
-
509
- /// Add metadata to trip
510
- /// - Parameter metadata: Metdata as [String: String].
511
- @objc
512
- func setTripMetadata(_ metadata: Any?) {
513
- let data = metadata as? [String: String] ?? [:]
514
- MoveSDKLauncher.shared.setTrip(metadata: data)
515
- }
516
-
517
- /// Wrapper for `MoveSDK.stopAutomaticDetection()`
518
- @objc
519
- func stopAutomaticDetection(
520
- _ resolve: RCTPromiseResolveBlock,
521
- rejecter reject: RCTPromiseRejectBlock
522
- ) {
523
- if MoveSDK.shared.stopAutomaticDetection() {
524
- resolve(true)
525
- } else {
526
- resolve(false)
527
- }
528
- }
529
-
530
- /// Wrapper for `MoveSDK.shutDown()`.
531
- /// - Parameters:
532
- /// - force: Force shutdown with possible data loss.
533
- /// - resolve: Resolve with "SUCCESS".
534
- /// - reject: Reject with error if SDK unitialized or if force is false and data upload fails.
535
- @objc
536
- func shutdown(_ force: Bool,
537
- resolver resolve: @escaping RCTPromiseResolveBlock,
538
- rejecter reject: @escaping RCTPromiseRejectBlock) {
539
- MoveSDKLauncher.shared.sdk.shutDown() { status in
540
- switch status {
541
- case .success:
542
- resolve("SUCCESS")
543
- case .uninitialized:
544
- reject(ErrorCode.uninitialized.rawValue, nil, nil)
545
- case .networkError:
546
- reject(ErrorCode.networkError.rawValue, nil, nil)
547
- }
548
- }
549
- }
550
-
551
- /// Wrapper for `MoveSDK.forceTripRecognition()`.
552
- @objc
553
- func forceTripRecognition(_ : Any?) {
554
- MoveSDKLauncher.shared.sdk.forceTripRecognition()
555
- }
556
-
557
- /// Wrapper for `MoveSDK.synchronizeUserData()`.
558
- /// - Parameters:
559
- /// - resolve: Resolve with bool whether succesful.
560
- /// - reject: Unused.
561
- @objc
562
- func synchronizeUserData(
563
- _ resolve: @escaping RCTPromiseResolveBlock,
564
- rejecter reject: @escaping RCTPromiseRejectBlock) {
565
- MoveSDKLauncher.shared.sdk.synchronizeUserData() { success in
566
- resolve(success)
567
- }
568
- }
569
-
570
- /// Wrapper for `MoveSDK.initiateAssistanceCall()`.
571
- /// - Parameters:
572
- /// - resolve: Resolve with `true` if successful.
573
- /// - reject: Reject if SDK uninitialized or network failure.
574
- @objc
575
- func initiateAssistanceCall(
576
- _ resolve: @escaping(RCTPromiseResolveBlock),
577
- rejecter reject: @escaping(RCTPromiseRejectBlock)
578
- ) {
579
- MoveSDKLauncher.shared.sdk.initiateAssistanceCall { status in
580
- switch status {
581
- case .success:
582
- resolve(true)
583
- case .initializationError:
584
- reject(ErrorCode.initializationError.rawValue, nil, nil)
585
- case .networkError:
586
- reject(ErrorCode.networkError.rawValue, nil, nil)
587
- }
588
- }
589
- }
590
-
591
- /// Wrapper for `MoveSDK.ignoreCurrentTrip()`.
592
- @objc
593
- func ignoreCurrentTrip() {
594
- MoveSDKLauncher.shared.sdk.ignoreCurrentTrip()
595
- }
596
-
597
- /// Wrapper for `MoveSDK.finishCurrentTrip()`.
598
- @objc
599
- func finishCurrentTrip() {
600
- MoveSDKLauncher.shared.sdk.finishCurrentTrip()
601
- }
602
-
603
- /// Device scanner start scanning.
604
- /// - Parameters:
605
- /// - filter: Device filter.
606
- /// - uuid: iBeacon proximity UUID. Optional.
607
- /// - manufacturerId: iBeacon manufacturerId. Unused.
608
- @objc
609
- func startScanningDevices(_ filter: [String], uuid: String?, manufacturerId: Any?) {
610
- DispatchQueue.main.async {
611
- if self.scanner == nil {
612
- self.scanner = MoveSdkDeviceScanner()
613
- }
614
- self.scanner?.delegate = self
615
- self.scanner?.startScanning(filter: filter, uuid: uuid)
616
- }
617
- }
618
-
619
- /// Wrapper for `MoveSDK.register(devices)`.
620
- /// - Parameters:
621
- /// - devices: Serialized devices list to register.
622
- /// - resolve: Resolve with `true`.
623
- /// - reject: Unused.
624
- @objc
625
- func registerDevices(_ devices: [Any],
626
- resolver resolve: @escaping RCTPromiseResolveBlock,
627
- rejecter reject: @escaping RCTPromiseRejectBlock) {
628
- let devices = MoveSDKLauncher.shared.convert(devices: devices)
629
- MoveSDKLauncher.shared.sdk.register(devices: devices)
630
- resolve(true)
631
- }
632
-
633
- /// Wrapper for `MoveSDK.unregister(devices)`.
634
- /// - Parameters:
635
- /// - devices: Serialized devices list to unregister.
636
- /// - resolve: Resolve with `true`.
637
- /// - reject: Unused.
638
- @objc
639
- func unregisterDevices(_ devices: [Any],
640
- resolver resolve: @escaping RCTPromiseResolveBlock,
641
- rejecter reject: @escaping RCTPromiseRejectBlock) {
642
- let devices = MoveSDKLauncher.shared.convert(devices: devices)
643
- MoveSDKLauncher.shared.sdk.unregister(devices: devices)
644
- resolve(true)
645
- }
646
-
647
- /// Device scanner stop scanning.
648
- @objc
649
- func stopScanningDevices() {
650
- DispatchQueue.main.async {
651
- self.scanner?.stopScanning()
652
- }
653
- }
654
-
655
- /// Wrapper for `MoveSDK.resolveSDKStateError()`.
656
- @objc
657
- func resolveError() {
658
- MoveSDKLauncher.shared.sdk.resolveSDKStateError()
659
- }
660
-
661
- /// Wrapper for React Native `send(event:data)` with `.appEvent`.
662
- /// - Parameters:
663
- /// - eventInfo: Message string.
664
- @objc
665
- func sendAppEvent(_ eventInfo: NSString) {
666
- send(event: .appEvent, data: ["eventInfo": "\(eventInfo)"])
667
- }
668
-
669
- /// Requests user motion activity permission.
670
- @objc
671
- func requestMotionPermission() {
672
- motionManager.queryActivityStarting(from: Date(), to: Date(), to: OperationQueue.main) { _, error in
673
- }
674
- }
675
-
676
- /// Requests user bluetooth permission.
677
- @objc
678
- func requestBluetoothAlwaysUsagePermission() {
679
- bluetoothManager.getBluetoothState() { _ in }
680
- }
681
-
682
- @objc
683
- func getBluetoothPermission(_ resolve: @escaping RCTPromiseResolveBlock,
684
- rejecter _: @escaping RCTPromiseRejectBlock) {
685
- bluetoothManager.getBluetoothState() { state in
686
- switch state {
687
- case .unknown:
688
- resolve(false)
689
- case .resetting:
690
- resolve(false)
691
- case .unsupported:
692
- resolve(false)
693
- case .unauthorized:
694
- resolve(false)
695
- case .poweredOff:
696
- resolve(true)
697
- case .poweredOn:
698
- resolve(true)
699
- @unknown default:
700
- resolve(false)
701
- }
702
- }
703
- }
704
-
705
- @objc
706
- func getBluetoothState(_ resolve: @escaping RCTPromiseResolveBlock,
707
- rejecter reject: @escaping RCTPromiseRejectBlock) {
708
- bluetoothManager.getBluetoothState() { state in
709
- switch state {
710
- case .unknown:
711
- resolve(false)
712
- case .resetting:
713
- resolve(false)
714
- case .unsupported:
715
- resolve(false)
716
- case .unauthorized:
717
- resolve(false)
718
- case .poweredOff:
719
- resolve(false)
720
- case .poweredOn:
721
- resolve(true)
722
- @unknown default:
723
- resolve(false)
724
- }
725
- }
726
- }
727
-
728
- /// Delegates initialize with launch options to the launcher.
729
- @objc public static func initIfPossible(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
730
- MoveSDKLauncher.shared.initIfPossibleWith(launchOptions: launchOptions)
731
- }
732
-
733
- /// Delegates perform background fetch to the launcher.
734
- @objc public static func performBackgroundFetch(_ completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
735
- MoveSDKLauncher.shared.performBackgroundFetch(completionHandler)
736
- }
737
-
738
- override func supportedEvents() -> [String]! {
739
- MoveSDKLauncher.Event.allCases.map { $0.rawValue }
740
- }
741
-
742
- static override func moduleName() -> String! {
743
- return "MoveSdk"
744
- }
745
-
746
- static override func requiresMainQueueSetup() -> Bool {
747
- // To let React Native know if your module needs to be initialized on the main thread, before any JavaScript code executes.
748
- // Otherwise you will see a warning that in the future your module may be initialized on a background thread unless you explicitly opt out
749
- return true
750
- }
751
- }
752
-
753
- extension RCTMoveSdk: MoveSdkDeviceScannerDelegate {
754
- func didDiscover(devices: [MoveDevice]) {
755
- send(event: .devices, data: MoveSDKLauncher.shared.convert(devices: devices))
756
- }
757
- }
758
-
759
- extension RCTMoveSdk: MoveSDKLauncherDelegate {
760
- func send(event: MoveSDKLauncher.Event, data: Any) {
761
- sendEvent(withName: event.rawValue, body: data)
762
- }
763
- }
764
-
765
- /// Move SDK launcher object.
766
- ///
767
- /// Shared singleton MoveSDK launcher responsible for hanging on to the gloabl SDK object.
768
- ///
769
- /// The react native plugin object isn't guaranteed to be loaded or unique.
770
- internal class MoveSDKLauncher {
771
- /// Sent event identifiers to React Native.
772
- internal enum Event: String, CaseIterable {
773
- /// App event.
774
- case appEvent = "MOVE_SDK_APP_EVENT"
775
- /// SDK state change event.
776
- case sdkState = "MOVE_SDK_STATE"
777
- /// SDK trip state change event.
778
- case tripState = "MOVE_SDK_TRIP_STATE"
779
- /// SDK auth state change event.
780
- case authState = "MOVE_SDK_AUTH_STATE"
781
- /// SDK warning listener event.
782
- case warning = "MOVE_SDK_WARNINGS"
783
- /// SDK failure listener event.
784
- case failure = "MOVE_SDK_ERRORS"
785
- /// SDK detected devices event.
786
- case devices = "MOVE_SDK_DEVICES"
787
- /// Device scanning event.
788
- case scanResult = "MOVE_SDK_SCAN_RESULT"
789
- /// Device state event.
790
- case deviceState = "MOVE_SDK_DEVICE_STATE"
791
- /// SDK configuration update event.
792
- case configUpdate = "MOVE_SDK_CONFIG_UPDATE"
793
- /// SDK trip start event.
794
- case tripStart = "MOVE_SDK_TRIP_START"
795
- /// Log event.
796
- case logEvent = "MOVE_SDK_LOG"
797
- /// SDK health listener event.
798
- case health = "MOVE_SDK_HEALTH"
799
- }
800
-
801
- /// User defaults kets.
802
- private enum DefaultsKey: String {
803
- /// Persisted auth object.
804
- case auth = "MOVE.WRAPPER.AUTH"
805
- /// Persisted config object.
806
- case config = "MOVE.WRAPPER.CONFIG"
807
- /// Persisted trip metadata.
808
- case metaData = "MOVE.WRAPPER.TRIP.METADATA"
809
- }
810
-
811
- /// Launcher delegate.
812
- ///
813
- /// The delegate is the allocated react native SDK plugin.
814
- weak var delegate: MoveSDKLauncherDelegate? {
815
- didSet {
816
- for (key, value) in pendingEvents {
817
- delegate?.send(event: key, data: value)
818
- }
819
- }
820
- }
821
-
822
- /// Persisted trip metadata.
823
- private var tripMetaData: [String: String] {
824
- didSet {
825
- MoveSDKLauncher.encode(tripMetaData, forKey: .metaData)
826
- }
827
- }
828
-
829
- /// Pending events triggered before event observer registered.
830
- private var pendingEvents: [Event: Any] = [:]
831
-
832
- /// Shared singleton.
833
- static let shared = MoveSDKLauncher()
834
-
835
- /// Global MoveSDK object reference.
836
- fileprivate let sdk = MoveSDK.shared
837
-
838
- /// Initialize the MoveSDK and register listeners to forward events to the delegate.
839
- init() {
840
- tripMetaData = MoveSDKLauncher.decode(.metaData) ?? [:]
841
-
842
- sdk.setSDKStateListener { state in
843
- let value = "\(state)".uppercased()
844
- self.send(event: .sdkState, data: ["state": "\(value)"])
845
- }
846
-
847
- sdk.setTripStateListener { state in
848
- let value = "\(state)".uppercased()
849
- self.send(event: .tripState, data: ["state": "\(value)"])
850
- }
851
-
852
- sdk.setTripStartListener { date in
853
- self.send(event: .tripStart, data: Int64(date.timeIntervalSince1970 * 1000.0))
854
- }
855
-
856
- sdk.setAuthStateUpdateListener { state in
857
- let value = "\(state)".uppercased()
858
- self.send(event: .authState, data: ["state": "\(value)"])
859
- }
860
-
861
- sdk.setServiceFailureListener { failures in
862
- let data: [String: Any] = ["errors": self.convert(failures: failures)]
863
- self.send(event: .failure, data: data)
864
- }
865
-
866
- sdk.setServiceWarningListener { warnings in
867
- let data: [String: Any] = ["warnings": self.convert(warnings: warnings)]
868
- self.send(event: .warning, data: data)
869
- }
870
-
871
- sdk.setDeviceDiscoveryListener { scanResults in
872
- let data = self.convert(scanResults: scanResults)
873
- self.send(event: .scanResult, data: data)
874
- }
875
-
876
- sdk.setDeviceStateListener { results in
877
- let data = self.convert(devices: results)
878
- self.send(event: .deviceState, data: data)
879
- }
880
-
881
- sdk.setRemoteConfigChangeListener { config in
882
- let services: [String] = config.services.reduce([]) { $0 + self.convert(service: $1, base: true) }
883
- let data = ["services": services]
884
- self.send(event: .configUpdate, data: data)
885
- }
886
-
887
- sdk.setTripMetaDataListener { tripStart, tripEnd in
888
- let metadata = self.tripMetaData
889
- self.tripMetaData = [:]
890
- return metadata
891
- }
892
-
893
- sdk.setLogListener { (event, value) in
894
- DispatchQueue.main.async {
895
- var data: [String: Any] = ["message": event]
896
-
897
- if let value = value {
898
- data["value"] = value
899
- }
900
-
901
- self.send(event: .logEvent, data: data)
902
- }
903
- }
904
-
905
- sdk.setHealthScoreListener { items in
906
- let data: [[String: String]] = items.map {
907
- ["reason": $0.reason.rawValue.snakeCased(), "description": $0.description]
908
- }
909
- self.send(event: .health, data: data)
910
- }
911
- }
912
-
913
- /// Send event to observer.
914
- /// - Parameters:
915
- /// - event: Event key.
916
- /// - data: Event object.
917
- ///
918
- /// Events are buffered when there is no observer.
919
- func send(event: Event, data: Any) {
920
- if let delegate {
921
- delegate.send(event: event, data: data)
922
- }
923
-
924
- pendingEvents[event] = data
925
- }
926
-
927
- /// Wrapper for `MoveSDK.getServiceWarnings()`.
928
- /// - Returns: Serialized SDK service warnings.
929
- fileprivate func getServiceWarnings() -> [MoveSDKErrorListItem] {
930
- return convert(warnings: sdk.getServiceWarnings())
931
- }
932
-
933
- /// Wrapper for `MoveSDK.getServiceFailures()`.
934
- /// - Returns: Serialized SDK service errors.
935
- fileprivate func getServiceFailures() -> [MoveSDKErrorListItem] {
936
- return convert(failures: sdk.getServiceFailures())
937
- }
938
-
939
- /// Deserialize device objects from React Native function arguments.
940
- /// - Parameters:
941
- /// - devices: React Native function arguments list.
942
- ///
943
- /// - Returns: List of deserialized `MoveDevice` objects.
944
- ///
945
- /// Passed to `register(devices)` or `unregister(devices)`.
946
- fileprivate func convert(devices: [Any]) -> [MoveDevice] {
947
- return devices.compactMap { values in
948
- guard let values = values as? [String: String] else { return nil }
949
- let encoded: String = values["data"] ?? ""
950
-
951
- let decoder = JSONDecoder()
952
- guard let data = encoded.data(using: .utf8) else { return nil }
953
- do {
954
- let device = try decoder.decode(MoveDevice.self, from: data)
955
- /* keep device name from info */
956
- return device
957
- } catch {
958
- return nil
959
- }
960
- }
961
- }
962
-
963
- /// Serialize device objects for React Native events.
964
- /// - Parameters:
965
- /// - devices: `MoveDevice` list.
966
- /// - Returns: List of serialized device objects.
967
- ///
968
- /// Used from `getRegisteredDevices()` or from device scanner.
969
- fileprivate func convert(devices: [MoveDevice]) -> [[String:String]] {
970
- var deviceList: [[String: String]] = []
971
- for device in devices {
972
- let encoder = JSONEncoder()
973
- do {
974
- let data = try encoder.encode(device)
975
- let str = String(data: data, encoding: .utf8) ?? ""
976
- let info: [String: String] = ["name": device.name, "data": str, "id": device.id, "isConnected": "\(device.isConnected)"]
977
- deviceList.append(info)
978
- } catch {
979
- print(error.localizedDescription)
980
- }
981
- }
982
-
983
- return deviceList
984
- }
985
-
986
- /// Serialize device scan results for React Native events.
987
- /// - Parameters:
988
- /// - scanResults: `MoveScanResult` list.
989
- ///
990
- /// - Returns: List of serialized device objects.
991
- ///
992
- /// Used from device detection listener.
993
- fileprivate func convert(scanResults: [MoveScanResult]) -> [[String: Any]] {
994
- var deviceList: [[String: Any]] = []
995
- for result in scanResults {
996
- let encoder = JSONEncoder()
997
- do {
998
- let data = try encoder.encode(result.device)
999
- let str = String(data: data, encoding: .utf8) ?? ""
1000
- let info: [String: Any] = ["name": result.device.name, "device": str, "id": result.device.id, "isDiscovered": result.isDiscovered]
1001
- deviceList.append(info)
1002
- } catch {
1003
- print(error.localizedDescription)
1004
- }
1005
- }
1006
-
1007
- return deviceList
1008
- }
1009
-
1010
- /// Serialize detection service.
1011
- /// - Parameters:
1012
- /// - service: Move service to be serialized.
1013
- ///
1014
- /// - Returns: List of one or more service strings for service and subservices.
1015
- fileprivate func convert(service: DolphinMoveSDK.MoveConfig.DetectionService, base: Bool = false) -> [String] {
1016
- switch service {
1017
- case let .driving(sub):
1018
- var services: [String] = base || sub.isEmpty ? [ServiceName.driving.rawValue] : []
1019
- for subservice in sub {
1020
- switch subservice {
1021
- case .drivingBehavior:
1022
- services.append(ServiceName.drivingBehavior.rawValue)
1023
- case .distractionFreeDriving:
1024
- services.append(ServiceName.distractionFreeDriving.rawValue)
1025
- case .deviceDiscovery:
1026
- services.append(ServiceName.deviceDiscovery.rawValue)
1027
- default: break
1028
- }
1029
- }
1030
- return services
1031
- case .cycling:
1032
- return [ServiceName.cycling.rawValue]
1033
- case let .walking(sub):
1034
- var services: [String] = base || sub.isEmpty ? [ServiceName.walking.rawValue] : []
1035
- for subservice in sub {
1036
- switch subservice {
1037
- case .location:
1038
- services.append(ServiceName.walkingLocation.rawValue)
1039
- default: break
1040
- }
1041
- }
1042
- return services
1043
- case .places:
1044
- return [ServiceName.places.rawValue]
1045
- case .publicTransport:
1046
- return [ServiceName.publicTransport.rawValue]
1047
- case .pointsOfInterest:
1048
- return [ServiceName.pointsOfInterest.rawValue]
1049
- case .automaticImpactDetection:
1050
- return [ServiceName.automaticImpactDetection.rawValue]
1051
- case .assistanceCall:
1052
- return [ServiceName.assistanceCall.rawValue]
1053
- @unknown default:
1054
- return [service.debugDescription]
1055
- }
1056
- }
1057
-
1058
- /// Serialize SDK service failures.
1059
- /// - Parameters:
1060
- /// - failures: Move service failures to be serialized.
1061
- ///
1062
- /// - Returns: List of error list items.
1063
- ///
1064
- /// Used in `MoveSDK.getServiceFailures()` and service failure listener.
1065
- fileprivate func convert(failures: [DolphinMoveSDK.MoveServiceFailure]) -> [MoveSDKErrorListItem] {
1066
- var converted: [MoveSDKErrorListItem] = []
1067
-
1068
- for failure in failures {
1069
- var reasons: [String] = []
1070
- switch failure.reason {
1071
- case let .missingPermission(permissions):
1072
- let content: [String] = permissions.map { self.permissionString($0) }
1073
- reasons = content
1074
- case .unauthorized:
1075
- reasons = ["Unauthorized"]
1076
- }
1077
- let services = convert(service: failure.service)
1078
- for service in services {
1079
- converted.append(["service": service, "reasons": reasons])
1080
- }
1081
- }
1082
-
1083
- return converted
1084
- }
1085
-
1086
- /// Serialize SDK service warnings.
1087
- /// - Parameters:
1088
- /// - failures: Move service warnings to be serialized.
1089
- ///
1090
- /// - Returns: List of error list items.
1091
- ///
1092
- /// Used in `MoveSDK.getServiceWarnings()` and service warning listener.
1093
- fileprivate func convert(warnings: [DolphinMoveSDK.MoveServiceWarning]) -> [MoveSDKErrorListItem] {
1094
- var converted: [MoveSDKErrorListItem] = []
1095
-
1096
- for warning in warnings {
1097
- var reasons: [String] = []
1098
- switch warning.reason {
1099
- case let .missingPermission(permissions):
1100
- let content: [String] = permissions.compactMap {
1101
- self.permissionString($0)
1102
- }
1103
- reasons = content
1104
- }
1105
- let services = convert(service: warning.service)
1106
- for service in services {
1107
- converted.append(["service": service, "reasons": reasons])
1108
- }
1109
- }
1110
-
1111
- return converted
1112
- }
1113
-
1114
- /// Serialize move permission object into string.
1115
- /// - Parameters:
1116
- /// - permission: Permission object to serialize.
1117
- ///
1118
- /// - Returns: Service permission string passed to React Native.
1119
- fileprivate func permissionString(_ permission: DolphinMoveSDK.MovePermission) -> String {
1120
- switch permission {
1121
- case .location:
1122
- return "LOCATION_PERMISSION_MISSING"
1123
- case .backgroundLocation:
1124
- return "BACKGROUND_LOCATION_PERMISSION_MISSING"
1125
- case .preciseLocation:
1126
- return "PRECISE_LOCATION_PERMISSION_MISSING"
1127
- case .motionActivity:
1128
- return "MOTION_PERMISSION_MISSING"
1129
- case .gyroscope:
1130
- return "GYROSCOPE_MISSING"
1131
- case .accelerometer:
1132
- return "ACCELEROMETER_MISSING"
1133
- case .bluetooth:
1134
- return "BLUETOOTH_TURNED_OFF"
1135
- case .bluetoothScan:
1136
- return "BLUETOOTH_PERMISSION_MISSING"
1137
- @unknown default:
1138
- return "UNKNOWN"
1139
- }
1140
- }
1141
-
1142
- /// Call SDK initializer with launch options.
1143
- /// - Parameters:
1144
- /// - launchOptions: Launch options.
1145
- ///
1146
- /// Required to be called from `willFinishLaunching` or `didFinishLaunching`.
1147
- internal func initIfPossibleWith(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
1148
- MoveSDK.shared.initialize(launchOptions: launchOptions)
1149
-
1150
- let oldConfig: OldConfig? = MoveSDKLauncher.decode(.config)
1151
- let oldAuth: OldAuth? = MoveSDKLauncher.decode(.auth)
1152
-
1153
- /// migrate
1154
- if let oldAuth = oldAuth, let oldConfig = oldConfig {
1155
- let auth = DolphinMoveSDK.MoveAuth(userToken: oldAuth.userToken, refreshToken: oldAuth.refreshToken, userID: oldAuth.contractID, projectID: oldAuth.productID)
1156
-
1157
- MoveSDK.shared.setup(auth: auth, config: oldConfig.convert())
1158
- MoveSDKLauncher.encode(nil as OldAuth?, forKey: .auth)
1159
- }
1160
-
1161
- let isInRunningState = UserDefaults.standard.bool(forKey: "MOVE.WRAPPER.RUNNING")
1162
- if isInRunningState {
1163
- sdk.startAutomaticDetection()
1164
- UserDefaults.standard.removeObject(forKey: "MOVE.WRAPPER.RUNNING")
1165
- }
1166
- }
1167
-
1168
- /// Delegate a background fetch.
1169
- /// - Parameters:
1170
- /// - completionHandler: Background fetch handler.
1171
- internal func performBackgroundFetch(_ completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
1172
- MoveSDK.shared.performBackgroundFetch(completionHandler)
1173
- }
1174
-
1175
- /// Call Move SDK `setup(auth:config:options)`.
1176
- /// - Parameters:
1177
- /// - auth: `MoveAuth` object.
1178
- /// - config: `MoveConfig` object.
1179
- /// - options: `MoveOptions` object.
1180
- internal func setup(auth: DolphinMoveSDK.MoveAuth, config: DolphinMoveSDK.MoveConfig, options: DolphinMoveSDK.MoveOptions) {
1181
- MoveSDK.shared.setup(auth: auth, config: config, options: options)
1182
- }
1183
-
1184
- /// Call Move SDK `setup(authCode:config:options:callback)`.
1185
- /// - Parameters:
1186
- /// - authCode: Authentication code.
1187
- /// - config: `MoveConfig` object.
1188
- /// - options: `MoveOptions` object.
1189
- internal func setup(authCode: String, config: DolphinMoveSDK.MoveConfig, options: DolphinMoveSDK.MoveOptions, callback: @escaping DolphinMoveSDK.MoveAuthCallback) {
1190
- MoveSDK.shared.setup(authCode: authCode, config: config, options: options, callback: callback)
1191
- }
1192
-
1193
- /// Decode from user defaults.
1194
- /// - Parameters:
1195
- /// - key: User defaults string key.
1196
- ///
1197
- /// - Returns: Decoded object.
1198
- private static func decode<T>(_ key: DefaultsKey) -> T? where T: Decodable {
1199
- let decoder = PropertyListDecoder()
1200
-
1201
- if let data = UserDefaults.standard.object(forKey: key.rawValue) as? Data {
1202
- return try? decoder.decode(T.self, from: data)
1203
- }
1204
-
1205
- return nil
1206
- }
1207
-
1208
- /// Encode to user defaults.
1209
- /// - Parameters:
1210
- /// - key: User defaults string key.
1211
- private static func encode<T>(_ encodable: T?, forKey key: DefaultsKey) where T: Encodable {
1212
- if let encodable = encodable {
1213
- let encoder = PropertyListEncoder()
1214
- if let data = try? encoder.encode(encodable) {
1215
- UserDefaults.standard.set(data, forKey: key.rawValue)
1216
- }
1217
- } else {
1218
- UserDefaults.standard.removeObject(forKey: key.rawValue)
1219
- }
1220
- }
1221
-
1222
- /// Add trip metadata.
1223
- /// - Parameter metadata: Meta data strings dictionary.
1224
- fileprivate func setTrip(metadata: [String: String]) {
1225
- var data = self.tripMetaData
1226
- for (key, value) in metadata {
1227
- data[key] = value
1228
- }
1229
- self.tripMetaData = data
1230
- }
1231
- }
1232
-
1233
- /// Persisted old auth object to be migrated.
1234
- struct OldAuth: Codable {
1235
- /// User token.
1236
- var userToken: String
1237
- /// Refresh token.
1238
- var refreshToken: String
1239
- /// User ID.
1240
- var contractID: String
1241
- /// Project ID.
1242
- var productID: Int64
1243
- }
1244
-
1245
- /// Old config to be migrated.
1246
- struct OldConfig: Codable {
1247
- /// Expresses modes of transport to be detected
1248
- enum TimelineDetectionService: Int, Codable {
1249
- /// Detect driving behaviour
1250
- case driving = 1
1251
-
1252
- /// Detect cycling behaviour
1253
- case bicycle = 2
1254
-
1255
- /// Detect walking behaviour
1256
- case walking = 3
1257
-
1258
- /// Detect visits
1259
- case places = 4
1260
-
1261
- case publicTransport = 5
1262
- }
1263
-
1264
- /// Expresses driving services to be detected
1265
- enum DrivingService: Int, Codable {
1266
- /// Detect distraction free driving
1267
- case dfd = 101
1268
-
1269
- /// Detect driving behaviour
1270
- case behaviour = 102
1271
- }
1272
-
1273
- /// Expresses walking services to be detected
1274
- enum WalkingService: Int, Codable {
1275
- /// Detects GPS location for collected walking events
1276
- case location = 301
1277
- }
1278
-
1279
- /// Expresses other services to be detected
1280
- enum OtherService: Int, Codable {
1281
- /// Monitor points of intrest
1282
- case poi = 401
1283
- case impact = 402
1284
- }
1285
-
1286
- /// Detection services.
1287
- var timelineDetectionService: [TimelineDetectionService]
1288
- /// Driving subservices.
1289
- var drivingServices: [DrivingService]
1290
- /// Walking subservices.
1291
- var walkingServices: [WalkingService]
1292
- /// Other services.
1293
- var otherServices: [OtherService]
1294
-
1295
- /// Update status frequency.
1296
- ///
1297
- /// This should be always taken from server.
1298
- var tripStatusUpdateFrequency: Double = -1
1299
-
1300
- /// Convert into `MoveConfig` object.
1301
- /// - Returns: `MoveConfig` object.
1302
- func convert() -> DolphinMoveSDK.MoveConfig {
1303
- let driving: [DolphinMoveSDK.MoveConfig.DrivingService] = drivingServices.map {
1304
- switch $0 {
1305
- case .behaviour:
1306
- return .drivingBehavior
1307
- case .dfd:
1308
- return .distractionFreeDriving
1309
- }
1310
- }
1311
-
1312
- let walking: [DolphinMoveSDK.MoveConfig.WalkingService] = walkingServices.map {
1313
- switch $0 {
1314
- case .location:
1315
- return .location
1316
- }
1317
- }
1318
-
1319
- let services: [DolphinMoveSDK.MoveConfig.DetectionService] = timelineDetectionService.map {
1320
- switch $0 {
1321
-
1322
- case .driving:
1323
- return .driving(driving)
1324
- case .bicycle:
1325
- return .cycling
1326
- case .walking:
1327
- return .walking(walking)
1328
- case .places:
1329
- return .places
1330
- case .publicTransport:
1331
- return .publicTransport
1332
- }
1333
- }
1334
-
1335
- let otherServices: [DolphinMoveSDK.MoveConfig.DetectionService] = otherServices.map {
1336
- switch $0 {
1337
- case .poi:
1338
- return .pointsOfInterest
1339
- case .impact:
1340
- return .automaticImpactDetection
1341
- }
1342
- }
1343
-
1344
- return DolphinMoveSDK.MoveConfig(detectionService: services + otherServices)
1345
- }
1346
- }
1347
-
1348
- extension String {
1349
- func snakeCased() -> String {
1350
- let pattern = "([a-z0-9])([A-Z])"
1351
-
1352
- if let regex = try? NSRegularExpression(pattern: pattern, options: []) {
1353
- let range = NSRange(location: 0, length: count)
1354
- return regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: "$1_$2").uppercased()
1355
- }
1356
-
1357
- return uppercased()
1358
- }
1359
- }