@wayq/beekon-rn 0.0.1 → 0.0.5
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 +4 -4
- package/README.md +94 -48
- package/android/build.gradle +11 -6
- package/android/src/main/java/in/wayq/beekonrn/BeekonRnModule.kt +428 -0
- package/android/src/main/java/{com → in}/wayq/beekonrn/BeekonRnPackage.kt +1 -1
- package/ios/BeekonRn.h +5 -1
- package/ios/BeekonRn.mm +90 -34
- package/ios/BeekonRn.swift +396 -116
- 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 +8636 -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 +236 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/PrivacyInfo.xcprivacy +1 -1
- 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 +8636 -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 +236 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/x86_64-apple-ios-simulator.abi.json +8636 -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 +236 -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 +2 -14
- package/lib/module/NativeBeekonRn.js +22 -7
- package/lib/module/NativeBeekonRn.js.map +1 -1
- package/lib/module/beekon.js +209 -60
- 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 +145 -23
- package/lib/module/internal/mappers.js.map +1 -1
- package/lib/module/types/enums.js +2 -0
- package/lib/module/types/{preset.js.map → enums.js.map} +1 -1
- package/lib/module/types/error.js +25 -0
- package/lib/module/types/error.js.map +1 -0
- package/lib/module/types/geofence.js +2 -0
- package/lib/module/types/{position.js.map → geofence.js.map} +1 -1
- package/lib/module/types/location.js +4 -0
- package/lib/module/types/location.js.map +1 -0
- package/lib/module/types/sync.js +2 -0
- package/lib/module/types/sync.js.map +1 -0
- package/lib/typescript/src/NativeBeekonRn.d.ts +113 -35
- package/lib/typescript/src/NativeBeekonRn.d.ts.map +1 -1
- package/lib/typescript/src/beekon.d.ts +84 -49
- package/lib/typescript/src/beekon.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +7 -4
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/internal/mappers.d.ts +16 -3
- package/lib/typescript/src/internal/mappers.d.ts.map +1 -1
- package/lib/typescript/src/types/config.d.ts +53 -31
- package/lib/typescript/src/types/config.d.ts.map +1 -1
- package/lib/typescript/src/types/enums.d.ts +48 -0
- package/lib/typescript/src/types/enums.d.ts.map +1 -0
- package/lib/typescript/src/types/error.d.ts +20 -0
- package/lib/typescript/src/types/error.d.ts.map +1 -0
- package/lib/typescript/src/types/geofence.d.ts +36 -0
- package/lib/typescript/src/types/geofence.d.ts.map +1 -0
- package/lib/typescript/src/types/location.d.ts +40 -0
- package/lib/typescript/src/types/location.d.ts.map +1 -0
- package/lib/typescript/src/types/state.d.ts +18 -9
- package/lib/typescript/src/types/state.d.ts.map +1 -1
- package/lib/typescript/src/types/sync.d.ts +27 -0
- package/lib/typescript/src/types/sync.d.ts.map +1 -0
- package/package.json +5 -6
- package/scripts/fetch-beekonkit.sh +5 -2
- package/src/NativeBeekonRn.ts +120 -34
- package/src/beekon.ts +235 -63
- package/src/index.tsx +23 -4
- package/src/internal/mappers.ts +213 -22
- package/src/types/config.ts +54 -31
- package/src/types/enums.ts +64 -0
- package/src/types/error.ts +25 -0
- package/src/types/geofence.ts +37 -0
- package/src/types/location.ts +45 -0
- package/src/types/state.ts +23 -7
- package/src/types/sync.ts +23 -0
- package/android/src/main/java/com/wayq/beekonrn/BeekonRnModule.kt +0 -233
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeDirectory +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeRequirements +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeRequirements-1 +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeResources +0 -233
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeSignature +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/_CodeSignature/CodeResources +0 -113
- package/lib/module/types/position.js +0 -2
- package/lib/module/types/preset.js +0 -2
- 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
|
@@ -0,0 +1,428 @@
|
|
|
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.ReadableArray
|
|
7
|
+
import com.facebook.react.bridge.ReadableMap
|
|
8
|
+
import com.facebook.react.bridge.WritableArray
|
|
9
|
+
import com.facebook.react.bridge.WritableMap
|
|
10
|
+
import `in`.wayq.beekon.AccuracyMode
|
|
11
|
+
import `in`.wayq.beekon.ActivityType
|
|
12
|
+
import `in`.wayq.beekon.Beekon
|
|
13
|
+
import `in`.wayq.beekon.BeekonConfig
|
|
14
|
+
import `in`.wayq.beekon.BeekonException
|
|
15
|
+
import `in`.wayq.beekon.BeekonGeofence
|
|
16
|
+
import `in`.wayq.beekon.BeekonState
|
|
17
|
+
import `in`.wayq.beekon.GeofenceEvent
|
|
18
|
+
import `in`.wayq.beekon.Location
|
|
19
|
+
import `in`.wayq.beekon.LocationQuality
|
|
20
|
+
import `in`.wayq.beekon.LocationTrigger
|
|
21
|
+
import `in`.wayq.beekon.MotionState
|
|
22
|
+
import `in`.wayq.beekon.NotificationConfig
|
|
23
|
+
import `in`.wayq.beekon.StationaryMode
|
|
24
|
+
import `in`.wayq.beekon.StopReason
|
|
25
|
+
import `in`.wayq.beekon.SyncConfig
|
|
26
|
+
import `in`.wayq.beekon.SyncFailure
|
|
27
|
+
import `in`.wayq.beekon.SyncStatus
|
|
28
|
+
import `in`.wayq.beekon.Transition
|
|
29
|
+
import java.time.Instant
|
|
30
|
+
import kotlinx.coroutines.CoroutineScope
|
|
31
|
+
import kotlinx.coroutines.Dispatchers
|
|
32
|
+
import kotlinx.coroutines.SupervisorJob
|
|
33
|
+
import kotlinx.coroutines.cancel
|
|
34
|
+
import kotlinx.coroutines.launch
|
|
35
|
+
|
|
36
|
+
class BeekonRnModule(reactContext: ReactApplicationContext) :
|
|
37
|
+
NativeBeekonRnSpec(reactContext) {
|
|
38
|
+
|
|
39
|
+
// Default dispatcher (not Main.immediate) — Codegen's emitOnX is thread-safe
|
|
40
|
+
// and marshals to JS internally, so collecting on Main buys nothing and risks
|
|
41
|
+
// jank if a mapper does work. SupervisorJob so one failing collector doesn't
|
|
42
|
+
// tear down its siblings.
|
|
43
|
+
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
|
44
|
+
|
|
45
|
+
init {
|
|
46
|
+
// No Beekon.initialize() — the SDK auto-initializes via AndroidX Startup.
|
|
47
|
+
scope.launch { Beekon.state.collect { emitOnState(stateToWire(it)) } }
|
|
48
|
+
scope.launch { Beekon.locations.collect { emitOnLocation(locationToWire(it)) } }
|
|
49
|
+
scope.launch {
|
|
50
|
+
Beekon.geofenceEvents.collect { emitOnGeofenceEvent(geofenceEventToWire(it)) }
|
|
51
|
+
}
|
|
52
|
+
scope.launch { Beekon.syncStatus.collect { emitOnSyncStatus(syncStatusToWire(it)) } }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Lifecycle (non-suspend native calls resolve directly)
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
override fun configure(config: ReadableMap, promise: Promise) {
|
|
60
|
+
try {
|
|
61
|
+
Beekon.configure(wireToConfig(config))
|
|
62
|
+
promise.resolve(null)
|
|
63
|
+
} catch (t: Throwable) {
|
|
64
|
+
promise.reject(errorCode(t), t.message ?: "configure failed", t)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
override fun start(promise: Promise) {
|
|
69
|
+
scope.launch {
|
|
70
|
+
try {
|
|
71
|
+
Beekon.start()
|
|
72
|
+
promise.resolve(null)
|
|
73
|
+
} catch (t: Throwable) {
|
|
74
|
+
promise.reject(errorCode(t), t.message ?: "start failed", t)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
override fun stop(promise: Promise) {
|
|
80
|
+
scope.launch {
|
|
81
|
+
try {
|
|
82
|
+
Beekon.stop()
|
|
83
|
+
promise.resolve(null)
|
|
84
|
+
} catch (t: Throwable) {
|
|
85
|
+
promise.reject(errorCode(t), t.message ?: "stop failed", t)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Android has no native resumeIfNeeded — Beekon.start() rehydrates the
|
|
91
|
+
// persisted intent (mirrors the Flutter plugin).
|
|
92
|
+
override fun resumeIfNeeded(promise: Promise) {
|
|
93
|
+
scope.launch {
|
|
94
|
+
try {
|
|
95
|
+
Beekon.start()
|
|
96
|
+
promise.resolve(null)
|
|
97
|
+
} catch (t: Throwable) {
|
|
98
|
+
promise.reject(errorCode(t), t.message ?: "resumeIfNeeded failed", t)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// History
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
override fun getLocations(fromMs: Double, toMs: Double, promise: Promise) {
|
|
108
|
+
scope.launch {
|
|
109
|
+
try {
|
|
110
|
+
val from = Instant.ofEpochMilli(fromMs.toLong())
|
|
111
|
+
val to = Instant.ofEpochMilli(toMs.toLong())
|
|
112
|
+
val arr: WritableArray = Arguments.createArray()
|
|
113
|
+
for (loc in Beekon.getLocations(from, to)) arr.pushMap(locationToWire(loc))
|
|
114
|
+
promise.resolve(arr)
|
|
115
|
+
} catch (t: Throwable) {
|
|
116
|
+
promise.reject(errorCode(t), t.message ?: "getLocations failed", t)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
override fun deleteLocations(beforeMs: Double, promise: Promise) {
|
|
122
|
+
scope.launch {
|
|
123
|
+
try {
|
|
124
|
+
// Negative is the wire sentinel for "delete all" (no cutoff).
|
|
125
|
+
val before = if (beforeMs < 0) null else Instant.ofEpochMilli(beforeMs.toLong())
|
|
126
|
+
promise.resolve(Beekon.deleteLocations(before))
|
|
127
|
+
} catch (t: Throwable) {
|
|
128
|
+
promise.reject(errorCode(t), t.message ?: "deleteLocations failed", t)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
override fun pendingUploadCount(promise: Promise) {
|
|
134
|
+
scope.launch {
|
|
135
|
+
try {
|
|
136
|
+
promise.resolve(Beekon.pendingUploadCount())
|
|
137
|
+
} catch (t: Throwable) {
|
|
138
|
+
promise.reject(errorCode(t), t.message ?: "pendingUploadCount failed", t)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
// Sync
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
|
|
147
|
+
override fun sync(promise: Promise) {
|
|
148
|
+
Beekon.sync()
|
|
149
|
+
promise.resolve(null)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
override fun setExtras(entries: ReadableArray, promise: Promise) {
|
|
153
|
+
Beekon.setExtras(entriesToMap(entries))
|
|
154
|
+
promise.resolve(null)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
// Geofences
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
|
|
161
|
+
override fun addGeofences(geofences: ReadableArray, promise: Promise) {
|
|
162
|
+
scope.launch {
|
|
163
|
+
try {
|
|
164
|
+
Beekon.addGeofences(wireToGeofences(geofences))
|
|
165
|
+
promise.resolve(null)
|
|
166
|
+
} catch (t: Throwable) {
|
|
167
|
+
promise.reject(errorCode(t), t.message ?: "addGeofences failed", t)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
override fun removeGeofences(ids: ReadableArray, promise: Promise) {
|
|
173
|
+
scope.launch {
|
|
174
|
+
try {
|
|
175
|
+
val list = (0 until ids.size()).mapNotNull { ids.getString(it) }
|
|
176
|
+
Beekon.removeGeofences(list)
|
|
177
|
+
promise.resolve(null)
|
|
178
|
+
} catch (t: Throwable) {
|
|
179
|
+
promise.reject(errorCode(t), t.message ?: "removeGeofences failed", t)
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
override fun listGeofences(promise: Promise) {
|
|
185
|
+
scope.launch {
|
|
186
|
+
try {
|
|
187
|
+
val arr: WritableArray = Arguments.createArray()
|
|
188
|
+
for (g in Beekon.listGeofences()) arr.pushMap(geofenceToWire(g))
|
|
189
|
+
promise.resolve(arr)
|
|
190
|
+
} catch (t: Throwable) {
|
|
191
|
+
promise.reject(errorCode(t), t.message ?: "listGeofences failed", t)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
override fun invalidate() {
|
|
197
|
+
super.invalidate()
|
|
198
|
+
scope.cancel()
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ---------------------------------------------------------------------------
|
|
202
|
+
// Mappers: wire (ReadableMap/Array) → Kotlin
|
|
203
|
+
// ---------------------------------------------------------------------------
|
|
204
|
+
|
|
205
|
+
private fun wireToConfig(map: ReadableMap): BeekonConfig {
|
|
206
|
+
val sync =
|
|
207
|
+
if (map.hasKey("sync") && !map.isNull("sync")) {
|
|
208
|
+
map.getMap("sync")?.let { wireToSyncConfig(it) }
|
|
209
|
+
} else {
|
|
210
|
+
null
|
|
211
|
+
}
|
|
212
|
+
val notification =
|
|
213
|
+
if (map.hasKey("notification") && !map.isNull("notification")) {
|
|
214
|
+
map.getMap("notification")?.let { wireToNotification(it) }
|
|
215
|
+
} else {
|
|
216
|
+
null
|
|
217
|
+
}
|
|
218
|
+
return BeekonConfig(
|
|
219
|
+
minTimeBetweenLocationsSeconds =
|
|
220
|
+
map.getDouble("minTimeBetweenLocationsSeconds").toLong(),
|
|
221
|
+
minDistanceBetweenLocationsMeters =
|
|
222
|
+
map.getDouble("minDistanceBetweenLocationsMeters"),
|
|
223
|
+
accuracyMode = toAccuracyMode(map.getString("accuracyMode")),
|
|
224
|
+
whenStationary = toStationaryMode(map.getString("whenStationary")),
|
|
225
|
+
stationaryRadiusMeters = map.getDouble("stationaryRadiusMeters"),
|
|
226
|
+
detectActivity = map.getBoolean("detectActivity"),
|
|
227
|
+
sync = sync,
|
|
228
|
+
notification = notification ?: NotificationConfig(),
|
|
229
|
+
)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
private fun wireToSyncConfig(map: ReadableMap): SyncConfig =
|
|
233
|
+
SyncConfig(
|
|
234
|
+
url = map.getString("url") ?: "",
|
|
235
|
+
headers = entriesToMap(map.getArray("headers")),
|
|
236
|
+
intervalSeconds = map.getDouble("intervalSeconds").toLong(),
|
|
237
|
+
batchSize = map.getDouble("batchSize").toInt(),
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
private fun wireToNotification(map: ReadableMap): NotificationConfig {
|
|
241
|
+
val title =
|
|
242
|
+
if (map.hasKey("title") && !map.isNull("title")) map.getString("title") else null
|
|
243
|
+
val text =
|
|
244
|
+
if (map.hasKey("text") && !map.isNull("text")) map.getString("text") else null
|
|
245
|
+
// Use the data-class default for `title` when the wire value is absent.
|
|
246
|
+
return if (title != null) {
|
|
247
|
+
NotificationConfig(title = title, text = text)
|
|
248
|
+
} else {
|
|
249
|
+
NotificationConfig(text = text)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
private fun wireToGeofences(arr: ReadableArray): List<BeekonGeofence> {
|
|
254
|
+
val out = ArrayList<BeekonGeofence>(arr.size())
|
|
255
|
+
for (i in 0 until arr.size()) {
|
|
256
|
+
val m = arr.getMap(i) ?: continue
|
|
257
|
+
out += BeekonGeofence(
|
|
258
|
+
id = m.getString("id") ?: "",
|
|
259
|
+
latitude = m.getDouble("lat"),
|
|
260
|
+
longitude = m.getDouble("lng"),
|
|
261
|
+
radiusMeters = m.getDouble("radiusMeters"),
|
|
262
|
+
notifyOnEntry = m.getBoolean("notifyOnEntry"),
|
|
263
|
+
notifyOnExit = m.getBoolean("notifyOnExit"),
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
return out
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private fun entriesToMap(arr: ReadableArray?): Map<String, String> {
|
|
270
|
+
if (arr == null) return emptyMap()
|
|
271
|
+
val out = LinkedHashMap<String, String>(arr.size())
|
|
272
|
+
for (i in 0 until arr.size()) {
|
|
273
|
+
val e = arr.getMap(i) ?: continue
|
|
274
|
+
val k = e.getString("key") ?: continue
|
|
275
|
+
val v = e.getString("value") ?: continue
|
|
276
|
+
out[k] = v
|
|
277
|
+
}
|
|
278
|
+
return out
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ---------------------------------------------------------------------------
|
|
282
|
+
// Mappers: Kotlin → wire (WritableMap)
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
|
|
285
|
+
private fun locationToWire(loc: Location): WritableMap {
|
|
286
|
+
val m = Arguments.createMap()
|
|
287
|
+
m.putString("id", loc.id)
|
|
288
|
+
m.putDouble("lat", loc.latitude)
|
|
289
|
+
m.putDouble("lng", loc.longitude)
|
|
290
|
+
m.putDouble("timestampMs", loc.timestamp.toEpochMilli().toDouble())
|
|
291
|
+
putNullableDouble(m, "accuracy", loc.accuracy)
|
|
292
|
+
putNullableDouble(m, "speed", loc.speed)
|
|
293
|
+
putNullableDouble(m, "bearing", loc.bearing)
|
|
294
|
+
putNullableDouble(m, "altitude", loc.altitude)
|
|
295
|
+
m.putString("quality", qualityToWire(loc.quality))
|
|
296
|
+
m.putString("trigger", triggerToWire(loc.trigger))
|
|
297
|
+
m.putString("motion", motionToWire(loc.motion))
|
|
298
|
+
val activity = loc.activity
|
|
299
|
+
if (activity != null) m.putString("activity", activityToWire(activity)) else m.putNull("activity")
|
|
300
|
+
m.putBoolean("isMock", loc.isMock)
|
|
301
|
+
return m
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
private fun geofenceToWire(g: BeekonGeofence): WritableMap {
|
|
305
|
+
val m = Arguments.createMap()
|
|
306
|
+
m.putString("id", g.id)
|
|
307
|
+
m.putDouble("lat", g.latitude)
|
|
308
|
+
m.putDouble("lng", g.longitude)
|
|
309
|
+
m.putDouble("radiusMeters", g.radiusMeters)
|
|
310
|
+
m.putBoolean("notifyOnEntry", g.notifyOnEntry)
|
|
311
|
+
m.putBoolean("notifyOnExit", g.notifyOnExit)
|
|
312
|
+
return m
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
private fun geofenceEventToWire(e: GeofenceEvent): WritableMap {
|
|
316
|
+
val m = Arguments.createMap()
|
|
317
|
+
m.putString("id", e.id)
|
|
318
|
+
m.putString("geofenceId", e.geofenceId)
|
|
319
|
+
m.putString("type", transitionToWire(e.type))
|
|
320
|
+
m.putDouble("timestampMs", e.timestamp.toEpochMilli().toDouble())
|
|
321
|
+
return m
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
private fun stateToWire(s: BeekonState): WritableMap {
|
|
325
|
+
val m = Arguments.createMap()
|
|
326
|
+
when (s) {
|
|
327
|
+
BeekonState.Idle -> m.putString("type", "idle")
|
|
328
|
+
BeekonState.Tracking -> m.putString("type", "tracking")
|
|
329
|
+
is BeekonState.Stopped -> {
|
|
330
|
+
m.putString("type", "stopped")
|
|
331
|
+
m.putString("stopReason", stopReasonToWire(s.reason))
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return m
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
private fun syncStatusToWire(s: SyncStatus): WritableMap {
|
|
338
|
+
val m = Arguments.createMap()
|
|
339
|
+
when (s) {
|
|
340
|
+
SyncStatus.Idle -> m.putString("type", "idle")
|
|
341
|
+
SyncStatus.Pending -> m.putString("type", "pending")
|
|
342
|
+
is SyncStatus.Failed -> {
|
|
343
|
+
m.putString("type", "failed")
|
|
344
|
+
m.putString("failure", syncFailureToWire(s.reason))
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return m
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
private fun putNullableDouble(map: WritableMap, key: String, value: Double?) {
|
|
351
|
+
if (value == null) map.putNull(key) else map.putDouble(key, value)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
// Enum mappers
|
|
356
|
+
// ---------------------------------------------------------------------------
|
|
357
|
+
|
|
358
|
+
private fun toAccuracyMode(s: String?): AccuracyMode = when (s) {
|
|
359
|
+
"high" -> AccuracyMode.High
|
|
360
|
+
"low" -> AccuracyMode.Low
|
|
361
|
+
else -> AccuracyMode.Balanced
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
private fun toStationaryMode(s: String?): StationaryMode = when (s) {
|
|
365
|
+
"keepTracking" -> StationaryMode.KeepTracking
|
|
366
|
+
"pauseWithCheckIns" -> StationaryMode.PauseWithCheckIns
|
|
367
|
+
else -> StationaryMode.Pause
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
private fun stopReasonToWire(r: StopReason): String = when (r) {
|
|
371
|
+
StopReason.User -> "user"
|
|
372
|
+
StopReason.PermissionDenied -> "permissionDenied"
|
|
373
|
+
StopReason.LocationServicesDisabled -> "locationServicesDisabled"
|
|
374
|
+
StopReason.LocationUnavailable -> "locationUnavailable"
|
|
375
|
+
StopReason.System -> "system"
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
private fun syncFailureToWire(f: SyncFailure): String = when (f) {
|
|
379
|
+
SyncFailure.Auth -> "auth"
|
|
380
|
+
SyncFailure.Rejected -> "rejected"
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
private fun qualityToWire(q: LocationQuality): String = when (q) {
|
|
384
|
+
LocationQuality.Ok -> "ok"
|
|
385
|
+
LocationQuality.LowAccuracy -> "lowAccuracy"
|
|
386
|
+
LocationQuality.ImplausibleSpeed -> "implausibleSpeed"
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
private fun triggerToWire(t: LocationTrigger): String = when (t) {
|
|
390
|
+
LocationTrigger.Interval -> "interval"
|
|
391
|
+
LocationTrigger.Motion -> "motion"
|
|
392
|
+
LocationTrigger.CheckIn -> "checkIn"
|
|
393
|
+
LocationTrigger.Geofence -> "geofence"
|
|
394
|
+
LocationTrigger.Manual -> "manual"
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
private fun motionToWire(m: MotionState): String = when (m) {
|
|
398
|
+
MotionState.Moving -> "moving"
|
|
399
|
+
MotionState.Stationary -> "stationary"
|
|
400
|
+
MotionState.Unknown -> "unknown"
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
private fun activityToWire(a: ActivityType): String = when (a) {
|
|
404
|
+
ActivityType.Stationary -> "stationary"
|
|
405
|
+
ActivityType.Walking -> "walking"
|
|
406
|
+
ActivityType.Running -> "running"
|
|
407
|
+
ActivityType.Cycling -> "cycling"
|
|
408
|
+
ActivityType.Automotive -> "automotive"
|
|
409
|
+
ActivityType.Unknown -> "unknown"
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
private fun transitionToWire(t: Transition): String = when (t) {
|
|
413
|
+
Transition.Enter -> "enter"
|
|
414
|
+
Transition.Exit -> "exit"
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Maps native exceptions to stable JS-side codes, shared with iOS so JS can
|
|
418
|
+
// switch on them platform-agnostically.
|
|
419
|
+
private fun errorCode(t: Throwable): String = when (t) {
|
|
420
|
+
is BeekonException.StorageException -> "STORAGE_FAILURE"
|
|
421
|
+
is BeekonException.InvalidGeofence -> "INVALID_GEOFENCE"
|
|
422
|
+
else -> "INTERNAL_ERROR"
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
companion object {
|
|
426
|
+
const val NAME = NativeBeekonRnSpec.NAME
|
|
427
|
+
}
|
|
428
|
+
}
|
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,13 @@
|
|
|
1
1
|
#import "BeekonRn.h"
|
|
2
|
-
// Auto-generated
|
|
2
|
+
// Auto-generated Swift interop header for the BeekonRnImpl class. Its path
|
|
3
|
+
// depends on how the host links pods: under `<BeekonRn/…>` with
|
|
4
|
+
// `use_frameworks!` (framework), or as a same-target generated header with
|
|
5
|
+
// static linking (the React Native default). Support both.
|
|
6
|
+
#if __has_include(<BeekonRn/BeekonRn-Swift.h>)
|
|
7
|
+
#import <BeekonRn/BeekonRn-Swift.h>
|
|
8
|
+
#else
|
|
3
9
|
#import "BeekonRn-Swift.h"
|
|
10
|
+
#endif
|
|
4
11
|
|
|
5
12
|
@implementation BeekonRn {
|
|
6
13
|
BeekonRnImpl *_impl;
|
|
@@ -11,39 +18,43 @@
|
|
|
11
18
|
if (self) {
|
|
12
19
|
__weak __typeof(self) weakSelf = self;
|
|
13
20
|
_impl = [[BeekonRnImpl alloc]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
initOnState:^(NSDictionary *_Nonnull s) {
|
|
22
|
+
[weakSelf emitOnState:s];
|
|
23
|
+
}
|
|
24
|
+
onLocation:^(NSDictionary *_Nonnull l) {
|
|
25
|
+
[weakSelf emitOnLocation:l];
|
|
26
|
+
}
|
|
27
|
+
onGeofenceEvent:^(NSDictionary *_Nonnull e) {
|
|
28
|
+
[weakSelf emitOnGeofenceEvent:e];
|
|
29
|
+
}
|
|
30
|
+
onSyncStatus:^(NSDictionary *_Nonnull st) {
|
|
31
|
+
[weakSelf emitOnSyncStatus:st];
|
|
32
|
+
}];
|
|
20
33
|
}
|
|
21
34
|
return self;
|
|
22
35
|
}
|
|
23
36
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
// Called by React Native on teardown (RCTInvalidating). The Codegen base class
|
|
38
|
+
// derives from NSObject, which has no `invalidate`, so there's no super to call.
|
|
39
|
+
- (void)invalidate {
|
|
40
|
+
[_impl invalidate];
|
|
27
41
|
}
|
|
28
42
|
|
|
29
|
-
|
|
43
|
+
/// Registers Beekon's background tasks. Call from the host AppDelegate's
|
|
44
|
+
/// `application:didFinishLaunchingWithOptions:` (it must run before that method
|
|
45
|
+
/// returns). Exposed as a class method so hosts don't import BeekonKit directly.
|
|
46
|
+
+ (void)registerBackgroundTasks {
|
|
47
|
+
[BeekonRnImpl registerBackgroundTasks];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// MARK: - Lifecycle
|
|
51
|
+
|
|
52
|
+
- (void)configure:(NSDictionary *)config
|
|
30
53
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
31
54
|
reject:(RCTPromiseRejectBlock)reject {
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
NSDictionary *dict = @{
|
|
36
|
-
@"preset": config.preset() ?: @"balanced",
|
|
37
|
-
@"distanceFilterMeters": config.distanceFilterMeters().has_value()
|
|
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],
|
|
44
|
-
};
|
|
45
|
-
// Note: iOS doesn't use androidNotification — passed but ignored.
|
|
46
|
-
[_impl configure:dict resolver:resolve rejecter:reject];
|
|
55
|
+
// The config crosses as a plain dictionary (UnsafeObject); the Swift side
|
|
56
|
+
// parses it. iOS ignores `notification` (Android-only).
|
|
57
|
+
[_impl configure:config resolver:resolve rejecter:reject];
|
|
47
58
|
}
|
|
48
59
|
|
|
49
60
|
- (void)start:(RCTPromiseResolveBlock)resolve
|
|
@@ -56,16 +67,61 @@
|
|
|
56
67
|
[_impl stopWithResolver:resolve rejecter:reject];
|
|
57
68
|
}
|
|
58
69
|
|
|
59
|
-
- (void)
|
|
60
|
-
|
|
61
|
-
[_impl
|
|
70
|
+
- (void)resumeIfNeeded:(RCTPromiseResolveBlock)resolve
|
|
71
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
72
|
+
[_impl resumeIfNeededWithResolver:resolve rejecter:reject];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// MARK: - History
|
|
76
|
+
|
|
77
|
+
- (void)getLocations:(double)fromMs
|
|
78
|
+
toMs:(double)toMs
|
|
79
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
80
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
81
|
+
[_impl getLocationsFromMs:fromMs toMs:toMs resolver:resolve rejecter:reject];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
- (void)deleteLocations:(double)beforeMs
|
|
85
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
86
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
87
|
+
[_impl deleteLocationsBeforeMs:beforeMs resolver:resolve rejecter:reject];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
- (void)pendingUploadCount:(RCTPromiseResolveBlock)resolve
|
|
91
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
92
|
+
[_impl pendingUploadCountWithResolver:resolve rejecter:reject];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// MARK: - Sync
|
|
96
|
+
|
|
97
|
+
- (void)sync:(RCTPromiseResolveBlock)resolve
|
|
98
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
99
|
+
[_impl syncWithResolver:resolve rejecter:reject];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
- (void)setExtras:(NSArray *)entries
|
|
103
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
104
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
105
|
+
[_impl setExtras:entries resolver:resolve rejecter:reject];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// MARK: - Geofences
|
|
109
|
+
|
|
110
|
+
- (void)addGeofences:(NSArray *)geofences
|
|
111
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
112
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
113
|
+
[_impl addGeofences:geofences resolver:resolve rejecter:reject];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
- (void)removeGeofences:(NSArray *)ids
|
|
117
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
118
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
119
|
+
[_impl removeGeofences:ids resolver:resolve rejecter:reject];
|
|
62
120
|
}
|
|
63
121
|
|
|
64
|
-
- (void)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
reject:(RCTPromiseRejectBlock)reject {
|
|
68
|
-
[_impl historyFromMs:fromMs toMs:toMs resolver:resolve rejecter:reject];
|
|
122
|
+
- (void)listGeofences:(RCTPromiseResolveBlock)resolve
|
|
123
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
124
|
+
[_impl listGeofencesWithResolver:resolve rejecter:reject];
|
|
69
125
|
}
|
|
70
126
|
|
|
71
127
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|