react-native-pointr 9.8.0 → 10.0.0

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 (41) hide show
  1. package/API_REFERENCE.md +284 -315
  2. package/CHANGELOG.md +42 -0
  3. package/EXTENDING.md +11 -16
  4. package/README.md +14 -14
  5. package/WAYFINDING_EVENTS.md +5 -3
  6. package/android/build.gradle +1 -1
  7. package/android/src/main/java/com/pointr/PTRCoreExtensions.kt +33 -2
  8. package/android/src/main/java/com/pointr/PTRMapWidgetActionType.kt +17 -0
  9. package/android/src/main/java/com/pointr/PTRMapWidgetManager.kt +162 -406
  10. package/android/src/main/java/com/pointr/{PointrModule.kt → PTRNativeLibrary.kt} +150 -32
  11. package/android/src/main/java/com/pointr/{PointrPackage.kt → PTRPackage.kt} +2 -2
  12. package/ios/PTRMapWidgetContainerView.swift +174 -187
  13. package/ios/PTRMapWidgetManager-Bridging.m +12 -64
  14. package/ios/PTRMapWidgetManager.swift +164 -136
  15. package/ios/PTRNativeLibrary-Bridging.m +38 -2
  16. package/ios/PTRNativeLibrary.swift +206 -26
  17. package/package.json +5 -3
  18. package/react-native-pointr.podspec +1 -1
  19. package/src/NativePointrModule.ts +70 -0
  20. package/src/PTRMapWidgetUtils.ts +67 -144
  21. package/src/actions/index.ts +171 -0
  22. package/src/api/MapWidgetApi.ts +8 -8
  23. package/src/api/PointrSdk.ts +50 -91
  24. package/src/components/index.tsx +27 -26
  25. package/src/constants/index.ts +32 -13
  26. package/src/hooks/index.ts +1 -0
  27. package/src/hooks/usePointrGeofences.ts +37 -0
  28. package/src/hooks/usePointrSdk.ts +12 -5
  29. package/src/index.tsx +37 -70
  30. package/src/managers/PTRPoiManager.ts +2 -2
  31. package/src/types/PTRPoi.ts +5 -2
  32. package/src/types/PTRPosition.ts +15 -5
  33. package/src/types/PTRSite.ts +46 -0
  34. package/src/types/PTRWayfindingEvent.ts +11 -7
  35. package/src/types/config.ts +1 -0
  36. package/src/types/events.ts +1 -0
  37. package/src/types/index.ts +4 -0
  38. package/android/src/main/java/com/pointr/PTRMapWidgetCommandType.kt +0 -20
  39. package/src/PTRCommand.ts +0 -153
  40. package/src/api/index.ts +0 -9
  41. package/src/commands/index.ts +0 -275
@@ -38,7 +38,7 @@ import kotlin.random.Random
38
38
  import kotlin.reflect.KMutableProperty1
39
39
 
40
40
  @SuppressLint("LogNotTimber")
41
- class PointrModule(reactContext: ReactApplicationContext) :
41
+ class PTRNativeLibrary(reactContext: ReactApplicationContext) :
42
42
  ReactContextBaseJavaModule(reactContext) {
43
43
 
44
44
  private val positionManagerListener: PositioningManager.Listener
@@ -101,12 +101,6 @@ class PointrModule(reactContext: ReactApplicationContext) :
101
101
 
102
102
  @ReactMethod
103
103
  fun addListener(eventName: String) {
104
- // TODO as per documentation, this should get invoked when addListener is called
105
- // on the JS side, but it does not get invoked
106
- if (listenerCount == 0) {
107
- // Set up any upstream listeners or background tasks as necessary
108
- start { args -> Plog.v("Pointr started and listeners added") }
109
- }
110
104
  listenerCount += 1
111
105
  }
112
106
 
@@ -114,7 +108,6 @@ class PointrModule(reactContext: ReactApplicationContext) :
114
108
  fun removeListeners(count: Int) {
115
109
  listenerCount -= count
116
110
  if (listenerCount == 0) {
117
- // Remove upstream listeners, stop unnecessary background tasks
118
111
  removePointrListeners()
119
112
  }
120
113
  }
@@ -136,20 +129,22 @@ class PointrModule(reactContext: ReactApplicationContext) :
136
129
  }
137
130
 
138
131
  @ReactMethod
