react-native-pointr 9.6.0 → 9.8.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 +1035 -557
- package/CHANGELOG.md +12 -0
- package/README.md +75 -216
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/pointr/PTRMapWidgetManager.kt +165 -2
- package/ios/PTRMapWidgetContainerView.swift +185 -2
- package/ios/PTRMapWidgetManager-Bridging.m +6 -0
- package/ios/PTRNativeLibrary.swift +14 -0
- package/package.json +16 -5
- package/react-native-pointr.podspec +1 -1
- package/src/PTRMapWidgetUtils.ts +2 -8
- package/src/api/MapWidgetApi.ts +45 -0
- package/src/api/PointrSdk.ts +241 -0
- package/src/api/index.ts +9 -0
- package/src/commands/index.ts +275 -0
- package/src/components/index.tsx +130 -0
- package/src/constants/index.ts +104 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/usePointrEvents.ts +40 -0
- package/src/hooks/usePointrPois.ts +41 -0
- package/src/hooks/usePointrPosition.ts +31 -0
- package/src/hooks/usePointrSdk.ts +41 -0
- package/src/index.tsx +87 -7
- package/src/{PTRPoiManager.ts → managers/PTRPoiManager.ts} +1 -1
- package/src/types/config.ts +57 -0
- package/src/types/events.ts +106 -0
- package/src/types/index.ts +35 -0
|
@@ -6,7 +6,34 @@ import PointrKit
|
|
|
6
6
|
@objc var onMapWidgetDidEndLoading: RCTBubblingEventBlock?
|
|
7
7
|
|
|
8
8
|
@objc var onWayfindingEvent: RCTBubblingEventBlock?
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
// Declarative command prop — JSON string encoding command type and its parameters.
|
|
11
|
+
// When set alongside an optional sdkConfig prop, the widget auto-starts and focuses
|
|
12
|
+
// without the JS caller needing to imperatively dispatch a command afterwards.
|
|
13
|
+
//
|
|
14
|
+
// Expected shape: { "type": "site"|"building"|"level"|"poi"|"path"|"staticPath"|"staticWayfinding",
|
|
15
|
+
// "site": "...", "building"?: "...", "level"?: 0,
|
|
16
|
+
// "poi"?: "...", "fromPoi"?: "...", "toPoi"?: "...",
|
|
17
|
+
// "sourcePoi"?: "...", "destinationPoi"?: "..." }
|
|
18
|
+
@objc var command: String? {
|
|
19
|
+
didSet { pendingCommandString = command }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Optional SDK config prop — JSON with clientId / licenseKey / baseUrl / logLevel.
|
|
23
|
+
// When provided the widget uses these credentials instead of the globally-configured params.
|
|
24
|
+
@objc var sdkConfig: String? {
|
|
25
|
+
didSet { applySDKConfigIfNeeded() }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Optional map widget UI configuration — JSON encoding PTRMapWidgetConfiguration keys.
|
|
29
|
+
// Applied before the map widget is created so that it takes effect on first render.
|
|
30
|
+
@objc var mapWidgetConfig: String? {
|
|
31
|
+
didSet { applyMapWidgetConfigIfNeeded() }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private var pendingCommandString: String?
|
|
35
|
+
private var commandDidExecute = false
|
|
36
|
+
|
|
10
37
|
private(set) var mapWidget: PTRMapWidgetViewController?
|
|
11
38
|
var semaphore: DispatchSemaphore?
|
|
12
39
|
var site: PTRSite?
|
|
@@ -65,9 +92,13 @@ import PointrKit
|
|
|
65
92
|
print("PTRMapWidget - Pointr is not running")
|
|
66
93
|
}
|
|
67
94
|
}
|
|
95
|
+
if let existingWidget = self.mapWidget {
|
|
96
|
+
print("PTRMapWidget - reusing existing map widget, performing new action")
|
|
97
|
+
existingWidget.performAction(action)
|
|
98
|
+
return existingWidget
|
|
99
|
+
}
|
|
68
100
|
print("PTRMapWidget - initializing map widget")
|
|
69
101
|
let mapWidget = PTRMapWidgetViewController(action: action, configuration: PTRNativeLibrary.mapWidgetConfiguration)
|
|
70
|
-
self.mapWidget?.removeListener(self)
|
|
71
102
|
self.mapWidget = mapWidget
|
|
72
103
|
let adapter = WayfindingEventsAdapter(container: self, mapWidget: mapWidget)
|
|
73
104
|
self.wayfindingEventsAdapter = adapter
|
|
@@ -77,6 +108,7 @@ import PointrKit
|
|
|
77
108
|
}
|
|
78
109
|
|
|
79
110
|
@objc func present(_ mapWidget: PTRMapWidgetViewController) {
|
|
111
|
+
guard mapWidget.view.superview == nil else { return }
|
|
80
112
|
addSubview(mapWidget.view)
|
|
81
113
|
mapWidget.view.translatesAutoresizingMaskIntoConstraints = false
|
|
82
114
|
NSLayoutConstraint.activate([
|
|
@@ -295,5 +327,156 @@ import PointrKit
|
|
|
295
327
|
semaphore.wait()
|
|
296
328
|
return Pointr.shared.state
|
|
297
329
|
}
|
|
330
|
+
|
|
331
|
+
// MARK: - Declarative command prop handling
|
|
332
|
+
|
|
333
|
+
override func didMoveToWindow() {
|
|
334
|
+
super.didMoveToWindow()
|
|
335
|
+
guard window != nil, !commandDidExecute, let jsonString = pendingCommandString else { return }
|
|
336
|
+
commandDidExecute = true
|
|
337
|
+
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
|
|
338
|
+
self?.executeCommandFromJSON(jsonString)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
private func applySDKConfigIfNeeded() {
|
|
343
|
+
guard let jsonString = sdkConfig,
|
|
344
|
+
let data = jsonString.data(using: .utf8),
|
|
345
|
+
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { return }
|
|
346
|
+
if let clientId = json["clientId"] as? String { PTRNativeLibrary.params.clientIdentifier = clientId }
|
|
347
|
+
if let licenseKey = json["licenseKey"] as? String { PTRNativeLibrary.params.licenseKey = licenseKey }
|
|
348
|
+
if let baseUrl = json["baseUrl"] as? String { PTRNativeLibrary.params.baseUrl = baseUrl }
|
|
349
|
+
if let logLevel = json["logLevel"] as? Int32 {
|
|
350
|
+
PTRNativeLibrary.params.loggerLevel = PTRLoggerLevel(rawValue: logLevel) ?? .error
|
|
351
|
+
}
|
|
352
|
+
PTRNativeLibrary.params.mode = PointrDebugMode()
|
|
353
|
+
PTRNativeLibrary.mapWidgetConfiguration.sdkParams = PTRNativeLibrary.params
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
private func applyMapWidgetConfigIfNeeded() {
|
|
357
|
+
guard let jsonString = mapWidgetConfig,
|
|
358
|
+
let data = jsonString.data(using: .utf8),
|
|
359
|
+
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { return }
|
|
360
|
+
let cfg = PTRNativeLibrary.mapWidgetConfiguration
|
|
361
|
+
let mirror = Mirror(reflecting: cfg)
|
|
362
|
+
for child in mirror.children {
|
|
363
|
+
guard let key = child.label, let value = json[key] as? Bool else { continue }
|
|
364
|
+
cfg.setValue(value, forKey: key)
|
|
365
|
+
}
|
|
366
|
+
// The following properties are computed in PTRMapWidgetConfiguration, so Mirror
|
|
367
|
+
// does not include them in children. Assign them directly.
|
|
368
|
+
if let value = json["isQuickAccessEnabled"] as? Bool {
|
|
369
|
+
cfg.isQuickAccessEnabled = value
|
|
370
|
+
}
|
|
371
|
+
if let value = json["isMarkMyCarEnabled"] as? Bool {
|
|
372
|
+
cfg.isMarkMyCarEnabled = value
|
|
373
|
+
}
|
|
374
|
+
if let value = json["isInfoButtonEnabled"] as? Bool {
|
|
375
|
+
cfg.isInfoButtonEnabled = value
|
|
376
|
+
}
|
|
377
|
+
if let value = json["shouldFocusOnFirstUserPosition"] as? Bool {
|
|
378
|
+
cfg.shouldFocusOnFirstUserPosition = value
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
private func executeCommandFromJSON(_ jsonString: String) {
|
|
383
|
+
guard let data = jsonString.data(using: .utf8),
|
|
384
|
+
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
385
|
+
let type = json["type"] as? String else {
|
|
386
|
+
print("PTRMapWidget: invalid command JSON")
|
|
387
|
+
return
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
let siteId = json["site"] as? String ?? ""
|
|
391
|
+
let buildingId = json["building"] as? String ?? ""
|
|
392
|
+
let levelIndex = json["level"] as? Int ?? 0
|
|
393
|
+
let poiId = json["poi"] as? String ?? ""
|
|
394
|
+
let fromPoiId = json["fromPoi"] as? String ?? ""
|
|
395
|
+
let toPoiId = json["toPoi"] as? String ?? ""
|
|
396
|
+
let sourcePoiId = json["sourcePoi"] as? String ?? ""
|
|
397
|
+
let destinationPoiId = json["destinationPoi"] as? String ?? ""
|
|
398
|
+
|
|
399
|
+
let action: PTRMapWidgetAction
|
|
400
|
+
let commandParams: [String: Any]
|
|
401
|
+
|
|
402
|
+
switch type {
|
|
403
|
+
case "site":
|
|
404
|
+
let location = PTRMapWidgetSiteLocation(siteIdentifier: siteId, isExternalIdentifiers: true)
|
|
405
|
+
let focus = PTRMapWidgetMapFocusAction(location: location, completion: nil)
|
|
406
|
+
commandParams = ["command": "site", "siteExternalIdentifier": siteId]
|
|
407
|
+
focus.completion = { [weak self] error in
|
|
408
|
+
var p = commandParams; p["error"] = error?.errorCode ?? ""
|
|
409
|
+
self?.ptrMapWidgetDidEndLoading(withParameters: p)
|
|
410
|
+
}
|
|
411
|
+
action = focus
|
|
412
|
+
|
|
413
|
+
case "building":
|
|
414
|
+
let location = PTRMapWidgetBuildingLocation(siteIdentifier: siteId, buildingIdentifier: buildingId, isExternalIdentifiers: true)
|
|
415
|
+
let focus = PTRMapWidgetMapFocusAction(location: location, completion: nil)
|
|
416
|
+
commandParams = ["command": "building", "siteExternalIdentifier": siteId, "buildingExternalIdentifier": buildingId]
|
|
417
|
+
focus.completion = { [weak self] error in
|
|
418
|
+
var p = commandParams; p["error"] = error?.errorCode ?? ""
|
|
419
|
+
self?.ptrMapWidgetDidEndLoading(withParameters: p)
|
|
420
|
+
}
|
|
421
|
+
action = focus
|
|
422
|
+
|
|
423
|
+
case "level":
|
|
424
|
+
let location = PTRMapWidgetLevelLocation(siteIdentifier: siteId, buildingIdentifier: buildingId, levelIndex: levelIndex, isExternalIdentifiers: true)
|
|
425
|
+
let focus = PTRMapWidgetMapFocusAction(location: location, completion: nil)
|
|
426
|
+
commandParams = ["command": "level", "siteExternalIdentifier": siteId, "buildingExternalIdentifier": buildingId, "levelIndex": levelIndex]
|
|
427
|
+
focus.completion = { [weak self] error in
|
|
428
|
+
var p = commandParams; p["error"] = error?.errorCode ?? ""
|
|
429
|
+
self?.ptrMapWidgetDidEndLoading(withParameters: p)
|
|
430
|
+
}
|
|
431
|
+
action = focus
|
|
432
|
+
|
|
433
|
+
case "poi":
|
|
434
|
+
let location = PTRMapWidgetPoiLocation(siteIdentifier: siteId, poiIdentifier: poiId, isExternalIdentifiers: true)
|
|
435
|
+
let focus = PTRMapWidgetMapFocusAction(location: location, completion: nil)
|
|
436
|
+
commandParams = ["command": "poi", "siteExternalIdentifier": siteId, "poiExternalIdentifier": poiId]
|
|
437
|
+
focus.completion = { [weak self] error in
|
|
438
|
+
var p = commandParams; p["error"] = error?.errorCode ?? ""
|
|
439
|
+
self?.ptrMapWidgetDidEndLoading(withParameters: p)
|
|
440
|
+
}
|
|
441
|
+
action = focus
|
|
442
|
+
|
|
443
|
+
case "path":
|
|
444
|
+
let wayfinding = PTRMapWidgetWayfindingAction(poiDestination: PTRMapWidgetPoiLocation(siteIdentifier: siteId, poiIdentifier: poiId, isExternalIdentifiers: true))
|
|
445
|
+
commandParams = ["command": "path", "siteExternalIdentifier": siteId, "poiExternalIdentifier": poiId]
|
|
446
|
+
wayfinding.completion = { [weak self] error in
|
|
447
|
+
var p = commandParams; p["error"] = error?.errorCode ?? ""
|
|
448
|
+
self?.ptrMapWidgetDidEndLoading(withParameters: p)
|
|
449
|
+
}
|
|
450
|
+
action = wayfinding
|
|
451
|
+
|
|
452
|
+
case "staticPath":
|
|
453
|
+
DispatchQueue.global(qos: .default).async { [weak self] in
|
|
454
|
+
self?.showStaticPath(siteId, fromPoiExternalIdentifier: fromPoiId, toPoiExternalIdentifier: toPoiId)
|
|
455
|
+
}
|
|
456
|
+
return
|
|
457
|
+
|
|
458
|
+
case "staticWayfinding":
|
|
459
|
+
let srcLocation = PTRMapWidgetPoiLocation(siteIdentifier: siteId, poiIdentifier: sourcePoiId, isExternalIdentifiers: true)
|
|
460
|
+
let dstLocation = PTRMapWidgetPoiLocation(siteIdentifier: siteId, poiIdentifier: destinationPoiId, isExternalIdentifiers: true)
|
|
461
|
+
let sw = PTRMapWidgetStaticWayfindingAction(poiSource: srcLocation, poiDestination: dstLocation)
|
|
462
|
+
commandParams = ["command": "staticWayfinding", "siteExternalIdentifier": siteId, "sourcePoiExternalIdentifier": sourcePoiId, "destinationPoiExternalIdentifier": destinationPoiId]
|
|
463
|
+
sw.completion = { [weak self] error in
|
|
464
|
+
var p = commandParams; p["error"] = error?.localizedDescription ?? ""
|
|
465
|
+
self?.ptrMapWidgetDidEndLoading(withParameters: p)
|
|
466
|
+
}
|
|
467
|
+
action = sw
|
|
468
|
+
|
|
469
|
+
default:
|
|
470
|
+
print("PTRMapWidget: unknown command type '\(type)'")
|
|
471
|
+
return
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
waitForPointrState()
|
|
475
|
+
DispatchQueue.main.async { [weak self] in
|
|
476
|
+
guard let self = self else { return }
|
|
477
|
+
let mapWidget = self.getMapWidget(action)
|
|
478
|
+
self.present(mapWidget)
|
|
479
|
+
}
|
|
480
|
+
}
|
|
298
481
|
}
|
|
299
482
|
|
|
@@ -17,6 +17,12 @@ RCT_EXPORT_VIEW_PROPERTY(onMapWidgetDidEndLoading, RCTBubblingEventBlock)
|
|
|
17
17
|
|
|
18
18
|
RCT_EXPORT_VIEW_PROPERTY(onWayfindingEvent, RCTBubblingEventBlock)
|
|
19
19
|
|
|
20
|
+
RCT_EXPORT_VIEW_PROPERTY(command, NSString)
|
|
21
|
+
|
|
22
|
+
RCT_EXPORT_VIEW_PROPERTY(sdkConfig, NSString)
|
|
23
|
+
|
|
24
|
+
RCT_EXPORT_VIEW_PROPERTY(mapWidgetConfig, NSString)
|
|
25
|
+
|
|
20
26
|
RCT_EXTERN_METHOD(site:(nonnull NSNumber *)reactTag
|
|
21
27
|
siteExternalIdentifier:(NSString *)siteExternalIdentifier)
|
|
22
28
|
RCT_EXTERN_METHOD(building:(nonnull NSNumber *)reactTag
|
|
@@ -38,6 +38,20 @@ class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
|
|
|
38
38
|
}
|
|
39
39
|
mapWidgetConfiguration.setValue(value, forKey: key)
|
|
40
40
|
}
|
|
41
|
+
// The following properties are computed in PTRMapWidgetConfiguration, so Mirror
|
|
42
|
+
// does not include them in children. Assign them directly.
|
|
43
|
+
if let value = configuration["isQuickAccessEnabled"] as? Bool {
|
|
44
|
+
mapWidgetConfiguration.isQuickAccessEnabled = value
|
|
45
|
+
}
|
|
46
|
+
if let value = configuration["isMarkMyCarEnabled"] as? Bool {
|
|
47
|
+
mapWidgetConfiguration.isMarkMyCarEnabled = value
|
|
48
|
+
}
|
|
49
|
+
if let value = configuration["isInfoButtonEnabled"] as? Bool {
|
|
50
|
+
mapWidgetConfiguration.isInfoButtonEnabled = value
|
|
51
|
+
}
|
|
52
|
+
if let value = configuration["shouldFocusOnFirstUserPosition"] as? Bool {
|
|
53
|
+
mapWidgetConfiguration.shouldFocusOnFirstUserPosition = value
|
|
54
|
+
}
|
|
41
55
|
}
|
|
42
56
|
}
|
|
43
57
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-pointr",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.8.0",
|
|
4
4
|
"description": "Pointr React-Native Module",
|
|
5
5
|
"main": "src/index",
|
|
6
6
|
"files": [
|
|
@@ -25,17 +25,28 @@
|
|
|
25
25
|
"version": "0.41.0"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"react-native": ">=0.
|
|
29
|
-
"react": ">=
|
|
28
|
+
"react-native": ">=0.72",
|
|
29
|
+
"react": ">=18"
|
|
30
|
+
},
|
|
31
|
+
"peerDependenciesMeta": {
|
|
32
|
+
"react": {
|
|
33
|
+
"optional": true
|
|
34
|
+
},
|
|
35
|
+
"react-native": {
|
|
36
|
+
"optional": true
|
|
37
|
+
}
|
|
30
38
|
},
|
|
31
39
|
"devDependencies": {
|
|
32
|
-
"@types/node": "
|
|
33
|
-
"react-native": "
|
|
40
|
+
"@types/node": ">=20",
|
|
41
|
+
"react-native": "0.82.1",
|
|
42
|
+
"typescript": "^5.8.3"
|
|
34
43
|
},
|
|
35
44
|
"engines": {
|
|
36
45
|
"node": ">=20"
|
|
37
46
|
},
|
|
38
47
|
"scripts": {
|
|
48
|
+
"check-react": "./check_react.sh",
|
|
49
|
+
"typescript": "tsc --noEmit",
|
|
39
50
|
"prepare-dist": "chmod +x prepare-distribution.sh && ./prepare-distribution.sh"
|
|
40
51
|
}
|
|
41
52
|
}
|
|
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
|
|
|
16
16
|
|
|
17
17
|
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
18
18
|
|
|
19
|
-
s.dependency 'PointrKit', '9.
|
|
19
|
+
s.dependency 'PointrKit', '9.8.0'
|
|
20
20
|
|
|
21
21
|
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
|
22
22
|
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
|
package/src/PTRMapWidgetUtils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UIManager } from 'react-native';
|
|
2
|
-
import { PTRSiteCommand, PTRBuildingCommand, PTRLevelCommand, PTRPoiCommand, PTRPathCommand, PTRStaticPathCommand, PTRStaticWayfindingCommand, PTRCommand, PTRCommandType, PTRMarkMyCarLevelCommand, PTRMarkMyCarSiteCommand, PTRShowMyCarSiteCommand, PTRStartAndFocusCommand } from '
|
|
2
|
+
import { PTRSiteCommand, PTRBuildingCommand, PTRLevelCommand, PTRPoiCommand, PTRPathCommand, PTRStaticPathCommand, PTRStaticWayfindingCommand, PTRCommand, PTRCommandType, PTRMarkMyCarLevelCommand, PTRMarkMyCarSiteCommand, PTRShowMyCarSiteCommand, PTRStartAndFocusCommand } from './PTRCommand';
|
|
3
3
|
/**
|
|
4
4
|
* Handle PTRStartAndFocusCommand specifically
|
|
5
5
|
* @param reactTag view tag of the map widget
|
|
@@ -7,10 +7,8 @@ import { PTRSiteCommand, PTRBuildingCommand, PTRLevelCommand, PTRPoiCommand, PTR
|
|
|
7
7
|
*/
|
|
8
8
|
const handleStartAndFocusCommand = (reactTag: number, startAndFocusCommand: PTRStartAndFocusCommand) => {
|
|
9
9
|
const innerCommand = startAndFocusCommand.command;
|
|
10
|
-
console.info('Handling PTRStartAndFocusCommand with type:', innerCommand.type);
|
|
11
10
|
// Build arguments based on the inner command type
|
|
12
11
|
let args: any[];
|
|
13
|
-
console.info('Inner command details:', innerCommand);
|
|
14
12
|
|
|
15
13
|
switch (innerCommand.type) {
|
|
16
14
|
case PTRCommandType.SITE: {
|
|
@@ -73,7 +71,6 @@ const handleStartAndFocusCommand = (reactTag: number, startAndFocusCommand: PTRS
|
|
|
73
71
|
console.error('Unsupported command type in PTRStartAndFocusCommand:', innerCommand.type);
|
|
74
72
|
return;
|
|
75
73
|
}
|
|
76
|
-
console.info('Dispatching startAndFocus with args:', args);
|
|
77
74
|
UIManager.dispatchViewManagerCommand(
|
|
78
75
|
reactTag,
|
|
79
76
|
'startAndFocus',
|
|
@@ -89,15 +86,12 @@ const handleStartAndFocusCommand = (reactTag: number, startAndFocusCommand: PTRS
|
|
|
89
86
|
export const showMapWidget = (reactTag: number, ptrCommand: PTRCommand | PTRStartAndFocusCommand) => {
|
|
90
87
|
// Check if it's a PTRStartAndFocusCommand (which doesn't have a 'type' property)
|
|
91
88
|
if ('command' in ptrCommand) {
|
|
92
|
-
|
|
93
|
-
console.log(`Showing map widget with start and focus command: ${startAndFocusCommand.command.type} and reactTag: ${reactTag}`);
|
|
94
|
-
handleStartAndFocusCommand(reactTag, startAndFocusCommand);
|
|
89
|
+
handleStartAndFocusCommand(reactTag, ptrCommand as PTRStartAndFocusCommand);
|
|
95
90
|
return;
|
|
96
91
|
}
|
|
97
92
|
|
|
98
93
|
// Handle regular PTRCommand
|
|
99
94
|
const command = ptrCommand as PTRCommand;
|
|
100
|
-
console.log(`Showing map widget with command: ${command.type} and reactTag: ${reactTag}`);
|
|
101
95
|
switch (command.type) {
|
|
102
96
|
case PTRCommandType.SITE: {
|
|
103
97
|
const siteCommand = ptrCommand as PTRSiteCommand;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map Widget API utilities
|
|
3
|
+
* Provides type-safe command execution for the map widget
|
|
4
|
+
* @module api/MapWidgetApi
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { findNodeHandle } from 'react-native';
|
|
8
|
+
import type { PTRCommand } from '../commands';
|
|
9
|
+
import { PTRErrorMessages } from '../constants';
|
|
10
|
+
import { showMapWidget } from '../PTRMapWidgetUtils';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Execute a command on the map widget
|
|
14
|
+
* @param mapRef - Reference to the map widget component
|
|
15
|
+
* @param command - Command to execute
|
|
16
|
+
* @throws Error if mapRef is null or command is invalid
|
|
17
|
+
*/
|
|
18
|
+
export function executeMapCommand(
|
|
19
|
+
mapRef: React.RefObject<any> | any,
|
|
20
|
+
command: PTRCommand
|
|
21
|
+
): void {
|
|
22
|
+
if (!mapRef) {
|
|
23
|
+
throw new Error(PTRErrorMessages.NO_MAP_REF);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const ref = 'current' in mapRef ? mapRef.current : mapRef;
|
|
27
|
+
const reactTag = findNodeHandle(ref);
|
|
28
|
+
|
|
29
|
+
if (!reactTag) {
|
|
30
|
+
throw new Error(PTRErrorMessages.NO_MAP_REF);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!command || !command.type) {
|
|
34
|
+
throw new Error(PTRErrorMessages.INVALID_COMMAND);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
showMapWidget(reactTag, command);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error('Error executing map command:', error);
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pointr SDK singleton wrapper
|
|
3
|
+
* Provides a clean, type-safe API for the Pointr SDK
|
|
4
|
+
* @module api/PointrSdk
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
|
|
8
|
+
import type { PTRConfiguration, PTRMapWidgetConfiguration, PTRStateCallback } from '../types/config';
|
|
9
|
+
import type { PTRPosition } from '../types/PTRPosition';
|
|
10
|
+
import { PTRState, PTRLogLevel, PTRErrorMessages, PTREvents } from '../constants';
|
|
11
|
+
|
|
12
|
+
const LINKING_ERROR =
|
|
13
|
+
`The package 'react-native-pointr' doesn't seem to be linked. Make sure: \n\n` +
|
|
14
|
+
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
|
|
15
|
+
'- You rebuilt the app after installing the package\n' +
|
|
16
|
+
'- You are not using Expo Go\n';
|
|
17
|
+
|
|
18
|
+
const PTRNativePointrLibrary = NativeModules.PTRNativePointrLibrary
|
|
19
|
+
? NativeModules.PTRNativePointrLibrary
|
|
20
|
+
: new Proxy(
|
|
21
|
+
{},
|
|
22
|
+
{
|
|
23
|
+
get() {
|
|
24
|
+
throw new Error(LINKING_ERROR);
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Singleton class for managing the Pointr SDK
|
|
31
|
+
*/
|
|
32
|
+
export class PointrSdk {
|
|
33
|
+
private static instance: PointrSdk | null = null;
|
|
34
|
+
private state: PTRState = PTRState.NOT_INITIALIZED;
|
|
35
|
+
private config: PTRConfiguration | null = null;
|
|
36
|
+
private eventEmitter: NativeEventEmitter;
|
|
37
|
+
|
|
38
|
+
private constructor() {
|
|
39
|
+
this.eventEmitter = new NativeEventEmitter(PTRNativePointrLibrary);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get the singleton instance of PointrSdk
|
|
44
|
+
*/
|
|
45
|
+
public static getInstance(): PointrSdk {
|
|
46
|
+
if (!PointrSdk.instance) {
|
|
47
|
+
PointrSdk.instance = new PointrSdk();
|
|
48
|
+
}
|
|
49
|
+
return PointrSdk.instance;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Initialize the Pointr SDK with configuration
|
|
54
|
+
* @param config - Configuration options
|
|
55
|
+
* @throws Error if already initialized or invalid config
|
|
56
|
+
*/
|
|
57
|
+
public initialize(config: PTRConfiguration): void {
|
|
58
|
+
if (this.state !== PTRState.NOT_INITIALIZED) {
|
|
59
|
+
throw new Error(PTRErrorMessages.ALREADY_INITIALIZED);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!config.clientId || !config.licenseKey || !config.baseUrl) {
|
|
63
|
+
throw new Error(PTRErrorMessages.INVALID_CONFIG);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.state = PTRState.INITIALIZING;
|
|
67
|
+
this.config = config;
|
|
68
|
+
|
|
69
|
+
const logLevel = config.logLevel ?? PTRLogLevel.ERROR;
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
PTRNativePointrLibrary.initialize(
|
|
73
|
+
config.clientId,
|
|
74
|
+
config.licenseKey,
|
|
75
|
+
config.baseUrl,
|
|
76
|
+
logLevel
|
|
77
|
+
);
|
|
78
|
+
this.state = PTRState.INITIALIZED;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
this.state = PTRState.ERROR;
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Start the Pointr SDK
|
|
87
|
+
* @param callback - Optional callback for state changes
|
|
88
|
+
* @throws Error if not initialized
|
|
89
|
+
*/
|
|
90
|
+
public start(callback?: PTRStateCallback): void {
|
|
91
|
+
if (this.state === PTRState.NOT_INITIALIZED) {
|
|
92
|
+
throw new Error(PTRErrorMessages.NOT_INITIALIZED);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this.state = PTRState.STARTING;
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
PTRNativePointrLibrary.start((state: string) => {
|
|
99
|
+
this.state = PTRState.RUNNING;
|
|
100
|
+
if (callback) {
|
|
101
|
+
callback(state);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
} catch (error) {
|
|
105
|
+
this.state = PTRState.ERROR;
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Stop the Pointr SDK
|
|
112
|
+
*/
|
|
113
|
+
public stop(): void {
|
|
114
|
+
if (this.state === PTRState.RUNNING) {
|
|
115
|
+
try {
|
|
116
|
+
PTRNativePointrLibrary.stop();
|
|
117
|
+
this.state = PTRState.STOPPED;
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error('Error stopping Pointr SDK:', error);
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Get the current SDK state
|
|
127
|
+
*/
|
|
128
|
+
public getState(): PTRState {
|
|
129
|
+
return this.state;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Check if SDK is initialized
|
|
134
|
+
*/
|
|
135
|
+
public isInitialized(): boolean {
|
|
136
|
+
return this.state !== PTRState.NOT_INITIALIZED;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Check if SDK is started and running
|
|
141
|
+
*/
|
|
142
|
+
public isStarted(): boolean {
|
|
143
|
+
return this.state === PTRState.RUNNING;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get the current configuration
|
|
148
|
+
*/
|
|
149
|
+
public getConfig(): PTRConfiguration | null {
|
|
150
|
+
return this.config;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Get the event emitter for subscribing to Pointr events
|
|
155
|
+
*/
|
|
156
|
+
public getEventEmitter(): NativeEventEmitter {
|
|
157
|
+
return this.eventEmitter;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Subscribe to position updates
|
|
162
|
+
* @param callback - Function to call when position is updated
|
|
163
|
+
* @returns Subscription that can be removed
|
|
164
|
+
*/
|
|
165
|
+
public onPositionUpdate(callback: (position: any) => void) {
|
|
166
|
+
return this.eventEmitter.addListener(
|
|
167
|
+
PTREvents.ON_POSITION_CALCULATED,
|
|
168
|
+
callback
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Subscribe to building click events
|
|
174
|
+
* @param callback - Function to call when building is clicked
|
|
175
|
+
* @returns Subscription that can be removed
|
|
176
|
+
*/
|
|
177
|
+
public onBuildingClick(callback: (event: any) => void) {
|
|
178
|
+
return this.eventEmitter.addListener(
|
|
179
|
+
PTREvents.ON_BUILDING_CLICKED,
|
|
180
|
+
callback
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Subscribe to site click events
|
|
186
|
+
* @param callback - Function to call when site is clicked
|
|
187
|
+
* @returns Subscription that can be removed
|
|
188
|
+
*/
|
|
189
|
+
public onSiteClick(callback: (event: any) => void) {
|
|
190
|
+
return this.eventEmitter.addListener(PTREvents.ON_SITE_CLICKED, callback);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Subscribe to geofence events
|
|
195
|
+
* @param callback - Function to call when geofence event occurs
|
|
196
|
+
* @returns Subscription that can be removed
|
|
197
|
+
*/
|
|
198
|
+
public onGeofenceEvent(callback: (event: any) => void) {
|
|
199
|
+
return this.eventEmitter.addListener(
|
|
200
|
+
PTREvents.ON_GEOFENCE_EVENT,
|
|
201
|
+
callback
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Set the map widget configuration
|
|
207
|
+
* Must be called before the map widget renders to take effect.
|
|
208
|
+
* @param config - Map widget configuration options
|
|
209
|
+
*/
|
|
210
|
+
public setMapWidgetConfiguration(config: PTRMapWidgetConfiguration): void {
|
|
211
|
+
PTRNativePointrLibrary.setPointrMapWidgetConfiguration(JSON.stringify(config));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Get the current calculated position.
|
|
216
|
+
* Resolves with the position or null if unavailable.
|
|
217
|
+
*/
|
|
218
|
+
public getCurrentLocation(): Promise<PTRPosition | null> {
|
|
219
|
+
return new Promise((resolve) => {
|
|
220
|
+
PTRNativePointrLibrary.getCurrentLocation((result: any) => {
|
|
221
|
+
if (!result || typeof result === 'string') {
|
|
222
|
+
resolve(null);
|
|
223
|
+
} else {
|
|
224
|
+
resolve(result as PTRPosition);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Get native module reference (for advanced use cases)
|
|
232
|
+
*/
|
|
233
|
+
public getNativeModule() {
|
|
234
|
+
return PTRNativePointrLibrary;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Export singleton instance for easy access
|
|
240
|
+
*/
|
|
241
|
+
export const pointrSdk = PointrSdk.getInstance();
|