@wayq/beekon-rn 0.0.1 → 0.0.3
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/BeekonRn.podspec +3 -3
- package/README.md +24 -30
- package/android/build.gradle +3 -3
- package/android/src/main/java/in/wayq/beekonrn/BeekonRnModule.kt +182 -0
- package/android/src/main/java/{com → in}/wayq/beekonrn/BeekonRnPackage.kt +1 -1
- package/ios/BeekonRn.h +5 -1
- package/ios/BeekonRn.mm +15 -25
- package/ios/BeekonRn.swift +96 -116
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeDirectory +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeResources +105 -42
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeSignature +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/BeekonKit +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/Info.plist +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios.abi.json +2427 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios.swiftinterface +85 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/PrivacyInfo.xcprivacy +1 -1
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/_CodeSignature/CodeResources +36 -3
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/BeekonKit +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Info.plist +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios-simulator.abi.json +2427 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/arm64-apple-ios-simulator.swiftinterface +85 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/x86_64-apple-ios-simulator.abi.json +2427 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +85 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/PrivacyInfo.xcprivacy +1 -1
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/_CodeSignature/CodeResources +69 -3
- package/lib/module/NativeBeekonRn.js +2 -2
- package/lib/module/NativeBeekonRn.js.map +1 -1
- package/lib/module/beekon.js +50 -53
- package/lib/module/beekon.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/internal/mappers.js +49 -21
- package/lib/module/internal/mappers.js.map +1 -1
- package/lib/module/types/config.js +0 -2
- package/lib/module/types/error.js +19 -0
- package/lib/module/types/error.js.map +1 -0
- package/lib/module/types/location.js +2 -0
- package/lib/module/types/{position.js.map → location.js.map} +1 -1
- package/lib/typescript/src/NativeBeekonRn.d.ts +22 -26
- package/lib/typescript/src/NativeBeekonRn.d.ts.map +1 -1
- package/lib/typescript/src/beekon.d.ts +29 -42
- package/lib/typescript/src/beekon.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/internal/mappers.d.ts +10 -3
- package/lib/typescript/src/internal/mappers.d.ts.map +1 -1
- package/lib/typescript/src/types/config.d.ts +23 -31
- package/lib/typescript/src/types/config.d.ts.map +1 -1
- package/lib/typescript/src/types/error.d.ts +14 -0
- package/lib/typescript/src/types/error.d.ts.map +1 -0
- package/lib/typescript/src/types/location.d.ts +26 -0
- package/lib/typescript/src/types/location.d.ts.map +1 -0
- package/lib/typescript/src/types/state.d.ts +9 -9
- package/lib/typescript/src/types/state.d.ts.map +1 -1
- package/package.json +2 -2
- package/scripts/fetch-beekonkit.sh +5 -2
- package/src/NativeBeekonRn.ts +22 -26
- package/src/beekon.ts +58 -56
- package/src/index.tsx +3 -3
- package/src/internal/mappers.ts +52 -18
- package/src/types/config.ts +23 -32
- package/src/types/error.ts +22 -0
- package/src/types/location.ts +25 -0
- package/src/types/state.ts +13 -7
- package/android/src/main/java/com/wayq/beekonrn/BeekonRnModule.kt +0 -233
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeRequirements-1 +0 -0
- package/lib/module/types/position.js +0 -2
- package/lib/module/types/preset.js +0 -2
- package/lib/module/types/preset.js.map +0 -1
- package/lib/typescript/src/types/position.d.ts +0 -24
- package/lib/typescript/src/types/position.d.ts.map +0 -1
- package/lib/typescript/src/types/preset.d.ts +0 -12
- package/lib/typescript/src/types/preset.d.ts.map +0 -1
- package/src/types/position.ts +0 -23
- package/src/types/preset.ts +0 -11
package/BeekonRn.podspec
CHANGED
|
@@ -10,9 +10,9 @@ Pod::Spec.new do |s|
|
|
|
10
10
|
s.license = package["license"]
|
|
11
11
|
s.authors = package["author"]
|
|
12
12
|
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
s.platforms = { :ios => "
|
|
13
|
+
# BeekonKit targets iOS 17.0 (uses CLLocationUpdate.liveUpdates). The
|
|
14
|
+
# consuming app must also target iOS 17.0 or higher.
|
|
15
|
+
s.platforms = { :ios => "17.0" }
|
|
16
16
|
s.source = { :git => "https://github.com/wayqteam/beekon.git", :tag => "v#{s.version}" }
|
|
17
17
|
|
|
18
18
|
s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
|
package/README.md
CHANGED
|
@@ -2,19 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
React Native binding for the [Beekon](https://github.com/wayqteam/beekon) location SDK.
|
|
4
4
|
|
|
5
|
-
A thin pass-through over the native Android (`io.github.wayqteam:beekon`) and iOS (`BeekonKit`) libraries. The public TypeScript surface mirrors the Kotlin / Swift
|
|
5
|
+
A thin pass-through over the native Android (`io.github.wayqteam:beekon`) and iOS (`BeekonKit`) libraries. The public TypeScript surface mirrors the Kotlin / Swift APIs in shape: `configure / start / stop`, callback-backed `state` and `locations` streams, and a `history(from, to)` query.
|
|
6
6
|
|
|
7
|
-
Built on the React Native New Architecture (TurboModules + Codegen). The binding is a thin delegation layer — all logic, persistence, and OS integration lives natively. **Writes never cross into JavaScript**: in background the JS engine isn't guaranteed to be alive, so the native libraries own the persistence path end-to-end
|
|
8
|
-
|
|
9
|
-
See [`../docs/REQUIREMENTS.md`](../docs/REQUIREMENTS.md) for the full cross-platform spec.
|
|
7
|
+
Built on the React Native New Architecture (TurboModules + Codegen). The binding is a thin delegation layer — all logic, persistence, and OS integration lives natively. **Writes never cross into JavaScript**: in background the JS engine isn't guaranteed to be alive, so the native libraries own the persistence path end-to-end.
|
|
10
8
|
|
|
11
9
|
## Requirements
|
|
12
10
|
|
|
13
11
|
| Area | Floor |
|
|
14
12
|
|---|---|
|
|
15
13
|
| React Native | 0.76+ (target 0.85) |
|
|
16
|
-
| iOS |
|
|
17
|
-
| Android | API
|
|
14
|
+
| iOS | 17.0 |
|
|
15
|
+
| Android | API 26 |
|
|
18
16
|
| New Architecture | required (Old Arch is unsupported) |
|
|
19
17
|
|
|
20
18
|
## Install
|
|
@@ -63,22 +61,18 @@ The library does NOT request permissions itself — your app must. Use a library
|
|
|
63
61
|
## Usage
|
|
64
62
|
|
|
65
63
|
```ts
|
|
66
|
-
import { Beekon, type BeekonState, type
|
|
64
|
+
import { Beekon, type BeekonState, type Location } from '@wayq/beekon-rn';
|
|
67
65
|
|
|
68
|
-
// Subscribe — returns an unsubscribe function.
|
|
66
|
+
// Subscribe — returns an unsubscribe function. State replays the latest value
|
|
67
|
+
// to new subscribers; locations is broadcast (no replay).
|
|
69
68
|
const offState = Beekon.onState((s: BeekonState) => console.log('state', s));
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
// Initialize once at startup.
|
|
73
|
-
await Beekon.init();
|
|
69
|
+
const offLoc = Beekon.onLocation((l: Location) => console.log('location', l));
|
|
74
70
|
|
|
75
|
-
// Configure
|
|
71
|
+
// Configure. Defaults: 30 s / 100 m. Pass 0 to disable a gate.
|
|
76
72
|
await Beekon.configure({
|
|
77
|
-
|
|
73
|
+
intervalSeconds: 10,
|
|
74
|
+
distanceMeters: 30,
|
|
78
75
|
androidNotification: {
|
|
79
|
-
channelId: 'beekon_tracking',
|
|
80
|
-
channelName: 'Beekon location tracking',
|
|
81
|
-
notificationId: 1001,
|
|
82
76
|
title: 'Tracking',
|
|
83
77
|
text: 'Recording your route',
|
|
84
78
|
smallIconResName: 'ic_notification', // drawable in your app
|
|
@@ -89,33 +83,33 @@ await Beekon.start();
|
|
|
89
83
|
// ... later
|
|
90
84
|
await Beekon.stop();
|
|
91
85
|
|
|
92
|
-
// Read past
|
|
93
|
-
const
|
|
86
|
+
// Read past fixes.
|
|
87
|
+
const fixes = await Beekon.history(new Date(Date.now() - 3600_000), new Date());
|
|
94
88
|
|
|
95
89
|
// Cleanup.
|
|
96
90
|
offState();
|
|
97
|
-
|
|
91
|
+
offLoc();
|
|
98
92
|
```
|
|
99
93
|
|
|
100
94
|
## API
|
|
101
95
|
|
|
102
96
|
| Method | Description |
|
|
103
97
|
|---|---|
|
|
104
|
-
| `Beekon.
|
|
105
|
-
| `Beekon.
|
|
106
|
-
| `Beekon.
|
|
107
|
-
| `Beekon.
|
|
108
|
-
| `Beekon.shutdown()` | Final teardown. Most apps don't need this. |
|
|
109
|
-
| `Beekon.history(from, to)` | Read persisted positions in range. |
|
|
98
|
+
| `Beekon.configure(config)` | Set sampling thresholds. Optional. |
|
|
99
|
+
| `Beekon.start()` | Begin tracking. State → `tracking`. |
|
|
100
|
+
| `Beekon.stop()` | Stop tracking. Idempotent. State → `stopped` (`reason: 'user'`). |
|
|
101
|
+
| `Beekon.history(from, to)` | Read persisted fixes in range. |
|
|
110
102
|
| `Beekon.onState(cb)` | Subscribe to state. Returns unsubscribe fn. |
|
|
111
|
-
| `Beekon.
|
|
103
|
+
| `Beekon.onLocation(cb)` | Subscribe to gated fixes. Returns unsubscribe fn. |
|
|
104
|
+
|
|
105
|
+
State is a discriminated union on `kind`: `'idle' | 'tracking' | 'stopped'`. The `'stopped'` variant carries a `reason: 'user' | 'permissionDenied' | 'locationServicesDisabled' | 'system'` (`'system'` is Android-only).
|
|
112
106
|
|
|
113
|
-
Errors are thrown as `
|
|
114
|
-
`
|
|
107
|
+
Errors are thrown as `BeekonError` instances with `kind`:
|
|
108
|
+
`'permissionDenied'`, `'locationServicesDisabled'`, `'storageFailure'`.
|
|
115
109
|
|
|
116
110
|
## Storage and retention
|
|
117
111
|
|
|
118
|
-
The native SDKs persist every gated
|
|
112
|
+
The native SDKs persist every gated fix locally (Room on Android, GRDB on iOS) — JS is a passive reader. Retention: **TTL 7 days OR most recent 100 K rows**, whichever is smaller; auto-pruned on each write batch.
|
|
119
113
|
|
|
120
114
|
## License
|
|
121
115
|
|
package/android/build.gradle
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
buildscript {
|
|
2
2
|
ext.BeekonRn = [
|
|
3
|
-
kotlinVersion: "2.
|
|
3
|
+
kotlinVersion: "2.1.20",
|
|
4
4
|
minSdkVersion: 24,
|
|
5
5
|
compileSdkVersion: 36,
|
|
6
6
|
targetSdkVersion: 36
|
|
@@ -33,7 +33,7 @@ apply plugin: "kotlin-android"
|
|
|
33
33
|
apply plugin: "com.facebook.react"
|
|
34
34
|
|
|
35
35
|
android {
|
|
36
|
-
namespace "
|
|
36
|
+
namespace "in.wayq.beekonrn"
|
|
37
37
|
|
|
38
38
|
compileSdkVersion getExtOrDefault("compileSdkVersion")
|
|
39
39
|
|
|
@@ -72,7 +72,7 @@ dependencies {
|
|
|
72
72
|
// Native Beekon SDK — published from beekon-android/ via Maven Central.
|
|
73
73
|
// Pinned exact in v0.x to avoid surprise breakage; loosen to a range when
|
|
74
74
|
// the SDK reaches v1 stability.
|
|
75
|
-
implementation "io.github.wayqteam:beekon:0.0.
|
|
75
|
+
implementation "io.github.wayqteam:beekon:0.0.3"
|
|
76
76
|
// Kotlin coroutines — required for collecting Beekon's StateFlow/SharedFlow.
|
|
77
77
|
// Beekon already depends on coroutines transitively, but declaring it here
|
|
78
78
|
// makes the dependency intent explicit.
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
package `in`.wayq.beekonrn
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.Promise
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.bridge.ReadableMap
|
|
7
|
+
import com.facebook.react.bridge.WritableArray
|
|
8
|
+
import com.facebook.react.bridge.WritableMap
|
|
9
|
+
import `in`.wayq.beekon.Beekon
|
|
10
|
+
import `in`.wayq.beekon.BeekonConfig
|
|
11
|
+
import `in`.wayq.beekon.BeekonError
|
|
12
|
+
import `in`.wayq.beekon.BeekonState
|
|
13
|
+
import `in`.wayq.beekon.Location
|
|
14
|
+
import `in`.wayq.beekon.StopReason
|
|
15
|
+
import java.time.Instant
|
|
16
|
+
import kotlinx.coroutines.CoroutineScope
|
|
17
|
+
import kotlinx.coroutines.Dispatchers
|
|
18
|
+
import kotlinx.coroutines.Job
|
|
19
|
+
import kotlinx.coroutines.SupervisorJob
|
|
20
|
+
import kotlinx.coroutines.cancel
|
|
21
|
+
import kotlinx.coroutines.launch
|
|
22
|
+
|
|
23
|
+
class BeekonRnModule(private val reactContext: ReactApplicationContext) :
|
|
24
|
+
NativeBeekonRnSpec(reactContext) {
|
|
25
|
+
|
|
26
|
+
// Default dispatcher (not Main.immediate) — Codegen's emitOnX is thread-safe
|
|
27
|
+
// and marshals to JS internally, so collecting on Main buys nothing and
|
|
28
|
+
// risks jank if any mapper does work. SupervisorJob so a single failure
|
|
29
|
+
// doesn't tear down siblings.
|
|
30
|
+
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
|
31
|
+
private var stateJob: Job? = null
|
|
32
|
+
private var locationsJob: Job? = null
|
|
33
|
+
|
|
34
|
+
init {
|
|
35
|
+
// Beekon.initialize is idempotent and does not start tracking. Safe to call
|
|
36
|
+
// from module construction — the application context is already alive.
|
|
37
|
+
Beekon.initialize(reactContext.applicationContext)
|
|
38
|
+
stateJob = scope.launch {
|
|
39
|
+
Beekon.state.collect { s -> emitOnState(stateToWire(s)) }
|
|
40
|
+
}
|
|
41
|
+
locationsJob = scope.launch {
|
|
42
|
+
Beekon.locations.collect { loc -> emitOnLocation(locationToWire(loc)) }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
override fun configure(config: ReadableMap, promise: Promise) {
|
|
47
|
+
scope.launch {
|
|
48
|
+
try {
|
|
49
|
+
Beekon.configure(wireToConfig(config))
|
|
50
|
+
promise.resolve(null)
|
|
51
|
+
} catch (t: Throwable) {
|
|
52
|
+
promise.reject(errorCode(t), t.message ?: "configure failed", t)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
override fun start(promise: Promise) {
|
|
58
|
+
scope.launch {
|
|
59
|
+
try {
|
|
60
|
+
Beekon.start()
|
|
61
|
+
promise.resolve(null)
|
|
62
|
+
} catch (t: Throwable) {
|
|
63
|
+
promise.reject(errorCode(t), t.message ?: "start failed", t)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
override fun stop(promise: Promise) {
|
|
69
|
+
scope.launch {
|
|
70
|
+
try {
|
|
71
|
+
Beekon.stop()
|
|
72
|
+
promise.resolve(null)
|
|
73
|
+
} catch (t: Throwable) {
|
|
74
|
+
promise.reject(errorCode(t), t.message ?: "stop failed", t)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
override fun history(fromMs: Double, toMs: Double, promise: Promise) {
|
|
80
|
+
scope.launch {
|
|
81
|
+
try {
|
|
82
|
+
val from = Instant.ofEpochMilli(fromMs.toLong())
|
|
83
|
+
val to = Instant.ofEpochMilli(toMs.toLong())
|
|
84
|
+
val locations = Beekon.history(from, to)
|
|
85
|
+
val arr: WritableArray = Arguments.createArray()
|
|
86
|
+
for (loc in locations) arr.pushMap(locationToWire(loc))
|
|
87
|
+
promise.resolve(arr)
|
|
88
|
+
} catch (t: Throwable) {
|
|
89
|
+
promise.reject(errorCode(t), t.message ?: "history failed", t)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
override fun invalidate() {
|
|
95
|
+
super.invalidate()
|
|
96
|
+
scope.cancel()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// Mappers (Wire ↔ Kotlin types)
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
|
|
103
|
+
private fun wireToConfig(map: ReadableMap): BeekonConfig {
|
|
104
|
+
val intervalSeconds = map.getDouble("intervalSeconds").toLong()
|
|
105
|
+
val distanceMeters = map.getDouble("distanceMeters")
|
|
106
|
+
val notification = map.getMap("androidNotification")
|
|
107
|
+
?.let { wireToNotification(it) }
|
|
108
|
+
?: BeekonConfig.Notification()
|
|
109
|
+
return BeekonConfig(
|
|
110
|
+
intervalSeconds = intervalSeconds,
|
|
111
|
+
distanceMeters = distanceMeters,
|
|
112
|
+
notification = notification,
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private fun wireToNotification(map: ReadableMap): BeekonConfig.Notification {
|
|
117
|
+
val title = if (map.hasKey("title") && !map.isNull("title")) map.getString("title") else null
|
|
118
|
+
val text = if (map.hasKey("text") && !map.isNull("text")) map.getString("text") else null
|
|
119
|
+
val resName =
|
|
120
|
+
if (map.hasKey("smallIconResName") && !map.isNull("smallIconResName"))
|
|
121
|
+
map.getString("smallIconResName")
|
|
122
|
+
else null
|
|
123
|
+
val smallIcon: Int? = resName?.let {
|
|
124
|
+
val pkg = reactContext.packageName
|
|
125
|
+
val id = reactContext.resources.getIdentifier(it, "drawable", pkg)
|
|
126
|
+
if (id == 0) {
|
|
127
|
+
throw IllegalArgumentException("drawable resource '$it' not found in package '$pkg'")
|
|
128
|
+
}
|
|
129
|
+
id
|
|
130
|
+
}
|
|
131
|
+
return BeekonConfig.Notification(title = title, text = text, smallIcon = smallIcon)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private fun locationToWire(loc: Location): WritableMap {
|
|
135
|
+
val m = Arguments.createMap()
|
|
136
|
+
m.putDouble("lat", loc.lat)
|
|
137
|
+
m.putDouble("lng", loc.lng)
|
|
138
|
+
m.putDouble("timestampMs", loc.timestamp.toEpochMilli().toDouble())
|
|
139
|
+
putNullableDouble(m, "accuracy", loc.accuracy)
|
|
140
|
+
putNullableDouble(m, "speed", loc.speed)
|
|
141
|
+
putNullableDouble(m, "bearing", loc.bearing)
|
|
142
|
+
putNullableDouble(m, "altitude", loc.altitude)
|
|
143
|
+
return m
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private fun putNullableDouble(map: WritableMap, key: String, value: Double?) {
|
|
147
|
+
if (value == null) map.putNull(key) else map.putDouble(key, value)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private fun stateToWire(s: BeekonState): WritableMap {
|
|
151
|
+
val m = Arguments.createMap()
|
|
152
|
+
when (s) {
|
|
153
|
+
BeekonState.Idle -> m.putString("type", "idle")
|
|
154
|
+
BeekonState.Tracking -> m.putString("type", "tracking")
|
|
155
|
+
is BeekonState.Stopped -> {
|
|
156
|
+
m.putString("type", "stopped")
|
|
157
|
+
m.putString("stopReason", stopReasonToWire(s.reason))
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return m
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private fun stopReasonToWire(r: StopReason): String = when (r) {
|
|
164
|
+
StopReason.User -> "user"
|
|
165
|
+
StopReason.PermissionDenied -> "permissionDenied"
|
|
166
|
+
StopReason.LocationServicesDisabled -> "locationServicesDisabled"
|
|
167
|
+
StopReason.System -> "system"
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Maps native error sealed types to stable JS-side codes. Same code strings
|
|
171
|
+
// on iOS so JS can switch on them platform-agnostically.
|
|
172
|
+
private fun errorCode(t: Throwable): String = when (t) {
|
|
173
|
+
is BeekonError.PermissionDenied -> "PERMISSION_DENIED"
|
|
174
|
+
is BeekonError.LocationServicesDisabled -> "LOCATION_SERVICES_DISABLED"
|
|
175
|
+
is BeekonError.StorageFailure -> "STORAGE_FAILURE"
|
|
176
|
+
else -> "INTERNAL_ERROR"
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
companion object {
|
|
180
|
+
const val NAME = NativeBeekonRnSpec.NAME
|
|
181
|
+
}
|
|
182
|
+
}
|
package/ios/BeekonRn.h
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
#import <BeekonRnSpec/BeekonRnSpec.h>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// Inherit from NativeBeekonRnSpecBase (codegen-provided) — it ships the
|
|
4
|
+
// concrete `emitOnState:` / `emitOnLocation:` implementations that bridge
|
|
5
|
+
// to JS via the EventEmitter callback. Conform to the protocol for the
|
|
6
|
+
// method-side TurboModule contract.
|
|
7
|
+
@interface BeekonRn : NativeBeekonRnSpecBase <NativeBeekonRnSpec>
|
|
4
8
|
|
|
5
9
|
@end
|
package/ios/BeekonRn.mm
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#import "BeekonRn.h"
|
|
2
|
-
// Auto-generated bridging header from the Swift impl
|
|
3
|
-
|
|
2
|
+
// Auto-generated bridging header from the Swift impl. With `use_frameworks!`
|
|
3
|
+
// in the host Podfile (required for Swift pods), CocoaPods generates this
|
|
4
|
+
// inside the BeekonRn framework, so the framework-style import is needed.
|
|
5
|
+
#import <BeekonRn/BeekonRn-Swift.h>
|
|
4
6
|
|
|
5
7
|
@implementation BeekonRn {
|
|
6
8
|
BeekonRnImpl *_impl;
|
|
@@ -11,38 +13,31 @@
|
|
|
11
13
|
if (self) {
|
|
12
14
|
__weak __typeof(self) weakSelf = self;
|
|
13
15
|
_impl = [[BeekonRnImpl alloc]
|
|
14
|
-
|
|
16
|
+
initOnState:^(NSDictionary *_Nonnull s) {
|
|
15
17
|
[weakSelf emitOnState:s];
|
|
16
18
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
onLocation:^(NSDictionary *_Nonnull l) {
|
|
20
|
+
[weakSelf emitOnLocation:l];
|
|
21
|
+
}];
|
|
20
22
|
}
|
|
21
23
|
return self;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
- (void)
|
|
25
|
-
|
|
26
|
-
[
|
|
26
|
+
- (void)invalidate {
|
|
27
|
+
[_impl invalidate];
|
|
28
|
+
[super invalidate];
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
- (void)configure:(JS::NativeBeekonRn::WireConfig &)config
|
|
30
32
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
31
33
|
reject:(RCTPromiseRejectBlock)reject {
|
|
32
34
|
// Codegen passes the struct; round-trip through NSDictionary so the Swift
|
|
33
|
-
// side can decode generically without an iOS-specific spec import.
|
|
34
|
-
//
|
|
35
|
+
// side can decode generically without an iOS-specific spec import. iOS
|
|
36
|
+
// ignores `androidNotification` — passed through but unused.
|
|
35
37
|
NSDictionary *dict = @{
|
|
36
|
-
@"
|
|
37
|
-
@"
|
|
38
|
-
? @(config.distanceFilterMeters().value())
|
|
39
|
-
: (id)[NSNull null],
|
|
40
|
-
@"intervalMillis": config.intervalMillis().has_value()
|
|
41
|
-
? @(config.intervalMillis().value())
|
|
42
|
-
: (id)[NSNull null],
|
|
43
|
-
@"licenseKey": config.licenseKey() ?: (id)[NSNull null],
|
|
38
|
+
@"intervalSeconds": @(config.intervalSeconds()),
|
|
39
|
+
@"distanceMeters": @(config.distanceMeters()),
|
|
44
40
|
};
|
|
45
|
-
// Note: iOS doesn't use androidNotification — passed but ignored.
|
|
46
41
|
[_impl configure:dict resolver:resolve rejecter:reject];
|
|
47
42
|
}
|
|
48
43
|
|
|
@@ -56,11 +51,6 @@
|
|
|
56
51
|
[_impl stopWithResolver:resolve rejecter:reject];
|
|
57
52
|
}
|
|
58
53
|
|
|
59
|
-
- (void)shutdown:(RCTPromiseResolveBlock)resolve
|
|
60
|
-
reject:(RCTPromiseRejectBlock)reject {
|
|
61
|
-
[_impl shutdownWithResolver:resolve rejecter:reject];
|
|
62
|
-
}
|
|
63
|
-
|
|
64
54
|
- (void)history:(double)fromMs
|
|
65
55
|
toMs:(double)toMs
|
|
66
56
|
resolve:(RCTPromiseResolveBlock)resolve
|