@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/src/internal/mappers.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import type { BeekonConfig } from '../types/config';
|
|
2
|
-
import type { BeekonState,
|
|
3
|
-
import type {
|
|
4
|
-
import
|
|
2
|
+
import type { BeekonState, StopReason } from '../types/state';
|
|
3
|
+
import type { Location } from '../types/location';
|
|
4
|
+
import { BeekonError, type BeekonErrorKind } from '../types/error';
|
|
5
|
+
import type { WireConfig, WireLocation, WireState } from '../NativeBeekonRn';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_INTERVAL_SECONDS = 30;
|
|
8
|
+
const DEFAULT_DISTANCE_METERS = 100;
|
|
5
9
|
|
|
6
10
|
export function configToWire(config: BeekonConfig): WireConfig {
|
|
7
11
|
return {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
intervalMillis: config.intervalMillis,
|
|
12
|
+
intervalSeconds: config.intervalSeconds ?? DEFAULT_INTERVAL_SECONDS,
|
|
13
|
+
distanceMeters: config.distanceMeters ?? DEFAULT_DISTANCE_METERS,
|
|
11
14
|
androidNotification: config.androidNotification,
|
|
12
|
-
licenseKey: config.licenseKey,
|
|
13
15
|
};
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
export function
|
|
18
|
+
export function wireToLocation(w: WireLocation): Location {
|
|
17
19
|
return {
|
|
18
20
|
lat: w.lat,
|
|
19
21
|
lng: w.lng,
|
|
@@ -25,26 +27,58 @@ export function wireToPosition(w: WirePosition): Position {
|
|
|
25
27
|
};
|
|
26
28
|
}
|
|
27
29
|
|
|
28
|
-
function
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
function toStopReason(s: string | undefined): StopReason {
|
|
31
|
+
switch (s) {
|
|
32
|
+
case 'user':
|
|
33
|
+
case 'permissionDenied':
|
|
34
|
+
case 'locationServicesDisabled':
|
|
35
|
+
case 'system':
|
|
36
|
+
return s;
|
|
37
|
+
default:
|
|
38
|
+
// Defensive — native should never emit an unknown reason.
|
|
39
|
+
return 'user';
|
|
40
|
+
}
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
export function wireToState(w: WireState): BeekonState {
|
|
34
44
|
switch (w.type) {
|
|
35
45
|
case 'idle':
|
|
36
46
|
return { kind: 'idle' };
|
|
37
|
-
case 'starting':
|
|
38
|
-
return { kind: 'starting' };
|
|
39
47
|
case 'tracking':
|
|
40
48
|
return { kind: 'tracking' };
|
|
41
|
-
case 'paused':
|
|
42
|
-
return { kind: 'paused', reason: toPauseReason(w.pauseReason) };
|
|
43
49
|
case 'stopped':
|
|
44
|
-
return { kind: 'stopped' };
|
|
50
|
+
return { kind: 'stopped', reason: toStopReason(w.stopReason) };
|
|
45
51
|
default:
|
|
46
|
-
//
|
|
47
|
-
// forward-compat: treat as idle rather than throwing.
|
|
52
|
+
// Forward-compat: treat unknown as idle rather than throwing.
|
|
48
53
|
return { kind: 'idle' };
|
|
49
54
|
}
|
|
50
55
|
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Re-throw a native promise rejection as a typed `BeekonError`. Native modules
|
|
59
|
+
* encode the kind in the error code string (`PERMISSION_DENIED`,
|
|
60
|
+
* `LOCATION_SERVICES_DISABLED`, `STORAGE_FAILURE`); anything else falls
|
|
61
|
+
* through as the original error.
|
|
62
|
+
*/
|
|
63
|
+
export function rethrowAsBeekonError(e: unknown): never {
|
|
64
|
+
const code = (e as { code?: string } | undefined)?.code;
|
|
65
|
+
const message = (e as { message?: string } | undefined)?.message ?? String(e);
|
|
66
|
+
const kind = codeToKind(code);
|
|
67
|
+
if (kind) {
|
|
68
|
+
throw new BeekonError(kind, message);
|
|
69
|
+
}
|
|
70
|
+
throw e;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function codeToKind(code: string | undefined): BeekonErrorKind | undefined {
|
|
74
|
+
switch (code) {
|
|
75
|
+
case 'PERMISSION_DENIED':
|
|
76
|
+
return 'permissionDenied';
|
|
77
|
+
case 'LOCATION_SERVICES_DISABLED':
|
|
78
|
+
return 'locationServicesDisabled';
|
|
79
|
+
case 'STORAGE_FAILURE':
|
|
80
|
+
return 'storageFailure';
|
|
81
|
+
default:
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
}
|
package/src/types/config.ts
CHANGED
|
@@ -1,42 +1,33 @@
|
|
|
1
|
-
import type { Preset } from './preset';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
* Foreground
|
|
5
|
-
* because
|
|
6
|
-
*
|
|
2
|
+
* Foreground-service notification overrides. Android-only — required by the
|
|
3
|
+
* platform because every location foreground service must show a persistent
|
|
4
|
+
* notification. All fields are optional; missing values resolve at runtime
|
|
5
|
+
* against the host app's label and icon. Ignored on iOS.
|
|
7
6
|
*/
|
|
8
7
|
export type AndroidNotificationConfig = {
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
/** Foreground notification id. Must be > 0. */
|
|
14
|
-
notificationId: number;
|
|
15
|
-
/** Notification title shown in the status bar. */
|
|
16
|
-
title: string;
|
|
17
|
-
/** Notification body text. */
|
|
18
|
-
text: string;
|
|
8
|
+
/** Notification title. Defaults to "Location active". */
|
|
9
|
+
title?: string;
|
|
10
|
+
/** Notification body text. Defaults to the host app's label. */
|
|
11
|
+
text?: string;
|
|
19
12
|
/**
|
|
20
|
-
* Drawable resource name
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* `
|
|
13
|
+
* Drawable resource name (e.g. `ic_notification`) — resolved at runtime via
|
|
14
|
+
* `Resources.getIdentifier()` against the host app's `res/drawable*` folders.
|
|
15
|
+
* Pass the resource name without extension or `R.drawable.` prefix. Defaults
|
|
16
|
+
* to the host app's `applicationInfo.icon`.
|
|
24
17
|
*/
|
|
25
|
-
smallIconResName
|
|
18
|
+
smallIconResName?: string;
|
|
26
19
|
};
|
|
27
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Tracking configuration. Two knobs: a minimum time interval and a minimum
|
|
23
|
+
* distance between emitted fixes. A fix is admitted only when **both** gates
|
|
24
|
+
* are satisfied. Pass `0` to disable a gate.
|
|
25
|
+
*/
|
|
28
26
|
export type BeekonConfig = {
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
intervalMillis?: number;
|
|
35
|
-
/**
|
|
36
|
-
* Required when running on Android. Ignored on iOS. The plugin throws
|
|
37
|
-
* `NOT_CONFIGURED` if missing on Android.
|
|
38
|
-
*/
|
|
27
|
+
/** Minimum seconds between admitted fixes. Default: `30`. `0` disables the time gate. */
|
|
28
|
+
intervalSeconds?: number;
|
|
29
|
+
/** Minimum metres between admitted fixes. Default: `100`. `0` disables the distance gate. */
|
|
30
|
+
distanceMeters?: number;
|
|
31
|
+
/** Android-only notification overrides. Ignored on iOS. */
|
|
39
32
|
androidNotification?: AndroidNotificationConfig;
|
|
40
|
-
/** Optional license key. Reserved for future use. */
|
|
41
|
-
licenseKey?: string;
|
|
42
33
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error kinds thrown from `Beekon.start()` / `Beekon.history()`. Match the
|
|
3
|
+
* native `BeekonError` cases byte-for-byte.
|
|
4
|
+
*/
|
|
5
|
+
export type BeekonErrorKind =
|
|
6
|
+
| 'permissionDenied'
|
|
7
|
+
| 'locationServicesDisabled'
|
|
8
|
+
| 'storageFailure';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Typed error surfaced from the bridge. The native module rejects promises
|
|
12
|
+
* with the kind encoded as the error code; the facade re-wraps into this.
|
|
13
|
+
*/
|
|
14
|
+
export class BeekonError extends Error {
|
|
15
|
+
public readonly kind: BeekonErrorKind;
|
|
16
|
+
|
|
17
|
+
constructor(kind: BeekonErrorKind, message: string) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = 'BeekonError';
|
|
20
|
+
this.kind = kind;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A single location fix as emitted by the native SDK after gating. Fields map
|
|
3
|
+
* 1:1 to `in.wayq.beekon.Location` on Android and `BeekonKit.Location` on iOS.
|
|
4
|
+
*
|
|
5
|
+
* `lat`, `lng`, and `timestamp` are always present. The four optional fields
|
|
6
|
+
* are `null` when the OS did not report a value — the SDK never invents a
|
|
7
|
+
* value to mask absence (e.g. a stationary device returns `bearing === null`,
|
|
8
|
+
* not `0`).
|
|
9
|
+
*/
|
|
10
|
+
export type Location = {
|
|
11
|
+
/** Latitude in degrees, WGS-84. */
|
|
12
|
+
lat: number;
|
|
13
|
+
/** Longitude in degrees, WGS-84. */
|
|
14
|
+
lng: number;
|
|
15
|
+
/** Horizontal accuracy in meters (1-sigma); `null` if unreported. */
|
|
16
|
+
accuracy: number | null;
|
|
17
|
+
/** Speed in m/s; `null` if unreported. */
|
|
18
|
+
speed: number | null;
|
|
19
|
+
/** Bearing in degrees `[0, 360)` clockwise from true north; `null` if unreported. */
|
|
20
|
+
bearing: number | null;
|
|
21
|
+
/** Altitude in meters above the WGS-84 ellipsoid; `null` if unreported. */
|
|
22
|
+
altitude: number | null;
|
|
23
|
+
/** Time the OS provider reported this fix (not when JS received it). */
|
|
24
|
+
timestamp: Date;
|
|
25
|
+
};
|
package/src/types/state.ts
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Reason a tracking session ended. Mirrors `StopReason` on both platforms.
|
|
3
|
+
*
|
|
4
|
+
* `'system'` is Android-only — surfaces when the OS terminates the foreground
|
|
5
|
+
* service (memory pressure, force-stop). iOS will never emit `'system'`.
|
|
4
6
|
*/
|
|
5
|
-
export type
|
|
7
|
+
export type StopReason =
|
|
8
|
+
| 'user'
|
|
9
|
+
| 'permissionDenied'
|
|
10
|
+
| 'locationServicesDisabled'
|
|
11
|
+
| 'system';
|
|
6
12
|
|
|
7
13
|
/**
|
|
8
|
-
* Tracking state. Mirrors the native `BeekonState` sealed
|
|
14
|
+
* Tracking state. Mirrors the native `BeekonState` sealed type on both
|
|
9
15
|
* platforms. Use the `kind` field as a discriminator.
|
|
16
|
+
*
|
|
17
|
+
* Lifecycle: `idle → tracking → stopped(reason)`.
|
|
10
18
|
*/
|
|
11
19
|
export type BeekonState =
|
|
12
20
|
| { kind: 'idle' }
|
|
13
|
-
| { kind: 'starting' }
|
|
14
21
|
| { kind: 'tracking' }
|
|
15
|
-
| { kind: '
|
|
16
|
-
| { kind: 'stopped' };
|
|
22
|
+
| { kind: 'stopped'; reason: StopReason };
|
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
package com.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 com.wayq.beekon.Beekon
|
|
10
|
-
import com.wayq.beekon.BeekonConfig
|
|
11
|
-
import com.wayq.beekon.BeekonError
|
|
12
|
-
import com.wayq.beekon.BeekonState
|
|
13
|
-
import com.wayq.beekon.NotificationConfig
|
|
14
|
-
import com.wayq.beekon.PauseReason
|
|
15
|
-
import com.wayq.beekon.Position
|
|
16
|
-
import com.wayq.beekon.Preset
|
|
17
|
-
import java.time.Instant
|
|
18
|
-
import kotlinx.coroutines.CoroutineScope
|
|
19
|
-
import kotlinx.coroutines.Dispatchers
|
|
20
|
-
import kotlinx.coroutines.Job
|
|
21
|
-
import kotlinx.coroutines.SupervisorJob
|
|
22
|
-
import kotlinx.coroutines.cancel
|
|
23
|
-
import kotlinx.coroutines.flow.collect
|
|
24
|
-
import kotlinx.coroutines.launch
|
|
25
|
-
|
|
26
|
-
class BeekonRnModule(private val reactContext: ReactApplicationContext) :
|
|
27
|
-
NativeBeekonRnSpec(reactContext) {
|
|
28
|
-
|
|
29
|
-
// Default dispatcher (not Main.immediate) — Codegen's emitOnX is thread-safe
|
|
30
|
-
// and marshals to JS internally, so collecting on Main buys nothing and
|
|
31
|
-
// risks jank if any mapper does work. SupervisorJob so a single failure
|
|
32
|
-
// doesn't tear down siblings.
|
|
33
|
-
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
|
34
|
-
private var stateJob: Job? = null
|
|
35
|
-
private var positionsJob: Job? = null
|
|
36
|
-
|
|
37
|
-
override fun initialize(promise: Promise) {
|
|
38
|
-
scope.launch {
|
|
39
|
-
try {
|
|
40
|
-
Beekon.initialize(reactContext.applicationContext)
|
|
41
|
-
|
|
42
|
-
// Idempotent: re-init replaces collectors. Native flows are hot
|
|
43
|
-
// (StateFlow / SharedFlow) so resubscription replays the latest value.
|
|
44
|
-
stateJob?.cancel()
|
|
45
|
-
positionsJob?.cancel()
|
|
46
|
-
stateJob = scope.launch {
|
|
47
|
-
Beekon.state.collect { s -> emitOnState(stateToWire(s)) }
|
|
48
|
-
}
|
|
49
|
-
positionsJob = scope.launch {
|
|
50
|
-
Beekon.positions.collect { p -> emitOnPosition(positionToWire(p)) }
|
|
51
|
-
}
|
|
52
|
-
promise.resolve(null)
|
|
53
|
-
} catch (t: Throwable) {
|
|
54
|
-
promise.reject(errorCode(t), t.message ?: "init failed", t)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
override fun configure(config: ReadableMap, promise: Promise) {
|
|
60
|
-
scope.launch {
|
|
61
|
-
try {
|
|
62
|
-
Beekon.configure(wireToConfig(config))
|
|
63
|
-
promise.resolve(null)
|
|
64
|
-
} catch (t: Throwable) {
|
|
65
|
-
promise.reject(errorCode(t), t.message ?: "configure failed", t)
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
override fun start(promise: Promise) {
|
|
71
|
-
scope.launch {
|
|
72
|
-
try {
|
|
73
|
-
Beekon.start()
|
|
74
|
-
promise.resolve(null)
|
|
75
|
-
} catch (t: Throwable) {
|
|
76
|
-
promise.reject(errorCode(t), t.message ?: "start failed", t)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
override fun stop(promise: Promise) {
|
|
82
|
-
scope.launch {
|
|
83
|
-
try {
|
|
84
|
-
Beekon.stop()
|
|
85
|
-
promise.resolve(null)
|
|
86
|
-
} catch (t: Throwable) {
|
|
87
|
-
promise.reject(errorCode(t), t.message ?: "stop failed", t)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
override fun shutdown(promise: Promise) {
|
|
93
|
-
scope.launch {
|
|
94
|
-
try {
|
|
95
|
-
stateJob?.cancel()
|
|
96
|
-
positionsJob?.cancel()
|
|
97
|
-
Beekon.shutdown()
|
|
98
|
-
promise.resolve(null)
|
|
99
|
-
} catch (t: Throwable) {
|
|
100
|
-
promise.reject(errorCode(t), t.message ?: "shutdown failed", t)
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
override fun history(fromMs: Double, toMs: Double, promise: Promise) {
|
|
106
|
-
scope.launch {
|
|
107
|
-
try {
|
|
108
|
-
val from = Instant.ofEpochMilli(fromMs.toLong())
|
|
109
|
-
val to = Instant.ofEpochMilli(toMs.toLong())
|
|
110
|
-
val positions = Beekon.history(from, to)
|
|
111
|
-
val arr: WritableArray = Arguments.createArray()
|
|
112
|
-
for (p in positions) arr.pushMap(positionToWire(p))
|
|
113
|
-
promise.resolve(arr)
|
|
114
|
-
} catch (t: Throwable) {
|
|
115
|
-
promise.reject(errorCode(t), t.message ?: "history failed", t)
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
override fun invalidate() {
|
|
121
|
-
super.invalidate()
|
|
122
|
-
scope.cancel()
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// ---------------------------------------------------------------------------
|
|
126
|
-
// Mappers (Wire ↔ Kotlin types)
|
|
127
|
-
// ---------------------------------------------------------------------------
|
|
128
|
-
|
|
129
|
-
private fun wireToConfig(map: ReadableMap): BeekonConfig {
|
|
130
|
-
val preset = when (map.getString("preset")) {
|
|
131
|
-
"saver" -> Preset.Saver
|
|
132
|
-
"precision" -> Preset.Precision
|
|
133
|
-
else -> Preset.Balanced
|
|
134
|
-
}
|
|
135
|
-
val distanceFilterMeters =
|
|
136
|
-
if (map.hasKey("distanceFilterMeters") && !map.isNull("distanceFilterMeters"))
|
|
137
|
-
map.getDouble("distanceFilterMeters").toFloat()
|
|
138
|
-
else null
|
|
139
|
-
val intervalMillis =
|
|
140
|
-
if (map.hasKey("intervalMillis") && !map.isNull("intervalMillis"))
|
|
141
|
-
map.getDouble("intervalMillis").toLong()
|
|
142
|
-
else null
|
|
143
|
-
val notifMap = map.getMap("androidNotification")
|
|
144
|
-
?: throw IllegalArgumentException(
|
|
145
|
-
"androidNotification is required when running on Android"
|
|
146
|
-
)
|
|
147
|
-
val licenseKey =
|
|
148
|
-
if (map.hasKey("licenseKey") && !map.isNull("licenseKey"))
|
|
149
|
-
map.getString("licenseKey")
|
|
150
|
-
else null
|
|
151
|
-
|
|
152
|
-
return BeekonConfig(
|
|
153
|
-
preset = preset,
|
|
154
|
-
distanceFilterMeters = distanceFilterMeters,
|
|
155
|
-
intervalMillis = intervalMillis,
|
|
156
|
-
notification = wireToNotificationConfig(notifMap),
|
|
157
|
-
licenseKey = licenseKey,
|
|
158
|
-
)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
private fun wireToNotificationConfig(map: ReadableMap): NotificationConfig {
|
|
162
|
-
val resName = map.getString("smallIconResName")
|
|
163
|
-
?: throw IllegalArgumentException("smallIconResName is required")
|
|
164
|
-
val pkg = reactContext.packageName
|
|
165
|
-
val iconId = reactContext.resources.getIdentifier(resName, "drawable", pkg)
|
|
166
|
-
if (iconId == 0) {
|
|
167
|
-
throw IllegalArgumentException(
|
|
168
|
-
"drawable resource '$resName' not found in package '$pkg'"
|
|
169
|
-
)
|
|
170
|
-
}
|
|
171
|
-
return NotificationConfig(
|
|
172
|
-
channelId = map.getString("channelId")
|
|
173
|
-
?: throw IllegalArgumentException("channelId is required"),
|
|
174
|
-
channelName = map.getString("channelName")
|
|
175
|
-
?: throw IllegalArgumentException("channelName is required"),
|
|
176
|
-
notificationId = map.getInt("notificationId"),
|
|
177
|
-
title = map.getString("title")
|
|
178
|
-
?: throw IllegalArgumentException("title is required"),
|
|
179
|
-
text = map.getString("text")
|
|
180
|
-
?: throw IllegalArgumentException("text is required"),
|
|
181
|
-
smallIcon = iconId,
|
|
182
|
-
)
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
private fun positionToWire(p: Position): WritableMap {
|
|
186
|
-
val m = Arguments.createMap()
|
|
187
|
-
m.putDouble("lat", p.lat)
|
|
188
|
-
m.putDouble("lng", p.lng)
|
|
189
|
-
m.putDouble("accuracy", p.accuracy.toDouble())
|
|
190
|
-
m.putDouble("speed", p.speed.toDouble())
|
|
191
|
-
m.putDouble("bearing", p.bearing.toDouble())
|
|
192
|
-
m.putDouble("altitude", p.altitude)
|
|
193
|
-
m.putDouble("timestampMs", p.timestamp.toEpochMilli().toDouble())
|
|
194
|
-
return m
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
private fun stateToWire(s: BeekonState): WritableMap {
|
|
198
|
-
val m = Arguments.createMap()
|
|
199
|
-
when (s) {
|
|
200
|
-
BeekonState.Idle -> m.putString("type", "idle")
|
|
201
|
-
BeekonState.Starting -> m.putString("type", "starting")
|
|
202
|
-
BeekonState.Tracking -> m.putString("type", "tracking")
|
|
203
|
-
is BeekonState.Paused -> {
|
|
204
|
-
m.putString("type", "paused")
|
|
205
|
-
m.putString("pauseReason", pauseReasonToWire(s.reason))
|
|
206
|
-
}
|
|
207
|
-
BeekonState.Stopped -> m.putString("type", "stopped")
|
|
208
|
-
}
|
|
209
|
-
return m
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
private fun pauseReasonToWire(r: PauseReason): String = when (r) {
|
|
213
|
-
PauseReason.PermissionRevoked -> "permissionRevoked"
|
|
214
|
-
PauseReason.LocationDisabled -> "locationDisabled"
|
|
215
|
-
PauseReason.Unknown -> "unknown"
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Maps native error sealed types to stable JS-side codes. Same code strings
|
|
219
|
-
// on iOS so JS can switch on them platform-agnostically.
|
|
220
|
-
private fun errorCode(t: Throwable): String = when (t) {
|
|
221
|
-
is BeekonError.NotInitialised -> "NOT_INITIALISED"
|
|
222
|
-
is BeekonError.NotConfigured -> "NOT_CONFIGURED"
|
|
223
|
-
is BeekonError.PermissionDenied -> "PERMISSION_DENIED"
|
|
224
|
-
is BeekonError.NoGmsAvailable -> "NO_GMS_AVAILABLE"
|
|
225
|
-
is BeekonError.ServiceFailed -> "SERVICE_FAILED"
|
|
226
|
-
is BeekonError.InternalError -> "INTERNAL_ERROR"
|
|
227
|
-
else -> "INTERNAL_ERROR"
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
companion object {
|
|
231
|
-
const val NAME = NativeBeekonRnSpec.NAME
|
|
232
|
-
}
|
|
233
|
-
}
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["types/preset.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A single location fix as emitted by the native SDK after gating. Fields map
|
|
3
|
-
* 1:1 to `com.wayq.beekon.Position` on Android and `Beekon.Position` on iOS.
|
|
4
|
-
*
|
|
5
|
-
* The SDK does NOT smooth or filter positions beyond the gate — values are
|
|
6
|
-
* forwarded as the OS provider reported them (raw passthrough).
|
|
7
|
-
*/
|
|
8
|
-
export type Position = {
|
|
9
|
-
/** Latitude in degrees, WGS-84. */
|
|
10
|
-
lat: number;
|
|
11
|
-
/** Longitude in degrees, WGS-84. */
|
|
12
|
-
lng: number;
|
|
13
|
-
/** Horizontal accuracy in meters (1-sigma). */
|
|
14
|
-
accuracy: number;
|
|
15
|
-
/** Speed in m/s. May be 0 if the OS provider doesn't supply it. */
|
|
16
|
-
speed: number;
|
|
17
|
-
/** Bearing in degrees clockwise from true north. */
|
|
18
|
-
bearing: number;
|
|
19
|
-
/** Altitude in meters above the WGS-84 ellipsoid. */
|
|
20
|
-
altitude: number;
|
|
21
|
-
/** Time the OS provider reported this fix (not when JS received it). */
|
|
22
|
-
timestamp: Date;
|
|
23
|
-
};
|
|
24
|
-
//# sourceMappingURL=position.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"position.d.ts","sourceRoot":"","sources":["../../../../src/types/position.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,SAAS,EAAE,IAAI,CAAC;CACjB,CAAC"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sampling preset. Determines the gating interval and distance threshold the
|
|
3
|
-
* native SDK uses before emitting a position. Per `docs/REQUIREMENTS.md`:
|
|
4
|
-
*
|
|
5
|
-
* | Preset | Interval | Distance | Battery (typical) |
|
|
6
|
-
* |-----------|----------|----------|-------------------|
|
|
7
|
-
* | saver | 60_000ms | 150 m | 3–8% |
|
|
8
|
-
* | balanced | 30_000ms | 100 m | 5–10% |
|
|
9
|
-
* | precision | 10_000ms | 30 m | 15–25% |
|
|
10
|
-
*/
|
|
11
|
-
export type Preset = 'saver' | 'balanced' | 'precision';
|
|
12
|
-
//# sourceMappingURL=preset.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../../../../src/types/preset.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,CAAC"}
|
package/src/types/position.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A single location fix as emitted by the native SDK after gating. Fields map
|
|
3
|
-
* 1:1 to `com.wayq.beekon.Position` on Android and `Beekon.Position` on iOS.
|
|
4
|
-
*
|
|
5
|
-
* The SDK does NOT smooth or filter positions beyond the gate — values are
|
|
6
|
-
* forwarded as the OS provider reported them (raw passthrough).
|
|
7
|
-
*/
|
|
8
|
-
export type Position = {
|
|
9
|
-
/** Latitude in degrees, WGS-84. */
|
|
10
|
-
lat: number;
|
|
11
|
-
/** Longitude in degrees, WGS-84. */
|
|
12
|
-
lng: number;
|
|
13
|
-
/** Horizontal accuracy in meters (1-sigma). */
|
|
14
|
-
accuracy: number;
|
|
15
|
-
/** Speed in m/s. May be 0 if the OS provider doesn't supply it. */
|
|
16
|
-
speed: number;
|
|
17
|
-
/** Bearing in degrees clockwise from true north. */
|
|
18
|
-
bearing: number;
|
|
19
|
-
/** Altitude in meters above the WGS-84 ellipsoid. */
|
|
20
|
-
altitude: number;
|
|
21
|
-
/** Time the OS provider reported this fix (not when JS received it). */
|
|
22
|
-
timestamp: Date;
|
|
23
|
-
};
|
package/src/types/preset.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sampling preset. Determines the gating interval and distance threshold the
|
|
3
|
-
* native SDK uses before emitting a position. Per `docs/REQUIREMENTS.md`:
|
|
4
|
-
*
|
|
5
|
-
* | Preset | Interval | Distance | Battery (typical) |
|
|
6
|
-
* |-----------|----------|----------|-------------------|
|
|
7
|
-
* | saver | 60_000ms | 150 m | 3–8% |
|
|
8
|
-
* | balanced | 30_000ms | 100 m | 5–10% |
|
|
9
|
-
* | precision | 10_000ms | 30 m | 15–25% |
|
|
10
|
-
*/
|
|
11
|
-
export type Preset = 'saver' | 'balanced' | 'precision';
|