react-native-pointr 9.1.0 → 9.3.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 (78) hide show
  1. package/API_REFERENCE.md +887 -0
  2. package/CHANGELOG.md +35 -0
  3. package/EXTENDING.md +419 -0
  4. package/README.md +221 -117
  5. package/WAYFINDING_EVENTS.md +243 -0
  6. package/android/build.gradle +3 -16
  7. package/android/src/main/java/com/pointr/PTRCoreExtensions.kt +126 -0
  8. package/android/src/main/java/com/pointr/PTRMapWidgetCommandType.kt +3 -1
  9. package/android/src/main/java/com/pointr/PTRMapWidgetManager.kt +160 -11
  10. package/android/src/main/java/com/pointr/PointrModule.kt +106 -3
  11. package/example/pointr_rn_demo/.bundle/config +2 -0
  12. package/example/pointr_rn_demo/.eslintrc.js +4 -0
  13. package/example/pointr_rn_demo/.prettierrc.js +5 -0
  14. package/example/pointr_rn_demo/.watchmanconfig +1 -0
  15. package/example/pointr_rn_demo/App.tsx +323 -0
  16. package/example/pointr_rn_demo/Gemfile +16 -0
  17. package/example/pointr_rn_demo/Gemfile.lock +111 -0
  18. package/example/pointr_rn_demo/README.md +188 -0
  19. package/example/pointr_rn_demo/__tests__/App.test.tsx +13 -0
  20. package/example/pointr_rn_demo/android/app/build.gradle +119 -0
  21. package/example/pointr_rn_demo/android/app/debug.keystore +0 -0
  22. package/example/pointr_rn_demo/android/app/proguard-rules.pro +10 -0
  23. package/example/pointr_rn_demo/android/app/src/main/AndroidManifest.xml +27 -0
  24. package/example/pointr_rn_demo/android/app/src/main/java/com/pointr_rn_demo/MainActivity.kt +22 -0
  25. package/example/pointr_rn_demo/android/app/src/main/java/com/pointr_rn_demo/MainApplication.kt +27 -0
  26. package/example/pointr_rn_demo/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  27. package/example/pointr_rn_demo/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  28. package/example/pointr_rn_demo/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  29. package/example/pointr_rn_demo/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  30. package/example/pointr_rn_demo/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  31. package/example/pointr_rn_demo/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  32. package/example/pointr_rn_demo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  33. package/example/pointr_rn_demo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  34. package/example/pointr_rn_demo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  35. package/example/pointr_rn_demo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  36. package/example/pointr_rn_demo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  37. package/example/pointr_rn_demo/android/app/src/main/res/values/strings.xml +3 -0
  38. package/example/pointr_rn_demo/android/app/src/main/res/values/styles.xml +9 -0
  39. package/example/pointr_rn_demo/android/build.gradle +32 -0
  40. package/example/pointr_rn_demo/android/gradle.properties +44 -0
  41. package/example/pointr_rn_demo/android/settings.gradle +6 -0
  42. package/example/pointr_rn_demo/app.json +4 -0
  43. package/example/pointr_rn_demo/babel.config.js +3 -0
  44. package/example/pointr_rn_demo/index.js +16 -0
  45. package/example/pointr_rn_demo/ios/.xcode.env +11 -0
  46. package/example/pointr_rn_demo/ios/Podfile +40 -0
  47. package/example/pointr_rn_demo/ios/Podfile.lock +2767 -0
  48. package/example/pointr_rn_demo/ios/pointr_rn_demo/AppDelegate.swift +48 -0
  49. package/example/pointr_rn_demo/ios/pointr_rn_demo/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  50. package/example/pointr_rn_demo/ios/pointr_rn_demo/Images.xcassets/Contents.json +6 -0
  51. package/example/pointr_rn_demo/ios/pointr_rn_demo/Info.plist +63 -0
  52. package/example/pointr_rn_demo/ios/pointr_rn_demo/LaunchScreen.storyboard +47 -0
  53. package/example/pointr_rn_demo/ios/pointr_rn_demo/PrivacyInfo.xcprivacy +37 -0
  54. package/example/pointr_rn_demo/ios/pointr_rn_demo.xcodeproj/project.pbxproj +496 -0
  55. package/example/pointr_rn_demo/ios/pointr_rn_demo.xcodeproj/xcshareddata/xcschemes/pointr_rn_demo.xcscheme +88 -0
  56. package/example/pointr_rn_demo/ios/pointr_rn_demo.xcworkspace/contents.xcworkspacedata +10 -0
  57. package/example/pointr_rn_demo/jest.config.js +3 -0
  58. package/example/pointr_rn_demo/metro.config.js +22 -0
  59. package/example/pointr_rn_demo/package-lock.json +11747 -0
  60. package/example/pointr_rn_demo/package.json +46 -0
  61. package/example/pointr_rn_demo/prepare-demo-distribution.sh +103 -0
  62. package/example/pointr_rn_demo/tsconfig.json +5 -0
  63. package/ios/PTRMapWidgetContainerView.swift +59 -7
  64. package/ios/PTRMapWidgetManager-Bridging.m +65 -1
  65. package/ios/PTRMapWidgetManager.swift +185 -144
  66. package/ios/PTRNativeLibrary-Bridging.m +4 -0
  67. package/ios/PTRNativeLibrary.swift +244 -18
  68. package/package.json +16 -2
  69. package/prepare-distribution.sh +84 -0
  70. package/react-native-pointr.podspec +1 -1
  71. package/src/PTRCommand.ts +34 -1
  72. package/src/PTRMapWidgetUtils.ts +105 -5
  73. package/src/PTRPoiManager.ts +20 -0
  74. package/src/index.tsx +40 -1
  75. package/src/types/PTRGeometry.ts +70 -0
  76. package/src/types/PTRPoi.ts +49 -0
  77. package/src/types/PTRPosition.ts +22 -0
  78. package/src/types/PTRWayfindingEvent.ts +18 -0
