react-native-nitro-compass 1.0.9 → 1.2.0
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/README.md +166 -20
- package/android/src/main/java/com/margelo/nitro/nitrocompass/HybridNitroCompass.kt +718 -105
- package/ios/HybridNitroCompass.swift +119 -6
- package/lib/commonjs/hook.js +102 -11
- package/lib/commonjs/hook.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/multiplex.js +23 -2
- package/lib/commonjs/multiplex.js.map +1 -1
- package/lib/module/hook.js +103 -12
- package/lib/module/hook.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/multiplex.js +23 -2
- package/lib/module/multiplex.js.map +1 -1
- package/lib/typescript/src/hook.d.ts +49 -1
- package/lib/typescript/src/hook.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/multiplex.d.ts.map +1 -1
- package/lib/typescript/src/specs/NitroCompass.nitro.d.ts +158 -18
- package/lib/typescript/src/specs/NitroCompass.nitro.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JCompassSample.hpp +7 -3
- package/nitrogen/generated/android/c++/JDebugInfo.hpp +85 -0
- package/nitrogen/generated/android/c++/JHybridNitroCompassSpec.cpp +21 -0
- package/nitrogen/generated/android/c++/JHybridNitroCompassSpec.hpp +4 -0
- package/nitrogen/generated/android/c++/JSensorKind.hpp +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/CompassSample.kt +9 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/DebugInfo.kt +86 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/HybridNitroCompassSpec.kt +16 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrocompass/SensorKind.kt +4 -3
- package/nitrogen/generated/ios/NitroCompass-Swift-Cxx-Bridge.hpp +12 -0
- package/nitrogen/generated/ios/NitroCompass-Swift-Cxx-Umbrella.hpp +3 -0
- package/nitrogen/generated/ios/c++/HybridNitroCompassSpecSwift.hpp +29 -0
- package/nitrogen/generated/ios/swift/CompassSample.swift +7 -2
- package/nitrogen/generated/ios/swift/DebugInfo.swift +64 -0
- package/nitrogen/generated/ios/swift/HybridNitroCompassSpec.swift +4 -0
- package/nitrogen/generated/ios/swift/HybridNitroCompassSpec_cxx.swift +45 -0
- package/nitrogen/generated/ios/swift/SensorKind.swift +8 -4
- package/nitrogen/generated/shared/c++/CompassSample.hpp +6 -2
- package/nitrogen/generated/shared/c++/DebugInfo.hpp +111 -0
- package/nitrogen/generated/shared/c++/HybridNitroCompassSpec.cpp +4 -0
- package/nitrogen/generated/shared/c++/HybridNitroCompassSpec.hpp +7 -0
- package/nitrogen/generated/shared/c++/SensorKind.hpp +10 -6
- package/package.json +2 -2
- package/src/hook.ts +161 -12
- package/src/index.ts +2 -0
- package/src/multiplex.ts +23 -2
- package/src/specs/NitroCompass.nitro.ts +164 -18
|
@@ -43,6 +43,18 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
43
43
|
return q
|
|
44
44
|
}()
|
|
45
45
|
private var lastInterference: Bool?
|
|
46
|
+
// Most recent calibrated magnetic-field magnitude (µT). Surfaced on
|
|
47
|
+
// every CompassSample so consumers can render a strength meter; -1
|
|
48
|
+
// until CMDeviceMotion produces its first calibrated reading.
|
|
49
|
+
private var lastFieldUt: Double = -1
|
|
50
|
+
// Counter of consecutive non-uncalibrated motion samples. CoreMotion's
|
|
51
|
+
// bias estimate takes a second or two of normal motion to converge
|
|
52
|
+
// after subscribe; emitting interference transitions before then
|
|
53
|
+
// produces false positives because the early "calibrated" field is
|
|
54
|
+
// dominated by the device's own internal bias. Wait for N stable
|
|
55
|
+
// samples before trusting the magnitude reading.
|
|
56
|
+
private var motionStableSampleCount: Int = 0
|
|
57
|
+
private static let motionStableSampleThreshold: Int = 5
|
|
46
58
|
private var pauseOnBackground: Bool = true
|
|
47
59
|
private var started: Bool = false
|
|
48
60
|
private var isSubscribed: Bool = false
|
|
@@ -59,7 +71,10 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
59
71
|
super.init()
|
|
60
72
|
let setup = {
|
|
61
73
|
let m = CLLocationManager()
|
|
62
|
-
|
|
74
|
+
// headingFilter is overwritten by subscribe() each start(); the
|
|
75
|
+
// init value is only relevant if a caller queried headingFilter
|
|
76
|
+
// before start, which nothing does. Pick the default that matches
|
|
77
|
+
// activeFilterDegrees so a stray query is consistent.
|
|
63
78
|
m.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
|
|
64
79
|
self.manager = m
|
|
65
80
|
}
|
|
@@ -183,11 +198,35 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
183
198
|
}
|
|
184
199
|
}
|
|
185
200
|
|
|
201
|
+
// CLLocationManager filters heading internally with Apple's own
|
|
202
|
+
// algorithm; layering an EMA on top would only add latency. Kept as a
|
|
203
|
+
// no-op so cross-platform JS callers can call it unconditionally.
|
|
204
|
+
func setSmoothing(alpha: Double) throws {}
|
|
205
|
+
|
|
186
206
|
func getDiagnostics() throws -> SensorDiagnostics? {
|
|
187
207
|
guard CLLocationManager.headingAvailable() else { return nil }
|
|
188
208
|
return SensorDiagnostics(sensor: .corelocation)
|
|
189
209
|
}
|
|
190
210
|
|
|
211
|
+
// iOS lets CLLocationManager handle the gyro+mag fusion + bias
|
|
212
|
+
// estimation internally, so most of the Android-side debug fields
|
|
213
|
+
// have no analogue on this side. We surface the two we *can*
|
|
214
|
+
// observe (current interference state, last field strength) and
|
|
215
|
+
// report sentinel "n/a" values for the rest, matching the iOS
|
|
216
|
+
// notes in the DebugInfo doc.
|
|
217
|
+
func getDebugInfo() throws -> DebugInfo {
|
|
218
|
+
return DebugInfo(
|
|
219
|
+
interferenceActive: lastInterference == true,
|
|
220
|
+
msSinceLastBiasJump: -1,
|
|
221
|
+
expectedFieldMicroTesla: -1,
|
|
222
|
+
lastFieldMicroTesla: lastFieldUt,
|
|
223
|
+
fusedYawDeg: Double.nan,
|
|
224
|
+
lastYawRateDegPerS: 0,
|
|
225
|
+
hasGameRotationVector: false,
|
|
226
|
+
usingUncalibratedMag: false
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
|
|
191
230
|
func getCurrentHeading() throws -> CompassSample? {
|
|
192
231
|
return lastSample
|
|
193
232
|
}
|
|
@@ -196,8 +235,18 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
196
235
|
declinationDeg = degrees
|
|
197
236
|
}
|
|
198
237
|
|
|
238
|
+
// No-op on iOS — `CLLocationManager` already uses GPS-derived location
|
|
239
|
+
// internally for all field-related reasoning (true-north, declination,
|
|
240
|
+
// expected field strength). Layering our own lookup on top would be
|
|
241
|
+
// redundant. Provided for cross-platform JS callers.
|
|
242
|
+
func setLocation(latitude: Double, longitude: Double) throws {}
|
|
243
|
+
|
|
199
244
|
func setOnCalibrationNeeded(onChange: @escaping (_ quality: AccuracyQuality) -> Void) throws {
|
|
200
245
|
calibrationCb = onChange
|
|
246
|
+
// Replay current bucket so a late-registering consumer sees the
|
|
247
|
+
// truth instead of waiting for the next transition. Mirrors the
|
|
248
|
+
// setOnInterferenceDetected behavior.
|
|
249
|
+
if let last = lastQuality { onChange(last) }
|
|
201
250
|
}
|
|
202
251
|
|
|
203
252
|
func setOnInterferenceDetected(onChange: @escaping (_ interferenceDetected: Bool) -> Void) throws {
|
|
@@ -217,6 +266,30 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
217
266
|
}
|
|
218
267
|
}
|
|
219
268
|
|
|
269
|
+
func recalibrate() throws {
|
|
270
|
+
// Stop/start the heading subscription and reset every cached
|
|
271
|
+
// signal. Apple's CLLocationManager handles soft/hard-iron
|
|
272
|
+
// calibration internally — the recovery itself still requires the
|
|
273
|
+
// user to move the device through varying orientations — but
|
|
274
|
+
// dropping our own cached state ensures the next callback isn't
|
|
275
|
+
// suppressed by stale `lastQuality` / `lastInterference`
|
|
276
|
+
// comparisons, and dismisses any pending heading-calibration
|
|
277
|
+
// overlay so the consumer can prompt fresh.
|
|
278
|
+
guard started else { return }
|
|
279
|
+
// dismissHeadingCalibrationDisplay touches UIKit-adjacent state and
|
|
280
|
+
// must run on main. recalibrate() may be called from the JS thread.
|
|
281
|
+
DispatchQueue.main.async { [weak self] in
|
|
282
|
+
self?.manager.dismissHeadingCalibrationDisplay()
|
|
283
|
+
}
|
|
284
|
+
let wasSubscribed = isSubscribed
|
|
285
|
+
if wasSubscribed { unsubscribe() }
|
|
286
|
+
lastSample = nil
|
|
287
|
+
lastQuality = nil
|
|
288
|
+
lastInterference = nil
|
|
289
|
+
lastFieldUt = -1
|
|
290
|
+
if wasSubscribed { subscribe() }
|
|
291
|
+
}
|
|
292
|
+
|
|
220
293
|
func getPermissionStatus() throws -> PermissionStatus {
|
|
221
294
|
return Self.mapAuthStatus(manager.authorizationStatus)
|
|
222
295
|
}
|
|
@@ -291,12 +364,28 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
291
364
|
guard motionManager.isDeviceMotionAvailable,
|
|
292
365
|
!motionManager.isDeviceMotionActive else { return }
|
|
293
366
|
motionManager.deviceMotionUpdateInterval = 0.2 // 5Hz
|
|
367
|
+
motionStableSampleCount = 0
|
|
294
368
|
motionManager.startDeviceMotionUpdates(to: motionQueue) { [weak self] motion, _ in
|
|
295
369
|
guard let self = self, let m = motion else { return }
|
|
296
370
|
let cal = m.magneticField
|
|
297
|
-
if cal.accuracy == .uncalibrated {
|
|
371
|
+
if cal.accuracy == .uncalibrated {
|
|
372
|
+
// Bias estimate not yet usable. Reset stability counter so the
|
|
373
|
+
// post-convergence count starts fresh.
|
|
374
|
+
self.motionStableSampleCount = 0
|
|
375
|
+
return
|
|
376
|
+
}
|
|
298
377
|
let f = cal.field
|
|
299
378
|
let magnitude = sqrt(f.x * f.x + f.y * f.y + f.z * f.z)
|
|
379
|
+
self.lastFieldUt = magnitude
|
|
380
|
+
|
|
381
|
+
// Wait for N consecutive non-uncalibrated samples before letting
|
|
382
|
+
// magnitude drive interference transitions. Without this, the
|
|
383
|
+
// first second post-subscribe routinely fires false positives
|
|
384
|
+
// because the bias estimate hasn't converged yet.
|
|
385
|
+
if self.motionStableSampleCount < Self.motionStableSampleThreshold {
|
|
386
|
+
self.motionStableSampleCount += 1
|
|
387
|
+
return
|
|
388
|
+
}
|
|
300
389
|
self.evaluateInterference(magnitude: magnitude)
|
|
301
390
|
}
|
|
302
391
|
}
|
|
@@ -305,6 +394,7 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
305
394
|
if motionManager.isDeviceMotionActive {
|
|
306
395
|
motionManager.stopDeviceMotionUpdates()
|
|
307
396
|
}
|
|
397
|
+
motionStableSampleCount = 0
|
|
308
398
|
}
|
|
309
399
|
|
|
310
400
|
private func evaluateInterference(magnitude: Double) {
|
|
@@ -354,23 +444,33 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
354
444
|
lastSample = nil
|
|
355
445
|
lastQuality = nil
|
|
356
446
|
lastInterference = nil
|
|
447
|
+
lastFieldUt = -1
|
|
357
448
|
}
|
|
358
449
|
|
|
359
450
|
private func deliver(heading magnetic: Double, accuracy: Double) {
|
|
360
451
|
var heading = magnetic + declinationDeg
|
|
361
452
|
heading = heading.truncatingRemainder(dividingBy: 360)
|
|
362
453
|
if heading < 0 { heading += 360 }
|
|
363
|
-
let sample = CompassSample(
|
|
454
|
+
let sample = CompassSample(
|
|
455
|
+
heading: heading,
|
|
456
|
+
accuracy: accuracy,
|
|
457
|
+
fieldStrengthMicroTesla: lastFieldUt
|
|
458
|
+
)
|
|
364
459
|
lastSample = sample
|
|
365
460
|
|
|
461
|
+
// CLLocationManager.headingAccuracy is conservative — even a
|
|
462
|
+
// well-calibrated compass usually reports 5–15°, and values under
|
|
463
|
+
// 5° are basically never produced. Bucket against the realistic
|
|
464
|
+
// distribution so `.high` is reachable, mirroring how Android maps
|
|
465
|
+
// SENSOR_STATUS_ACCURACY_HIGH.
|
|
366
466
|
let quality: AccuracyQuality
|
|
367
467
|
if accuracy < 0 {
|
|
368
468
|
quality = .unreliable
|
|
369
|
-
} else if accuracy <
|
|
469
|
+
} else if accuracy < 20 {
|
|
370
470
|
quality = .high
|
|
371
|
-
} else if accuracy <
|
|
471
|
+
} else if accuracy < 35 {
|
|
372
472
|
quality = .medium
|
|
373
|
-
} else if accuracy <
|
|
473
|
+
} else if accuracy < 55 {
|
|
374
474
|
quality = .low
|
|
375
475
|
} else {
|
|
376
476
|
quality = .unreliable
|
|
@@ -387,6 +487,19 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
387
487
|
}
|
|
388
488
|
|
|
389
489
|
private func applyHeadingOrientation() {
|
|
490
|
+
// Prefer device orientation for face-up / face-down — those don't
|
|
491
|
+
// appear in interfaceOrientation but matter for headings on tablets
|
|
492
|
+
// held flat. Fall back to interfaceOrientation for the standard
|
|
493
|
+
// four cases (which respects app rotation locks).
|
|
494
|
+
let device = UIDevice.current.orientation
|
|
495
|
+
if device == .faceUp {
|
|
496
|
+
manager.headingOrientation = .faceUp
|
|
497
|
+
return
|
|
498
|
+
}
|
|
499
|
+
if device == .faceDown {
|
|
500
|
+
manager.headingOrientation = .faceDown
|
|
501
|
+
return
|
|
502
|
+
}
|
|
390
503
|
let scene = UIApplication.shared.connectedScenes
|
|
391
504
|
.compactMap { $0 as? UIWindowScene }
|
|
392
505
|
.first
|
package/lib/commonjs/hook.js
CHANGED
|
@@ -17,6 +17,7 @@ var _multiplex = require("./multiplex");
|
|
|
17
17
|
function useCompass(options = {}) {
|
|
18
18
|
const {
|
|
19
19
|
filterDegrees = 1,
|
|
20
|
+
smoothingAlpha = 0.2,
|
|
20
21
|
declination = 0,
|
|
21
22
|
pauseOnBackground = true,
|
|
22
23
|
enabled = true
|
|
@@ -24,17 +25,46 @@ function useCompass(options = {}) {
|
|
|
24
25
|
const [reading, setReading] = (0, _react.useState)(null);
|
|
25
26
|
const [quality, setQuality] = (0, _react.useState)(null);
|
|
26
27
|
const [interfering, setInterfering] = (0, _react.useState)(false);
|
|
27
|
-
const [hasCompass] = (0, _react.useState)(() => _native.NitroCompass.hasCompass());
|
|
28
|
-
const [diagnostics] = (0, _react.useState)(() => _native.NitroCompass.getDiagnostics());
|
|
29
28
|
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
29
|
+
// Wrap in try/catch so a missing/misconfigured native module doesn't
|
|
30
|
+
// throw during render — return safe defaults and let the host UI
|
|
31
|
+
// surface "no compass". Without this, the throw bubbles up and
|
|
32
|
+
// becomes a render error that blanks the screen.
|
|
33
|
+
const [hasCompass] = (0, _react.useState)(() => {
|
|
34
|
+
try {
|
|
35
|
+
return _native.NitroCompass.hasCompass();
|
|
36
|
+
} catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
const [diagnostics] = (0, _react.useState)(() => {
|
|
41
|
+
try {
|
|
42
|
+
return _native.NitroCompass.getDiagnostics();
|
|
43
|
+
} catch {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
const [permission, setPermission] = (0, _react.useState)(() => {
|
|
48
|
+
try {
|
|
49
|
+
return _native.NitroCompass.getPermissionStatus();
|
|
50
|
+
} catch {
|
|
51
|
+
return 'unknown';
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Tracked via refs so the heading-subscription effect can re-apply
|
|
56
|
+
// the user's filter and smoothing after a stop/start cycle without
|
|
57
|
+
// restarting on every option change.
|
|
33
58
|
const filterRef = (0, _react.useRef)(filterDegrees);
|
|
34
59
|
filterRef.current = filterDegrees;
|
|
60
|
+
const smoothingRef = (0, _react.useRef)(smoothingAlpha);
|
|
61
|
+
smoothingRef.current = smoothingAlpha;
|
|
35
62
|
(0, _react.useEffect)(() => {
|
|
36
63
|
_native.NitroCompass.setFilter(filterDegrees);
|
|
37
64
|
}, [filterDegrees]);
|
|
65
|
+
(0, _react.useEffect)(() => {
|
|
66
|
+
_native.NitroCompass.setSmoothing(smoothingAlpha);
|
|
67
|
+
}, [smoothingAlpha]);
|
|
38
68
|
(0, _react.useEffect)(() => {
|
|
39
69
|
_native.NitroCompass.setDeclination(declination);
|
|
40
70
|
}, [declination]);
|
|
@@ -50,20 +80,81 @@ function useCompass(options = {}) {
|
|
|
50
80
|
return (0, _multiplex.addInterferenceListener)(setInterfering);
|
|
51
81
|
}, [hasCompass]);
|
|
52
82
|
(0, _react.useEffect)(() => {
|
|
53
|
-
if (!hasCompass || !enabled)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
83
|
+
if (!hasCompass || !enabled) {
|
|
84
|
+
// When the user disables the hook, clear stale UI state.
|
|
85
|
+
// Without this, `reading` / `interfering` keep their last value
|
|
86
|
+
// forever, so the consumer's UI can't tell "subscription is off"
|
|
87
|
+
// from "compass is currently quiet".
|
|
88
|
+
setReading(null);
|
|
89
|
+
setInterfering(false);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
let off;
|
|
93
|
+
try {
|
|
94
|
+
off = (0, _multiplex.addHeadingListener)(setReading);
|
|
95
|
+
// Multiplex starts the sensor with a default filter; re-apply
|
|
96
|
+
// the current options after subscribing. recalibrate() can also
|
|
97
|
+
// reset native smoothing state, so we pin our chosen alpha back
|
|
98
|
+
// here as well.
|
|
99
|
+
_native.NitroCompass.setFilter(filterRef.current);
|
|
100
|
+
_native.NitroCompass.setSmoothing(smoothingRef.current);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
// start() throws on iOS when location authorization is denied.
|
|
103
|
+
// Swallow it here so the hook tree doesn't unmount; consumers
|
|
104
|
+
// should call NitroCompass.requestPermission() explicitly before
|
|
105
|
+
// setting enabled=true if they want to recover.
|
|
106
|
+
// eslint-disable-next-line no-console
|
|
107
|
+
console.warn('[NitroCompass] failed to start heading subscription:', e);
|
|
108
|
+
}
|
|
58
109
|
return off;
|
|
59
110
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
60
111
|
}, [hasCompass, enabled]);
|
|
112
|
+
|
|
113
|
+
// Stable callbacks so consumers' useEffect deps don't churn on every
|
|
114
|
+
// render. All four are thin wrappers around NitroCompass; the hook's
|
|
115
|
+
// own state isn't reactive to recalibrate/setLocation since neither
|
|
116
|
+
// changes any field returned here.
|
|
117
|
+
const getCurrentHeading = (0, _react.useCallback)(() => {
|
|
118
|
+
try {
|
|
119
|
+
return _native.NitroCompass.getCurrentHeading();
|
|
120
|
+
} catch {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
}, []);
|
|
124
|
+
const recalibrate = (0, _react.useCallback)(() => {
|
|
125
|
+
try {
|
|
126
|
+
_native.NitroCompass.recalibrate();
|
|
127
|
+
} catch {
|
|
128
|
+
// Native missing — nothing to do.
|
|
129
|
+
}
|
|
130
|
+
}, []);
|
|
131
|
+
const setLocation = (0, _react.useCallback)((latitude, longitude) => {
|
|
132
|
+
try {
|
|
133
|
+
_native.NitroCompass.setLocation(latitude, longitude);
|
|
134
|
+
} catch {
|
|
135
|
+
// Native missing — silently ignored.
|
|
136
|
+
}
|
|
137
|
+
}, []);
|
|
138
|
+
const requestPermission = (0, _react.useCallback)(async () => {
|
|
139
|
+
try {
|
|
140
|
+
const status = await _native.NitroCompass.requestPermission();
|
|
141
|
+
setPermission(status);
|
|
142
|
+
return status;
|
|
143
|
+
} catch {
|
|
144
|
+
return 'denied';
|
|
145
|
+
}
|
|
146
|
+
}, []);
|
|
61
147
|
return {
|
|
62
148
|
reading,
|
|
63
149
|
quality,
|
|
64
150
|
interfering,
|
|
65
151
|
hasCompass,
|
|
66
|
-
diagnostics
|
|
152
|
+
diagnostics,
|
|
153
|
+
permission,
|
|
154
|
+
getCurrentHeading,
|
|
155
|
+
recalibrate,
|
|
156
|
+
setLocation,
|
|
157
|
+
requestPermission
|
|
67
158
|
};
|
|
68
159
|
}
|
|
69
160
|
//# sourceMappingURL=hook.js.map
|
package/lib/commonjs/hook.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_native","_multiplex","useCompass","options","filterDegrees","declination","pauseOnBackground","enabled","reading","setReading","useState","quality","setQuality","interfering","setInterfering","hasCompass","NitroCompass","diagnostics","getDiagnostics","filterRef","useRef","current","useEffect","setFilter","setDeclination","setPauseOnBackground","addCalibrationListener","addInterferenceListener","off","addHeadingListener"],"sourceRoot":"../../src","sources":["hook.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;
|
|
1
|
+
{"version":3,"names":["_react","require","_native","_multiplex","useCompass","options","filterDegrees","smoothingAlpha","declination","pauseOnBackground","enabled","reading","setReading","useState","quality","setQuality","interfering","setInterfering","hasCompass","NitroCompass","diagnostics","getDiagnostics","undefined","permission","setPermission","getPermissionStatus","filterRef","useRef","current","smoothingRef","useEffect","setFilter","setSmoothing","setDeclination","setPauseOnBackground","addCalibrationListener","addInterferenceListener","off","addHeadingListener","e","console","warn","getCurrentHeading","useCallback","recalibrate","setLocation","latitude","longitude","requestPermission","status"],"sourceRoot":"../../src","sources":["hook.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_native","require","_multiplex","_hook"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"names":["_native","require","_multiplex","_hook"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,IAAAA,OAAA,GAAAC,OAAA;AAYA,IAAAC,UAAA,GAAAD,OAAA;AAMA,IAAAE,KAAA,GAAAF,OAAA","ignoreList":[]}
|
|
@@ -77,6 +77,13 @@ function addHeadingListener(cb) {
|
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
// Module-level no-op kept stable so we can swap it back into the native
|
|
81
|
+
// callback slot when the last listener leaves — releasing references
|
|
82
|
+
// to old dispatcher closures, which matters when the JS module is
|
|
83
|
+
// re-evaluated (Metro Fast Refresh, jest module reset).
|
|
84
|
+
const NOOP_CALIBRATION = _ => {};
|
|
85
|
+
const NOOP_INTERFERENCE = _ => {};
|
|
86
|
+
|
|
80
87
|
/**
|
|
81
88
|
* Subscribe to calibration-bucket transitions. Only fires while a
|
|
82
89
|
* heading subscription is active. Returns the unsubscribe function.
|
|
@@ -88,7 +95,17 @@ function addCalibrationListener(cb) {
|
|
|
88
95
|
}
|
|
89
96
|
calibrationListeners.add(cb);
|
|
90
97
|
return () => {
|
|
91
|
-
calibrationListeners.delete(cb);
|
|
98
|
+
if (!calibrationListeners.delete(cb)) return;
|
|
99
|
+
if (calibrationListeners.size === 0) {
|
|
100
|
+
// Detach our dispatcher from the native side. Without this, a
|
|
101
|
+
// module reload (Metro Fast Refresh, jest resetModules) leaves
|
|
102
|
+
// the old dispatcher pinned in native memory while a new module
|
|
103
|
+
// load installs a *second* dispatcher pointing at a fresh
|
|
104
|
+
// listener Set — splitting events between the two and silently
|
|
105
|
+
// dropping the now-orphaned listeners.
|
|
106
|
+
_native.NitroCompass.setOnCalibrationNeeded(NOOP_CALIBRATION);
|
|
107
|
+
calibrationRegistered = false;
|
|
108
|
+
}
|
|
92
109
|
};
|
|
93
110
|
}
|
|
94
111
|
|
|
@@ -103,7 +120,11 @@ function addInterferenceListener(cb) {
|
|
|
103
120
|
}
|
|
104
121
|
interferenceListeners.add(cb);
|
|
105
122
|
return () => {
|
|
106
|
-
interferenceListeners.delete(cb);
|
|
123
|
+
if (!interferenceListeners.delete(cb)) return;
|
|
124
|
+
if (interferenceListeners.size === 0) {
|
|
125
|
+
_native.NitroCompass.setOnInterferenceDetected(NOOP_INTERFERENCE);
|
|
126
|
+
interferenceRegistered = false;
|
|
127
|
+
}
|
|
107
128
|
};
|
|
108
129
|
}
|
|
109
130
|
//# sourceMappingURL=multiplex.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_native","require","headingListeners","Set","calibrationListeners","interferenceListeners","calibrationRegistered","interferenceRegistered","DEFAULT_FILTER_DEG","dispatchHeading","sample","cb","Array","from","e","console","error","dispatchCalibration","quality","dispatchInterference","detected","addHeadingListener","wasEmpty","size","add","NitroCompass","start","delete","stop","addCalibrationListener","setOnCalibrationNeeded","addInterferenceListener","setOnInterferenceDetected"],"sourceRoot":"../../src","sources":["multiplex.ts"],"mappings":";;;;;;;;AAgBA,IAAAA,OAAA,GAAAC,OAAA;AAhBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAWA,MAAMC,gBAAgB,GAAG,IAAIC,GAAG,CAAkB,CAAC;AACnD,MAAMC,oBAAoB,GAAG,IAAID,GAAG,CAAsB,CAAC;AAC3D,MAAME,qBAAqB,GAAG,IAAIF,GAAG,CAAuB,CAAC;AAE7D,IAAIG,qBAAqB,GAAG,KAAK;AACjC,IAAIC,sBAAsB,GAAG,KAAK;AAElC,MAAMC,kBAAkB,GAAG,CAAC;AAE5B,SAASC,eAAeA,CAACC,MAAqB,EAAE;EAC9C,KAAK,MAAMC,EAAE,IAAIC,KAAK,CAACC,IAAI,CAACX,gBAAgB,CAAC,EAAE;IAC7C,IAAI;MACFS,EAAE,CAACD,MAAM,CAAC;IACZ,CAAC,CAAC,OAAOI,CAAC,EAAE;MACVC,OAAO,CAACC,KAAK,CAAC,wCAAwC,EAAEF,CAAC,CAAC;IAC5D;EACF;AACF;AAEA,SAASG,mBAAmBA,CAACC,OAAwB,EAAE;EACrD,KAAK,MAAMP,EAAE,IAAIC,KAAK,CAACC,IAAI,CAACT,oBAAoB,CAAC,EAAE;IACjD,IAAI;MACFO,EAAE,CAACO,OAAO,CAAC;IACb,CAAC,CAAC,OAAOJ,CAAC,EAAE;MACVC,OAAO,CAACC,KAAK,CAAC,4CAA4C,EAAEF,CAAC,CAAC;IAChE;EACF;AACF;AAEA,SAASK,oBAAoBA,CAACC,QAAiB,EAAE;EAC/C,KAAK,MAAMT,EAAE,IAAIC,KAAK,CAACC,IAAI,CAACR,qBAAqB,CAAC,EAAE;IAClD,IAAI;MACFM,EAAE,CAACS,QAAQ,CAAC;IACd,CAAC,CAAC,OAAON,CAAC,EAAE;MACVC,OAAO,CAACC,KAAK,CAAC,6CAA6C,EAAEF,CAAC,CAAC;IACjE;EACF;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASO,kBAAkBA,CAACV,EAAmB,EAAc;EAClE,MAAMW,QAAQ,GAAGpB,gBAAgB,CAACqB,IAAI,KAAK,CAAC;EAC5CrB,gBAAgB,CAACsB,GAAG,CAACb,EAAE,CAAC;EACxB,IAAIW,QAAQ,EAAE;IACZG,oBAAY,CAACC,KAAK,CAAClB,kBAAkB,EAAEC,eAAe,CAAC;EACzD;EACA,OAAO,MAAM;IACX,IAAI,CAACP,gBAAgB,CAACyB,MAAM,CAAChB,EAAE,CAAC,EAAE;IAClC,IAAIT,gBAAgB,CAACqB,IAAI,KAAK,CAAC,EAAE;MAC/BE,oBAAY,CAACG,IAAI,CAAC,CAAC;IACrB;EACF,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACO,
|
|
1
|
+
{"version":3,"names":["_native","require","headingListeners","Set","calibrationListeners","interferenceListeners","calibrationRegistered","interferenceRegistered","DEFAULT_FILTER_DEG","dispatchHeading","sample","cb","Array","from","e","console","error","dispatchCalibration","quality","dispatchInterference","detected","addHeadingListener","wasEmpty","size","add","NitroCompass","start","delete","stop","NOOP_CALIBRATION","_","NOOP_INTERFERENCE","addCalibrationListener","setOnCalibrationNeeded","addInterferenceListener","setOnInterferenceDetected"],"sourceRoot":"../../src","sources":["multiplex.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/module/hook.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { NitroCompass } from './native';
|
|
5
5
|
import { addCalibrationListener, addHeadingListener, addInterferenceListener } from './multiplex';
|
|
6
6
|
/**
|
|
@@ -13,6 +13,7 @@ import { addCalibrationListener, addHeadingListener, addInterferenceListener } f
|
|
|
13
13
|
export function useCompass(options = {}) {
|
|
14
14
|
const {
|
|
15
15
|
filterDegrees = 1,
|
|
16
|
+
smoothingAlpha = 0.2,
|
|
16
17
|
declination = 0,
|
|
17
18
|
pauseOnBackground = true,
|
|
18
19
|
enabled = true
|
|
@@ -20,17 +21,46 @@ export function useCompass(options = {}) {
|
|
|
20
21
|
const [reading, setReading] = useState(null);
|
|
21
22
|
const [quality, setQuality] = useState(null);
|
|
22
23
|
const [interfering, setInterfering] = useState(false);
|
|
23
|
-
const [hasCompass] = useState(() => NitroCompass.hasCompass());
|
|
24
|
-
const [diagnostics] = useState(() => NitroCompass.getDiagnostics());
|
|
25
24
|
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
25
|
+
// Wrap in try/catch so a missing/misconfigured native module doesn't
|
|
26
|
+
// throw during render — return safe defaults and let the host UI
|
|
27
|
+
// surface "no compass". Without this, the throw bubbles up and
|
|
28
|
+
// becomes a render error that blanks the screen.
|
|
29
|
+
const [hasCompass] = useState(() => {
|
|
30
|
+
try {
|
|
31
|
+
return NitroCompass.hasCompass();
|
|
32
|
+
} catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const [diagnostics] = useState(() => {
|
|
37
|
+
try {
|
|
38
|
+
return NitroCompass.getDiagnostics();
|
|
39
|
+
} catch {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
const [permission, setPermission] = useState(() => {
|
|
44
|
+
try {
|
|
45
|
+
return NitroCompass.getPermissionStatus();
|
|
46
|
+
} catch {
|
|
47
|
+
return 'unknown';
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Tracked via refs so the heading-subscription effect can re-apply
|
|
52
|
+
// the user's filter and smoothing after a stop/start cycle without
|
|
53
|
+
// restarting on every option change.
|
|
29
54
|
const filterRef = useRef(filterDegrees);
|
|
30
55
|
filterRef.current = filterDegrees;
|
|
56
|
+
const smoothingRef = useRef(smoothingAlpha);
|
|
57
|
+
smoothingRef.current = smoothingAlpha;
|
|
31
58
|
useEffect(() => {
|
|
32
59
|
NitroCompass.setFilter(filterDegrees);
|
|
33
60
|
}, [filterDegrees]);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
NitroCompass.setSmoothing(smoothingAlpha);
|
|
63
|
+
}, [smoothingAlpha]);
|
|
34
64
|
useEffect(() => {
|
|
35
65
|
NitroCompass.setDeclination(declination);
|
|
36
66
|
}, [declination]);
|
|
@@ -46,20 +76,81 @@ export function useCompass(options = {}) {
|
|
|
46
76
|
return addInterferenceListener(setInterfering);
|
|
47
77
|
}, [hasCompass]);
|
|
48
78
|
useEffect(() => {
|
|
49
|
-
if (!hasCompass || !enabled)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
79
|
+
if (!hasCompass || !enabled) {
|
|
80
|
+
// When the user disables the hook, clear stale UI state.
|
|
81
|
+
// Without this, `reading` / `interfering` keep their last value
|
|
82
|
+
// forever, so the consumer's UI can't tell "subscription is off"
|
|
83
|
+
// from "compass is currently quiet".
|
|
84
|
+
setReading(null);
|
|
85
|
+
setInterfering(false);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
let off;
|
|
89
|
+
try {
|
|
90
|
+
off = addHeadingListener(setReading);
|
|
91
|
+
// Multiplex starts the sensor with a default filter; re-apply
|
|
92
|
+
// the current options after subscribing. recalibrate() can also
|
|
93
|
+
// reset native smoothing state, so we pin our chosen alpha back
|
|
94
|
+
// here as well.
|
|
95
|
+
NitroCompass.setFilter(filterRef.current);
|
|
96
|
+
NitroCompass.setSmoothing(smoothingRef.current);
|
|
97
|
+
} catch (e) {
|
|
98
|
+
// start() throws on iOS when location authorization is denied.
|
|
99
|
+
// Swallow it here so the hook tree doesn't unmount; consumers
|
|
100
|
+
// should call NitroCompass.requestPermission() explicitly before
|
|
101
|
+
// setting enabled=true if they want to recover.
|
|
102
|
+
// eslint-disable-next-line no-console
|
|
103
|
+
console.warn('[NitroCompass] failed to start heading subscription:', e);
|
|
104
|
+
}
|
|
54
105
|
return off;
|
|
55
106
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
56
107
|
}, [hasCompass, enabled]);
|
|
108
|
+
|
|
109
|
+
// Stable callbacks so consumers' useEffect deps don't churn on every
|
|
110
|
+
// render. All four are thin wrappers around NitroCompass; the hook's
|
|
111
|
+
// own state isn't reactive to recalibrate/setLocation since neither
|
|
112
|
+
// changes any field returned here.
|
|
113
|
+
const getCurrentHeading = useCallback(() => {
|
|
114
|
+
try {
|
|
115
|
+
return NitroCompass.getCurrentHeading();
|
|
116
|
+
} catch {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
}, []);
|
|
120
|
+
const recalibrate = useCallback(() => {
|
|
121
|
+
try {
|
|
122
|
+
NitroCompass.recalibrate();
|
|
123
|
+
} catch {
|
|
124
|
+
// Native missing — nothing to do.
|
|
125
|
+
}
|
|
126
|
+
}, []);
|
|
127
|
+
const setLocation = useCallback((latitude, longitude) => {
|
|
128
|
+
try {
|
|
129
|
+
NitroCompass.setLocation(latitude, longitude);
|
|
130
|
+
} catch {
|
|
131
|
+
// Native missing — silently ignored.
|
|
132
|
+
}
|
|
133
|
+
}, []);
|
|
134
|
+
const requestPermission = useCallback(async () => {
|
|
135
|
+
try {
|
|
136
|
+
const status = await NitroCompass.requestPermission();
|
|
137
|
+
setPermission(status);
|
|
138
|
+
return status;
|
|
139
|
+
} catch {
|
|
140
|
+
return 'denied';
|
|
141
|
+
}
|
|
142
|
+
}, []);
|
|
57
143
|
return {
|
|
58
144
|
reading,
|
|
59
145
|
quality,
|
|
60
146
|
interfering,
|
|
61
147
|
hasCompass,
|
|
62
|
-
diagnostics
|
|
148
|
+
diagnostics,
|
|
149
|
+
permission,
|
|
150
|
+
getCurrentHeading,
|
|
151
|
+
recalibrate,
|
|
152
|
+
setLocation,
|
|
153
|
+
requestPermission
|
|
63
154
|
};
|
|
64
155
|
}
|
|
65
156
|
//# sourceMappingURL=hook.js.map
|
package/lib/module/hook.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useEffect","useRef","useState","NitroCompass","addCalibrationListener","addHeadingListener","addInterferenceListener","useCompass","options","filterDegrees","declination","pauseOnBackground","enabled","reading","setReading","quality","setQuality","interfering","setInterfering","hasCompass","diagnostics","getDiagnostics","filterRef","current","setFilter","setDeclination","setPauseOnBackground","off"],"sourceRoot":"../../src","sources":["hook.ts"],"mappings":";;AAAA,SAASA,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;
|
|
1
|
+
{"version":3,"names":["useCallback","useEffect","useRef","useState","NitroCompass","addCalibrationListener","addHeadingListener","addInterferenceListener","useCompass","options","filterDegrees","smoothingAlpha","declination","pauseOnBackground","enabled","reading","setReading","quality","setQuality","interfering","setInterfering","hasCompass","diagnostics","getDiagnostics","undefined","permission","setPermission","getPermissionStatus","filterRef","current","smoothingRef","setFilter","setSmoothing","setDeclination","setPauseOnBackground","off","e","console","warn","getCurrentHeading","recalibrate","setLocation","latitude","longitude","requestPermission","status"],"sourceRoot":"../../src","sources":["hook.ts"],"mappings":";;AAAA,SAASA,WAAW,EAAEC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AAOhE,SAASC,YAAY,QAAQ,UAAU;AACvC,SACEC,sBAAsB,EACtBC,kBAAkB,EAClBC,uBAAuB,QAClB,aAAa;AA2FpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,UAAUA,CACxBC,OAA0B,GAAG,CAAC,CAAC,EACb;EAClB,MAAM;IACJC,aAAa,GAAG,CAAC;IACjBC,cAAc,GAAG,GAAG;IACpBC,WAAW,GAAG,CAAC;IACfC,iBAAiB,GAAG,IAAI;IACxBC,OAAO,GAAG;EACZ,CAAC,GAAGL,OAAO;EAEX,MAAM,CAACM,OAAO,EAAEC,UAAU,CAAC,GAAGb,QAAQ,CAAuB,IAAI,CAAC;EAClE,MAAM,CAACc,OAAO,EAAEC,UAAU,CAAC,GAAGf,QAAQ,CAAyB,IAAI,CAAC;EACpE,MAAM,CAACgB,WAAW,EAAEC,cAAc,CAAC,GAAGjB,QAAQ,CAAC,KAAK,CAAC;;EAErD;EACA;EACA;EACA;EACA,MAAM,CAACkB,UAAU,CAAC,GAAGlB,QAAQ,CAAC,MAAM;IAClC,IAAI;MACF,OAAOC,YAAY,CAACiB,UAAU,CAAC,CAAC;IAClC,CAAC,CAAC,MAAM;MACN,OAAO,KAAK;IACd;EACF,CAAC,CAAC;EACF,MAAM,CAACC,WAAW,CAAC,GAAGnB,QAAQ,CAAC,MAAM;IACnC,IAAI;MACF,OAAOC,YAAY,CAACmB,cAAc,CAAC,CAAC;IACtC,CAAC,CAAC,MAAM;MACN,OAAOC,SAAS;IAClB;EACF,CAAC,CAAC;EACF,MAAM,CAACC,UAAU,EAAEC,aAAa,CAAC,GAAGvB,QAAQ,CAAmB,MAAM;IACnE,IAAI;MACF,OAAOC,YAAY,CAACuB,mBAAmB,CAAC,CAAC;IAC3C,CAAC,CAAC,MAAM;MACN,OAAO,SAAS;IAClB;EACF,CAAC,CAAC;;EAEF;EACA;EACA;EACA,MAAMC,SAAS,GAAG1B,MAAM,CAACQ,aAAa,CAAC;EACvCkB,SAAS,CAACC,OAAO,GAAGnB,aAAa;EACjC,MAAMoB,YAAY,GAAG5B,MAAM,CAACS,cAAc,CAAC;EAC3CmB,YAAY,CAACD,OAAO,GAAGlB,cAAc;EAErCV,SAAS,CAAC,MAAM;IACdG,YAAY,CAAC2B,SAAS,CAACrB,aAAa,CAAC;EACvC,CAAC,EAAE,CAACA,aAAa,CAAC,CAAC;EAEnBT,SAAS,CAAC,MAAM;IACdG,YAAY,CAAC4B,YAAY,CAACrB,cAAc,CAAC;EAC3C,CAAC,EAAE,CAACA,cAAc,CAAC,CAAC;EAEpBV,SAAS,CAAC,MAAM;IACdG,YAAY,CAAC6B,cAAc,CAACrB,WAAW,CAAC;EAC1C,CAAC,EAAE,CAACA,WAAW,CAAC,CAAC;EAEjBX,SAAS,CAAC,MAAM;IACdG,YAAY,CAAC8B,oBAAoB,CAACrB,iBAAiB,CAAC;EACtD,CAAC,EAAE,CAACA,iBAAiB,CAAC,CAAC;EAEvBZ,SAAS,CAAC,MAAM;IACd,IAAI,CAACoB,UAAU,EAAE;IACjB,OAAOhB,sBAAsB,CAACa,UAAU,CAAC;EAC3C,CAAC,EAAE,CAACG,UAAU,CAAC,CAAC;EAEhBpB,SAAS,CAAC,MAAM;IACd,IAAI,CAACoB,UAAU,EAAE;IACjB,OAAOd,uBAAuB,CAACa,cAAc,CAAC;EAChD,CAAC,EAAE,CAACC,UAAU,CAAC,CAAC;EAEhBpB,SAAS,CAAC,MAAM;IACd,IAAI,CAACoB,UAAU,IAAI,CAACP,OAAO,EAAE;MAC3B;MACA;MACA;MACA;MACAE,UAAU,CAAC,IAAI,CAAC;MAChBI,cAAc,CAAC,KAAK,CAAC;MACrB;IACF;IACA,IAAIe,GAA6B;IACjC,IAAI;MACFA,GAAG,GAAG7B,kBAAkB,CAACU,UAAU,CAAC;MACpC;MACA;MACA;MACA;MACAZ,YAAY,CAAC2B,SAAS,CAACH,SAAS,CAACC,OAAO,CAAC;MACzCzB,YAAY,CAAC4B,YAAY,CAACF,YAAY,CAACD,OAAO,CAAC;IACjD,CAAC,CAAC,OAAOO,CAAC,EAAE;MACV;MACA;MACA;MACA;MACA;MACAC,OAAO,CAACC,IAAI,CAAC,sDAAsD,EAAEF,CAAC,CAAC;IACzE;IACA,OAAOD,GAAG;IACV;EACF,CAAC,EAAE,CAACd,UAAU,EAAEP,OAAO,CAAC,CAAC;;EAEzB;EACA;EACA;EACA;EACA,MAAMyB,iBAAiB,GAAGvC,WAAW,CAAC,MAAM;IAC1C,IAAI;MACF,OAAOI,YAAY,CAACmC,iBAAiB,CAAC,CAAC;IACzC,CAAC,CAAC,MAAM;MACN,OAAOf,SAAS;IAClB;EACF,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMgB,WAAW,GAAGxC,WAAW,CAAC,MAAM;IACpC,IAAI;MACFI,YAAY,CAACoC,WAAW,CAAC,CAAC;IAC5B,CAAC,CAAC,MAAM;MACN;IAAA;EAEJ,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMC,WAAW,GAAGzC,WAAW,CAAC,CAAC0C,QAAgB,EAAEC,SAAiB,KAAK;IACvE,IAAI;MACFvC,YAAY,CAACqC,WAAW,CAACC,QAAQ,EAAEC,SAAS,CAAC;IAC/C,CAAC,CAAC,MAAM;MACN;IAAA;EAEJ,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMC,iBAAiB,GAAG5C,WAAW,CAAC,YAAuC;IAC3E,IAAI;MACF,MAAM6C,MAAM,GAAG,MAAMzC,YAAY,CAACwC,iBAAiB,CAAC,CAAC;MACrDlB,aAAa,CAACmB,MAAM,CAAC;MACrB,OAAOA,MAAM;IACf,CAAC,CAAC,MAAM;MACN,OAAO,QAAQ;IACjB;EACF,CAAC,EAAE,EAAE,CAAC;EAEN,OAAO;IACL9B,OAAO;IACPE,OAAO;IACPE,WAAW;IACXE,UAAU;IACVC,WAAW;IACXG,UAAU;IACVc,iBAAiB;IACjBC,WAAW;IACXC,WAAW;IACXG;EACF,CAAC;AACH","ignoreList":[]}
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NitroCompass","addCalibrationListener","addHeadingListener","addInterferenceListener","useCompass"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"names":["NitroCompass","addCalibrationListener","addHeadingListener","addInterferenceListener","useCompass"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAUA,SAASA,YAAY,QAAQ,UAAU;AAYvC,SACEC,sBAAsB,EACtBC,kBAAkB,EAClBC,uBAAuB,QAClB,aAAa;AAEpB,SAASC,UAAU,QAAQ,QAAQ","ignoreList":[]}
|