react-native-nitro-compass 1.1.0 → 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 +141 -20
- package/android/src/main/java/com/margelo/nitro/nitrocompass/HybridNitroCompass.kt +654 -133
- package/ios/HybridNitroCompass.swift +106 -3
- package/lib/commonjs/hook.js +98 -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 +99 -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 +39 -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 +142 -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 +17 -0
- package/nitrogen/generated/android/c++/JHybridNitroCompassSpec.hpp +3 -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 +12 -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 +23 -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 +3 -0
- package/nitrogen/generated/ios/swift/HybridNitroCompassSpec_cxx.swift +34 -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 +3 -0
- package/nitrogen/generated/shared/c++/HybridNitroCompassSpec.hpp +6 -0
- package/nitrogen/generated/shared/c++/SensorKind.hpp +10 -6
- package/package.json +2 -2
- package/src/hook.ts +146 -12
- package/src/index.ts +2 -0
- package/src/multiplex.ts +23 -2
- package/src/specs/NitroCompass.nitro.ts +147 -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
|
}
|
|
@@ -193,6 +208,25 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
193
208
|
return SensorDiagnostics(sensor: .corelocation)
|
|
194
209
|
}
|
|
195
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
|
+
|
|
196
230
|
func getCurrentHeading() throws -> CompassSample? {
|
|
197
231
|
return lastSample
|
|
198
232
|
}
|
|
@@ -201,8 +235,18 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
201
235
|
declinationDeg = degrees
|
|
202
236
|
}
|
|
203
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
|
+
|
|
204
244
|
func setOnCalibrationNeeded(onChange: @escaping (_ quality: AccuracyQuality) -> Void) throws {
|
|
205
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) }
|
|
206
250
|
}
|
|
207
251
|
|
|
208
252
|
func setOnInterferenceDetected(onChange: @escaping (_ interferenceDetected: Bool) -> Void) throws {
|
|
@@ -222,6 +266,30 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
222
266
|
}
|
|
223
267
|
}
|
|
224
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
|
+
|
|
225
293
|
func getPermissionStatus() throws -> PermissionStatus {
|
|
226
294
|
return Self.mapAuthStatus(manager.authorizationStatus)
|
|
227
295
|
}
|
|
@@ -296,12 +364,28 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
296
364
|
guard motionManager.isDeviceMotionAvailable,
|
|
297
365
|
!motionManager.isDeviceMotionActive else { return }
|
|
298
366
|
motionManager.deviceMotionUpdateInterval = 0.2 // 5Hz
|
|
367
|
+
motionStableSampleCount = 0
|
|
299
368
|
motionManager.startDeviceMotionUpdates(to: motionQueue) { [weak self] motion, _ in
|
|
300
369
|
guard let self = self, let m = motion else { return }
|
|
301
370
|
let cal = m.magneticField
|
|
302
|
-
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
|
+
}
|
|
303
377
|
let f = cal.field
|
|
304
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
|
+
}
|
|
305
389
|
self.evaluateInterference(magnitude: magnitude)
|
|
306
390
|
}
|
|
307
391
|
}
|
|
@@ -310,6 +394,7 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
310
394
|
if motionManager.isDeviceMotionActive {
|
|
311
395
|
motionManager.stopDeviceMotionUpdates()
|
|
312
396
|
}
|
|
397
|
+
motionStableSampleCount = 0
|
|
313
398
|
}
|
|
314
399
|
|
|
315
400
|
private func evaluateInterference(magnitude: Double) {
|
|
@@ -359,13 +444,18 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
359
444
|
lastSample = nil
|
|
360
445
|
lastQuality = nil
|
|
361
446
|
lastInterference = nil
|
|
447
|
+
lastFieldUt = -1
|
|
362
448
|
}
|
|
363
449
|
|
|
364
450
|
private func deliver(heading magnetic: Double, accuracy: Double) {
|
|
365
451
|
var heading = magnetic + declinationDeg
|
|
366
452
|
heading = heading.truncatingRemainder(dividingBy: 360)
|
|
367
453
|
if heading < 0 { heading += 360 }
|
|
368
|
-
let sample = CompassSample(
|
|
454
|
+
let sample = CompassSample(
|
|
455
|
+
heading: heading,
|
|
456
|
+
accuracy: accuracy,
|
|
457
|
+
fieldStrengthMicroTesla: lastFieldUt
|
|
458
|
+
)
|
|
369
459
|
lastSample = sample
|
|
370
460
|
|
|
371
461
|
// CLLocationManager.headingAccuracy is conservative — even a
|
|
@@ -397,6 +487,19 @@ class HybridNitroCompass: HybridNitroCompassSpec {
|
|
|
397
487
|
}
|
|
398
488
|
|
|
399
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
|
+
}
|
|
400
503
|
let scene = UIApplication.shared.connectedScenes
|
|
401
504
|
.compactMap { $0 as? UIWindowScene }
|
|
402
505
|
.first
|
package/lib/commonjs/hook.js
CHANGED
|
@@ -25,14 +25,40 @@ function useCompass(options = {}) {
|
|
|
25
25
|
const [reading, setReading] = (0, _react.useState)(null);
|
|
26
26
|
const [quality, setQuality] = (0, _react.useState)(null);
|
|
27
27
|
const [interfering, setInterfering] = (0, _react.useState)(false);
|
|
28
|
-
const [hasCompass] = (0, _react.useState)(() => _native.NitroCompass.hasCompass());
|
|
29
|
-
const [diagnostics] = (0, _react.useState)(() => _native.NitroCompass.getDiagnostics());
|
|
30
28
|
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
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.
|
|
34
58
|
const filterRef = (0, _react.useRef)(filterDegrees);
|
|
35
59
|
filterRef.current = filterDegrees;
|
|
60
|
+
const smoothingRef = (0, _react.useRef)(smoothingAlpha);
|
|
61
|
+
smoothingRef.current = smoothingAlpha;
|
|
36
62
|
(0, _react.useEffect)(() => {
|
|
37
63
|
_native.NitroCompass.setFilter(filterDegrees);
|
|
38
64
|
}, [filterDegrees]);
|
|
@@ -54,20 +80,81 @@ function useCompass(options = {}) {
|
|
|
54
80
|
return (0, _multiplex.addInterferenceListener)(setInterfering);
|
|
55
81
|
}, [hasCompass]);
|
|
56
82
|
(0, _react.useEffect)(() => {
|
|
57
|
-
if (!hasCompass || !enabled)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
+
}
|
|
62
109
|
return off;
|
|
63
110
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
64
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
|
+
}, []);
|
|
65
147
|
return {
|
|
66
148
|
reading,
|
|
67
149
|
quality,
|
|
68
150
|
interfering,
|
|
69
151
|
hasCompass,
|
|
70
|
-
diagnostics
|
|
152
|
+
diagnostics,
|
|
153
|
+
permission,
|
|
154
|
+
getCurrentHeading,
|
|
155
|
+
recalibrate,
|
|
156
|
+
setLocation,
|
|
157
|
+
requestPermission
|
|
71
158
|
};
|
|
72
159
|
}
|
|
73
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","smoothingAlpha","declination","pauseOnBackground","enabled","reading","setReading","useState","quality","setQuality","interfering","setInterfering","hasCompass","NitroCompass","diagnostics","getDiagnostics","filterRef","useRef","current","useEffect","setFilter","setSmoothing","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
|
/**
|
|
@@ -21,14 +21,40 @@ export function useCompass(options = {}) {
|
|
|
21
21
|
const [reading, setReading] = useState(null);
|
|
22
22
|
const [quality, setQuality] = useState(null);
|
|
23
23
|
const [interfering, setInterfering] = useState(false);
|
|
24
|
-
const [hasCompass] = useState(() => NitroCompass.hasCompass());
|
|
25
|
-
const [diagnostics] = useState(() => NitroCompass.getDiagnostics());
|
|
26
24
|
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
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.
|
|
30
54
|
const filterRef = useRef(filterDegrees);
|
|
31
55
|
filterRef.current = filterDegrees;
|
|
56
|
+
const smoothingRef = useRef(smoothingAlpha);
|
|
57
|
+
smoothingRef.current = smoothingAlpha;
|
|
32
58
|
useEffect(() => {
|
|
33
59
|
NitroCompass.setFilter(filterDegrees);
|
|
34
60
|
}, [filterDegrees]);
|
|
@@ -50,20 +76,81 @@ export function useCompass(options = {}) {
|
|
|
50
76
|
return addInterferenceListener(setInterfering);
|
|
51
77
|
}, [hasCompass]);
|
|
52
78
|
useEffect(() => {
|
|
53
|
-
if (!hasCompass || !enabled)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
+
}
|
|
58
105
|
return off;
|
|
59
106
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
60
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
|
+
}, []);
|
|
61
143
|
return {
|
|
62
144
|
reading,
|
|
63
145
|
quality,
|
|
64
146
|
interfering,
|
|
65
147
|
hasCompass,
|
|
66
|
-
diagnostics
|
|
148
|
+
diagnostics,
|
|
149
|
+
permission,
|
|
150
|
+
getCurrentHeading,
|
|
151
|
+
recalibrate,
|
|
152
|
+
setLocation,
|
|
153
|
+
requestPermission
|
|
67
154
|
};
|
|
68
155
|
}
|
|
69
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","smoothingAlpha","declination","pauseOnBackground","enabled","reading","setReading","quality","setQuality","interfering","setInterfering","hasCompass","diagnostics","getDiagnostics","filterRef","current","setFilter","setSmoothing","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":"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","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":[]}
|
package/lib/module/multiplex.js
CHANGED
|
@@ -71,6 +71,13 @@ export function addHeadingListener(cb) {
|
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
// Module-level no-op kept stable so we can swap it back into the native
|
|
75
|
+
// callback slot when the last listener leaves — releasing references
|
|
76
|
+
// to old dispatcher closures, which matters when the JS module is
|
|
77
|
+
// re-evaluated (Metro Fast Refresh, jest module reset).
|
|
78
|
+
const NOOP_CALIBRATION = _ => {};
|
|
79
|
+
const NOOP_INTERFERENCE = _ => {};
|
|
80
|
+
|
|
74
81
|
/**
|
|
75
82
|
* Subscribe to calibration-bucket transitions. Only fires while a
|
|
76
83
|
* heading subscription is active. Returns the unsubscribe function.
|
|
@@ -82,7 +89,17 @@ export function addCalibrationListener(cb) {
|
|
|
82
89
|
}
|
|
83
90
|
calibrationListeners.add(cb);
|
|
84
91
|
return () => {
|
|
85
|
-
calibrationListeners.delete(cb);
|
|
92
|
+
if (!calibrationListeners.delete(cb)) return;
|
|
93
|
+
if (calibrationListeners.size === 0) {
|
|
94
|
+
// Detach our dispatcher from the native side. Without this, a
|
|
95
|
+
// module reload (Metro Fast Refresh, jest resetModules) leaves
|
|
96
|
+
// the old dispatcher pinned in native memory while a new module
|
|
97
|
+
// load installs a *second* dispatcher pointing at a fresh
|
|
98
|
+
// listener Set — splitting events between the two and silently
|
|
99
|
+
// dropping the now-orphaned listeners.
|
|
100
|
+
NitroCompass.setOnCalibrationNeeded(NOOP_CALIBRATION);
|
|
101
|
+
calibrationRegistered = false;
|
|
102
|
+
}
|
|
86
103
|
};
|
|
87
104
|
}
|
|
88
105
|
|
|
@@ -97,7 +114,11 @@ export function addInterferenceListener(cb) {
|
|
|
97
114
|
}
|
|
98
115
|
interferenceListeners.add(cb);
|
|
99
116
|
return () => {
|
|
100
|
-
interferenceListeners.delete(cb);
|
|
117
|
+
if (!interferenceListeners.delete(cb)) return;
|
|
118
|
+
if (interferenceListeners.size === 0) {
|
|
119
|
+
NitroCompass.setOnInterferenceDetected(NOOP_INTERFERENCE);
|
|
120
|
+
interferenceRegistered = false;
|
|
121
|
+
}
|
|
101
122
|
};
|
|
102
123
|
}
|
|
103
124
|
//# sourceMappingURL=multiplex.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NitroCompass","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","start","delete","stop","addCalibrationListener","setOnCalibrationNeeded","addInterferenceListener","setOnInterferenceDetected"],"sourceRoot":"../../src","sources":["multiplex.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAKA,SAASA,YAAY,QAAQ,UAAU;AAMvC,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;AACA,OAAO,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;IACZrB,YAAY,CAACwB,KAAK,CAACjB,kBAAkB,EAAEC,eAAe,CAAC;EACzD;EACA,OAAO,MAAM;IACX,IAAI,CAACP,gBAAgB,CAACwB,MAAM,CAACf,EAAE,CAAC,EAAE;IAClC,IAAIT,gBAAgB,CAACqB,IAAI,KAAK,CAAC,EAAE;MAC/BtB,YAAY,CAAC0B,IAAI,CAAC,CAAC;IACrB;EACF,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA,OAAO,
|
|
1
|
+
{"version":3,"names":["NitroCompass","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","start","delete","stop","NOOP_CALIBRATION","_","NOOP_INTERFERENCE","addCalibrationListener","setOnCalibrationNeeded","addInterferenceListener","setOnInterferenceDetected"],"sourceRoot":"../../src","sources":["multiplex.ts"],"mappings":"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","ignoreList":[]}
|