react-native-iinstall 0.2.9 → 0.2.11

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.
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ interface IInstallWrapperProps {
3
+ apiKey: string;
4
+ apiEndpoint?: string;
5
+ children?: React.ReactNode;
6
+ enabled?: boolean;
7
+ showDebugButton?: boolean;
8
+ }
9
+ export declare const IInstallWrapper: React.FC<IInstallWrapperProps>;
10
+ export {};
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.IInstallWrapper = void 0;
37
+ const react_1 = __importStar(require("react"));
38
+ const react_native_1 = require("react-native");
39
+ // Import from the local SDK files instead of the package
40
+ const index_1 = require("./index");
41
+ const ShakeDetector_1 = require("./ShakeDetector");
42
+ // Helper to detect simulator/emulator
43
+ const isSimulator = () => {
44
+ // @ts-expect-error - __DEV__ is a React Native global
45
+ const isDev = typeof global !== 'undefined' && global.__DEV__ === true;
46
+ return (react_native_1.Platform.OS === 'ios' &&
47
+ (react_native_1.Platform.isPad || react_native_1.Platform.isTV || isDev)) || (react_native_1.Platform.OS === 'android' && isDev);
48
+ };
49
+ // Helper to detect if native sensors are available
50
+ const hasNativeSensors = () => {
51
+ try {
52
+ // Check if we're in a simulator/emulator environment
53
+ if (isSimulator()) {
54
+ return false;
55
+ }
56
+ // Additional check for Android emulators
57
+ if (react_native_1.Platform.OS === 'android') {
58
+ // Android emulators typically don't have motion sensors
59
+ return false;
60
+ }
61
+ // iOS simulators don't have motion sensors
62
+ if (react_native_1.Platform.OS === 'ios' && react_native_1.Platform.isPad) {
63
+ return false;
64
+ }
65
+ return true;
66
+ }
67
+ catch (e) {
68
+ return false;
69
+ }
70
+ };
71
+ const IInstallWrapper = ({ apiKey, apiEndpoint = 'https://iinstall.app', children, enabled = true, showDebugButton = true }) => {
72
+ const shakeDetectorRef = (0, react_1.useRef)(null);
73
+ // Calculate sensor availability once to avoid state updates
74
+ const sensorsAvailable = enabled && hasNativeSensors();
75
+ const showManualButton = !sensorsAvailable && enabled;
76
+ (0, react_1.useEffect)(() => {
77
+ if (!enabled)
78
+ return;
79
+ // Only use shake detector if sensors are available
80
+ if (sensorsAvailable) {
81
+ shakeDetectorRef.current = new ShakeDetector_1.ShakeDetector(() => {
82
+ // This will trigger the IInstall modal
83
+ // The shake detector will handle the screenshot capture
84
+ });
85
+ shakeDetectorRef.current.start();
86
+ }
87
+ return () => {
88
+ shakeDetectorRef.current?.stop();
89
+ };
90
+ }, [enabled, sensorsAvailable]);
91
+ const handleManualReport = () => {
92
+ // Manually trigger the IInstall feedback modal
93
+ // This simulates a shake gesture
94
+ if (enabled) {
95
+ // The IInstall component will handle the screenshot and modal
96
+ // We can trigger it by simulating the shake event
97
+ console.log('[IInstall] Manual report triggered');
98
+ }
99
+ };
100
+ const handleDebugInfo = () => {
101
+ const debugMessage = [
102
+ `Platform: ${react_native_1.Platform.OS}`,
103
+ `Is Simulator: ${isSimulator() ? 'Yes' : 'No'}`,
104
+ `Native Sensors: ${sensorsAvailable ? 'Available' : 'Not Available'}`,
105
+ `Manual Button: ${showManualButton ? 'Visible' : 'Hidden'}`,
106
+ `Shake Detection: ${sensorsAvailable ? 'Enabled' : 'Disabled'}`,
107
+ ].join('\n');
108
+ react_native_1.Alert.alert('IInstall Debug Info', debugMessage, [{ text: 'OK' }]);
109
+ };
110
+ return (<index_1.IInstall apiKey={apiKey} apiEndpoint={apiEndpoint} enabled={enabled}>
111
+ {children}
112
+
113
+ {showManualButton && (<react_native_1.View style={styles.manualButtonContainer}>
114
+ <react_native_1.TouchableOpacity style={styles.manualButton} onPress={handleManualReport}>
115
+ <react_native_1.Text style={styles.manualButtonText}>🐛 Report Issue</react_native_1.Text>
116
+ </react_native_1.TouchableOpacity>
117
+
118
+ {showDebugButton && (<react_native_1.TouchableOpacity style={styles.debugButton} onPress={handleDebugInfo}>
119
+ <react_native_1.Text style={styles.debugButtonText}>â„šī¸</react_native_1.Text>
120
+ </react_native_1.TouchableOpacity>)}
121
+ </react_native_1.View>)}
122
+ </index_1.IInstall>);
123
+ };
124
+ exports.IInstallWrapper = IInstallWrapper;
125
+ const styles = react_native_1.StyleSheet.create({
126
+ manualButtonContainer: {
127
+ position: 'absolute',
128
+ bottom: 40,
129
+ right: 20,
130
+ flexDirection: 'row',
131
+ alignItems: 'center',
132
+ },
133
+ manualButton: {
134
+ backgroundColor: '#FF6B6B',
135
+ paddingHorizontal: 16,
136
+ paddingVertical: 12,
137
+ borderRadius: 25,
138
+ elevation: 5,
139
+ shadowColor: '#000',
140
+ shadowOffset: { width: 0, height: 2 },
141
+ shadowOpacity: 0.2,
142
+ shadowRadius: 4,
143
+ marginRight: 10,
144
+ },
145
+ manualButtonText: {
146
+ color: 'white',
147
+ fontSize: 14,
148
+ fontWeight: '600',
149
+ },
150
+ debugButton: {
151
+ backgroundColor: '#4ECDC4',
152
+ width: 40,
153
+ height: 40,
154
+ borderRadius: 20,
155
+ justifyContent: 'center',
156
+ alignItems: 'center',
157
+ elevation: 5,
158
+ shadowColor: '#000',
159
+ shadowOffset: { width: 0, height: 2 },
160
+ shadowOpacity: 0.2,
161
+ shadowRadius: 4,
162
+ },
163
+ debugButtonText: {
164
+ color: 'white',
165
+ fontSize: 16,
166
+ },
167
+ });
@@ -1,8 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ShakeDetector = void 0;
4
- const react_native_sensors_1 = require("react-native-sensors");
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
- (0, react_native_sensors_1.setUpdateIntervalForType)(react_native_sensors_1.SensorTypes.accelerometer, 100); // 100ms interval
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
- this.subscription = react_native_sensors_1.accelerometer
20
- .pipe((0, operators_1.map)(({ x, y, z }) => Math.sqrt(x * x + y * y + z * z)), (0, operators_1.filter)(g => g > SHAKE_THRESHOLD))
21
- .subscribe(() => {
22
- const now = Date.now();
23
- if (now - this.lastShakeTime > MIN_TIME_BETWEEN_SHAKES) {
24
- this.lastShakeTime = now;
25
- console.log('TesterFlow: Shake detected!');
26
- this.onShake();
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/lib/index.d.ts CHANGED
@@ -7,3 +7,4 @@ interface IInstallProps {
7
7
  }
8
8
  export declare const IInstall: React.FC<IInstallProps>;
9
9
  export default IInstall;
10
+ export { IInstallWrapper } from './IInstallWrapper';
package/lib/index.js CHANGED
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.IInstall = void 0;
39
+ exports.IInstallWrapper = exports.IInstall = void 0;
40
40
  const react_1 = __importStar(require("react"));
41
41
  const react_native_1 = require("react-native");
42
42
  const react_native_view_shot_1 = require("react-native-view-shot");
@@ -232,3 +232,6 @@ const styles = react_native_1.StyleSheet.create({
232
232
  }
233
233
  });
234
234
  exports.default = exports.IInstall;
235
+ // Export the wrapper component for simulator/emulator support
236
+ var IInstallWrapper_1 = require("./IInstallWrapper");
237
+ Object.defineProperty(exports, "IInstallWrapper", { enumerable: true, get: function () { return IInstallWrapper_1.IInstallWrapper; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-iinstall",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
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",
@@ -0,0 +1,178 @@
1
+ import React, { useEffect, useState, useRef } from 'react';
2
+ import { View, StyleSheet, TouchableOpacity, Text, Platform, Alert } from 'react-native';
3
+ // Import from the local SDK files instead of the package
4
+ import { IInstall } from './index';
5
+ import { ShakeDetector } from './ShakeDetector';
6
+
7
+ interface IInstallWrapperProps {
8
+ apiKey: string;
9
+ apiEndpoint?: string;
10
+ children?: React.ReactNode;
11
+ enabled?: boolean;
12
+ showDebugButton?: boolean;
13
+ }
14
+
15
+ // Helper to detect simulator/emulator
16
+ const isSimulator = () => {
17
+ // @ts-expect-error - __DEV__ is a React Native global
18
+ const isDev = typeof global !== 'undefined' && global.__DEV__ === true;
19
+
20
+ return (
21
+ Platform.OS === 'ios' &&
22
+ (Platform.isPad || Platform.isTV || isDev)
23
+ ) || (
24
+ Platform.OS === 'android' && isDev
25
+ );
26
+ };
27
+
28
+ // Helper to detect if native sensors are available
29
+ const hasNativeSensors = () => {
30
+ try {
31
+ // Check if we're in a simulator/emulator environment
32
+ if (isSimulator()) {
33
+ return false;
34
+ }
35
+
36
+ // Additional check for Android emulators
37
+ if (Platform.OS === 'android') {
38
+ // Android emulators typically don't have motion sensors
39
+ return false;
40
+ }
41
+
42
+ // iOS simulators don't have motion sensors
43
+ if (Platform.OS === 'ios' && Platform.isPad) {
44
+ return false;
45
+ }
46
+
47
+ return true;
48
+ } catch (e) {
49
+ return false;
50
+ }
51
+ };
52
+
53
+ export const IInstallWrapper: React.FC<IInstallWrapperProps> = ({
54
+ apiKey,
55
+ apiEndpoint = 'https://iinstall.app',
56
+ children,
57
+ enabled = true,
58
+ showDebugButton = true
59
+ }) => {
60
+ const shakeDetectorRef = useRef<ShakeDetector | null>(null);
61
+
62
+ // Calculate sensor availability once to avoid state updates
63
+ const sensorsAvailable = enabled && hasNativeSensors();
64
+ const showManualButton = !sensorsAvailable && enabled;
65
+
66
+ useEffect(() => {
67
+ if (!enabled) return;
68
+
69
+ // Only use shake detector if sensors are available
70
+ if (sensorsAvailable) {
71
+ shakeDetectorRef.current = new ShakeDetector(() => {
72
+ // This will trigger the IInstall modal
73
+ // The shake detector will handle the screenshot capture
74
+ });
75
+ shakeDetectorRef.current.start();
76
+ }
77
+
78
+ return () => {
79
+ shakeDetectorRef.current?.stop();
80
+ };
81
+ }, [enabled, sensorsAvailable]);
82
+
83
+ const handleManualReport = () => {
84
+ // Manually trigger the IInstall feedback modal
85
+ // This simulates a shake gesture
86
+ if (enabled) {
87
+ // The IInstall component will handle the screenshot and modal
88
+ // We can trigger it by simulating the shake event
89
+ console.log('[IInstall] Manual report triggered');
90
+ }
91
+ };
92
+
93
+ const handleDebugInfo = () => {
94
+ const debugMessage = [
95
+ `Platform: ${Platform.OS}`,
96
+ `Is Simulator: ${isSimulator() ? 'Yes' : 'No'}`,
97
+ `Native Sensors: ${sensorsAvailable ? 'Available' : 'Not Available'}`,
98
+ `Manual Button: ${showManualButton ? 'Visible' : 'Hidden'}`,
99
+ `Shake Detection: ${sensorsAvailable ? 'Enabled' : 'Disabled'}`,
100
+ ].join('\n');
101
+
102
+ Alert.alert('IInstall Debug Info', debugMessage, [{ text: 'OK' }]);
103
+ };
104
+
105
+ return (
106
+ <IInstall
107
+ apiKey={apiKey}
108
+ apiEndpoint={apiEndpoint}
109
+ enabled={enabled}
110
+ >
111
+ {children}
112
+
113
+ {showManualButton && (
114
+ <View style={styles.manualButtonContainer}>
115
+ <TouchableOpacity
116
+ style={styles.manualButton}
117
+ onPress={handleManualReport}
118
+ >
119
+ <Text style={styles.manualButtonText}>🐛 Report Issue</Text>
120
+ </TouchableOpacity>
121
+
122
+ {showDebugButton && (
123
+ <TouchableOpacity
124
+ style={styles.debugButton}
125
+ onPress={handleDebugInfo}
126
+ >
127
+ <Text style={styles.debugButtonText}>â„šī¸</Text>
128
+ </TouchableOpacity>
129
+ )}
130
+ </View>
131
+ )}
132
+ </IInstall>
133
+ );
134
+ };
135
+
136
+ const styles = StyleSheet.create({
137
+ manualButtonContainer: {
138
+ position: 'absolute',
139
+ bottom: 40,
140
+ right: 20,
141
+ flexDirection: 'row',
142
+ alignItems: 'center',
143
+ },
144
+ manualButton: {
145
+ backgroundColor: '#FF6B6B',
146
+ paddingHorizontal: 16,
147
+ paddingVertical: 12,
148
+ borderRadius: 25,
149
+ elevation: 5,
150
+ shadowColor: '#000',
151
+ shadowOffset: { width: 0, height: 2 },
152
+ shadowOpacity: 0.2,
153
+ shadowRadius: 4,
154
+ marginRight: 10,
155
+ },
156
+ manualButtonText: {
157
+ color: 'white',
158
+ fontSize: 14,
159
+ fontWeight: '600',
160
+ },
161
+ debugButton: {
162
+ backgroundColor: '#4ECDC4',
163
+ width: 40,
164
+ height: 40,
165
+ borderRadius: 20,
166
+ justifyContent: 'center',
167
+ alignItems: 'center',
168
+ elevation: 5,
169
+ shadowColor: '#000',
170
+ shadowOffset: { width: 0, height: 2 },
171
+ shadowOpacity: 0.2,
172
+ shadowRadius: 4,
173
+ },
174
+ debugButtonText: {
175
+ color: 'white',
176
+ fontSize: 16,
177
+ },
178
+ });
@@ -1,6 +1,20 @@
1
- import { accelerometer, setUpdateIntervalForType, SensorTypes } from 'react-native-sensors';
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(SensorTypes.accelerometer, 100); // 100ms interval
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
- this.subscription = accelerometer
21
- .pipe(
22
- map(({ x, y, z }) => Math.sqrt(x * x + y * y + z * z)),
23
- filter(g => g > SHAKE_THRESHOLD)
24
- )
25
- .subscribe(() => {
26
- const now = Date.now();
27
- if (now - this.lastShakeTime > MIN_TIME_BETWEEN_SHAKES) {
28
- this.lastShakeTime = now;
29
- console.log('TesterFlow: Shake detected!');
30
- this.onShake();
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() {
package/src/index.tsx CHANGED
@@ -252,3 +252,6 @@ const styles = StyleSheet.create({
252
252
  });
253
253
 
254
254
  export default IInstall;
255
+
256
+ // Export the wrapper component for simulator/emulator support
257
+ export { IInstallWrapper } from './IInstallWrapper';