yaver-feedback-react-native 0.9.3 → 0.9.4
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/dist/ShakeDetector.js
CHANGED
|
@@ -97,6 +97,13 @@ class ShakeDetector {
|
|
|
97
97
|
* want the extra native surface get the Dev-menu path only.
|
|
98
98
|
*/
|
|
99
99
|
subscribeAccelerometer(onShake) {
|
|
100
|
+
// expo-sensors exposes an Accelerometer facade on web, but browsers have
|
|
101
|
+
// no native shake gesture and some versions construct a NativeEventEmitter
|
|
102
|
+
// backed by a module without addListener/removeListeners. Subscribing then
|
|
103
|
+
// crashes the host app's React commit phase. Preserve the SDK's explicit
|
|
104
|
+
// controls on web and skip only this impossible sensor transport.
|
|
105
|
+
if (react_native_1.Platform.OS === 'web')
|
|
106
|
+
return;
|
|
100
107
|
let Accelerometer = null;
|
|
101
108
|
try {
|
|
102
109
|
// Optional peer dep — if it isn't installed, we simply skip this path.
|
|
@@ -113,23 +120,30 @@ class ShakeDetector {
|
|
|
113
120
|
catch {
|
|
114
121
|
// Some platforms reject zero-value intervals; fall through with defaults
|
|
115
122
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
this.
|
|
131
|
-
|
|
132
|
-
|
|
123
|
+
try {
|
|
124
|
+
this.accelSub = Accelerometer.addListener(({ x, y, z }) => {
|
|
125
|
+
// Magnitude of acceleration vector (in g). Subtract 1 so a stationary
|
|
126
|
+
// device reports ~0 rather than the 1g of gravity.
|
|
127
|
+
const mag = Math.sqrt(x * x + y * y + z * z);
|
|
128
|
+
if (mag - 1 < ACCEL_THRESHOLD_G - 1)
|
|
129
|
+
return;
|
|
130
|
+
const now = Date.now();
|
|
131
|
+
this.peakTimestamps.push(now);
|
|
132
|
+
// Drop peaks that fell out of the rolling window.
|
|
133
|
+
while (this.peakTimestamps.length > 0 &&
|
|
134
|
+
now - this.peakTimestamps[0] > ACCEL_WINDOW_MS) {
|
|
135
|
+
this.peakTimestamps.shift();
|
|
136
|
+
}
|
|
137
|
+
if (this.peakTimestamps.length >= ACCEL_MIN_HITS) {
|
|
138
|
+
this.fire(onShake);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// A host may include expo-sensors without linking its native module.
|
|
144
|
+
// Optional shake support must never take down the host application.
|
|
145
|
+
this.accelSub = null;
|
|
146
|
+
}
|
|
133
147
|
}
|
|
134
148
|
}
|
|
135
149
|
exports.ShakeDetector = ShakeDetector;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Browsers cannot provide a native shake gesture. expo-sensors still exports
|
|
3
|
+
// an Accelerometer facade there, and older SDK builds attempted to subscribe
|
|
4
|
+
// to it, crashing the host React tree through NativeEventEmitter.
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const sensorAddListener = jest.fn(() => ({ remove: jest.fn() }));
|
|
7
|
+
const devEventAddListener = jest.fn(() => ({ remove: jest.fn() }));
|
|
8
|
+
jest.mock('react-native', () => ({
|
|
9
|
+
Platform: { OS: 'web' },
|
|
10
|
+
NativeModules: {},
|
|
11
|
+
DeviceEventEmitter: { addListener: devEventAddListener },
|
|
12
|
+
}));
|
|
13
|
+
jest.mock('expo-sensors', () => ({
|
|
14
|
+
Accelerometer: {
|
|
15
|
+
setUpdateInterval: jest.fn(),
|
|
16
|
+
addListener: sensorAddListener,
|
|
17
|
+
},
|
|
18
|
+
}), { virtual: true });
|
|
19
|
+
const ShakeDetector_1 = require("../ShakeDetector");
|
|
20
|
+
it('keeps explicit SDK controls alive without touching the native sensor on web', () => {
|
|
21
|
+
const detector = new ShakeDetector_1.ShakeDetector();
|
|
22
|
+
expect(() => detector.start(jest.fn())).not.toThrow();
|
|
23
|
+
expect(sensorAddListener).not.toHaveBeenCalled();
|
|
24
|
+
// The ordinary DeviceEventEmitter lane remains harmless and removable.
|
|
25
|
+
expect(devEventAddListener).toHaveBeenCalledTimes(1);
|
|
26
|
+
expect(() => detector.stop()).not.toThrow();
|
|
27
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yaver-feedback-react-native",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "Visual feedback SDK for Yaver — bug reports, screen recording, voice vibe coding, and local-first developer workflows",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/src/ShakeDetector.ts
CHANGED
|
@@ -96,6 +96,13 @@ export class ShakeDetector {
|
|
|
96
96
|
* want the extra native surface get the Dev-menu path only.
|
|
97
97
|
*/
|
|
98
98
|
private subscribeAccelerometer(onShake: () => void): void {
|
|
99
|
+
// expo-sensors exposes an Accelerometer facade on web, but browsers have
|
|
100
|
+
// no native shake gesture and some versions construct a NativeEventEmitter
|
|
101
|
+
// backed by a module without addListener/removeListeners. Subscribing then
|
|
102
|
+
// crashes the host app's React commit phase. Preserve the SDK's explicit
|
|
103
|
+
// controls on web and skip only this impossible sensor transport.
|
|
104
|
+
if (Platform.OS === 'web') return;
|
|
105
|
+
|
|
99
106
|
let Accelerometer: {
|
|
100
107
|
setUpdateInterval: (ms: number) => void;
|
|
101
108
|
addListener: (cb: (d: { x: number; y: number; z: number }) => void) => {
|
|
@@ -116,24 +123,30 @@ export class ShakeDetector {
|
|
|
116
123
|
// Some platforms reject zero-value intervals; fall through with defaults
|
|
117
124
|
}
|
|
118
125
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
126
|
+
try {
|
|
127
|
+
this.accelSub = Accelerometer.addListener(({ x, y, z }) => {
|
|
128
|
+
// Magnitude of acceleration vector (in g). Subtract 1 so a stationary
|
|
129
|
+
// device reports ~0 rather than the 1g of gravity.
|
|
130
|
+
const mag = Math.sqrt(x * x + y * y + z * z);
|
|
131
|
+
if (mag - 1 < ACCEL_THRESHOLD_G - 1) return;
|
|
124
132
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
const now = Date.now();
|
|
134
|
+
this.peakTimestamps.push(now);
|
|
135
|
+
// Drop peaks that fell out of the rolling window.
|
|
136
|
+
while (
|
|
137
|
+
this.peakTimestamps.length > 0 &&
|
|
138
|
+
now - this.peakTimestamps[0] > ACCEL_WINDOW_MS
|
|
139
|
+
) {
|
|
140
|
+
this.peakTimestamps.shift();
|
|
141
|
+
}
|
|
142
|
+
if (this.peakTimestamps.length >= ACCEL_MIN_HITS) {
|
|
143
|
+
this.fire(onShake);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
} catch {
|
|
147
|
+
// A host may include expo-sensors without linking its native module.
|
|
148
|
+
// Optional shake support must never take down the host application.
|
|
149
|
+
this.accelSub = null;
|
|
150
|
+
}
|
|
138
151
|
}
|
|
139
152
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Browsers cannot provide a native shake gesture. expo-sensors still exports
|
|
2
|
+
// an Accelerometer facade there, and older SDK builds attempted to subscribe
|
|
3
|
+
// to it, crashing the host React tree through NativeEventEmitter.
|
|
4
|
+
|
|
5
|
+
const sensorAddListener = jest.fn(() => ({ remove: jest.fn() }));
|
|
6
|
+
const devEventAddListener = jest.fn(() => ({ remove: jest.fn() }));
|
|
7
|
+
|
|
8
|
+
jest.mock('react-native', () => ({
|
|
9
|
+
Platform: { OS: 'web' },
|
|
10
|
+
NativeModules: {},
|
|
11
|
+
DeviceEventEmitter: { addListener: devEventAddListener },
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
jest.mock('expo-sensors', () => ({
|
|
15
|
+
Accelerometer: {
|
|
16
|
+
setUpdateInterval: jest.fn(),
|
|
17
|
+
addListener: sensorAddListener,
|
|
18
|
+
},
|
|
19
|
+
}), { virtual: true });
|
|
20
|
+
|
|
21
|
+
import { ShakeDetector } from '../ShakeDetector';
|
|
22
|
+
|
|
23
|
+
it('keeps explicit SDK controls alive without touching the native sensor on web', () => {
|
|
24
|
+
const detector = new ShakeDetector();
|
|
25
|
+
expect(() => detector.start(jest.fn())).not.toThrow();
|
|
26
|
+
expect(sensorAddListener).not.toHaveBeenCalled();
|
|
27
|
+
// The ordinary DeviceEventEmitter lane remains harmless and removable.
|
|
28
|
+
expect(devEventAddListener).toHaveBeenCalledTimes(1);
|
|
29
|
+
expect(() => detector.stop()).not.toThrow();
|
|
30
|
+
});
|