react-native-pointr 9.9.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.
- package/API_REFERENCE.md +284 -315
- package/CHANGELOG.md +36 -0
- package/EXTENDING.md +11 -16
- package/README.md +14 -14
- package/WAYFINDING_EVENTS.md +5 -3
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/pointr/PTRCoreExtensions.kt +33 -2
- package/android/src/main/java/com/pointr/PTRMapWidgetActionType.kt +17 -0
- package/android/src/main/java/com/pointr/PTRMapWidgetManager.kt +162 -406
- package/android/src/main/java/com/pointr/{PointrModule.kt → PTRNativeLibrary.kt} +150 -32
- package/android/src/main/java/com/pointr/{PointrPackage.kt → PTRPackage.kt} +2 -2
- package/ios/PTRMapWidgetContainerView.swift +174 -187
- package/ios/PTRMapWidgetManager-Bridging.m +12 -64
- package/ios/PTRMapWidgetManager.swift +164 -136
- package/ios/PTRNativeLibrary-Bridging.m +38 -2
- package/ios/PTRNativeLibrary.swift +206 -26
- package/package.json +5 -3
- package/react-native-pointr.podspec +1 -1
- package/src/NativePointrModule.ts +70 -0
- package/src/PTRMapWidgetUtils.ts +67 -144
- package/src/actions/index.ts +171 -0
- package/src/api/MapWidgetApi.ts +8 -8
- package/src/api/PointrSdk.ts +50 -91
- package/src/components/index.tsx +27 -26
- package/src/constants/index.ts +32 -13
- package/src/hooks/index.ts +1 -0
- package/src/hooks/usePointrGeofences.ts +37 -0
- package/src/hooks/usePointrSdk.ts +12 -5
- package/src/index.tsx +37 -70
- package/src/managers/PTRPoiManager.ts +2 -2
- package/src/types/PTRPoi.ts +5 -2
- package/src/types/PTRPosition.ts +15 -5
- package/src/types/PTRSite.ts +46 -0
- package/src/types/PTRWayfindingEvent.ts +11 -7
- package/src/types/config.ts +1 -0
- package/src/types/events.ts +1 -0
- package/src/types/index.ts +4 -0
- package/android/src/main/java/com/pointr/PTRMapWidgetCommandType.kt +0 -20
- package/src/PTRCommand.ts +0 -153
- package/src/api/index.ts +0 -9
- 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
|
|
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(
|
|
140
|
-
Pointr.getPointr()?.let {
|
|
141
|
-
if (
|
|
132
|
+
fun start(promise: Promise) {
|
|
133
|
+
Pointr.getPointr()?.let { pointr ->
|
|
134
|
+
if (pointr.state == Pointr.State.RUNNING) {
|
|
142
135
|
setPointrListeners()
|
|
143
|
-
|
|
136
|
+
promise.resolve(null)
|
|
144
137
|
} else {
|
|
145
138
|
onPointrStartEnded { endState ->
|
|
146
|
-
|
|
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
|
-
|
|
199
|
+
// ─── Sites & Buildings ───────────────────────────────────────────────────
|
|
201
200
|
|
|
202
|
-
|
|
203
|
-
|
|
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
|
-
|
|
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
|
-
|
|
208
|
-
|
|
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
|
-
|
|
211
|
-
|
|
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
|
-
|
|
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
|
|
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 = "
|
|
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
|
|
9
|
+
class PTRPackage : ReactPackage {
|
|
10
10
|
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
11
|
-
return listOf(
|
|
11
|
+
return listOf(PTRNativeLibrary(reactContext))
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|