@wayq/beekon-rn 0.0.3 → 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 +1 -1
- package/README.md +91 -39
- package/android/build.gradle +9 -4
- package/android/src/main/java/in/wayq/beekonrn/BeekonRnModule.kt +306 -60
- package/ios/BeekonRn.mm +90 -24
- package/ios/BeekonRn.swift +360 -60
- 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 +7521 -1312
- 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 +191 -40
- 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 +7521 -1312
- 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 +191 -40
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/Modules/BeekonKit.swiftmodule/x86_64-apple-ios-simulator.abi.json +7521 -1312
- 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 +191 -40
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64_x86_64-simulator/BeekonKit.framework/_CodeSignature/CodeResources +2 -80
- package/lib/module/NativeBeekonRn.js +22 -7
- package/lib/module/NativeBeekonRn.js.map +1 -1
- package/lib/module/beekon.js +198 -46
- package/lib/module/beekon.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/internal/mappers.js +122 -28
- package/lib/module/internal/mappers.js.map +1 -1
- package/lib/module/types/config.js +2 -0
- package/lib/module/types/enums.js +2 -0
- package/lib/module/types/enums.js.map +1 -0
- package/lib/module/types/error.js +10 -4
- package/lib/module/types/error.js.map +1 -1
- package/lib/module/types/geofence.js +2 -0
- package/lib/module/types/geofence.js.map +1 -0
- package/lib/module/types/location.js +2 -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 +102 -20
- package/lib/typescript/src/NativeBeekonRn.d.ts.map +1 -1
- package/lib/typescript/src/beekon.d.ts +81 -33
- package/lib/typescript/src/beekon.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +5 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/internal/mappers.d.ts +12 -6
- package/lib/typescript/src/internal/mappers.d.ts.map +1 -1
- package/lib/typescript/src/types/config.d.ts +50 -20
- 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 +11 -5
- package/lib/typescript/src/types/error.d.ts.map +1 -1
- 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 +22 -8
- package/lib/typescript/src/types/location.d.ts.map +1 -1
- package/lib/typescript/src/types/state.d.ts +13 -4
- 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 +4 -5
- package/scripts/fetch-beekonkit.sh +5 -5
- package/src/NativeBeekonRn.ts +110 -20
- package/src/beekon.ts +219 -49
- package/src/index.tsx +21 -2
- package/src/internal/mappers.ts +187 -30
- package/src/types/config.ts +52 -20
- package/src/types/enums.ts +64 -0
- package/src/types/error.ts +11 -8
- package/src/types/geofence.ts +37 -0
- package/src/types/location.ts +28 -8
- package/src/types/state.ts +13 -3
- package/src/types/sync.ts +23 -0
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeDirectory +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeRequirements +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeResources +0 -296
- package/ios/Frameworks/BeekonKit.xcframework/_CodeSignature/CodeSignature +0 -0
- package/ios/Frameworks/BeekonKit.xcframework/ios-arm64/BeekonKit.framework/_CodeSignature/CodeResources +0 -146
|
@@ -3,54 +3,65 @@ package `in`.wayq.beekonrn
|
|
|
3
3
|
import com.facebook.react.bridge.Arguments
|
|
4
4
|
import com.facebook.react.bridge.Promise
|
|
5
5
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.bridge.ReadableArray
|
|
6
7
|
import com.facebook.react.bridge.ReadableMap
|
|
7
8
|
import com.facebook.react.bridge.WritableArray
|
|
8
9
|
import com.facebook.react.bridge.WritableMap
|
|
10
|
+
import `in`.wayq.beekon.AccuracyMode
|
|
11
|
+
import `in`.wayq.beekon.ActivityType
|
|
9
12
|
import `in`.wayq.beekon.Beekon
|
|
10
13
|
import `in`.wayq.beekon.BeekonConfig
|
|
11
|
-
import `in`.wayq.beekon.
|
|
14
|
+
import `in`.wayq.beekon.BeekonException
|
|
15
|
+
import `in`.wayq.beekon.BeekonGeofence
|
|
12
16
|
import `in`.wayq.beekon.BeekonState
|
|
17
|
+
import `in`.wayq.beekon.GeofenceEvent
|
|
13
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
|
|
14
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
|
|
15
29
|
import java.time.Instant
|
|
16
30
|
import kotlinx.coroutines.CoroutineScope
|
|
17
31
|
import kotlinx.coroutines.Dispatchers
|
|
18
|
-
import kotlinx.coroutines.Job
|
|
19
32
|
import kotlinx.coroutines.SupervisorJob
|
|
20
33
|
import kotlinx.coroutines.cancel
|
|
21
34
|
import kotlinx.coroutines.launch
|
|
22
35
|
|
|
23
|
-
class BeekonRnModule(
|
|
36
|
+
class BeekonRnModule(reactContext: ReactApplicationContext) :
|
|
24
37
|
NativeBeekonRnSpec(reactContext) {
|
|
25
38
|
|
|
26
39
|
// 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
|
-
//
|
|
29
|
-
//
|
|
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.
|
|
30
43
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
|
31
|
-
private var stateJob: Job? = null
|
|
32
|
-
private var locationsJob: Job? = null
|
|
33
44
|
|
|
34
45
|
init {
|
|
35
|
-
// Beekon.initialize
|
|
36
|
-
|
|
37
|
-
Beekon.
|
|
38
|
-
|
|
39
|
-
Beekon.
|
|
40
|
-
}
|
|
41
|
-
locationsJob = scope.launch {
|
|
42
|
-
Beekon.locations.collect { loc -> emitOnLocation(locationToWire(loc)) }
|
|
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)) }
|
|
43
51
|
}
|
|
52
|
+
scope.launch { Beekon.syncStatus.collect { emitOnSyncStatus(syncStatusToWire(it)) } }
|
|
44
53
|
}
|
|
45
54
|
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Lifecycle (non-suspend native calls resolve directly)
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
|
|
46
59
|
override fun configure(config: ReadableMap, promise: Promise) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
promise.reject(errorCode(t), t.message ?: "configure failed", t)
|
|
53
|
-
}
|
|
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)
|
|
54
65
|
}
|
|
55
66
|
}
|
|
56
67
|
|
|
@@ -76,17 +87,108 @@ class BeekonRnModule(private val reactContext: ReactApplicationContext) :
|
|
|
76
87
|
}
|
|
77
88
|
}
|
|
78
89
|
|
|
79
|
-
|
|
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) {
|
|
80
108
|
scope.launch {
|
|
81
109
|
try {
|
|
82
110
|
val from = Instant.ofEpochMilli(fromMs.toLong())
|
|
83
111
|
val to = Instant.ofEpochMilli(toMs.toLong())
|
|
84
|
-
val locations = Beekon.history(from, to)
|
|
85
112
|
val arr: WritableArray = Arguments.createArray()
|
|
86
|
-
for (loc in
|
|
113
|
+
for (loc in Beekon.getLocations(from, to)) arr.pushMap(locationToWire(loc))
|
|
87
114
|
promise.resolve(arr)
|
|
88
115
|
} catch (t: Throwable) {
|
|
89
|
-
promise.reject(errorCode(t), t.message ?: "
|
|
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)
|
|
90
192
|
}
|
|
91
193
|
}
|
|
92
194
|
}
|
|
@@ -97,54 +199,126 @@ class BeekonRnModule(private val reactContext: ReactApplicationContext) :
|
|
|
97
199
|
}
|
|
98
200
|
|
|
99
201
|
// ---------------------------------------------------------------------------
|
|
100
|
-
// Mappers (
|
|
202
|
+
// Mappers: wire (ReadableMap/Array) → Kotlin
|
|
101
203
|
// ---------------------------------------------------------------------------
|
|
102
204
|
|
|
103
205
|
private fun wireToConfig(map: ReadableMap): BeekonConfig {
|
|
104
|
-
val
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
+
}
|
|
109
218
|
return BeekonConfig(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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(),
|
|
113
229
|
)
|
|
114
230
|
}
|
|
115
231
|
|
|
116
|
-
private fun
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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)
|
|
130
250
|
}
|
|
131
|
-
return BeekonConfig.Notification(title = title, text = text, smallIcon = smallIcon)
|
|
132
251
|
}
|
|
133
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
|
+
|
|
134
285
|
private fun locationToWire(loc: Location): WritableMap {
|
|
135
286
|
val m = Arguments.createMap()
|
|
136
|
-
m.
|
|
137
|
-
m.putDouble("
|
|
287
|
+
m.putString("id", loc.id)
|
|
288
|
+
m.putDouble("lat", loc.latitude)
|
|
289
|
+
m.putDouble("lng", loc.longitude)
|
|
138
290
|
m.putDouble("timestampMs", loc.timestamp.toEpochMilli().toDouble())
|
|
139
291
|
putNullableDouble(m, "accuracy", loc.accuracy)
|
|
140
292
|
putNullableDouble(m, "speed", loc.speed)
|
|
141
293
|
putNullableDouble(m, "bearing", loc.bearing)
|
|
142
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)
|
|
143
301
|
return m
|
|
144
302
|
}
|
|
145
303
|
|
|
146
|
-
private fun
|
|
147
|
-
|
|
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
|
|
148
322
|
}
|
|
149
323
|
|
|
150
324
|
private fun stateToWire(s: BeekonState): WritableMap {
|
|
@@ -160,19 +334,91 @@ class BeekonRnModule(private val reactContext: ReactApplicationContext) :
|
|
|
160
334
|
return m
|
|
161
335
|
}
|
|
162
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
|
+
|
|
163
370
|
private fun stopReasonToWire(r: StopReason): String = when (r) {
|
|
164
371
|
StopReason.User -> "user"
|
|
165
372
|
StopReason.PermissionDenied -> "permissionDenied"
|
|
166
373
|
StopReason.LocationServicesDisabled -> "locationServicesDisabled"
|
|
374
|
+
StopReason.LocationUnavailable -> "locationUnavailable"
|
|
167
375
|
StopReason.System -> "system"
|
|
168
376
|
}
|
|
169
377
|
|
|
170
|
-
|
|
171
|
-
|
|
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.
|
|
172
419
|
private fun errorCode(t: Throwable): String = when (t) {
|
|
173
|
-
is
|
|
174
|
-
is
|
|
175
|
-
is BeekonError.StorageFailure -> "STORAGE_FAILURE"
|
|
420
|
+
is BeekonException.StorageException -> "STORAGE_FAILURE"
|
|
421
|
+
is BeekonException.InvalidGeofence -> "INVALID_GEOFENCE"
|
|
176
422
|
else -> "INTERNAL_ERROR"
|
|
177
423
|
}
|
|
178
424
|
|
package/ios/BeekonRn.mm
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
#import "BeekonRn.h"
|
|
2
|
-
// Auto-generated
|
|
3
|
-
//
|
|
4
|
-
//
|
|
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>)
|
|
5
7
|
#import <BeekonRn/BeekonRn-Swift.h>
|
|
8
|
+
#else
|
|
9
|
+
#import "BeekonRn-Swift.h"
|
|
10
|
+
#endif
|
|
6
11
|
|
|
7
12
|
@implementation BeekonRn {
|
|
8
13
|
BeekonRnImpl *_impl;
|
|
@@ -13,32 +18,43 @@
|
|
|
13
18
|
if (self) {
|
|
14
19
|
__weak __typeof(self) weakSelf = self;
|
|
15
20
|
_impl = [[BeekonRnImpl alloc]
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
+
}];
|
|
22
33
|
}
|
|
23
34
|
return self;
|
|
24
35
|
}
|
|
25
36
|
|
|
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.
|
|
26
39
|
- (void)invalidate {
|
|
27
40
|
[_impl invalidate];
|
|
28
|
-
[super invalidate];
|
|
29
41
|
}
|
|
30
42
|
|
|
31
|
-
|
|
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
|
|
32
53
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
33
54
|
reject:(RCTPromiseRejectBlock)reject {
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
NSDictionary *dict = @{
|
|
38
|
-
@"intervalSeconds": @(config.intervalSeconds()),
|
|
39
|
-
@"distanceMeters": @(config.distanceMeters()),
|
|
40
|
-
};
|
|
41
|
-
[_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];
|
|
42
58
|
}
|
|
43
59
|
|
|
44
60
|
- (void)start:(RCTPromiseResolveBlock)resolve
|
|
@@ -51,11 +67,61 @@
|
|
|
51
67
|
[_impl stopWithResolver:resolve rejecter:reject];
|
|
52
68
|
}
|
|
53
69
|
|
|
54
|
-
- (void)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
- (void)listGeofences:(RCTPromiseResolveBlock)resolve
|
|
123
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
124
|
+
[_impl listGeofencesWithResolver:resolve rejecter:reject];
|
|
59
125
|
}
|
|
60
126
|
|
|
61
127
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|