react-native-pointr 9.2.0 → 9.5.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/.vscode/settings.json +21 -0
- package/API_REFERENCE.md +887 -0
- package/CHANGELOG.md +45 -0
- package/EXTENDING.md +419 -0
- package/README.md +221 -117
- package/WAYFINDING_EVENTS.md +243 -0
- package/android/build.gradle +4 -5
- package/android/src/main/java/com/pointr/PTRCoreExtensions.kt +126 -0
- package/android/src/main/java/com/pointr/PTRMapWidgetCommandType.kt +2 -1
- package/android/src/main/java/com/pointr/PTRMapWidgetManager.kt +78 -16
- package/android/src/main/java/com/pointr/PointrModule.kt +106 -3
- package/example/pointr_rn_demo/.bundle/config +2 -0
- package/example/pointr_rn_demo/.eslintrc.js +4 -0
- package/example/pointr_rn_demo/.prettierrc.js +5 -0
- package/example/pointr_rn_demo/.watchmanconfig +1 -0
- package/example/pointr_rn_demo/App.tsx +323 -0
- package/example/pointr_rn_demo/Gemfile +16 -0
- package/example/pointr_rn_demo/Gemfile.lock +111 -0
- package/example/pointr_rn_demo/README.md +188 -0
- package/example/pointr_rn_demo/__tests__/App.test.tsx +13 -0
- package/example/pointr_rn_demo/android/app/build.gradle +119 -0
- package/example/pointr_rn_demo/android/app/debug.keystore +0 -0
- package/example/pointr_rn_demo/android/app/proguard-rules.pro +10 -0
- package/example/pointr_rn_demo/android/app/src/main/AndroidManifest.xml +27 -0
- package/example/pointr_rn_demo/android/app/src/main/java/com/pointr_rn_demo/MainActivity.kt +22 -0
- package/example/pointr_rn_demo/android/app/src/main/java/com/pointr_rn_demo/MainApplication.kt +27 -0
- package/example/pointr_rn_demo/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
- package/example/pointr_rn_demo/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/example/pointr_rn_demo/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/example/pointr_rn_demo/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/example/pointr_rn_demo/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/example/pointr_rn_demo/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/example/pointr_rn_demo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/example/pointr_rn_demo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/example/pointr_rn_demo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/example/pointr_rn_demo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/example/pointr_rn_demo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/example/pointr_rn_demo/android/app/src/main/res/values/strings.xml +3 -0
- package/example/pointr_rn_demo/android/app/src/main/res/values/styles.xml +9 -0
- package/example/pointr_rn_demo/android/build.gradle +34 -0
- package/example/pointr_rn_demo/android/gradle.properties +44 -0
- package/example/pointr_rn_demo/android/settings.gradle +6 -0
- package/example/pointr_rn_demo/app.json +4 -0
- package/example/pointr_rn_demo/babel.config.js +3 -0
- package/example/pointr_rn_demo/index.js +16 -0
- package/example/pointr_rn_demo/ios/.xcode.env +11 -0
- package/example/pointr_rn_demo/ios/Podfile +40 -0
- package/example/pointr_rn_demo/ios/pointr_rn_demo/AppDelegate.swift +48 -0
- package/example/pointr_rn_demo/ios/pointr_rn_demo/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
- package/example/pointr_rn_demo/ios/pointr_rn_demo/Images.xcassets/Contents.json +6 -0
- package/example/pointr_rn_demo/ios/pointr_rn_demo/Info.plist +63 -0
- package/example/pointr_rn_demo/ios/pointr_rn_demo/LaunchScreen.storyboard +47 -0
- package/example/pointr_rn_demo/ios/pointr_rn_demo/PrivacyInfo.xcprivacy +37 -0
- package/example/pointr_rn_demo/ios/pointr_rn_demo.xcodeproj/project.pbxproj +488 -0
- package/example/pointr_rn_demo/ios/pointr_rn_demo.xcodeproj/xcshareddata/xcschemes/pointr_rn_demo.xcscheme +88 -0
- package/example/pointr_rn_demo/ios/pointr_rn_demo.xcworkspace/contents.xcworkspacedata +10 -0
- package/example/pointr_rn_demo/jest.config.js +3 -0
- package/example/pointr_rn_demo/metro.config.js +22 -0
- package/example/pointr_rn_demo/package.json +47 -0
- package/example/pointr_rn_demo/prepare-demo-distribution.sh +103 -0
- package/example/pointr_rn_demo/tsconfig.json +5 -0
- package/ios/PTRMapWidgetContainerView.swift +56 -5
- package/ios/PTRMapWidgetManager-Bridging.m +7 -0
- package/ios/PTRMapWidgetManager.swift +28 -0
- package/ios/PTRNativeLibrary-Bridging.m +4 -0
- package/ios/PTRNativeLibrary.swift +208 -2
- package/package.json +16 -2
- package/prepare-distribution.sh +151 -0
- package/react-native-pointr.podspec +1 -1
- package/src/PTRCommand.ts +13 -0
- package/src/PTRMapWidgetUtils.ts +10 -1
- package/src/PTRPoiManager.ts +20 -0
- package/src/index.tsx +40 -1
- package/src/types/PTRGeometry.ts +70 -0
- package/src/types/PTRPoi.ts +49 -0
- package/src/types/PTRPosition.ts +22 -0
- package/src/types/PTRWayfindingEvent.ts +18 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Metro configuration
|
|
6
|
+
* https://reactnative.dev/docs/metro
|
|
7
|
+
*
|
|
8
|
+
* @type {import('@react-native/metro-config').MetroConfig}
|
|
9
|
+
*/
|
|
10
|
+
const config = {
|
|
11
|
+
watchFolders: [
|
|
12
|
+
path.resolve(__dirname, '../../../react-native-pointr'),
|
|
13
|
+
],
|
|
14
|
+
resolver: {
|
|
15
|
+
nodeModulesPaths: [
|
|
16
|
+
path.resolve(__dirname, 'node_modules'),
|
|
17
|
+
path.resolve(__dirname, '../../../react-native-pointr/node_modules'),
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
module.exports = mergeConfig(getDefaultConfig(__dirname), config);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pointr_rn_demo",
|
|
3
|
+
"version": "9.5.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"clean": "watchman watch-del-all || true && rm -rf node_modules ios/Pods ios/Podfile.lock ios/build android/.gradle android/app/build android/build",
|
|
7
|
+
"reset": "npm run clean && npm install && cd ios && pod install && cd ..",
|
|
8
|
+
"start": "npx react-native start",
|
|
9
|
+
"start:clean": "npx react-native start --reset-cache",
|
|
10
|
+
"android": "npx react-native run-android",
|
|
11
|
+
"ios": "npx react-native run-ios",
|
|
12
|
+
"lint": "eslint .",
|
|
13
|
+
"test": "jest",
|
|
14
|
+
"prepare-dist": "chmod +x prepare-demo-distribution.sh && ./prepare-demo-distribution.sh"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@react-native/new-app-screen": "0.82.1",
|
|
18
|
+
"react": "19.1.1",
|
|
19
|
+
"react-native": "^0.82.1",
|
|
20
|
+
"react-native-pointr": "file:../../../react-native-pointr",
|
|
21
|
+
"react-native-safe-area-context": "^5.6.2"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@babel/core": "^7.25.2",
|
|
25
|
+
"@babel/preset-env": "^7.25.3",
|
|
26
|
+
"@babel/runtime": "^7.25.0",
|
|
27
|
+
"@react-native-community/cli": "20.0.0",
|
|
28
|
+
"@react-native-community/cli-platform-android": "20.0.0",
|
|
29
|
+
"@react-native-community/cli-platform-ios": "20.0.0",
|
|
30
|
+
"@react-native/babel-preset": "0.82.1",
|
|
31
|
+
"@react-native/eslint-config": "0.82.1",
|
|
32
|
+
"@react-native/gradle-plugin": "^0.83.1",
|
|
33
|
+
"@react-native/metro-config": "0.82.1",
|
|
34
|
+
"@react-native/typescript-config": "0.82.1",
|
|
35
|
+
"@types/jest": "^29.5.13",
|
|
36
|
+
"@types/react": "^19.1.1",
|
|
37
|
+
"@types/react-test-renderer": "^19.1.0",
|
|
38
|
+
"eslint": "^8.19.0",
|
|
39
|
+
"jest": "^29.6.3",
|
|
40
|
+
"prettier": "2.8.8",
|
|
41
|
+
"react-test-renderer": "19.1.1",
|
|
42
|
+
"typescript": "^5.8.3"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=20"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Script to prepare pointr_rn_demo project for distribution
|
|
4
|
+
# This script cleans build artifacts, removes sensitive information, and creates a compressed archive
|
|
5
|
+
|
|
6
|
+
set -e # Exit on error
|
|
7
|
+
|
|
8
|
+
PROJECT_NAME="pointr_rn_demo"
|
|
9
|
+
VERSION=$(grep -o '"version": "[^"]*"' package.json | head -1 | sed 's/"version": "\(.*\)"/\1/')
|
|
10
|
+
OUTPUT_NAME="${PROJECT_NAME}-${VERSION}.zip"
|
|
11
|
+
TEMP_DIR="${PROJECT_NAME}_temp"
|
|
12
|
+
DIST_DIR="../../dist"
|
|
13
|
+
|
|
14
|
+
# Create dist directory if it doesn't exist and get absolute path
|
|
15
|
+
mkdir -p "${DIST_DIR}"
|
|
16
|
+
DIST_DIR_ABS=$(cd "${DIST_DIR}" && pwd)
|
|
17
|
+
|
|
18
|
+
echo "🧹 Starting demo project cleanup and preparation..."
|
|
19
|
+
echo "📌 Project version: ${VERSION}"
|
|
20
|
+
|
|
21
|
+
# Create a temporary copy of the project
|
|
22
|
+
echo "📦 Creating temporary copy..."
|
|
23
|
+
rsync -a --exclude="node_modules" \
|
|
24
|
+
--exclude="ios/Pods" \
|
|
25
|
+
--exclude="ios/build" \
|
|
26
|
+
--exclude="ios/Podfile.lock" \
|
|
27
|
+
--exclude="android/build" \
|
|
28
|
+
--exclude="android/app/build" \
|
|
29
|
+
--exclude="android/.gradle" \
|
|
30
|
+
--exclude="android/local.properties" \
|
|
31
|
+
--exclude=".DS_Store" \
|
|
32
|
+
--exclude="*.log" \
|
|
33
|
+
--exclude=".git" \
|
|
34
|
+
--exclude="prepare-demo-distribution.sh" \
|
|
35
|
+
./ "../${TEMP_DIR}/"
|
|
36
|
+
|
|
37
|
+
cd "../${TEMP_DIR}"
|
|
38
|
+
|
|
39
|
+
# Remove sensitive information from App.tsx
|
|
40
|
+
echo "🔒 Removing sensitive information..."
|
|
41
|
+
if [ -f "App.tsx" ]; then
|
|
42
|
+
# Replace credentials with placeholder values
|
|
43
|
+
sed -i '' 's/"1ee58e56-fc35-4ec4-b32e-5d49e65fb52d"/"YOUR_CLIENT_ID"/g' App.tsx
|
|
44
|
+
sed -i '' 's/"af5d9431-56a3-46a9-ae0a-65d9757528d1"/"YOUR_LICENSE_KEY"/g' App.tsx
|
|
45
|
+
sed -i '' 's|"https://sample-app-v9.pointr.cloud"|"https://your-instance.pointr.cloud"|g' App.tsx
|
|
46
|
+
echo "✓ Replaced credentials in App.tsx"
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Remove sensitive information from Android build.gradle
|
|
50
|
+
if [ -f "android/build.gradle" ]; then
|
|
51
|
+
sed -i '' "s/username 'discover'/username 'YOUR_MAVEN_USERNAME'/g" android/build.gradle
|
|
52
|
+
sed -i '' "s/password 'AKCp5ejy2i3iwwJbXZzCTvtgcarhYWLztx1TCxXzBdhhMK4Qjhp945jz7JwtMK5SBoARGLkdF'/password 'YOUR_MAVEN_PASSWORD'/g" android/build.gradle
|
|
53
|
+
echo "✓ Replaced Maven credentials in android/build.gradle"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Remove sensitive information from iOS Podfile
|
|
57
|
+
if [ -f "ios/Podfile" ]; then
|
|
58
|
+
sed -i '' "s|ENV\['POINTR_SDK_TOKEN'\] = 'sv=2023-01-03&st=2024-10-23T06%3A40%3A13Z&se=2035-11-08T06%3A40%3A00Z&sr=c&sp=r&sig=WaCbhxt4pMqf9Oqzgf%2FnDj1SbdvyzwCtFdsWLW4KFqA%3D'|ENV['POINTR_SDK_TOKEN'] = 'YOUR_POINTR_SDK_TOKEN'|g" ios/Podfile
|
|
59
|
+
echo "✓ Replaced Pointr SDK token in ios/Podfile"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Clean any remaining build artifacts
|
|
63
|
+
echo "🤖 Cleaning build artifacts..."
|
|
64
|
+
rm -rf node_modules
|
|
65
|
+
rm -rf ios/Pods ios/build ios/Podfile.lock
|
|
66
|
+
rm -rf android/build android/app/build android/.gradle
|
|
67
|
+
rm -f android/local.properties
|
|
68
|
+
rm -rf .gradle
|
|
69
|
+
rm -f .DS_Store
|
|
70
|
+
rm -f *.log npm-debug.log* yarn-debug.log* yarn-error.log*
|
|
71
|
+
rm -f package-lock.json yarn.lock
|
|
72
|
+
|
|
73
|
+
# Remove IDE and development files
|
|
74
|
+
echo "🗑️ Removing development files..."
|
|
75
|
+
rm -rf .vscode .idea
|
|
76
|
+
rm -rf .git .gitignore .github
|
|
77
|
+
rm -f .watchmanconfig
|
|
78
|
+
|
|
79
|
+
# Create the zip archive
|
|
80
|
+
echo "📦 Creating compressed archive..."
|
|
81
|
+
cd ..
|
|
82
|
+
zip -r "${OUTPUT_NAME}" "${TEMP_DIR}" -x "*.DS_Store" -q
|
|
83
|
+
|
|
84
|
+
# Move the archive to dist directory
|
|
85
|
+
mv "${OUTPUT_NAME}" "${DIST_DIR_ABS}/"
|
|
86
|
+
|
|
87
|
+
# Clean up temporary directory
|
|
88
|
+
echo "🧼 Cleaning up temporary files..."
|
|
89
|
+
rm -rf "${TEMP_DIR}"
|
|
90
|
+
|
|
91
|
+
cd "${PROJECT_NAME}"
|
|
92
|
+
|
|
93
|
+
echo "✅ Demo distribution package created successfully!"
|
|
94
|
+
echo "📦 Output file: ${OUTPUT_NAME}"
|
|
95
|
+
echo "📍 Location: ${DIST_DIR_ABS}/${OUTPUT_NAME}"
|
|
96
|
+
echo ""
|
|
97
|
+
echo "⚠️ Note: All sensitive credentials have been replaced with placeholders:"
|
|
98
|
+
echo " • App.tsx: YOUR_CLIENT_ID, YOUR_LICENSE_KEY, your-instance.pointr.cloud"
|
|
99
|
+
echo " • android/build.gradle: YOUR_MAVEN_USERNAME, YOUR_MAVEN_PASSWORD"
|
|
100
|
+
echo " • ios/Podfile: YOUR_POINTR_SDK_TOKEN"
|
|
101
|
+
echo ""
|
|
102
|
+
echo " Recipients must configure all credentials before running the app."
|
|
103
|
+
echo " See README.md in the package for detailed setup instructions."
|
|
@@ -1,29 +1,79 @@
|
|
|
1
1
|
import UIKit
|
|
2
2
|
import PointrKit
|
|
3
3
|
|
|
4
|
-
@objc class PTRMapWidgetContainerView: UIView, PTRSiteManagerDelegate, PTRDataManagerDelegate, PTRWayfindingManagerDelegate {
|
|
4
|
+
@objc class PTRMapWidgetContainerView: UIView, PTRSiteManagerDelegate, PTRDataManagerDelegate, PTRWayfindingManagerDelegate, PTRMapWidgetEventsListener {
|
|
5
5
|
|
|
6
6
|
@objc var onMapWidgetDidEndLoading: RCTBubblingEventBlock?
|
|
7
|
+
|
|
8
|
+
@objc var onWayfindingEvent: RCTBubblingEventBlock?
|
|
7
9
|
|
|
8
10
|
private(set) var mapWidget: PTRMapWidgetViewController?
|
|
9
11
|
var semaphore: DispatchSemaphore?
|
|
10
12
|
var site: PTRSite?
|
|
11
13
|
|
|
14
|
+
// Adapter to bridge PTRWayfindingEventsHandler (class) to our container callbacks
|
|
15
|
+
private class WayfindingEventsAdapter: PTRWayfindingEventsHandler {
|
|
16
|
+
weak var container: PTRMapWidgetContainerView?
|
|
17
|
+
|
|
18
|
+
init(container: PTRMapWidgetContainerView, mapWidget: PTRMapWidgetViewController) {
|
|
19
|
+
self.container = container
|
|
20
|
+
super.init(mapWidget: mapWidget)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
override func wayfindingDidTapCancel(destination: PTRFeature) {
|
|
24
|
+
print("PTRMapWidget - wayfinding cancelled")
|
|
25
|
+
super.wayfindingDidTapCancel(destination: destination)
|
|
26
|
+
container?.ptrWayfindingEvent(withParameters: ["type": -1, "poi": destination.dict])
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override func wayfindingDidTapClose(destination: PTRFeature) {
|
|
30
|
+
print("PTRMapWidget - wayfinding ended")
|
|
31
|
+
super.wayfindingDidTapClose(destination: destination)
|
|
32
|
+
container?.ptrWayfindingEvent(withParameters: ["type": 1, "poi": destination.dict])
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
func mapWidgetWillPresentWayfinding(_ mapWidget: PTRMapWidgetViewController) {
|
|
37
|
+
switch (mapWidget.layoutState) {
|
|
38
|
+
case .staticWayfinding(_, let destination, _):
|
|
39
|
+
print("PTRMapWidget - wayfinding started. Static path")
|
|
40
|
+
ptrWayfindingEvent(withParameters: ["type": 0, "poi": destination.dict])
|
|
41
|
+
case .wayfinding(let destination, _):
|
|
42
|
+
print("PTRMapWidget - wayfinding started. Dynamic path")
|
|
43
|
+
ptrWayfindingEvent(withParameters: ["type": 0, "poi": destination.dict])
|
|
44
|
+
default:
|
|
45
|
+
print("PTRMapWidget - Widget presented without wayfinding")
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private var wayfindingEventsAdapter: WayfindingEventsAdapter?
|
|
50
|
+
|
|
12
51
|
private let kLayerStaticPath = "static-path"
|
|
13
52
|
|
|
14
53
|
@objc func ptrMapWidgetDidEndLoading(withParameters parameters: [String: Any]) {
|
|
15
54
|
onMapWidgetDidEndLoading?(parameters)
|
|
16
55
|
}
|
|
56
|
+
|
|
57
|
+
@objc func ptrWayfindingEvent(withParameters parameters: [String: Any]) {
|
|
58
|
+
print("PTRMapWidget - Sending wayfinding event \(parameters)")
|
|
59
|
+
onWayfindingEvent?(parameters)
|
|
60
|
+
}
|
|
17
61
|
|
|
18
62
|
@objc func getMapWidget(_ action: PTRMapWidgetAction) -> PTRMapWidgetViewController {
|
|
19
63
|
if PTRNativeLibrary.mapWidgetConfiguration.sdkParams == nil {
|
|
20
64
|
if waitForPointrState() != .running {
|
|
21
|
-
print("Pointr is not running")
|
|
65
|
+
print("PTRMapWidget - Pointr is not running")
|
|
22
66
|
}
|
|
23
67
|
}
|
|
24
|
-
print("initializing map widget")
|
|
25
|
-
mapWidget = PTRMapWidgetViewController(action: action, configuration: PTRNativeLibrary.mapWidgetConfiguration)
|
|
26
|
-
|
|
68
|
+
print("PTRMapWidget - initializing map widget")
|
|
69
|
+
let mapWidget = PTRMapWidgetViewController(action: action, configuration: PTRNativeLibrary.mapWidgetConfiguration)
|
|
70
|
+
self.mapWidget?.removeListener(self)
|
|
71
|
+
self.mapWidget = mapWidget
|
|
72
|
+
let adapter = WayfindingEventsAdapter(container: self, mapWidget: mapWidget)
|
|
73
|
+
self.wayfindingEventsAdapter = adapter
|
|
74
|
+
mapWidget.wayfindingEventsHandler = adapter
|
|
75
|
+
mapWidget.addListener(self)
|
|
76
|
+
return mapWidget
|
|
27
77
|
}
|
|
28
78
|
|
|
29
79
|
@objc func present(_ mapWidget: PTRMapWidgetViewController) {
|
|
@@ -246,3 +296,4 @@ import PointrKit
|
|
|
246
296
|
return Pointr.shared.state
|
|
247
297
|
}
|
|
248
298
|
}
|
|
299
|
+
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
RCT_EXPORT_VIEW_PROPERTY(onMapWidgetDidEndLoading, RCTBubblingEventBlock)
|
|
17
17
|
|
|
18
|
+
RCT_EXPORT_VIEW_PROPERTY(onWayfindingEvent, RCTBubblingEventBlock)
|
|
19
|
+
|
|
18
20
|
RCT_EXTERN_METHOD(site:(nonnull NSNumber *)reactTag
|
|
19
21
|
siteExternalIdentifier:(NSString *)siteExternalIdentifier)
|
|
20
22
|
RCT_EXTERN_METHOD(building:(nonnull NSNumber *)reactTag
|
|
@@ -39,6 +41,11 @@ RCT_EXTERN_METHOD(staticPath:(nonnull NSNumber *)reactTag
|
|
|
39
41
|
fromPoiExternalIdentifier:(NSString *)fromPoiExternalIdentifier
|
|
40
42
|
toPoiExternalIdentifier:(NSString *)toPoiExternalIdentifier)
|
|
41
43
|
|
|
44
|
+
RCT_EXTERN_METHOD(staticWayfinding:(nonnull NSNumber *)reactTag
|
|
45
|
+
siteExternalIdentifier:(NSString *)siteExternalIdentifier
|
|
46
|
+
sourcePoiExternalIdentifier:(NSString *)sourcePoiExternalIdentifier
|
|
47
|
+
destinationPoiExternalIdentifier:(NSString *)destinationPoiExternalIdentifier)
|
|
48
|
+
|
|
42
49
|
RCT_EXTERN_METHOD(markMyCarForLevel:(nonnull NSNumber *)reactTag
|
|
43
50
|
siteExternalIdentifier:(NSString *)siteExternalIdentifier
|
|
44
51
|
buildingExternalIdentifier:(NSString *)buildingExternalIdentifier
|
|
@@ -116,6 +116,34 @@ public class PTRMapWidgetManager: RCTViewManager {
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
@objc func staticWayfinding(_ reactTag: NSNumber, siteExternalIdentifier: String, sourcePoiExternalIdentifier: String, destinationPoiExternalIdentifier: String) {
|
|
120
|
+
self.bridge.uiManager.addUIBlock { (uiManager, viewRegistry) in
|
|
121
|
+
guard let ptrMapWidgetContainerView = uiManager?.view(forReactTag: reactTag) as? PTRMapWidgetContainerView else {
|
|
122
|
+
print("Cannot find PTRMapWidgetContainerView with tag #\(reactTag)")
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let sourcePoiLocation = PTRMapWidgetPoiLocation(siteIdentifier: siteExternalIdentifier, poiIdentifier: sourcePoiExternalIdentifier, isExternalIdentifiers: true)
|
|
127
|
+
let destinationPoiLocation = PTRMapWidgetPoiLocation(siteIdentifier: siteExternalIdentifier, poiIdentifier: destinationPoiExternalIdentifier, isExternalIdentifiers: true)
|
|
128
|
+
|
|
129
|
+
let action = PTRMapWidgetStaticWayfindingAction(poiSource: sourcePoiLocation, poiDestination: destinationPoiLocation)
|
|
130
|
+
action.completion = { error in
|
|
131
|
+
let ptrCommand: [String: Any] = [
|
|
132
|
+
"command": "staticWayfinding",
|
|
133
|
+
"siteExternalIdentifier": siteExternalIdentifier,
|
|
134
|
+
"sourcePoiExternalIdentifier": sourcePoiExternalIdentifier,
|
|
135
|
+
"destinationPoiExternalIdentifier": destinationPoiExternalIdentifier,
|
|
136
|
+
"error": error?.localizedDescription ?? ""
|
|
137
|
+
]
|
|
138
|
+
ptrMapWidgetContainerView.ptrMapWidgetDidEndLoading(withParameters: ptrCommand)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
let mapWidget = ptrMapWidgetContainerView.getMapWidget(action)
|
|
142
|
+
print("calling show static wayfinding method of mapWidget")
|
|
143
|
+
ptrMapWidgetContainerView.present(mapWidget)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
119
147
|
@objc func markMyCarForLevel(_ reactTag: NSNumber, siteExternalIdentifier: String, buildingExternalIdentifier: String, levelIndex: Int, shouldShowPopup: Bool, animationType: Int) {
|
|
120
148
|
self.bridge.uiManager.addUIBlock { (uiManager, viewRegistry) in
|
|
121
149
|
guard let ptrMapWidgetContainerView = uiManager?.view(forReactTag: reactTag) as? PTRMapWidgetContainerView else {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import Foundation
|
|
2
1
|
import PointrKit
|
|
3
2
|
import React
|
|
4
3
|
|
|
@@ -6,6 +5,7 @@ import React
|
|
|
6
5
|
func onPositionManagerCalculatedLocation(location: [String: Any])
|
|
7
6
|
func onBuildingClicked(_ building: [String: Any])
|
|
8
7
|
func onSiteClicked(_ site: [String: Any])
|
|
8
|
+
func onGeofenceEvent(_ geofenceEvent: [String: Any])
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
@objc(PTRNativePointrLibrary)
|
|
@@ -63,7 +63,7 @@ class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
override func supportedEvents() -> [String]! {
|
|
66
|
-
return ["OnPositionManagerCalculatedLocation", "OnBuildingClicked", "OnSiteClicked"]
|
|
66
|
+
return ["OnPositionManagerCalculatedLocation", "OnBuildingClicked", "OnSiteClicked", "OnGeofenceEvent"]
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
override func startObserving() {
|
|
@@ -106,6 +106,48 @@ class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
|
|
|
106
106
|
return dictionary
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
// Converts a PTRGeofenceEvent object to [String: Any] dictionary by extracting its explicit fields
|
|
110
|
+
func convertGeofenceEventToDict(_ geofenceEvent: PTRGeofenceEvent) -> [String: Any] {
|
|
111
|
+
var dictionary = [String: Any]()
|
|
112
|
+
|
|
113
|
+
// Event type
|
|
114
|
+
let typeString = geofenceEvent.type == .enter ? "enter" : "exit"
|
|
115
|
+
dictionary.updateValue(typeString, forKey: "eventType")
|
|
116
|
+
|
|
117
|
+
// Event date (convert to milliseconds)
|
|
118
|
+
dictionary.updateValue(geofenceEvent.date.timeIntervalSince1970 * 1000, forKey: "timestamp")
|
|
119
|
+
|
|
120
|
+
// Geofence information
|
|
121
|
+
var geofenceDict = [String: Any]()
|
|
122
|
+
geofenceDict.updateValue(geofenceEvent.geofence.identifier, forKey: "id")
|
|
123
|
+
geofenceDict.updateValue(geofenceEvent.geofence.externalIdentifier, forKey: "externalId")
|
|
124
|
+
geofenceDict.updateValue(geofenceEvent.geofence.name, forKey: "name")
|
|
125
|
+
|
|
126
|
+
// Geofence type
|
|
127
|
+
let geofenceTypeString = geofenceEvent.geofence.type == .beacon ? "beacon" : "gps"
|
|
128
|
+
geofenceDict.updateValue(geofenceTypeString, forKey: "geofenceType")
|
|
129
|
+
|
|
130
|
+
// Geofence position (if available)
|
|
131
|
+
var positionDict = [String: Any]()
|
|
132
|
+
let position = geofenceEvent.geofence.position
|
|
133
|
+
positionDict.updateValue(position.coordinate.latitude, forKey: "latitude")
|
|
134
|
+
positionDict.updateValue(position.coordinate.longitude, forKey: "longitude")
|
|
135
|
+
geofenceDict.updateValue(positionDict, forKey: "position")
|
|
136
|
+
|
|
137
|
+
dictionary.updateValue(geofenceDict, forKey: "geofence")
|
|
138
|
+
|
|
139
|
+
// Notification information (if available)
|
|
140
|
+
if let notification = geofenceEvent.notification {
|
|
141
|
+
var notificationDict = [String: Any]()
|
|
142
|
+
notificationDict.updateValue(notification.identifier, forKey: "id")
|
|
143
|
+
notificationDict.updateValue(notification.message, forKey: "message")
|
|
144
|
+
notificationDict.updateValue(notification.date.timeIntervalSince1970 * 1000, forKey: "timestamp")
|
|
145
|
+
dictionary.updateValue(notificationDict, forKey: "geofenceNotification")
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return dictionary
|
|
149
|
+
}
|
|
150
|
+
|
|
109
151
|
func getAnimationTypeFromInt(value: Int) -> PTRMapAnimationType {
|
|
110
152
|
switch value {
|
|
111
153
|
case 0:
|
|
@@ -176,6 +218,7 @@ class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
|
|
|
176
218
|
dispatchGroup.wait()
|
|
177
219
|
if Pointr.shared.state == .running {
|
|
178
220
|
Pointr.shared.positioningManager?.addListener(self)
|
|
221
|
+
Pointr.shared.geofenceManager?.addListener(self)
|
|
179
222
|
}
|
|
180
223
|
callback([getPointrStateStringFromPointrState(state: Pointr.shared.state)])
|
|
181
224
|
}
|
|
@@ -183,6 +226,7 @@ class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
|
|
|
183
226
|
|
|
184
227
|
@objc func stop() {
|
|
185
228
|
Pointr.shared.positioningManager?.removeListener(self)
|
|
229
|
+
Pointr.shared.geofenceManager?.removeListener(self)
|
|
186
230
|
Pointr.shared.stop()
|
|
187
231
|
}
|
|
188
232
|
|
|
@@ -265,6 +309,23 @@ class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
|
|
|
265
309
|
callback([])
|
|
266
310
|
}
|
|
267
311
|
|
|
312
|
+
@objc(getPois:resolver:rejecter:)
|
|
313
|
+
func getPois(_ siteId: String,
|
|
314
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
315
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
316
|
+
|
|
317
|
+
// Ensure Pointr SDK is initialized
|
|
318
|
+
guard let site = Pointr.shared.siteManager?.site(withExternalIdentifier: siteId) else {
|
|
319
|
+
reject("ERROR", "Site not found: \(siteId)", nil)
|
|
320
|
+
return
|
|
321
|
+
}
|
|
322
|
+
// Get all POIs for the site
|
|
323
|
+
let pois = Pointr.shared.poiManager?.pois(for: site)?.getPoiList() ?? []
|
|
324
|
+
// Convert POIs to dictionary format (aligned with Kotlin implementation)
|
|
325
|
+
let poisData = pois.map { return $0.dict }
|
|
326
|
+
resolve(poisData)
|
|
327
|
+
}
|
|
328
|
+
|
|
268
329
|
// MARK: - Event Manager Delegate
|
|
269
330
|
|
|
270
331
|
func onPositionManagerCalculatedLocation(location: [String : Any]) {
|
|
@@ -272,6 +333,11 @@ class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
|
|
|
272
333
|
sendEvent(withName: "OnPositionManagerCalculatedLocation", body: location)
|
|
273
334
|
}
|
|
274
335
|
|
|
336
|
+
func onGeofenceEvent(_ geofenceEvent: [String: Any]) {
|
|
337
|
+
guard hasListeners else { return }
|
|
338
|
+
sendEvent(withName: "OnGeofenceEvent", body: geofenceEvent)
|
|
339
|
+
}
|
|
340
|
+
|
|
275
341
|
func onBuildingClicked(_ building: [String : Any]) {
|
|
276
342
|
guard hasListeners else { return }
|
|
277
343
|
sendEvent(withName: "OnBuildingClicked", body: building)
|
|
@@ -290,6 +356,12 @@ extension PTRNativeLibrary: PTRPositioningManagerDelegate {
|
|
|
290
356
|
}
|
|
291
357
|
}
|
|
292
358
|
|
|
359
|
+
extension PTRNativeLibrary: PTRGeofenceManagerDelegate {
|
|
360
|
+
func onGeofenceManagerGeofenceEvent(_ event: PTRGeofenceEvent) {
|
|
361
|
+
eventManagerDelegate?.onGeofenceEvent(self.convertGeofenceEventToDict(event))
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
293
365
|
// MARK: - PTRExitButtonEventsListener
|
|
294
366
|
extension PTRNativeLibrary: PTRExitButtonEventsListener {
|
|
295
367
|
func exitButtonDidTap() {
|
|
@@ -355,3 +427,137 @@ extension PTRNativeLibrary: PTRPermissionManagerDelegate {
|
|
|
355
427
|
return PTRNativeLibrary.shouldRequestPermissionsAtStartup
|
|
356
428
|
}
|
|
357
429
|
}
|
|
430
|
+
|
|
431
|
+
extension PTRFeature {
|
|
432
|
+
public var dict: [String: Any] {
|
|
433
|
+
var result: [String: Any] = [
|
|
434
|
+
"identifier": identifier,
|
|
435
|
+
"externalIdentifier": externalIdentifier,
|
|
436
|
+
"typeCode": typeCode,
|
|
437
|
+
"name": name
|
|
438
|
+
]
|
|
439
|
+
if let geometry = geometry {
|
|
440
|
+
result["geometry"] = geometry.dict
|
|
441
|
+
}
|
|
442
|
+
result["attributes"] = attributes.toDict
|
|
443
|
+
result["position"] = position.dict
|
|
444
|
+
return result
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
extension PTRPosition {
|
|
449
|
+
public var dict: [String: Any] {
|
|
450
|
+
var result: [String: Any] = [
|
|
451
|
+
"lat": coordinate.latitude,
|
|
452
|
+
"lon": coordinate.longitude,
|
|
453
|
+
"isValid": isValid(),
|
|
454
|
+
]
|
|
455
|
+
if let site = site {
|
|
456
|
+
result["sid"] = site.identifier
|
|
457
|
+
}
|
|
458
|
+
if let building = building {
|
|
459
|
+
result["bid"] = building.identifier
|
|
460
|
+
}
|
|
461
|
+
if let level = level {
|
|
462
|
+
result["lvl"] = level.index
|
|
463
|
+
}
|
|
464
|
+
return result
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
private extension Dictionary where Key == String, Value == Any {
|
|
469
|
+
var toDict: [String: Any] {
|
|
470
|
+
var result: [String: Any] = [:]
|
|
471
|
+
for (key, value) in self {
|
|
472
|
+
switch value {
|
|
473
|
+
case let v as Int: result[key] = v
|
|
474
|
+
case let v as Double: result[key] = v
|
|
475
|
+
case let v as Bool: result[key] = v
|
|
476
|
+
case let v as String: result[key] = v
|
|
477
|
+
case let v as [Any]:
|
|
478
|
+
result[key] = v.map { ($0 as? [String: Any])?.toDict ?? $0 }
|
|
479
|
+
case let v as [String: Any]:
|
|
480
|
+
result[key] = v.toDict
|
|
481
|
+
default: break
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
return result
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
extension PTRGeometry {
|
|
489
|
+
|
|
490
|
+
public var typeName : String {
|
|
491
|
+
switch (type) {
|
|
492
|
+
case .circle:
|
|
493
|
+
return "Circle"
|
|
494
|
+
case .multiLineString:
|
|
495
|
+
return "MultiLineString"
|
|
496
|
+
case .multiPoint:
|
|
497
|
+
return "MultiPoint"
|
|
498
|
+
case .multiPolygon:
|
|
499
|
+
return "MultiPolygon"
|
|
500
|
+
case .point:
|
|
501
|
+
return "Point"
|
|
502
|
+
case .polygon:
|
|
503
|
+
return "Polygon"
|
|
504
|
+
case .lineString:
|
|
505
|
+
return "LineString"
|
|
506
|
+
case .geometryCollection:
|
|
507
|
+
return "GeometryCollection"
|
|
508
|
+
@unknown default:
|
|
509
|
+
return "Unknown"
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
public var dict: [String: Any] {
|
|
515
|
+
// Default type name
|
|
516
|
+
var result: [String: Any] = ["type": typeName]
|
|
517
|
+
|
|
518
|
+
// Handle known geometry subclasses from PointrKit
|
|
519
|
+
switch self {
|
|
520
|
+
case let point as PTRGeoPoint:
|
|
521
|
+
// Single coordinate
|
|
522
|
+
let coord = point.coordinate
|
|
523
|
+
result["lat"] = coord.latitude
|
|
524
|
+
result["lon"] = coord.longitude
|
|
525
|
+
|
|
526
|
+
case let line as PTRGeoLineString:
|
|
527
|
+
// Array of coordinates
|
|
528
|
+
let coords = line.points.map { $0.dict }
|
|
529
|
+
result["points"] = coords
|
|
530
|
+
|
|
531
|
+
case let polygon as PTRGeoPolygon:
|
|
532
|
+
// Outer ring + inner rings (holes) if any
|
|
533
|
+
let exterior = polygon.outer.map { $0.dict }
|
|
534
|
+
let holes = polygon.inners.map { ring in
|
|
535
|
+
ring.map { $0.dict }
|
|
536
|
+
}
|
|
537
|
+
result["outer"] = exterior
|
|
538
|
+
result["inners"] = holes
|
|
539
|
+
|
|
540
|
+
case let multiPoint as PTRGeoMultiPoint:
|
|
541
|
+
let coords = multiPoint.points.map { $0.dict }
|
|
542
|
+
result["points"] = coords
|
|
543
|
+
|
|
544
|
+
case let multiLine as PTRGeoMultiLineString:
|
|
545
|
+
let lines = multiLine.lineStrings.map { line in
|
|
546
|
+
line.dict
|
|
547
|
+
}
|
|
548
|
+
result["lineStrings"] = lines
|
|
549
|
+
|
|
550
|
+
case let multiPolygon as PTRGeoMultiPolygon:
|
|
551
|
+
let polys = multiPolygon.polygons.map { poly in
|
|
552
|
+
poly.dict
|
|
553
|
+
}
|
|
554
|
+
result["polygons"] = polys
|
|
555
|
+
|
|
556
|
+
default:
|
|
557
|
+
// Unknown geometry type; keep only the type string
|
|
558
|
+
break
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return result
|
|
562
|
+
}
|
|
563
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-pointr",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.5.0",
|
|
4
4
|
"description": "Pointr React-Native Module",
|
|
5
5
|
"main": "src/index",
|
|
6
6
|
"author": " <> ()",
|
|
@@ -10,5 +10,19 @@
|
|
|
10
10
|
"type": "module-legacy",
|
|
11
11
|
"languages": "kotlin-swift",
|
|
12
12
|
"version": "0.41.0"
|
|
13
|
+
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"react-native": ">=0.64.0",
|
|
16
|
+
"react": ">=17.0.0"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^24.10.1",
|
|
20
|
+
"react-native": "^0.82.1"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=20"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"prepare-dist": "chmod +x prepare-distribution.sh && ./prepare-distribution.sh"
|
|
13
27
|
}
|
|
14
|
-
}
|
|
28
|
+
}
|