react-native-pointr 9.2.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.
- package/API_REFERENCE.md +887 -0
- package/CHANGELOG.md +35 -0
- package/EXTENDING.md +419 -0
- package/README.md +221 -117
- package/WAYFINDING_EVENTS.md +243 -0
- package/android/build.gradle +3 -4
- 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 +73 -11
- 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 +32 -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/Podfile.lock +2767 -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 +496 -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-lock.json +11747 -0
- package/example/pointr_rn_demo/package.json +46 -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 +84 -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
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,41 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [9.3.1] - 2026-01-07
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- **POI Management API**: New `getPois(siteId)` method to retrieve all Points of Interest for a specific site
|
|
11
|
+
- **Geofence Events**: Added `OnGeofenceEvent` listener for geofence enter/exit notifications
|
|
12
|
+
- Supports both beacon and GPS geofence types
|
|
13
|
+
- Includes position data and optional notification messages
|
|
14
|
+
- Available on both iOS and Android platforms
|
|
15
|
+
- **TypeScript Types**: Complete type definitions for better IDE support
|
|
16
|
+
- `PTRPoi` - Point of Interest data structure
|
|
17
|
+
- `PTRPosition` - Geographic position with site/building/level info
|
|
18
|
+
- `PTRGeometry` - Geometry types (Point, Polygon, LineString, Circle, etc.)
|
|
19
|
+
- `PTRWayfindingEvent` - Wayfinding navigation events
|
|
20
|
+
- `PTRPoiAttributes` - POI metadata and attributes
|
|
21
|
+
- **Module Exports**: Enhanced ES6 module exports
|
|
22
|
+
- Named exports for all commands, types, and utilities
|
|
23
|
+
- Default export maintains backward compatibility
|
|
24
|
+
- Tree-shaking support for optimized bundle sizes
|
|
25
|
+
- **POI Manager**: New `PTRPoiManager` utility module for POI operations
|
|
26
|
+
- **Platform Extensions**: Native extensions for iOS and Android
|
|
27
|
+
- iOS: `PTRFeature`, `PTRPosition` dictionary conversions
|
|
28
|
+
- Android: `PTRCoreExtensions` with Kotlin extension methods
|
|
29
|
+
- Distribution preparation script (`prepare-distribution.sh`) for creating clean, distributable package archives
|
|
30
|
+
- `prepare-dist` npm script for easy package distribution preparation
|
|
31
|
+
- Automated cleanup of build artifacts, git history, and development files during distribution
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
- **Event Listeners**: Geofence manager listeners now registered in `start()` and removed in `stop()`
|
|
35
|
+
- **Module Structure**: Migrated from CommonJS to ES6 module exports
|
|
36
|
+
- **iOS Implementation**: Improved Swift code organization and type safety
|
|
37
|
+
- **Android Implementation**: Enhanced Kotlin code with extension methods
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
- None.
|
|
41
|
+
|
|
7
42
|
## [8.16.1]
|
|
8
43
|
|
|
9
44
|
## Updates
|
package/EXTENDING.md
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
# Extending react-native-pointr Package
|
|
2
|
+
|
|
3
|
+
This guide demonstrates how to extend the functionality of the `react-native-pointr` package by adding new features. We'll use implementing a `getPois` function as an example to show the complete process of adding new functionality.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Extending the package involves three main steps:
|
|
8
|
+
|
|
9
|
+
1. **Add native code** - Implement the functionality in both iOS (Swift/Objective-C) and Android (Kotlin/Java)
|
|
10
|
+
2. **Create TypeScript interfaces** - Define types and interfaces for the new functionality
|
|
11
|
+
3. **Expose to JavaScript** - Make the functionality accessible from React Native
|
|
12
|
+
|
|
13
|
+
## Example: Adding getPois Functionality
|
|
14
|
+
|
|
15
|
+
This example shows how to add a function that retrieves all Points of Interest (POIs) for a specific site.
|
|
16
|
+
|
|
17
|
+
### Step 1: Add Native Implementation
|
|
18
|
+
|
|
19
|
+
#### iOS Implementation
|
|
20
|
+
|
|
21
|
+
**File: `ios/PTRNativePointrLibrary.swift`**
|
|
22
|
+
|
|
23
|
+
Add the following method to your native iOS module:
|
|
24
|
+
|
|
25
|
+
```swift
|
|
26
|
+
@objc(getPois:resolver:rejecter:)
|
|
27
|
+
func getPois(_ siteId: String,
|
|
28
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
29
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
30
|
+
|
|
31
|
+
// Ensure Pointr SDK is initialized
|
|
32
|
+
guard let site = Pointr.shared.getSite(withExternalIdentifier: siteId) else {
|
|
33
|
+
reject("ERROR", "Site not found: \(siteId)", nil)
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Get all POIs for the site
|
|
38
|
+
let pois = site.getAllPois()
|
|
39
|
+
|
|
40
|
+
// Convert POIs to dictionary format
|
|
41
|
+
let poisData = pois.map { poi -> [String: Any] in
|
|
42
|
+
return [
|
|
43
|
+
"id": poi.externalIdentifier,
|
|
44
|
+
"name": poi.name ?? "",
|
|
45
|
+
"buildingId": poi.building?.externalIdentifier ?? "",
|
|
46
|
+
"levelIndex": poi.level?.index ?? 0,
|
|
47
|
+
"category": poi.category ?? "",
|
|
48
|
+
"latitude": poi.coordinate.latitude,
|
|
49
|
+
"longitude": poi.coordinate.longitude
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
resolve(poisData)
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**File: `ios/PTRNativePointrLibrary.m`**
|
|
58
|
+
|
|
59
|
+
Add the method declaration to the bridge:
|
|
60
|
+
|
|
61
|
+
```objective-c
|
|
62
|
+
RCT_EXTERN_METHOD(getPois:(NSString *)siteId
|
|
63
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
64
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### Android Implementation
|
|
68
|
+
|
|
69
|
+
**File: `android/src/main/java/com/reactnativepointr/PTRNativePointrLibraryModule.kt`**
|
|
70
|
+
|
|
71
|
+
Add the following method to your native Android module:
|
|
72
|
+
|
|
73
|
+
```kotlin
|
|
74
|
+
@ReactMethod
|
|
75
|
+
fun getPois(siteId: String, promise: Promise) {
|
|
76
|
+
try {
|
|
77
|
+
// Ensure Pointr SDK is initialized
|
|
78
|
+
val site = Pointr.getSite(siteId)
|
|
79
|
+
|
|
80
|
+
if (site == null) {
|
|
81
|
+
promise.reject("ERROR", "Site not found: $siteId")
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Get all POIs for the site
|
|
86
|
+
val pois = site.getAllPois()
|
|
87
|
+
|
|
88
|
+
// Convert POIs to WritableArray
|
|
89
|
+
val poisArray = Arguments.createArray()
|
|
90
|
+
|
|
91
|
+
pois.forEach { poi ->
|
|
92
|
+
val poiMap = Arguments.createMap().apply {
|
|
93
|
+
putString("id", poi.externalIdentifier)
|
|
94
|
+
putString("name", poi.name ?: "")
|
|
95
|
+
putString("buildingId", poi.building?.externalIdentifier ?: "")
|
|
96
|
+
putInt("levelIndex", poi.level?.index ?: 0)
|
|
97
|
+
putString("category", poi.category ?: "")
|
|
98
|
+
putDouble("latitude", poi.coordinate.latitude)
|
|
99
|
+
putDouble("longitude", poi.coordinate.longitude)
|
|
100
|
+
}
|
|
101
|
+
poisArray.pushMap(poiMap)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
promise.resolve(poisArray)
|
|
105
|
+
|
|
106
|
+
} catch (e: Exception) {
|
|
107
|
+
promise.reject("ERROR", "Failed to get POIs: ${e.message}", e)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Step 2: Create TypeScript Interfaces
|
|
113
|
+
|
|
114
|
+
**File: `src/types/PTRPoi.ts`**
|
|
115
|
+
|
|
116
|
+
Create a new file to define the POI type:
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
/**
|
|
120
|
+
* Point of Interest (POI) data structure
|
|
121
|
+
*/
|
|
122
|
+
export interface PTRPoi {
|
|
123
|
+
/** Unique identifier for the POI */
|
|
124
|
+
id: string;
|
|
125
|
+
|
|
126
|
+
/** Display name of the POI */
|
|
127
|
+
name: string;
|
|
128
|
+
|
|
129
|
+
/** Building identifier where the POI is located */
|
|
130
|
+
buildingId: string;
|
|
131
|
+
|
|
132
|
+
/** Level/floor index where the POI is located */
|
|
133
|
+
levelIndex: number;
|
|
134
|
+
|
|
135
|
+
/** Category or type of the POI */
|
|
136
|
+
category: string;
|
|
137
|
+
|
|
138
|
+
/** Latitude coordinate */
|
|
139
|
+
latitude: number;
|
|
140
|
+
|
|
141
|
+
/** Longitude coordinate */
|
|
142
|
+
longitude: number;
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Step 3: Create JavaScript Wrapper
|
|
147
|
+
|
|
148
|
+
**File: `src/PTRNativePointrLibrary.ts`**
|
|
149
|
+
|
|
150
|
+
Create a wrapper function that provides a clean API:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { NativeModules } from 'react-native';
|
|
154
|
+
import { PTRPoi } from './types/PTRPoi';
|
|
155
|
+
|
|
156
|
+
const { PTRNativePointrLibrary } = NativeModules;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get all Points of Interest (POIs) for a specific site
|
|
160
|
+
* @param siteId - The external identifier of the site
|
|
161
|
+
* @returns Promise that resolves with an array of POIs
|
|
162
|
+
* @throws Error if the site is not found or if the operation fails
|
|
163
|
+
*/
|
|
164
|
+
export async function getPois(siteId: string): Promise<PTRPoi[]> {
|
|
165
|
+
try {
|
|
166
|
+
const pois = await PTRNativePointrLibrary.getPois(siteId);
|
|
167
|
+
return pois as PTRPoi[];
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.error('Failed to get POIs:', error);
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Step 4: Export the New Functionality
|
|
176
|
+
|
|
177
|
+
**File: `src/index.ts`**
|
|
178
|
+
|
|
179
|
+
Export the new functions and types from the main entry point:
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
// Existing exports
|
|
183
|
+
export * from './PTRCommand';
|
|
184
|
+
export * from './PTRMapWidgetUtils';
|
|
185
|
+
|
|
186
|
+
// New exports
|
|
187
|
+
export { getPois } from './PTRNativePointrLibrary';
|
|
188
|
+
export type { PTRPoi } from './types/PTRPoi';
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Step 5: Usage Example
|
|
192
|
+
|
|
193
|
+
Now you can use the new functionality in your React Native app:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import React, { useState, useEffect } from 'react';
|
|
197
|
+
import { View, Text, FlatList, ActivityIndicator } from 'react-native';
|
|
198
|
+
import { getPois, PTRPoi } from 'react-native-pointr';
|
|
199
|
+
|
|
200
|
+
function PoiListScreen() {
|
|
201
|
+
const [pois, setPois] = useState<PTRPoi[]>([]);
|
|
202
|
+
const [loading, setLoading] = useState(true);
|
|
203
|
+
const [error, setError] = useState<string | null>(null);
|
|
204
|
+
|
|
205
|
+
useEffect(() => {
|
|
206
|
+
loadPois();
|
|
207
|
+
}, []);
|
|
208
|
+
|
|
209
|
+
const loadPois = async () => {
|
|
210
|
+
try {
|
|
211
|
+
setLoading(true);
|
|
212
|
+
const siteId = 'your-site-id';
|
|
213
|
+
const poisData = await getPois(siteId);
|
|
214
|
+
setPois(poisData);
|
|
215
|
+
setError(null);
|
|
216
|
+
} catch (err) {
|
|
217
|
+
setError(err instanceof Error ? err.message : 'Failed to load POIs');
|
|
218
|
+
console.error('Error loading POIs:', err);
|
|
219
|
+
} finally {
|
|
220
|
+
setLoading(false);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
if (loading) {
|
|
225
|
+
return (
|
|
226
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
227
|
+
<ActivityIndicator size="large" />
|
|
228
|
+
<Text>Loading POIs...</Text>
|
|
229
|
+
</View>
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (error) {
|
|
234
|
+
return (
|
|
235
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
236
|
+
<Text style={{ color: 'red' }}>Error: {error}</Text>
|
|
237
|
+
</View>
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return (
|
|
242
|
+
<FlatList
|
|
243
|
+
data={pois}
|
|
244
|
+
keyExtractor={(item) => item.id}
|
|
245
|
+
renderItem={({ item }) => (
|
|
246
|
+
<View style={{ padding: 16, borderBottomWidth: 1, borderColor: '#ccc' }}>
|
|
247
|
+
<Text style={{ fontSize: 18, fontWeight: 'bold' }}>{item.name}</Text>
|
|
248
|
+
<Text>Category: {item.category}</Text>
|
|
249
|
+
<Text>Building: {item.buildingId}</Text>
|
|
250
|
+
<Text>Level: {item.levelIndex}</Text>
|
|
251
|
+
<Text>
|
|
252
|
+
Location: {item.latitude.toFixed(6)}, {item.longitude.toFixed(6)}
|
|
253
|
+
</Text>
|
|
254
|
+
</View>
|
|
255
|
+
)}
|
|
256
|
+
/>
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export default PoiListScreen;
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Best Practices for Extensions
|
|
264
|
+
|
|
265
|
+
### 1. Type Safety
|
|
266
|
+
|
|
267
|
+
Always define TypeScript interfaces for data structures:
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
export interface PTRCustomData {
|
|
271
|
+
id: string;
|
|
272
|
+
value: any;
|
|
273
|
+
// Add proper types
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### 2. Error Handling
|
|
278
|
+
|
|
279
|
+
Implement comprehensive error handling in both native and JavaScript code:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
try {
|
|
283
|
+
const result = await nativeModule.someMethod();
|
|
284
|
+
return result;
|
|
285
|
+
} catch (error) {
|
|
286
|
+
console.error('Operation failed:', error);
|
|
287
|
+
throw new Error(`Failed to execute: ${error.message}`);
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### 3. Promise-based APIs
|
|
292
|
+
|
|
293
|
+
Use Promises for asynchronous operations to provide a consistent API:
|
|
294
|
+
|
|
295
|
+
```swift
|
|
296
|
+
// iOS
|
|
297
|
+
@objc(someAsyncMethod:resolver:rejecter:)
|
|
298
|
+
func someAsyncMethod(_ param: String,
|
|
299
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
300
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
301
|
+
// Implementation
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
```kotlin
|
|
306
|
+
// Android
|
|
307
|
+
@ReactMethod
|
|
308
|
+
fun someAsyncMethod(param: String, promise: Promise) {
|
|
309
|
+
// Implementation
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### 4. Documentation
|
|
314
|
+
|
|
315
|
+
Document all new functionality with JSDoc comments:
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
/**
|
|
319
|
+
* Description of what the function does
|
|
320
|
+
* @param paramName - Description of the parameter
|
|
321
|
+
* @returns Description of what is returned
|
|
322
|
+
* @throws Description of potential errors
|
|
323
|
+
* @example
|
|
324
|
+
* ```typescript
|
|
325
|
+
* const result = await someFunction('value');
|
|
326
|
+
* ```
|
|
327
|
+
*/
|
|
328
|
+
export async function someFunction(paramName: string): Promise<ResultType> {
|
|
329
|
+
// Implementation
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### 5. Testing
|
|
334
|
+
|
|
335
|
+
Create test cases for new functionality:
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
import { getPois } from 'react-native-pointr';
|
|
339
|
+
|
|
340
|
+
describe('getPois', () => {
|
|
341
|
+
it('should return an array of POIs', async () => {
|
|
342
|
+
const pois = await getPois('test-site-id');
|
|
343
|
+
expect(Array.isArray(pois)).toBe(true);
|
|
344
|
+
expect(pois.length).toBeGreaterThan(0);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('should throw error for invalid site', async () => {
|
|
348
|
+
await expect(getPois('invalid-site')).rejects.toThrow();
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### 6. Platform Consistency
|
|
354
|
+
|
|
355
|
+
Ensure both iOS and Android implementations return the same data structure:
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
// Both platforms should return identical structure
|
|
359
|
+
{
|
|
360
|
+
id: string;
|
|
361
|
+
name: string;
|
|
362
|
+
// Same fields with same types
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Adding Event Listeners
|
|
367
|
+
|
|
368
|
+
For continuous data streams or callbacks, use event emitters:
|
|
369
|
+
|
|
370
|
+
### Native Side (iOS)
|
|
371
|
+
|
|
372
|
+
```swift
|
|
373
|
+
@objc
|
|
374
|
+
func sendEvent(_ name: String, body: Any) {
|
|
375
|
+
sendEvent(withName: name, body: body)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
override func supportedEvents() -> [String]! {
|
|
379
|
+
return ["onLocationUpdate", "onPoiEnter"]
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Native Side (Android)
|
|
384
|
+
|
|
385
|
+
```kotlin
|
|
386
|
+
private fun sendEvent(eventName: String, params: WritableMap?) {
|
|
387
|
+
reactContext
|
|
388
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
389
|
+
.emit(eventName, params)
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### JavaScript Side
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
import { NativeEventEmitter, NativeModules } from 'react-native';
|
|
397
|
+
|
|
398
|
+
const { PTRNativePointrLibrary } = NativeModules;
|
|
399
|
+
const eventEmitter = new NativeEventEmitter(PTRNativePointrLibrary);
|
|
400
|
+
|
|
401
|
+
export function subscribeToLocationUpdates(
|
|
402
|
+
callback: (location: PTRLocation) => void
|
|
403
|
+
): () => void {
|
|
404
|
+
const subscription = eventEmitter.addListener('onLocationUpdate', callback);
|
|
405
|
+
return () => subscription.remove();
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
## Conclusion
|
|
410
|
+
|
|
411
|
+
Extending the `react-native-pointr` package follows a consistent pattern:
|
|
412
|
+
|
|
413
|
+
1. Implement native functionality on both platforms
|
|
414
|
+
2. Define TypeScript types
|
|
415
|
+
3. Create JavaScript wrappers
|
|
416
|
+
4. Export from the package
|
|
417
|
+
5. Document and test
|
|
418
|
+
|
|
419
|
+
This approach ensures a maintainable, type-safe, and platform-consistent API for your React Native application.
|