react-native-iinstall 0.2.8 → 0.2.10
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/lib/FeedbackModal.js +14 -3
- package/lib/ShakeDetector.js +43 -12
- package/package.json +1 -1
- package/src/FeedbackModal.tsx +28 -6
- package/src/ShakeDetector.ts +46 -15
package/lib/FeedbackModal.js
CHANGED
|
@@ -220,8 +220,13 @@ const FeedbackModal = ({ visible, onClose, screenshotUri, videoUri, onStartRecor
|
|
|
220
220
|
};
|
|
221
221
|
if (!visible)
|
|
222
222
|
return null;
|
|
223
|
+
const dismissKeyboard = () => {
|
|
224
|
+
react_native_1.Keyboard.dismiss();
|
|
225
|
+
};
|
|
223
226
|
return (<react_native_1.Modal visible={visible} transparent animationType="slide" onRequestClose={handleClose}>
|
|
224
|
-
<react_native_1.
|
|
227
|
+
<react_native_1.TouchableWithoutFeedback onPress={dismissKeyboard}>
|
|
228
|
+
<react_native_1.KeyboardAvoidingView behavior={react_native_1.Platform.OS === 'ios' ? 'padding' : 'height'} style={styles.container}>
|
|
229
|
+
<react_native_1.ScrollView contentContainerStyle={styles.scrollContainer} keyboardShouldPersistTaps="handled" showsVerticalScrollIndicator={false}>
|
|
225
230
|
<react_native_1.View style={styles.card}>
|
|
226
231
|
<react_native_1.View style={styles.header}>
|
|
227
232
|
<react_native_1.Text style={styles.title}>Report an Issue</react_native_1.Text>
|
|
@@ -247,7 +252,7 @@ const FeedbackModal = ({ visible, onClose, screenshotUri, videoUri, onStartRecor
|
|
|
247
252
|
</react_native_1.View>)}
|
|
248
253
|
</react_native_1.View>
|
|
249
254
|
|
|
250
|
-
<react_native_1.TextInput style={styles.input} placeholder="What happened? Describe the bug..." placeholderTextColor="#999" multiline value={description} onChangeText={setDescription}/>
|
|
255
|
+
<react_native_1.TextInput style={styles.input} placeholder="What happened? Describe the bug..." placeholderTextColor="#999" multiline value={description} onChangeText={setDescription} returnKeyType="done" blurOnSubmit={true} onSubmitEditing={() => react_native_1.Keyboard.dismiss()}/>
|
|
251
256
|
|
|
252
257
|
{/* Media Actions Row */}
|
|
253
258
|
<react_native_1.View style={styles.actionsRow}>
|
|
@@ -268,7 +273,9 @@ const FeedbackModal = ({ visible, onClose, screenshotUri, videoUri, onStartRecor
|
|
|
268
273
|
{isSending ? (<react_native_1.ActivityIndicator color="#FFF"/>) : (<react_native_1.Text style={styles.submitText}>Send Feedback</react_native_1.Text>)}
|
|
269
274
|
</react_native_1.TouchableOpacity>
|
|
270
275
|
</react_native_1.View>
|
|
271
|
-
|
|
276
|
+
</react_native_1.ScrollView>
|
|
277
|
+
</react_native_1.KeyboardAvoidingView>
|
|
278
|
+
</react_native_1.TouchableWithoutFeedback>
|
|
272
279
|
</react_native_1.Modal>);
|
|
273
280
|
};
|
|
274
281
|
exports.FeedbackModal = FeedbackModal;
|
|
@@ -278,6 +285,10 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
278
285
|
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
279
286
|
justifyContent: 'flex-end',
|
|
280
287
|
},
|
|
288
|
+
scrollContainer: {
|
|
289
|
+
flexGrow: 1,
|
|
290
|
+
justifyContent: 'flex-end',
|
|
291
|
+
},
|
|
281
292
|
card: {
|
|
282
293
|
backgroundColor: '#FFF',
|
|
283
294
|
borderTopLeftRadius: 20,
|
package/lib/ShakeDetector.js
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ShakeDetector = void 0;
|
|
4
|
-
|
|
4
|
+
/* eslint-disable */
|
|
5
5
|
const operators_1 = require("rxjs/operators");
|
|
6
|
+
// Safe import for react-native-sensors to prevent crashes if native module is missing
|
|
7
|
+
let accelerometer;
|
|
8
|
+
let setUpdateIntervalForType;
|
|
9
|
+
let SensorTypes;
|
|
10
|
+
try {
|
|
11
|
+
const sensors = require('react-native-sensors');
|
|
12
|
+
accelerometer = sensors.accelerometer;
|
|
13
|
+
setUpdateIntervalForType = sensors.setUpdateIntervalForType;
|
|
14
|
+
SensorTypes = sensors.SensorTypes;
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
console.warn('[iInstall SDK] Shake detection disabled: react-native-sensors native module not found. Please ensure the native module is linked and the app is rebuilt.');
|
|
18
|
+
}
|
|
6
19
|
const SHAKE_THRESHOLD = 2.5; // g-force
|
|
7
20
|
const MIN_TIME_BETWEEN_SHAKES = 1000; // ms
|
|
8
21
|
class ShakeDetector {
|
|
@@ -11,21 +24,39 @@ class ShakeDetector {
|
|
|
11
24
|
onShake;
|
|
12
25
|
constructor(onShake) {
|
|
13
26
|
this.onShake = onShake;
|
|
14
|
-
(
|
|
27
|
+
if (setUpdateIntervalForType && SensorTypes) {
|
|
28
|
+
try {
|
|
29
|
+
setUpdateIntervalForType(SensorTypes.accelerometer, 100); // 100ms interval
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
console.warn('[iInstall SDK] Failed to set accelerometer update interval:', e);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
15
35
|
}
|
|
16
36
|
start() {
|
|
17
37
|
if (this.subscription)
|
|
18
38
|
return;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
39
|
+
if (!accelerometer) {
|
|
40
|
+
// Don't spam logs, just return silently or maybe log once if debugging
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
this.subscription = accelerometer
|
|
45
|
+
.pipe((0, operators_1.map)(({ x, y, z }) => Math.sqrt(x * x + y * y + z * z)), (0, operators_1.filter)((g) => g > SHAKE_THRESHOLD))
|
|
46
|
+
.subscribe(() => {
|
|
47
|
+
const now = Date.now();
|
|
48
|
+
if (now - this.lastShakeTime > MIN_TIME_BETWEEN_SHAKES) {
|
|
49
|
+
this.lastShakeTime = now;
|
|
50
|
+
console.log('TesterFlow: Shake detected!');
|
|
51
|
+
this.onShake();
|
|
52
|
+
}
|
|
53
|
+
}, (error) => {
|
|
54
|
+
console.warn('[iInstall SDK] Error in shake detection subscription:', error);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
console.warn('[iInstall SDK] Failed to start shake detection:', e);
|
|
59
|
+
}
|
|
29
60
|
}
|
|
30
61
|
stop() {
|
|
31
62
|
if (this.subscription) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-iinstall",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"description": "🎯 IInstall React Native SDK - The ultimate beta testing & QA feedback tool. Shake-to-report with voice recordings, screen recordings, and screenshots. Zero-config setup with TypeScript support. Perfect for beta testing, QA teams, and user feedback collection.",
|
|
5
5
|
"author": "TesterFlow Team",
|
|
6
6
|
"license": "MIT",
|
package/src/FeedbackModal.tsx
CHANGED
|
@@ -11,7 +11,10 @@ import {
|
|
|
11
11
|
Alert,
|
|
12
12
|
Platform,
|
|
13
13
|
KeyboardAvoidingView,
|
|
14
|
-
PermissionsAndroid
|
|
14
|
+
PermissionsAndroid,
|
|
15
|
+
Keyboard,
|
|
16
|
+
TouchableWithoutFeedback,
|
|
17
|
+
ScrollView
|
|
15
18
|
} from 'react-native';
|
|
16
19
|
import DeviceInfo from 'react-native-device-info';
|
|
17
20
|
import AudioRecorderPlayer, {
|
|
@@ -242,12 +245,22 @@ export const FeedbackModal: React.FC<FeedbackModalProps> = ({
|
|
|
242
245
|
|
|
243
246
|
if (!visible) return null;
|
|
244
247
|
|
|
248
|
+
const dismissKeyboard = () => {
|
|
249
|
+
Keyboard.dismiss();
|
|
250
|
+
};
|
|
251
|
+
|
|
245
252
|
return (
|
|
246
253
|
<Modal visible={visible} transparent animationType="slide" onRequestClose={handleClose}>
|
|
247
|
-
<
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
254
|
+
<TouchableWithoutFeedback onPress={dismissKeyboard}>
|
|
255
|
+
<KeyboardAvoidingView
|
|
256
|
+
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
|
257
|
+
style={styles.container}
|
|
258
|
+
>
|
|
259
|
+
<ScrollView
|
|
260
|
+
contentContainerStyle={styles.scrollContainer}
|
|
261
|
+
keyboardShouldPersistTaps="handled"
|
|
262
|
+
showsVerticalScrollIndicator={false}
|
|
263
|
+
>
|
|
251
264
|
<View style={styles.card}>
|
|
252
265
|
<View style={styles.header}>
|
|
253
266
|
<Text style={styles.title}>Report an Issue</Text>
|
|
@@ -284,6 +297,9 @@ export const FeedbackModal: React.FC<FeedbackModalProps> = ({
|
|
|
284
297
|
multiline
|
|
285
298
|
value={description}
|
|
286
299
|
onChangeText={setDescription}
|
|
300
|
+
returnKeyType="done"
|
|
301
|
+
blurOnSubmit={true}
|
|
302
|
+
onSubmitEditing={() => Keyboard.dismiss()}
|
|
287
303
|
/>
|
|
288
304
|
|
|
289
305
|
{/* Media Actions Row */}
|
|
@@ -321,7 +337,9 @@ export const FeedbackModal: React.FC<FeedbackModalProps> = ({
|
|
|
321
337
|
)}
|
|
322
338
|
</TouchableOpacity>
|
|
323
339
|
</View>
|
|
324
|
-
|
|
340
|
+
</ScrollView>
|
|
341
|
+
</KeyboardAvoidingView>
|
|
342
|
+
</TouchableWithoutFeedback>
|
|
325
343
|
</Modal>
|
|
326
344
|
);
|
|
327
345
|
};
|
|
@@ -332,6 +350,10 @@ const styles = StyleSheet.create({
|
|
|
332
350
|
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
333
351
|
justifyContent: 'flex-end',
|
|
334
352
|
},
|
|
353
|
+
scrollContainer: {
|
|
354
|
+
flexGrow: 1,
|
|
355
|
+
justifyContent: 'flex-end',
|
|
356
|
+
},
|
|
335
357
|
card: {
|
|
336
358
|
backgroundColor: '#FFF',
|
|
337
359
|
borderTopLeftRadius: 20,
|
package/src/ShakeDetector.ts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable */
|
|
2
2
|
import { map, filter } from 'rxjs/operators';
|
|
3
3
|
|
|
4
|
+
// Safe import for react-native-sensors to prevent crashes if native module is missing
|
|
5
|
+
let accelerometer: any;
|
|
6
|
+
let setUpdateIntervalForType: any;
|
|
7
|
+
let SensorTypes: any;
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const sensors = require('react-native-sensors');
|
|
11
|
+
accelerometer = sensors.accelerometer;
|
|
12
|
+
setUpdateIntervalForType = sensors.setUpdateIntervalForType;
|
|
13
|
+
SensorTypes = sensors.SensorTypes;
|
|
14
|
+
} catch (e) {
|
|
15
|
+
console.warn('[iInstall SDK] Shake detection disabled: react-native-sensors native module not found. Please ensure the native module is linked and the app is rebuilt.');
|
|
16
|
+
}
|
|
17
|
+
|
|
4
18
|
const SHAKE_THRESHOLD = 2.5; // g-force
|
|
5
19
|
const MIN_TIME_BETWEEN_SHAKES = 1000; // ms
|
|
6
20
|
|
|
@@ -11,25 +25,42 @@ export class ShakeDetector {
|
|
|
11
25
|
|
|
12
26
|
constructor(onShake: () => void) {
|
|
13
27
|
this.onShake = onShake;
|
|
14
|
-
setUpdateIntervalForType
|
|
28
|
+
if (setUpdateIntervalForType && SensorTypes) {
|
|
29
|
+
try {
|
|
30
|
+
setUpdateIntervalForType(SensorTypes.accelerometer, 100); // 100ms interval
|
|
31
|
+
} catch (e) {
|
|
32
|
+
console.warn('[iInstall SDK] Failed to set accelerometer update interval:', e);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
15
35
|
}
|
|
16
36
|
|
|
17
37
|
start() {
|
|
18
38
|
if (this.subscription) return;
|
|
19
39
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
if (!accelerometer) {
|
|
41
|
+
// Don't spam logs, just return silently or maybe log once if debugging
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
this.subscription = accelerometer
|
|
47
|
+
.pipe(
|
|
48
|
+
map(({ x, y, z }: any) => Math.sqrt(x * x + y * y + z * z)),
|
|
49
|
+
filter((g: number) => g > SHAKE_THRESHOLD)
|
|
50
|
+
)
|
|
51
|
+
.subscribe(() => {
|
|
52
|
+
const now = Date.now();
|
|
53
|
+
if (now - this.lastShakeTime > MIN_TIME_BETWEEN_SHAKES) {
|
|
54
|
+
this.lastShakeTime = now;
|
|
55
|
+
console.log('TesterFlow: Shake detected!');
|
|
56
|
+
this.onShake();
|
|
57
|
+
}
|
|
58
|
+
}, (error: any) => {
|
|
59
|
+
console.warn('[iInstall SDK] Error in shake detection subscription:', error);
|
|
60
|
+
});
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.warn('[iInstall SDK] Failed to start shake detection:', e);
|
|
63
|
+
}
|
|
33
64
|
}
|
|
34
65
|
|
|
35
66
|
stop() {
|