139
- fun start(callback: Callback?) {
140
- Pointr.getPointr()?.let {
141
- if (it.state == Pointr.State.RUNNING) {
132
+ fun start(promise: Promise) {
133
+ Pointr.getPointr()?.let { pointr ->
134
+ if (pointr.state == Pointr.State.RUNNING) {
142
135
  setPointrListeners()
143
- callback?.invoke(it.state.name)
136
+ promise.resolve(null)
144
137
  } else {
145
138
  onPointrStartEnded { endState ->
146
- callback?.invoke(endState)
139
+ if (endState == Pointr.State.RUNNING.name) {
140
+ promise.resolve(null)
141
+ } else {
142
+ promise.reject("START_FAILED", "Pointr failed to start: $endState")
143
+ }
147
144
  }
148
- Thread {
149
- it.start()
150
- }.start()
145
+ Thread { pointr.start() }.start()
151
146
  }
152
- }
147
+ } ?: promise.reject("NOT_INITIALIZED", "Pointr is not initialized")
153
148
  }
154
149
 
155
150
  @ReactMethod
@@ -187,39 +182,162 @@ class PointrModule(reactContext: ReactApplicationContext) :
187
182
  @ReactMethod
188
183
  fun getPois(siteId: String, promise: Promise) {
189
184
  try {
190
- Log.v(name, "get pois called $siteId")
191
- // Ensure Pointr SDK is initialized
192
185
  val site = Pointr.getPointr()?.siteManager?.getSiteByExternalIdentifier(siteId)
193
-
194
186
  if (site == null) {
195
- Log.e(name, "Site is null")
196
187
  promise.reject("ERROR", "Site not found: $siteId")
197
188
  return
198
189
  }
190
+ val pois = Pointr.getPointr()?.poiManager?.getPois(site)?.poiList ?: emptyList()
191
+ val poisArray = Arguments.createArray()
192
+ pois.forEach { poi -> poisArray.pushMap(poi.map) }
193
+ promise.resolve(poisArray)
194
+ } catch (e: Exception) {
195
+ promise.reject("ERROR", "Failed to get POIs: ${e.message}", e)
196
+ }
197
+ }
199
198
 
200
- Log.v(name, "getting pois")
199
+ // ─── Sites & Buildings ───────────────────────────────────────────────────
201
200
 
202
- // Get all POIs for the site
203
- val pois = Pointr.getPointr()?.poiManager?.getPois(site)?.poiList ?: emptyList()
201
+ @ReactMethod
202
+ fun getSites(promise: Promise) {
203
+ try {
204
+ val sites = Pointr.getPointr()?.siteManager?.sites ?: emptyList()
205
+ val arr = Arguments.createArray()
206
+ sites.forEach { site -> arr.pushMap(site.toWritableMap()) }
207
+ promise.resolve(arr)
208
+ } catch (e: Exception) {
209
+ promise.reject("ERROR", "Failed to get sites: ${e.message}", e)
210
+ }
211
+ }
204
212
 
205
- Log.v(name, "found ${pois.size} pois")
213
+ @ReactMethod
214
+ fun getBuildings(siteId: String, promise: Promise) {
215
+ try {
216
+ val site = Pointr.getPointr()?.siteManager?.getSiteByExternalIdentifier(siteId)
217
+ ?: return promise.reject("SITE_NOT_FOUND", "Site not found: $siteId")
218
+ val arr = Arguments.createArray()
219
+ site.buildings.forEach { b -> arr.pushMap(b.toWritableMap()) }
220
+ promise.resolve(arr)
221
+ } catch (e: Exception) {
222
+ promise.reject("ERROR", "Failed to get buildings: ${e.message}", e)
223
+ }
224
+ }
206
225
 
207
- // Convert POIs to WritableArray
208
- val poisArray = Arguments.createArray()
226
+ @ReactMethod
227
+ fun getSiteByExternalId(externalId: String, promise: Promise) {
228
+ try {
229
+ val site = Pointr.getPointr()?.siteManager?.getSiteByExternalIdentifier(externalId)
230
+ promise.resolve(site?.toWritableMap())
231
+ } catch (e: Exception) {
232
+ promise.reject("ERROR", "Failed to get site: ${e.message}", e)
233
+ }
234
+ }
209
235
 
210
- pois.forEach { poi ->
211
- poisArray.pushMap(poi.map)
236
+ @ReactMethod
237
+ fun getClientName(promise: Promise) {
238
+ try {
239
+ val clientId = Pointr.getPointr()?.ptrParams?.clientIdentifier ?: ""
240
+ promise.resolve(clientId)
241
+ } catch (e: Exception) {
242
+ promise.reject("ERROR", "Failed to get client name: ${e.message}", e)
243
+ }
244
+ }
245
+
246
+ // ─── POI Search ──────────────────────────────────────────────────────────
247
+
248
+ @ReactMethod
249
+ fun searchPois(siteId: String, query: String, promise: Promise) {
250
+ try {
251
+ val site = Pointr.getPointr()?.siteManager?.getSiteByExternalIdentifier(siteId)
252
+ ?: return promise.reject("SITE_NOT_FOUND", "Site not found: $siteId")
253
+ val allPois = Pointr.getPointr()?.poiManager?.getPois(site)?.poiList ?: emptyList()
254
+ val q = query.lowercase()
255
+ val filtered = allPois.filter { poi ->
256
+ poi.name?.lowercase()?.contains(q) == true ||
257
+ poi.externalIdentifier?.lowercase()?.contains(q) == true
258
+ }
259
+ val arr = Arguments.createArray()
260
+ filtered.forEach { poi ->
261
+ val m = poi.map
262
+ m.putDouble("score", 1.0)
263
+ m.putString("siteId", siteId)
264
+ arr.pushMap(m)
212
265
  }
266
+ promise.resolve(arr)
267
+ } catch (e: Exception) {
268
+ promise.reject("ERROR", "Failed to search POIs: ${e.message}", e)
269
+ }
270
+ }
213
271
 
214
- promise.resolve(poisArray)
272
+ // ─── Wayfinding ──────────────────────────────────────────────────────────
215
273
 
274
+ @ReactMethod
275
+ fun isWayfindingReady(siteId: String, promise: Promise) {
276
+ try {
277
+ val site = Pointr.getPointr()?.siteManager?.getSiteByExternalIdentifier(siteId)
278
+ ?: return promise.reject("SITE_NOT_FOUND", "Site not found: $siteId")
279
+ val ready = Pointr.getPointr()?.wayfindingManager?.isReadyForSite(site) ?: false
280
+ promise.resolve(ready)
216
281
  } catch (e: Exception) {
217
- promise.reject("ERROR", "Failed to get POIs: ${e.message}", e)
282
+ promise.reject("ERROR", "Failed to check wayfinding: ${e.message}", e)
283
+ }
284
+ }
285
+
286
+ @ReactMethod
287
+ fun calculateDistance(fromJson: String, toJson: String, promise: Promise) {
288
+ try {
289
+ val from = JSONObject(fromJson)
290
+ val to = JSONObject(toJson)
291
+ val fromLat = from.optDouble("lat", from.optDouble("latitude", 0.0))
292
+ val fromLon = from.optDouble("lon", from.optDouble("longitude", 0.0))
293
+ val toLat = to.optDouble("lat", to.optDouble("latitude", 0.0))
294
+ val toLon = to.optDouble("lon", to.optDouble("longitude", 0.0))
295
+ val results = FloatArray(1)
296
+ android.location.Location.distanceBetween(fromLat, fromLon, toLat, toLon, results)
297
+ promise.resolve(results[0].toDouble())
298
+ } catch (e: Exception) {
299
+ promise.reject("ERROR", "Failed to calculate distance: ${e.message}", e)
300
+ }
301
+ }
302
+
303
+ // ─── Geofences ───────────────────────────────────────────────────────────
304
+
305
+ @ReactMethod
306
+ fun getGeofences(siteId: String, promise: Promise) {
307
+ try {
308
+ val site = Pointr.getPointr()?.siteManager?.getSiteByExternalIdentifier(siteId)
309
+ ?: return promise.reject("SITE_NOT_FOUND", "Site not found: $siteId")
310
+ val geofenceManager = Pointr.getPointr()?.geofenceManager
311
+ val gpsGeofences = geofenceManager?.gpsGeofences
312
+ ?.filterNotNull()
313
+ ?.map { it to "gps" } ?: emptyList()
314
+ val beaconGeofences = geofenceManager?.getBeaconGeofences(site)
315
+ ?.filterNotNull()
316
+ ?.map { it to "beacon" } ?: emptyList()
317
+ val allGeofences = gpsGeofences + beaconGeofences
318
+ val arr = Arguments.createArray()
319
+ allGeofences.forEach { (gf, type) ->
320
+ val m = Arguments.createMap()
321
+ m.putString("id", gf.identifier)
322
+ m.putString("externalId", gf.externalIdentifier)
323
+ m.putString("name", gf.name)
324
+ m.putString("geofenceType", type)
325
+ val center = gf.enclosingCircle.center
326
+ val pos = Arguments.createMap()
327
+ pos.putDouble("lat", center.lat)
328
+ pos.putDouble("lon", center.lon)
329
+ pos.putBoolean("isValid", true)
330
+ m.putMap("position", pos)
331
+ arr.pushMap(m)
332
+ }
333
+ promise.resolve(arr)
334
+ } catch (e: Exception) {
335
+ promise.reject("ERROR", "Failed to get geofences: ${e.message}", e)
218
336
  }
219
337
  }
220
338
 
221
339
  companion object {
222
- const val NAME = "PTRNativePointrLibrary"
340
+ const val NAME = "PTRNativeLibrary"
223
341
  val mapWidgetConfiguration = PTRMapWidgetConfiguration.defaultConfiguration()
224
342
  const val siteInternalIdentifierKey = "siteInternalIdentifier"
225
343
  const val siteExternalIdentifierKey = "siteExternalIdentifier"
@@ -6,9 +6,9 @@ import com.facebook.react.bridge.ReactApplicationContext
6
6
  import com.facebook.react.uimanager.ViewManager
7
7
 
8
8
 
9
- class PointrPackage : ReactPackage {
9
+ class PTRPackage : ReactPackage {
10
10
  override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
11
- return listOf(PointrModule(reactContext))
11
+ return listOf(PTRNativeLibrary(reactContext))
12
12
  }
13
13
 
14
14
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {