@doorstepai/dropoff-sdk-capacitor 1.0.1 → 1.0.3

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 (38) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/java/ai/doorstep/dropoffsdk/capacitor/DoorstepAIDropoffSDKPlugin.kt +140 -2
  3. package/dist/docs.json +282 -1
  4. package/dist/esm/definitions.d.ts +82 -8
  5. package/dist/esm/index.js.map +1 -1
  6. package/dist/esm/web.d.ts +13 -1
  7. package/dist/esm/web.js +15 -0
  8. package/dist/esm/web.js.map +1 -1
  9. package/dist/plugin.cjs.js +15 -2
  10. package/dist/plugin.cjs.js.map +1 -1
  11. package/dist/plugin.js +15 -2
  12. package/dist/plugin.js.map +1 -1
  13. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/DoorstepDropoffSDK +0 -0
  14. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/Info.plist +0 -0
  15. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios.abi.json +5365 -1558
  16. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +82 -9
  17. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  18. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios.swiftinterface +82 -9
  19. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/_CodeSignature/CodeResources +11 -11
  20. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/dSYMs/DoorstepDropoffSDK.framework.dSYM/Contents/Resources/DWARF/DoorstepDropoffSDK +0 -0
  21. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/dSYMs/DoorstepDropoffSDK.framework.dSYM/Contents/Resources/Relocations/aarch64/DoorstepDropoffSDK.yml +2630 -2113
  22. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/DoorstepDropoffSDK +0 -0
  23. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Info.plist +0 -0
  24. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +5365 -1558
  25. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +82 -9
  26. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  27. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +82 -9
  28. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/x86_64-apple-ios-simulator.abi.json +5365 -1558
  29. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +82 -9
  30. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  31. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +82 -9
  32. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/_CodeSignature/CodeResources +21 -21
  33. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/DoorstepDropoffSDK.framework.dSYM/Contents/Resources/DWARF/DoorstepDropoffSDK +0 -0
  34. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/DoorstepDropoffSDK.framework.dSYM/Contents/Resources/Relocations/aarch64/DoorstepDropoffSDK.yml +2630 -2113
  35. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/DoorstepDropoffSDK.framework.dSYM/Contents/Resources/Relocations/x86_64/DoorstepDropoffSDK.yml +2616 -2102
  36. package/ios/Plugin/DoorstepAIDropoffSDKPlugin.m +5 -0
  37. package/ios/Plugin/DoorstepAIDropoffSDKPlugin.swift +132 -1
  38. package/package.json +1 -1
@@ -17,6 +17,11 @@ CAP_PLUGIN(DoorstepAIDropoffSDKPlugin, "DoorstepAIDropoffSDK",
17
17
  CAP_PLUGIN_METHOD(markDropoff, CAPPluginReturnPromise);
18
18
  CAP_PLUGIN_METHOD(newEvent, CAPPluginReturnPromise);
19
19
  CAP_PLUGIN_METHOD(stopDelivery, CAPPluginReturnPromise);
20
+ CAP_PLUGIN_METHOD(startRouteGeofencing, CAPPluginReturnPromise);
21
+ CAP_PLUGIN_METHOD(updateRouteStops, CAPPluginReturnPromise);
22
+ CAP_PLUGIN_METHOD(stopRouteGeofencing, CAPPluginReturnPromise);
23
+ CAP_PLUGIN_METHOD(resumeRouteGeofencingIfNeeded, CAPPluginReturnPromise);
24
+ CAP_PLUGIN_METHOD(getMonitoredStops, CAPPluginReturnPromise);
20
25
  CAP_PLUGIN_METHOD(checkPermissions, CAPPluginReturnPromise);
21
26
  CAP_PLUGIN_METHOD(requestPermissions, CAPPluginReturnPromise);
22
27
  )
@@ -4,6 +4,7 @@ import UIKit
4
4
  import SwiftUI
5
5
  import CoreLocation
6
6
  import CoreMotion
7
+ import CoreBluetooth
7
8
  import DoorstepDropoffSDK
8
9
 
9
10
  @objc(DoorstepAIDropoffSDKPlugin)
@@ -16,6 +17,26 @@ public class DoorstepAIDropoffSDKPlugin: CAPPlugin, CLLocationManagerDelegate {
16
17
  return m
17
18
  }()
18
19
  private var pendingLocationContinuation: CheckedContinuation<Void, Never>?