@@ -0,0 +1,126 @@
1
+ package com.pointr
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.ReadableMap
5
+ import com.pointrlabs.core.geojson.PTRFeature
6
+ import com.pointrlabs.core.geometry.GeoMultiPoint
7
+ import com.pointrlabs.core.geometry.GeoMultiPolygon
8
+ import com.pointrlabs.core.geometry.GeoPoint
9
+ import com.pointrlabs.core.geometry.GeoPolygon
10
+ import com.pointrlabs.core.geometry.Geometry
11
+ import com.pointrlabs.core.positioning.model.Position
12
+
13
+ val Position.map
14
+ get() = Arguments.createMap().apply {
15
+ putDouble("lat", lat)
16
+ putDouble("lon", lon)
17
+ putBoolean("isValid", isValid())
18
+ putString("sid", siteIdentifier)
19
+ putString("bid", buildingIdentifier)
20
+ putInt("lvl", levelIndex)
21
+ }
22
+
23
+ private fun getAttributes(attributes: Map<*, *>): ReadableMap {
24
+ return Arguments.createMap().apply {
25
+ attributes.forEach { (key, value) ->
26
+ when (value) {
27
+ is Long -> putLong(key.toString(), value)
28
+
29
+ is Int -> putInt(key.toString(), value)
30
+
31
+ is Boolean -> putBoolean(key.toString(), value)
32
+
33
+ is String -> putString(key.toString(), value)
34
+
35
+ is Double -> putDouble(key.toString(), value)
36
+
37
+ is List<*> -> {
38
+ putArray(key.toString(), Arguments.createArray().apply {
39
+ value.forEach { v ->
40
+ when (v) {
41
+ is Int -> pushInt(v)
42
+ is Double -> pushDouble(v)
43
+ is Long -> pushLong(v)
44
+ is Boolean -> pushBoolean(v)
45
+ is String -> pushString(v)
46
+ else -> pushNull()
47
+ }
48
+ }
49
+ })
50
+ }
51
+
52
+ is Map<*, *> -> putMap(key.toString(), getAttributes(value))
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ val PTRFeature.map
59
+ get() = Arguments.createMap().apply {
60
+ putString("identifier", identifier)
61
+ putString("externalIdentifier", externalIdentifier)
62
+ putString("typeCode", typeCode)
63
+ putMap("geometry", geometry.map)
64
+ putMap("attributes", getAttributes(attributes))
65
+ putString("name", name)
66
+ putMap("position", position.map)
67
+ }
68
+
69
+ val GeoPoint.map
70
+ get() = Arguments.createMap().apply {
71
+ putString("type", type.name)
72
+ putDouble("lat", lat)
73
+ putDouble("lon", lon)
74
+ }
75
+
76
+ val GeoPolygon.map
77
+ get() = Arguments.createMap().apply {
78
+ putString("type", type.name)
79
+ putArray("outer", Arguments.createArray().apply {
80
+ outer.forEach { point ->
81
+ pushMap(point.map)
82
+ }
83
+ })
84
+ if (inners.isNotEmpty()) {
85
+ putArray("inners", Arguments.createArray().apply {
86
+ inners.forEach { inner ->
87
+ Arguments.createArray().apply {
88
+ inner.forEach { point ->
89
+ pushMap(point.map)
90
+ }
91
+ }
92
+ }
93
+ })
94
+ }
95
+ }
96
+
97
+ val GeoMultiPoint.map
98
+ get() = Arguments.createMap().apply {
99
+ putString("type", type.name)
100
+ putArray("points", Arguments.createArray().apply {
101
+ points.forEach { point ->
102
+ pushMap(point.map)
103
+ }
104
+ })
105
+ }
106
+
107
+ val GeoMultiPolygon.map
108
+ get() = Arguments.createMap().apply {
109
+ putString("type", type.name)
110
+ putArray("polygons", Arguments.createArray().apply {
111
+ polygons.forEach { polygon ->
112
+ pushMap(polygon.map)
113
+ }
114
+ })
115
+ }
116
+
117
+ val Geometry.map
118
+ get() = when (this) {
119
+ is GeoPoint -> this.map
120
+ is GeoPolygon -> this.map
121
+ is GeoMultiPoint -> this.map
122
+ is GeoMultiPolygon -> this.map
123
+ else -> Arguments.createMap().apply {
124
+ putString("type", type.name)
125
+ }
126
+ }
@@ -2,7 +2,7 @@ package com.pointr
2
2
 
3
3
  import androidx.annotation.StringDef
4
4
 
5
- @StringDef(value = [PTRMapWidgetCommandType.SITE, PTRMapWidgetCommandType.BUILDING, PTRMapWidgetCommandType.LEVEL, PTRMapWidgetCommandType.POI, PTRMapWidgetCommandType.PATH, PTRMapWidgetCommandType.STATIC_PATH])
5
+ @StringDef(value = [PTRMapWidgetCommandType.SITE, PTRMapWidgetCommandType.BUILDING, PTRMapWidgetCommandType.LEVEL, PTRMapWidgetCommandType.POI, PTRMapWidgetCommandType.PATH, PTRMapWidgetCommandType.STATIC_PATH, PTRMapWidgetCommandType.STATIC_WAYFINDING, PTRMapWidgetCommandType.START_AND_FOCUS])
6
6
  annotation class PTRMapWidgetCommandType {
7
7
  companion object {
8
8
  const val SITE = "site"
@@ -11,8 +11,10 @@ annotation class PTRMapWidgetCommandType {
11
11
  const val POI = "poi"
12
12
  const val PATH = "path"
13
13
  const val STATIC_PATH = "staticPath"
14
+ const val STATIC_WAYFINDING = "staticWayfinding"
14
15
  const val MARK_MY_CAR_LEVEL = "markMyCarForLevel"
15
16
  const val MARK_MY_CAR_SITE = "markMyCarForSite"
16
17
  const val SHOW_MY_CAR_SITE = "showMyCarForSite"
18
+ const val START_AND_FOCUS = "startAndFocus"
17
19
  }
18
20
  }
@@ -17,6 +17,7 @@ import com.pointrlabs.core.management.DataManager
17
17
  import com.pointrlabs.core.management.Pointr
18
18
  import com.pointrlabs.core.management.interfaces.PointrListener
19
19
  import com.pointrlabs.core.management.models.ErrorMessage
20
+ import com.pointrlabs.core.management.models.PTRParams
20
21
  import com.pointrlabs.core.management.models.Site
21
22
  import com.pointrlabs.core.management.models.deeplink.PTRMapWidgetAction
22
23
  import com.pointrlabs.core.management.models.deeplink.PTRMapWidgetBuildingLocation
@@ -26,15 +27,20 @@ import com.pointrlabs.core.management.models.deeplink.PTRMapWidgetMarkMyCarActio
26
27
  import com.pointrlabs.core.management.models.deeplink.PTRMapWidgetPoiLocation
27
28
  import com.pointrlabs.core.management.models.deeplink.PTRMapWidgetShowMyCarAction
28
29
  import com.pointrlabs.core.management.models.deeplink.PTRMapWidgetSiteLocation
30
+ import com.pointrlabs.core.management.models.deeplink.PTRMapWidgetStaticWayfindingAction
29
31
  import com.pointrlabs.core.management.models.deeplink.PTRMapWidgetWayfindingAction
30
32
  import com.pointrlabs.core.nativecore.wrappers.Plog
33
+ import com.pointrlabs.core.poi.models.Poi
31
34
  import com.pointrlabs.core.site.SiteManager
32
35
  import com.pointrlabs.core.util.models.error.PTRError
33
36
  import com.pointrlabs.core.wayfinding.WayfindingManager
37
+ import com.pointrlabs.core.wayfinding.session.RouteSession
38
+ import com.pointrlabs.core.wayfinding.session.RouteSessionState
34
39
  import com.pointrlabs.ui.map.models.PTRMapSymbolLayer
35
40
  import com.pointrlabs.ui.map.models.events_listeners.MapEventsListener
36
41
  import com.pointrlabs.ui.map.models.events_listeners.MarkMyCarDetailsEvent
37
42
  import com.pointrlabs.ui.map.models.events_listeners.MarkMyCarDetailsEventsListener
43
+ import com.pointrlabs.ui.map.models.events_listeners.WayfindingEventsListener
38
44
  import com.pointrlabs.ui.map.views.PTRMapFragment
39
45
  import com.pointrlabs.ui.map.views.PTRMapWidgetFragment
40
46
  import com.pointrlabs.ui.map.views.wayfinding.MarkMyCarBottomSheet
@@ -43,24 +49,28 @@ import java.util.concurrent.Semaphore
43
49
 
44
50
  @SuppressLint("LogNotTimber")
45
51
  class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
46
- ViewGroupManager<FrameLayout>(), MapEventsListener, MarkMyCarDetailsEventsListener {
52
+ ViewGroupManager<FrameLayout>(), MapEventsListener, MarkMyCarDetailsEventsListener, WayfindingEventsListener {
47
53
 
48
54
  override fun getName() = REACT_CLASS
49
55
 
50
56
  private lateinit var frameLayout: FrameLayout
51
57
 
58
+ private var ptrMapWidgetFragment: PTRMapWidgetFragment? = null
59
+
52
60
  private fun getMapWidgetFragment(action: PTRMapWidgetAction): PTRMapWidgetFragment {
53
- Log.i("PTRMapWidgetManager", "Creating map widget fragment with action: $action")
61
+ Log.i(name, "Creating map widget fragment with action: $action")
54
62
  waitForPointrToRun()
55
- val ptrMapWidgetFragment = PTRMapWidgetFragment.newInstance(
63
+ ptrMapWidgetFragment?.removeListener(this)
64
+ ptrMapWidgetFragment = PTRMapWidgetFragment.newInstance(
56
65
  (reactContext.currentActivity as FragmentActivity).supportFragmentManager,
57
66
  frameLayout.id,
58
67
  PointrModule.mapWidgetConfiguration,
59
68
  action
60
69
  )
61
70
  Choreographer.getInstance().postFrameCallback(frameCallback)
62
- ptrMapWidgetFragment.addListener(this)
63
- return ptrMapWidgetFragment
71
+ Log.v(name, "Adding itself as listener to map widget")
72
+ ptrMapWidgetFragment?.addListener(this)
73
+ return ptrMapWidgetFragment!!
64
74
  }
65
75
 
66
76
  /**
@@ -144,7 +154,7 @@ class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
144
154
  )
145
155
  return@onComplete
146
156
  }
147
- Plog.i("Focus action completed, showing static path")
157
+ Log.i(name, "Focus action completed, showing static path")
148
158
 
149
159
  showStaticPath(
150
160
  ptrMapWidgetFragment,
@@ -156,6 +166,15 @@ class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
156
166
  return
157
167
  }
158
168
 
169
+ PTRMapWidgetCommandType.STATIC_WAYFINDING -> {
170
+ val siteId = args.getString(0).orEmpty()
171
+ val sourcePoiId = args.getString(1).orEmpty()
172
+ val destinationPoiId = args.getString(2).orEmpty()
173
+ val sourceLocation = PTRMapWidgetPoiLocation(siteId, sourcePoiId, isExternalIdentifier = true)
174
+ val destinationLocation = PTRMapWidgetPoiLocation(siteId, destinationPoiId, isExternalIdentifier = true)
175
+ PTRMapWidgetStaticWayfindingAction(sourceLocation, destinationLocation)
176
+ }
177
+
159
178
  PTRMapWidgetCommandType.MARK_MY_CAR_SITE -> {
160
179
  val siteId = args.getString(0).orEmpty()
161
180
  val location = PTRMapWidgetSiteLocation(siteId, isExternalIdentifier = true)
@@ -179,6 +198,55 @@ class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
179
198
  PTRMapWidgetShowMyCarAction(location, shouldShowPopup = args.getBoolean(1))
180
199
  }
181
200
 
201
+ PTRMapWidgetCommandType.START_AND_FOCUS -> {
202
+ // First 4 parameters are initialization parameters
203
+ val clientId = args.getString(0).orEmpty()
204
+ val licenceKey = args.getString(1).orEmpty()
205
+ val baseUrl = args.getString(2).orEmpty()
206
+ val logLevel = args.getInt(3)
207
+
208
+ val ptrParams = PTRParams(clientId, licenceKey, baseUrl)
209
+ ptrParams.logLevel = try {
210
+ Plog.LogLevel.entries[logLevel]
211
+ } catch (_: IllegalArgumentException) {
212
+ Plog.LogLevel.ERROR
213
+ }
214
+ PointrModule.mapWidgetConfiguration.sdkParams = ptrParams
215
+
216
+ // Next parameter is focus type (site, building, level, poi)
217
+ val focusType = args.getString(4).orEmpty()
218
+
219
+ // Create focus action based on type
220
+ val location = when (focusType) {
221
+ PTRMapWidgetCommandType.SITE -> {
222
+ val siteId = args.getString(5).orEmpty()
223
+ PTRMapWidgetSiteLocation(siteId, isExternalIdentifier = true)
224
+ }
225
+ PTRMapWidgetCommandType.BUILDING -> {
226
+ val siteId = args.getString(5).orEmpty()
227
+ val buildingId = args.getString(6).orEmpty()
228
+ PTRMapWidgetBuildingLocation(siteId, buildingId, isExternalIdentifier = true)
229
+ }
230
+ PTRMapWidgetCommandType.LEVEL -> {
231
+ val siteId = args.getString(5).orEmpty()
232
+ val buildingId = args.getString(6).orEmpty()
233
+ val levelIndex = args.getInt(7)
234
+ PTRMapWidgetLevelLocation(siteId, buildingId, levelIndex, isExternalIdentifier = true)
235
+ }
236
+ PTRMapWidgetCommandType.POI -> {
237
+ val siteId = args.getString(5).orEmpty()
238
+ val poiId = args.getString(6).orEmpty()
239
+ PTRMapWidgetPoiLocation(siteId, poiId, isExternalIdentifier = true)
240
+ }
241
+ else -> {
242
+ // Default to site if invalid focus type
243
+ val siteId = args.getString(5).orEmpty()
244
+ PTRMapWidgetSiteLocation(siteId, isExternalIdentifier = true)
245
+ }
246
+ }
247
+ PTRMapWidgetFocusAction(location)
248
+ }
249
+
182
250
  else -> return
183
251
  }
184
252
  action.onComplete = { error ->
@@ -237,6 +305,13 @@ class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
237
305
  event.putString("error", args[3] as String)
238
306
  }
239
307
 
308
+ PTRMapWidgetCommandType.STATIC_WAYFINDING -> {
309
+ event.putString("siteExternalIdentifier", args[0] as String)
310
+ event.putString("sourcePoiExternalIdentifier", args[1] as String)
311
+ event.putString("destinationPoiExternalIdentifier", args[2] as String)
312
+ event.putString("error", args[3] as String)
313
+ }
314
+
240
315
  PTRMapWidgetCommandType.MARK_MY_CAR_SITE -> {
241
316
  event.putString("siteExternalIdentifier", args[0] as String)
242
317
  event.putBoolean("shouldShowPopup", args[1] as Boolean)
@@ -260,10 +335,48 @@ class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
260
335
  event.putString("error", args[3] as String)
261
336
  }
262
337
 
338
+ PTRMapWidgetCommandType.START_AND_FOCUS -> {
339
+ event.putString("clientId", args[0] as String)
340
+ event.putString("licenceKey", args[1] as String)
341
+ event.putString("baseUrl", args[2] as String)
342
+ event.putInt("logLevel", (args[3] as Number).toInt())
343
+ event.putString("focusType", args[4] as String)
344
+
345
+ // Add focus-specific parameters based on focus type
346
+ val focusType = args[4] as String
347
+ when (focusType) {
348
+ PTRMapWidgetCommandType.SITE -> {
349
+ event.putString("siteExternalIdentifier", args[5] as String)
350
+ event.putString("error", args.last().toString())
351
+ }
352
+ PTRMapWidgetCommandType.BUILDING -> {
353
+ event.putString("siteExternalIdentifier", args[5] as String)
354
+ event.putString("buildingExternalIdentifier", args[6] as String)
355
+ event.putString("error", args.last().toString())
356
+ }
357
+ PTRMapWidgetCommandType.LEVEL -> {
358
+ event.putString("siteExternalIdentifier", args[5] as String)
359
+ event.putString("buildingExternalIdentifier", args[6] as String)
360
+ event.putInt("levelIndex", (args[7] as Number).toInt())
361
+ event.putString("error", args.last().toString())
362
+ }
363
+ PTRMapWidgetCommandType.POI -> {
364
+ event.putString("siteExternalIdentifier", args[5] as String)
365
+ event.putString("poiExternalIdentifier", args[6] as String)
366
+ event.putString("error", args.last().toString())
367
+ }
368
+ else -> {
369
+ event.putString("siteExternalIdentifier", args[5] as String)
370
+ event.putString("error", args.last().toString())
371
+ }
372
+ }
373
+ }
374
+
263
375
  else -> {
264
376
  return
265
377
  }
266
378
  }
379
+ Log.v(name, "sending onMapWidgetDidEndLoading with event: $event")
267
380
  reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(
268
381
  frameLayout.id,
269
382
  "onMapWidgetDidEndLoading",
@@ -271,12 +384,29 @@ class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
271
384
  )
272
385
  }
273
386
 
387
+ private fun onWayfindingEvent(type: Int, poi: Poi?) {
388
+ val event: WritableMap = WritableNativeMap()
389
+ event.putInt("type" , type)
390
+ event.putMap("poi", poi?.map)
391
+ Log.v(name, "Sending event for wayfinding: $event")
392
+ reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(
393
+ frameLayout.id,
394
+ "onWayfindingEvent",
395
+ event
396
+ )
397
+ }
398
+
274
399
  override fun getExportedCustomBubblingEventTypeConstants(): Map<String, Any> {
275
400
  return mapOf(
276
401
  "onMapWidgetDidEndLoading" to mapOf(
277
402
  "phasedRegistrationNames" to mapOf(
278
403
  "bubbled" to "onMapWidgetDidEndLoading"
279
404
  )
405
+ ),
406
+ "onWayfindingEvent" to mapOf(
407
+ "phasedRegistrationNames" to mapOf(
408
+ "bubbled" to "onWayfindingEvent"
409
+ )
280
410
  )
281
411
  )
282
412
  }
@@ -374,7 +504,7 @@ class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
374
504
  )
375
505
  return@addLayer
376
506
  }
377
- Log.i("PTRMapWidgetManager", "Static path layer added successfully")
507
+ Log.i(name, "Static path layer added successfully")
378
508
 
379
509
  ptrMapWidgetFragment.mapFragment?.addFeatures(
380
510
  listOf(source, target),
@@ -390,7 +520,7 @@ class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
390
520
  )
391
521
  return@addFeatures
392
522
  }
393
- Log.i("PTRMapWidgetManager", "POI features added successfully")
523
+ Log.i(name, "POI features added successfully")
394
524
  ptrMapWidgetFragment.mapFragment?.currentRoute = route
395
525
  mapWidgetDidEndLoading(
396
526
  PTRMapWidgetCommandType.STATIC_PATH,
@@ -520,12 +650,12 @@ class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
520
650
 
521
651
  override fun mapDidEndLoading(mapFragment: PTRMapFragment) {
522
652
  super.mapDidEndLoading(mapFragment)
523
- Log.i("PTRMapWidgetManager", "Map loaded")
653
+ Log.i(name, "Map loaded")
524
654
  }
525
655
 
526
656
  override fun mapDidFailToLoad(mapFragment: PTRMapFragment, ptrError: PTRError) {
527
657
  super.mapDidFailToLoad(mapFragment, ptrError)
528
- Log.e("PTRMapWidgetManager", "Map failed to load: $ptrError")
658
+ Log.e(name, "Map failed to load: $ptrError")
529
659
  }
530
660
 
531
661
  override fun onMarkMyCarDetailsEvent(
@@ -533,7 +663,7 @@ class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
533
663
  markMyCarDetailsEvent: MarkMyCarDetailsEvent
534
664
  ) {
535
665
  super.onMarkMyCarDetailsEvent(markMyCarSheet, markMyCarDetailsEvent)
536
- Plog.i("Mark my car details event: $markMyCarDetailsEvent")
666
+ Log.i(name, "Mark my car details event: $markMyCarDetailsEvent")
537
667
  }
538
668
 
539
669
  private val frameCallback = object : Choreographer.FrameCallback {
@@ -553,6 +683,25 @@ class PTRMapWidgetManager(private val reactContext: ReactApplicationContext) :
553
683
  }
554
684
  }
555
685
 
686
+ override fun wayfindingDidShown() {
687
+ Log.v(name, "Wayfinding did shown")
688
+ val destination = (ptrMapWidgetFragment?.mapFragment?.currentRouteSession?.destination as? Poi)
689
+ onWayfindingEvent(0, destination)
690
+
691
+ }
692
+
693
+ override fun wayfindingDidTapClose() {
694
+ Log.v(name, "Wayfinding cancelled")
695
+ val destination = (ptrMapWidgetFragment?.mapFragment?.currentRouteSession?.destination as? Poi)
696
+ onWayfindingEvent(-1, destination)
697
+ }
698
+
699
+ override fun wayfindingDone() {
700
+ Log.v(name, "Wayfinding done")
701
+ val destination = (ptrMapWidgetFragment?.mapFragment?.currentRouteSession?.destination as? Poi)
702
+ onWayfindingEvent(1, destination)
703
+ }
704
+
556
705
  companion object {
557
706
  const val REACT_CLASS = "PTRMapWidget"
558
707
  const val LAYER_STATIC_PATH = "sym-static-path"
@@ -8,11 +8,16 @@ import android.os.Parcelable
8
8
  import android.util.Log
9
9
  import com.facebook.react.bridge.Arguments
10
10
  import com.facebook.react.bridge.Callback
11
+ import com.facebook.react.bridge.Promise
11
12
  import com.facebook.react.bridge.ReactApplicationContext
12
13
  import com.facebook.react.bridge.ReactContextBaseJavaModule
13
14
  import com.facebook.react.bridge.ReactMethod
14
15
  import com.facebook.react.bridge.WritableMap
15
16
  import com.facebook.react.modules.core.DeviceEventManagerModule
17
+ import com.pointrlabs.core.geofence.GeofenceEvent
18
+ import com.pointrlabs.core.geofence.GeofenceEventType
19
+ import com.pointrlabs.core.geofence.GeofenceType
20
+ import com.pointrlabs.core.management.GeofenceManager
16
21
  import com.pointrlabs.core.management.Pointr
17
22
  import com.pointrlabs.core.management.PositioningManager
18
23
  import com.pointrlabs.core.management.interfaces.PointrListener
@@ -20,6 +25,7 @@ import com.pointrlabs.core.management.models.Building
20
25
  import com.pointrlabs.core.management.models.PTRParams
21
26
  import com.pointrlabs.core.management.models.Site
22
27
  import com.pointrlabs.core.nativecore.wrappers.Plog
28
+ import com.pointrlabs.core.poi.models.Poi
23
29
  import com.pointrlabs.core.positioning.model.CalculatedPosition
24
30
  import com.pointrlabs.core.positioning.model.PositioningTypes
25
31
  import com.pointrlabs.core.util.models.error.PTRError
@@ -36,6 +42,7 @@ class PointrModule(reactContext: ReactApplicationContext) :
36
42
  ReactContextBaseJavaModule(reactContext) {
37
43
 
38
44
  private val positionManagerListener: PositioningManager.Listener
45
+ private val geofenceListener : GeofenceManager.Listener
39
46
  private var listenerCount = 0
40
47
 
41
48
  init {
@@ -45,6 +52,12 @@ class PointrModule(reactContext: ReactApplicationContext) :
45
52
  sendEventToJs(reactContext, OnPositionManagerCalculatedLocation, params)
46
53
  }
47
54
  }
55
+ geofenceListener = object : GeofenceManager.Listener {
56
+ override fun onGeofenceManagerGeofenceEvent(geofenceEvent: GeofenceEvent) {
57
+ val params = buildParamsForGeofenceEvent(geofenceEvent)
58
+ sendEventToJs(reactContext, OnGeofenceEvent, params)
59
+ }
60
+ }
48
61
  setPointrListeners()
49
62
  }
50
63
 
@@ -70,7 +83,7 @@ class PointrModule(reactContext: ReactApplicationContext) :
70
83
  Log.e("Pointr", "Permission manager is not ready")
71
84
  return
72
85
  }
73
- val activity = currentActivity ?: run {
86
+ val activity = reactApplicationContext.currentActivity ?: run {
74
87
  Log.e("Pointr", "Could not get current activity")
75
88
  return
76
89
  }
@@ -111,7 +124,7 @@ class PointrModule(reactContext: ReactApplicationContext) :
111
124
  clientId: String,
112
125
  licenceKey: String,
113
126
  baseUrl: String,
114
- logLevel: Int
127
+ logLevel: Int = 0
115
128
  ) {
116
129
  initialize(
117
130
  reactApplicationContext,
@@ -171,6 +184,40 @@ class PointrModule(reactContext: ReactApplicationContext) :
171
184
  }
172
185
  }
173
186
 
187
+ @ReactMethod
188
+ fun getPois(siteId: String, promise: Promise) {
189
+ try {
190
+ Log.v(name, "get pois called $siteId")
191
+ // Ensure Pointr SDK is initialized
192
+ val site = Pointr.getPointr()?.siteManager?.getSiteByExternalIdentifier(siteId)
193
+
194
+ if (site == null) {
195
+ Log.e(name, "Site is null")
196
+ promise.reject("ERROR", "Site not found: $siteId")
197
+ return
198
+ }
199
+
200
+ Log.v(name, "getting pois")
201
+
202
+ // Get all POIs for the site
203
+ val pois = Pointr.getPointr()?.poiManager?.getPois(site)?.poiList ?: emptyList()
204
+
205
+ Log.v(name, "found ${pois.size} pois")
206
+
207
+ // Convert POIs to WritableArray
208
+ val poisArray = Arguments.createArray()
209
+
210
+ pois.forEach { poi ->
211
+ poisArray.pushMap(poi.map)
212
+ }
213
+
214
+ promise.resolve(poisArray)
215
+
216
+ } catch (e: Exception) {
217
+ promise.reject("ERROR", "Failed to get POIs: ${e.message}", e)
218
+ }
219
+ }
220
+
174
221
  companion object {
175
222
  const val NAME = "PTRNativePointrLibrary"
176
223
  val mapWidgetConfiguration = PTRMapWidgetConfiguration.defaultConfiguration()
@@ -189,6 +236,8 @@ class PointrModule(reactContext: ReactApplicationContext) :
189
236
  const val OnBuildingClicked = "OnBuildingClicked"
190
237
  const val OnSiteClicked = "OnSiteClicked"
191
238
 
239
+ const val OnGeofenceEvent = "OnGeofenceEvent"
240
+
192
241
  var shouldRequestPermissionsAtStartup = true
193
242
 
194
243
  fun sendEventToJs(
@@ -305,6 +354,9 @@ class PointrModule(reactContext: ReactApplicationContext) :
305
354
  dialog.setCanceledOnTouchOutside(false)
306
355
  dialog.show()
307
356
  }
357
+
358
+
359
+
308
360
  // endregion [com.pointrlabs.core.map.models.events_listeners.CustomMapEventsListener]
309
361
  }
310
362
 
@@ -343,7 +395,7 @@ class PointrModule(reactContext: ReactApplicationContext) :
343
395
  clientId: String,
344
396
  licenceKey: String,
345
397
  baseUrl: String,
346
- logLevel: Int
398
+ logLevel: Int = 0
347
399
  ) {
348
400
  val ptrParams = PTRParams(clientId, licenceKey, baseUrl)
349
401
  try {
@@ -355,6 +407,55 @@ class PointrModule(reactContext: ReactApplicationContext) :
355
407
  Pointr.with(reactContext, ptrParams)
356
408
  }
357
409
 
410
+ private fun buildParamsForGeofenceEvent(geofenceEvent: GeofenceEvent): WritableMap {
411
+ val params: WritableMap = Arguments.createMap()
412
+
413
+ //TODO: Add PTRGeofenceEvent's timestamp
414
+
415
+ // Event type (enter, exit)
416
+ val eventType = when (geofenceEvent.type) {
417
+ GeofenceEventType.Enter -> "enter"
418
+ else -> "exit"
419
+ }
420
+ params.putString("eventType", eventType)
421
+
422
+ // Geofence information
423
+ val geofence = geofenceEvent.geofence
424
+ val geofenceMap = Arguments.createMap().apply {
425
+ putString("id", geofence.identifier)
426
+ putString("externalId", geofence.externalIdentifier)
427
+ putString("name", geofence.name)
428
+
429
+ val geofenceType = when (geofence.type) {
430
+ GeofenceType.GPS -> "gps"
431
+ else -> "beacon"
432
+ }
433
+ params.putString("geofenceType", geofenceType)
434
+
435
+ // Position information
436
+ val position = geofence.position
437
+ val positionMap = Arguments.createMap().apply {
438
+ putDouble("latitude", position.lat)
439
+ putDouble("longitude", position.lon)
440
+ }
441
+ putMap("position", positionMap)
442
+ }
443
+
444
+ params.putMap("geofence", geofenceMap)
445
+
446
+ // Geofence notification information if available
447
+ geofenceEvent.geofenceNotification?.let { notification ->
448
+ val notificationMap = Arguments.createMap().apply {
449
+ putString("id", notification.id)
450
+ putString("message", notification.message)
451
+ putLong("timestamp", notification.timeStamp)
452
+ }
453
+ params.putMap("geofenceNotification", notificationMap)
454
+ }
455
+
456
+ return params
457
+ }
458
+
358
459
  private fun onPointrStartEnded(action: (String) -> Unit) {
359
460
  val pointr = Pointr.getPointr() ?: return
360
461
  pointr.addListener(object : PointrListener {
@@ -373,12 +474,14 @@ class PointrModule(reactContext: ReactApplicationContext) :
373
474
  val pointr = Pointr.getPointr() ?: return
374
475
  if (pointr.state != Pointr.State.RUNNING) return
375
476
  pointr.positioningManager?.removeListener(positionManagerListener)
477
+ pointr.geofenceManager?.removeListener(geofenceListener)
376
478
  }
377
479
 
378
480
  private fun setPointrListeners() {
379
481
  val pointr = Pointr.getPointr() ?: return
380
482
  if (pointr.state != Pointr.State.RUNNING) return
381
483
  pointr.positioningManager?.addListener(positionManagerListener)
484
+ pointr.geofenceManager?.addListener(geofenceListener)
382
485
  if (shouldRequestPermissionsAtStartup) {
383
486
  requestPermissions()
384
487
  } else {
@@ -0,0 +1,2 @@
1
+ BUNDLE_PATH: "vendor/bundle"
2
+ BUNDLE_FORCE_RUBY_PLATFORM: 1
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: '@react-native',
4
+ };
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ arrowParens: 'avoid',
3
+ singleQuote: true,
4
+ trailingComma: 'all',
5
+ };
@@ -0,0 +1 @@
1
+ {}