20
+ private var btManager: CBCentralManager?
21
+
22
+ override public func load() {
23
+ // Bridge the two native geofence-session notifications onto one Capacitor
24
+ // listener event ("geofenceSessionEvent"), matching the RN/Flutter shape.
25
+ NotificationCenter.default.addObserver(self, selector: #selector(onGeofenceStarted(_:)), name: DoorstepAI.geofenceSessionStartedNotification, object: nil)
26
+ NotificationCenter.default.addObserver(self, selector: #selector(onGeofenceStopped(_:)), name: DoorstepAI.geofenceSessionStoppedNotification, object: nil)
27
+ }
28
+
29
+ @objc private func onGeofenceStarted(_ note: Notification) { emitGeofenceEvent(note, "STARTED") }
30
+ @objc private func onGeofenceStopped(_ note: Notification) { emitGeofenceEvent(note, "STOPPED") }
31
+
32
+ private func emitGeofenceEvent(_ note: Notification, _ type: String) {
33
+ let info = note.userInfo ?? [:]
34
+ notifyListeners("geofenceSessionEvent", data: [
35
+ "deliveryId": (info["deliveryId"] as? String) ?? "",
36
+ "type": type,
37
+ "reason": (info["reason"] as? String) ?? ""
38
+ ])
39
+ }
19
40
 
20
41
  /// Mounts `DoorstepAIRoot` as a 0pt invisible subview of the webview's
21
42
  /// view controller, mirroring the Flutter wrapper's zero-height `UiKitView`.
@@ -212,9 +233,10 @@ public class DoorstepAIDropoffSDKPlugin: CAPPlugin, CLLocationManagerDelegate {
212
233
  let deliveryId = call.getString("deliveryId") else {
213
234
  return call.reject("INVALID_ARGUMENTS: eventName or deliveryId missing")
214
235
  }
236
+ let eventTimestamp = call.getDouble("timestamp")
215
237
  Task {
216
238
  do {
217
- try await DoorstepAI.newEvent(eventName: eventName, deliveryId: deliveryId)
239
+ try await DoorstepAI.newEvent(eventName: eventName, deliveryId: deliveryId, timestamp: eventTimestamp)
218
240
  call.resolve()
219
241
  } catch {
220
242
  call.reject("Failed to send event: \(error.localizedDescription)", "E_NEW_EVENT")
@@ -271,9 +293,18 @@ public class DoorstepAIDropoffSDKPlugin: CAPPlugin, CLLocationManagerDelegate {
271
293
  @unknown default: activity = "denied"
272
294
  }
273
295
 
296
+ let bluetooth: String
297
+ switch CBManager.authorization {
298
+ case .notDetermined: bluetooth = "prompt"
299
+ case .restricted, .denied: bluetooth = "denied"
300
+ case .allowedAlways: bluetooth = "granted"
301
+ @unknown default: bluetooth = "denied"
302
+ }
303
+
274
304
  return [
275
305
  "location": location,
276
306
  "activity": activity,
307
+ "bluetooth": bluetooth,
277
308
  ]
278
309
  }
279
310
 
@@ -283,11 +314,24 @@ public class DoorstepAIDropoffSDKPlugin: CAPPlugin, CLLocationManagerDelegate {
283
314
  await requestLocationAuthorization()
284
315
  case "activity":
285
316
  await requestActivityAuthorization()
317
+ case "bluetooth":
318
+ await requestBluetoothAuthorization()
286
319
  default:
287
320
  break
288
321
  }
289
322
  }
290
323
 
324
+ private func requestBluetoothAuthorization() async {
325
+ // Instantiating a CBCentralManager is the canonical way to trigger the iOS
326
+ // Bluetooth permission prompt when authorization is .notDetermined (requires
327
+ // NSBluetoothAlwaysUsageDescription in the host Info.plist). Opt-in only.
328
+ guard CBManager.authorization == .notDetermined else { return }
329
+ await withCheckedContinuation { (cont: CheckedContinuation<Void, Never>) in
330
+ btManager = CBCentralManager(delegate: nil, queue: nil)
331
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { cont.resume() }
332
+ }
333
+ }
334
+
291
335
  private func requestLocationAuthorization() async {
292
336
  guard clManager.authorizationStatus == .notDetermined else { return }
293
337
  await withCheckedContinuation { (cont: CheckedContinuation<Void, Never>) in
@@ -324,4 +368,91 @@ public class DoorstepAIDropoffSDKPlugin: CAPPlugin, CLLocationManagerDelegate {
324
368
  }
325
369
  return LatLngObject(lat: lat, lng: lng)
326
370
  }
371
+
372
+ // MARK: - Route geofencing
373
+
374
+ @objc func startRouteGeofencing(_ call: CAPPluginCall) {
375
+ let stops = parseStops(call.getArray("stops"))
376
+ if stops.isEmpty {
377
+ return call.reject("startRouteGeofencing requires at least one valid stop (deliveryId + latitude + longitude)", "E_ROUTE_GEOFENCING")
378
+ }
379
+ let opts = parseRouteOptions(call.getObject("options"))
380
+ DispatchQueue.main.async {
381
+ DoorstepAI.startRouteGeofencing(stops: stops, options: opts)
382
+ call.resolve()
383
+ }
384
+ }
385
+
386
+ @objc func updateRouteStops(_ call: CAPPluginCall) {
387
+ let stops = parseStops(call.getArray("stops"))
388
+ DispatchQueue.main.async {
389
+ DoorstepAI.updateRouteStops(stops)
390
+ call.resolve()
391
+ }
392
+ }
393
+
394
+ @objc func stopRouteGeofencing(_ call: CAPPluginCall) {
395
+ DispatchQueue.main.async {
396
+ DoorstepAI.stopRouteGeofencing()
397
+ call.resolve()
398
+ }
399
+ }
400
+
401
+ @objc func resumeRouteGeofencingIfNeeded(_ call: CAPPluginCall) {
402
+ DispatchQueue.main.async {
403
+ DoorstepAI.resumeRouteGeofencingIfNeeded()
404
+ call.resolve()
405
+ }
406
+ }
407
+
408
+ @objc func getMonitoredStops(_ call: CAPPluginCall) {
409
+ DispatchQueue.main.async {
410
+ call.resolve(["stops": DoorstepAI.monitoredStops.map { self.serializeStop($0) }])
411
+ }
412
+ }
413
+
414
+ private func parseStops(_ raw: JSArray?) -> [DeliveryStop] {
415
+ guard let raw = raw, let arr = raw as? [[String: Any]] else { return [] }
416
+ return arr.compactMap { parseDeliveryStop($0) }
417
+ }
418
+
419
+ private func parseDeliveryStop(_ raw: [String: Any]) -> DeliveryStop? {
420
+ guard let deliveryId = raw["deliveryId"] as? String,
421
+ let latitude = (raw["latitude"] as? NSNumber)?.doubleValue,
422
+ let longitude = (raw["longitude"] as? NSNumber)?.doubleValue else {
423
+ return nil
424
+ }
425
+ return DeliveryStop(
426
+ deliveryId: deliveryId,
427
+ address: (raw["address"] as? String) ?? "",
428
+ latitude: latitude,
429
+ longitude: longitude,
430
+ radiusMeters: (raw["radiusMeters"] as? NSNumber)?.doubleValue,
431
+ customerId: raw["customerId"] as? String,
432
+ driverId: raw["driverId"] as? String
433
+ )
434
+ }
435
+
436
+ // iOS RouteGeofenceOptions has no `manualForeground` (the OS owns background
437
+ // region monitoring); a JS-supplied manualForeground is intentionally ignored.
438
+ private func parseRouteOptions(_ o: JSObject?) -> RouteGeofenceOptions {
439
+ return RouteGeofenceOptions(
440
+ defaultRadiusMeters: (o?["defaultRadiusMeters"] as? NSNumber)?.doubleValue ?? 250,
441
+ timeoutSeconds: (o?["timeoutSeconds"] as? NSNumber)?.doubleValue,
442
+ autoStopAfterDropoffSeconds: (o?["autoStopAfterDropoffSeconds"] as? NSNumber)?.doubleValue
443
+ )
444
+ }
445
+
446
+ private func serializeStop(_ s: DeliveryStop) -> [String: Any] {
447
+ var m: [String: Any] = [
448
+ "deliveryId": s.deliveryId,
449
+ "address": s.address,
450
+ "latitude": s.latitude,
451
+ "longitude": s.longitude
452
+ ]
453
+ if let r = s.radiusMeters { m["radiusMeters"] = r }
454
+ if let c = s.customerId { m["customerId"] = c }
455
+ if let d = s.driverId { m["driverId"] = d }
456
+ return m
457
+ }
327
458
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doorstepai/dropoff-sdk-capacitor",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Capacitor plugin for DoorstepAI's Dropoff SDK",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",