shakebug-react-native 2.4.15 → 2.4.17
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 +6 -0
- package/android/src/main/java/com/shakebug/ConnectivityReceiver.java +12 -7
- package/android/src/main/java/com/shakebug/DrawingView.java +13 -3
- package/android/src/main/java/com/shakebug/RecordScreenModule.java +6 -3
- package/android/src/main/java/com/shakebug/ViewShot.java +1 -0
- package/ios/CustomScreenShot/ShakebugSDKCustomScreenCapture.m +6 -2
- package/ios/ScreenShot/ShakebugCapture.m +3 -1
- package/ios/SketchCanvas/DrawingView.m +14 -1
- package/package.json +1 -1
- package/shakebug-react-native-2.4.15.tgz +0 -0
- package/src/Assets/images/shake.png +0 -0
- package/src/Assets/images/undo.png +0 -0
- package/src/Assets/images/undo@2x.png +0 -0
- package/src/Assets/images/undo@3x.png +0 -0
- package/src/Componanats/CustomAlert.js +8 -4
- package/src/Componanats/Icons.js +278 -0
- package/src/Componanats/KeyboardAvoidingWrapper.js +31 -39
- package/src/Componanats/LoadingModal.js +7 -4
- package/src/Componanats/NavigationContext.js +8 -1
- package/src/Componanats/ReviewModal.js +18 -11
- package/src/Componanats/SafeAreaHelper.js +70 -0
- package/src/Componanats/ShakeFunction.js +655 -364
- package/src/Componanats/ShakebugBottomSheet.js +729 -0
- package/src/Componanats/Theme.js +96 -0
- package/src/Componanats/ZoomableImage.js +350 -0
- package/src/Componanats/localization.js +32 -3
- package/src/Screens/AddDetailsScreen.js +800 -439
- package/src/Screens/FirstScreen.js +950 -540
- package/src/Screens/Shakebug.js +78 -44
- package/src/Screens/TrimVideoScreen.js +40 -7
- package/src/index.tsx +16 -7
- package/shakebug-react-native-2.4.14.tgz +0 -0
|
@@ -1,257 +1,325 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
View,
|
|
3
|
+
Text,
|
|
4
|
+
Platform,
|
|
5
|
+
Image,
|
|
6
|
+
NativeModules,
|
|
7
|
+
DeviceEventEmitter,
|
|
8
|
+
NativeEventEmitter,
|
|
9
|
+
StatusBar,
|
|
10
|
+
PanResponder,
|
|
11
|
+
Animated,
|
|
12
|
+
AppState,
|
|
13
|
+
Dimensions,
|
|
14
|
+
LogBox,
|
|
15
|
+
StyleSheet,
|
|
16
|
+
Alert,
|
|
17
|
+
PermissionsAndroid,
|
|
18
|
+
Linking,
|
|
19
|
+
} from 'react-native';
|
|
20
|
+
import React, { useRef, useEffect, useState } from 'react';
|
|
3
21
|
import { SensorTypes, setUpdateIntervalForType, accelerometer } from '../../Sensor/src/index';
|
|
4
22
|
import { ShakebugCapture, captureScreen } from '../index';
|
|
5
23
|
import { TouchableOpacity } from 'react-native';
|
|
6
24
|
import RecordScreen from '../../RecordScreen/src/index';
|
|
7
25
|
import { ClearCanvas, RNDrawingView } from '../Screens/StrockView';
|
|
8
|
-
import DeviceInfo
|
|
26
|
+
import DeviceInfo from '../../DeviceInfo';
|
|
9
27
|
import { useNavigation } from './NavigationContext';
|
|
10
|
-
|
|
11
|
-
console.ignoredYellowBox = ["Warning: Each", "Warning: Failed", "Possible", "WARN"];
|
|
12
|
-
|
|
13
|
-
import { logger, consoleTransport } from "react-native-logs";
|
|
14
|
-
import { ActivityIndicator } from 'react-native';
|
|
28
|
+
import { logger, consoleTransport } from 'react-native-logs';
|
|
15
29
|
import { useGlobalState } from './GlobalStateContext';
|
|
16
30
|
import LoadingModal from './LoadingModal';
|
|
31
|
+
import CustomeAlert from './CustomAlert';
|
|
32
|
+
import ShakebugBottomSheet from './ShakebugBottomSheet';
|
|
33
|
+
import { getLocalizedString, Localization } from './localization';
|
|
34
|
+
import { launchImageLibrary } from '../../ImageOrVedioPicker/src/index';
|
|
17
35
|
|
|
18
|
-
|
|
36
|
+
console.ignoredYellowBox = ['Warning: Each', 'Warning: Failed', 'Possible', 'WARN'];
|
|
37
|
+
LogBox.ignoreAllLogs();
|
|
19
38
|
|
|
20
39
|
let intervalId = null;
|
|
21
|
-
const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitle, allowToReportBugByShaking, allowToReportBugByScreenCapture, allowCrashReport }) => {
|
|
22
40
|
|
|
23
|
-
|
|
41
|
+
const ShakeFunction = ({
|
|
42
|
+
children,
|
|
43
|
+
themeColor = '#272B32',
|
|
44
|
+
showTutorialScreen,
|
|
45
|
+
SDKScreenTitle,
|
|
46
|
+
allowToReportBugByShaking,
|
|
47
|
+
allowToReportBugByScreenCapture,
|
|
48
|
+
allowCrashReport,
|
|
49
|
+
}) => {
|
|
50
|
+
const {
|
|
51
|
+
ShakebugSDKScreenShotDetector,
|
|
52
|
+
ShakebugSDKSharedPreferencesModule,
|
|
53
|
+
ShakebugSDKCustomScreenCapture,
|
|
54
|
+
RNCameraPermission,
|
|
55
|
+
} = NativeModules;
|
|
24
56
|
|
|
25
57
|
const { navigate, focusedScreen, goToScreenAtIndex } = useNavigation();
|
|
26
58
|
|
|
27
|
-
let isFocused = focusedScreen
|
|
28
|
-
const [isLoading, setIsLoading] = useState(false)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
if (Platform.OS == 'android') {
|
|
34
|
-
ShakebugSDKScreenShotDetector.startObserving();
|
|
35
|
-
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
const subscription = DeviceEventEmitter.addListener('ScreenshotTaken', async () => {
|
|
38
|
-
if (allowToReportBugByScreenCapture == true) {
|
|
39
|
-
if (!global.isScreenShotDetected && global.application_id != "" && global.application_id != undefined) {
|
|
40
|
-
OpenShakebug()
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
})
|
|
59
|
+
let isFocused = focusedScreen === 'ShakebugHome';
|
|
60
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
61
|
+
const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false);
|
|
62
|
+
const [capturedScreenshot, setCapturedScreenshot] = useState(null);
|
|
63
|
+
const [isAlert, setIsAlert] = useState(false);
|
|
64
|
+
const [isAlertText, setIsAlertText] = useState('');
|
|
44
65
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const screenShotEmitter = new NativeEventEmitter(ShakebugSDKScreenShotDetector);
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
const subscription = screenShotEmitter.addListener(
|
|
52
|
-
'ScreenshotTaken',
|
|
53
|
-
(event) => {
|
|
54
|
-
if (allowToReportBugByScreenCapture == true) {
|
|
55
|
-
// setIsScreenShot(true)
|
|
56
|
-
if (!global.isScreenShotDetected && global.application_id != "" && global.application_id != undefined) {
|
|
57
|
-
OpenShakebug()
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
);
|
|
66
|
+
const KEY_SHAKE_DISABLED_UNTIL = 'SHAKE_DISABLED_UNTIL';
|
|
67
|
+
const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
|
|
68
|
+
const [isShakeDisabled, setIsShakeDisabled] = useState(false);
|
|
69
|
+
const shakeDisabledUntilRef = useRef(0);
|
|
62
70
|
|
|
63
|
-
|
|
64
|
-
}, []);
|
|
65
|
-
}
|
|
71
|
+
const { setIsRecordingStart, setIsScreenShot, isScrenShot } = useGlobalState();
|
|
66
72
|
|
|
67
73
|
const ref = useRef();
|
|
68
|
-
let canvasRef = useRef()
|
|
69
|
-
const [isShow, setIsShow] = useState()
|
|
70
|
-
const [time, setTime] = useState(
|
|
71
|
-
const [
|
|
72
|
-
const [isDraw, setIsDraw] = useState(false)
|
|
74
|
+
let canvasRef = useRef();
|
|
75
|
+
const [isShow, setIsShow] = useState(false);
|
|
76
|
+
const [time, setTime] = useState('00:00');
|
|
77
|
+
const [isDraw, setIsDraw] = useState(false);
|
|
73
78
|
const startTimeRef = useRef(null);
|
|
74
79
|
const appState = useRef(AppState.currentState);
|
|
75
|
-
const [triggered, setTriggred] = useState(global.isTrigger);
|
|
76
|
-
const [restrictedView, setRestrictedView] = useState([])
|
|
77
80
|
|
|
78
81
|
const defaultConfig = {
|
|
79
|
-
levels: {
|
|
80
|
-
|
|
81
|
-
info: 1,
|
|
82
|
-
warn: 2,
|
|
83
|
-
error: 3,
|
|
84
|
-
},
|
|
85
|
-
severity: "debug",
|
|
82
|
+
levels: { debug: 0, info: 1, warn: 2, error: 3 },
|
|
83
|
+
severity: 'debug',
|
|
86
84
|
transport: consoleTransport,
|
|
87
85
|
transportOptions: {
|
|
88
|
-
colors: {
|
|
89
|
-
info: "blueBright",
|
|
90
|
-
warn: "yellowBright",
|
|
91
|
-
error: "redBright",
|
|
92
|
-
},
|
|
86
|
+
colors: { info: 'blueBright', warn: 'yellowBright', error: 'redBright' },
|
|
93
87
|
},
|
|
94
88
|
async: true,
|
|
95
|
-
dateFormat:
|
|
89
|
+
dateFormat: 'time',
|
|
96
90
|
printLevel: false,
|
|
97
91
|
printDate: false,
|
|
98
92
|
fixedExtLvlLength: false,
|
|
99
|
-
enabled: global.makeLogEnabled
|
|
93
|
+
enabled: global.makeLogEnabled === true,
|
|
100
94
|
};
|
|
101
95
|
|
|
102
|
-
|
|
103
|
-
var log = logger.createLogger(defaultConfig);
|
|
96
|
+
const log = logger.createLogger(defaultConfig);
|
|
104
97
|
|
|
105
98
|
const isBugReportingEnabled = () => {
|
|
106
99
|
return global.allowBugReport !== false && allowToReportBugByShaking !== false;
|
|
107
100
|
};
|
|
108
101
|
|
|
102
|
+
const checkShakeDisabledStatus = async () => {
|
|
103
|
+
try {
|
|
104
|
+
if (ShakebugSDKSharedPreferencesModule && ShakebugSDKSharedPreferencesModule.getString) {
|
|
105
|
+
const stored = await ShakebugSDKSharedPreferencesModule.getString(KEY_SHAKE_DISABLED_UNTIL);
|
|
106
|
+
if (stored) {
|
|
107
|
+
const timestamp = parseInt(stored, 10);
|
|
108
|
+
if (!isNaN(timestamp) && timestamp > 0) {
|
|
109
|
+
if (Date.now() < timestamp) {
|
|
110
|
+
shakeDisabledUntilRef.current = timestamp;
|
|
111
|
+
setIsShakeDisabled(true);
|
|
112
|
+
return;
|
|
113
|
+
} else {
|
|
114
|
+
// 7 days elapsed, re-enable
|
|
115
|
+
await ShakebugSDKSharedPreferencesModule.setString(KEY_SHAKE_DISABLED_UNTIL, '');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
} catch (e) {
|
|
121
|
+
log.warn('Failed to check shake disabled status', e);
|
|
122
|
+
}
|
|
123
|
+
shakeDisabledUntilRef.current = 0;
|
|
124
|
+
setIsShakeDisabled(false);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
checkShakeDisabledStatus();
|
|
129
|
+
}, []);
|
|
130
|
+
|
|
131
|
+
// Hardware screenshot detection
|
|
132
|
+
const allowScreenCaptureRef = useRef(allowToReportBugByScreenCapture);
|
|
133
|
+
const lastScreenshotTimeRef = useRef(0);
|
|
134
|
+
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
allowScreenCaptureRef.current = allowToReportBugByScreenCapture;
|
|
137
|
+
}, [allowToReportBugByScreenCapture]);
|
|
138
|
+
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
try {
|
|
141
|
+
if (ShakebugSDKScreenShotDetector && typeof ShakebugSDKScreenShotDetector.startObserving === 'function') {
|
|
142
|
+
ShakebugSDKScreenShotDetector.startObserving();
|
|
143
|
+
}
|
|
144
|
+
} catch (e) {
|
|
145
|
+
log.warn('Failed to start screenshot observer', e);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const onScreenshot = () => {
|
|
149
|
+
const now = Date.now();
|
|
150
|
+
if (now - lastScreenshotTimeRef.current < 1200) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
lastScreenshotTimeRef.current = now;
|
|
154
|
+
|
|
155
|
+
log.info('ScreenshotTaken event detected', {
|
|
156
|
+
allowScreenCapture: allowScreenCaptureRef.current,
|
|
157
|
+
isScreenShotDetected: global.isScreenShotDetected,
|
|
158
|
+
isBottomSheetOpen,
|
|
159
|
+
isRecording: global.isRecording,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
if (allowScreenCaptureRef.current === true) {
|
|
163
|
+
if (!global.isScreenShotDetected && !isBottomSheetOpen && !global.isRecording && !global.isShakebugSDKOpen) {
|
|
164
|
+
OpenShakebug(true);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
let subscription = null;
|
|
170
|
+
if (Platform.OS === 'android') {
|
|
171
|
+
subscription = DeviceEventEmitter.addListener('ScreenshotTaken', onScreenshot);
|
|
172
|
+
} else if (ShakebugSDKScreenShotDetector) {
|
|
173
|
+
const screenShotEmitter = new NativeEventEmitter(ShakebugSDKScreenShotDetector);
|
|
174
|
+
subscription = screenShotEmitter.addListener('ScreenshotTaken', onScreenshot);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return () => {
|
|
178
|
+
if (subscription && typeof subscription.remove === 'function') {
|
|
179
|
+
subscription.remove();
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
if (ShakebugSDKScreenShotDetector && typeof ShakebugSDKScreenShotDetector.stopObserving === 'function') {
|
|
183
|
+
ShakebugSDKScreenShotDetector.stopObserving();
|
|
184
|
+
}
|
|
185
|
+
} catch (e) {}
|
|
186
|
+
};
|
|
187
|
+
}, [isBottomSheetOpen, allowToReportBugByScreenCapture]);
|
|
188
|
+
|
|
189
|
+
// Manual trigger listener
|
|
109
190
|
useEffect(() => {
|
|
110
191
|
const triggerSubscription = DeviceEventEmitter.addListener('TriggerBugReportingEvent', () => {
|
|
111
|
-
log.info(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
setTimeout(() => {
|
|
116
|
-
OpenShakebug(true); // Pass true to bypass shake checks
|
|
117
|
-
}, 200);
|
|
192
|
+
log.info('TriggerBugReportingEvent received');
|
|
193
|
+
global.isShakebugOpen = false;
|
|
194
|
+
if (!isBottomSheetOpen && !global.isRecording) {
|
|
195
|
+
OpenShakebug(true);
|
|
118
196
|
}
|
|
119
197
|
});
|
|
120
198
|
return () => triggerSubscription.remove();
|
|
121
|
-
}, []);
|
|
199
|
+
}, [isBottomSheetOpen]);
|
|
122
200
|
|
|
123
201
|
setUpdateIntervalForType(SensorTypes.accelerometer, 200);
|
|
124
202
|
|
|
125
|
-
let iscrashSaveed = ""
|
|
126
203
|
const BASE_URL = global.ShakebugSDKEndPointURL;
|
|
127
204
|
const API_KEY = global.ShakebugSDKEndPointURLheaderKey;
|
|
128
205
|
|
|
129
|
-
|
|
206
|
+
// Check tutorial screen
|
|
130
207
|
useEffect(() => {
|
|
131
208
|
async function fetchIsFirstTime() {
|
|
132
209
|
let showTutorialScreenFirstTime = showTutorialScreen;
|
|
133
210
|
const isVisited = await ShakebugSDKSharedPreferencesModule.getString('isVisited');
|
|
134
|
-
if (isVisited
|
|
135
|
-
ShakebugSDKSharedPreferencesModule.setString(
|
|
211
|
+
if (isVisited === '' || isVisited === undefined) {
|
|
212
|
+
ShakebugSDKSharedPreferencesModule.setString('isVisited', 'true');
|
|
136
213
|
}
|
|
137
214
|
|
|
138
|
-
if (showTutorialScreenFirstTime
|
|
215
|
+
if (showTutorialScreenFirstTime === true || showTutorialScreenFirstTime === undefined) {
|
|
139
216
|
setTimeout(() => {
|
|
140
|
-
if (
|
|
141
|
-
navigate(
|
|
217
|
+
if (isVisited !== 'true' || isVisited === '' || isVisited === undefined) {
|
|
218
|
+
navigate('TutorialScreen');
|
|
142
219
|
}
|
|
143
|
-
}, 200)
|
|
220
|
+
}, 200);
|
|
144
221
|
}
|
|
145
222
|
}
|
|
146
223
|
fetchIsFirstTime();
|
|
147
224
|
}, []);
|
|
148
225
|
|
|
149
|
-
|
|
226
|
+
// Check saved crash report
|
|
150
227
|
useEffect(() => {
|
|
151
|
-
async function
|
|
152
|
-
iscrashSaveed = await ShakebugSDKSharedPreferencesModule.getString('iscrashSaveed')
|
|
153
|
-
const Custom_User_Id = await ShakebugSDKSharedPreferencesModule.getString('custom_user_id')
|
|
154
|
-
|
|
155
|
-
if (iscrashSaveed.length > 10 && allowCrashReport) {
|
|
156
|
-
|
|
157
|
-
let data = JSON.parse(iscrashSaveed)
|
|
158
|
-
|
|
159
|
-
const formData = new FormData();
|
|
160
|
-
formData.append("method", "addIssue");
|
|
161
|
-
formData.append("description", data["desc"]);
|
|
162
|
-
formData.append("applicationsid", data["application_id"]);
|
|
163
|
-
formData.append("session_id", data["session_id"]);
|
|
164
|
-
formData.append("batteryLevel", data["batteryLevel"]);
|
|
165
|
-
formData.append("image", "");
|
|
166
|
-
formData.append("memory", data["memory"]);
|
|
167
|
-
formData.append("email", "");
|
|
168
|
-
formData.append("bugtypes", "crashed");
|
|
169
|
-
formData.append("devicemodel", `${data["architecture"]} -- ${data["model"]}`);
|
|
170
|
-
formData.append("osversion", data["osversion"]);
|
|
171
|
-
formData.append("internettype", data["internetType"]);
|
|
172
|
-
formData.append("created", data["created"]);
|
|
173
|
-
formData.append("isVideo", 0);
|
|
174
|
-
formData.append("appversion", data["appversion"]);
|
|
175
|
-
formData.append("custom_user_id", Custom_User_Id || "")
|
|
176
|
-
formData.append("sdk_version", global.sdk_version)
|
|
177
|
-
|
|
228
|
+
async function fetchCrashData() {
|
|
229
|
+
const iscrashSaveed = await ShakebugSDKSharedPreferencesModule.getString('iscrashSaveed');
|
|
230
|
+
const Custom_User_Id = await ShakebugSDKSharedPreferencesModule.getString('custom_user_id');
|
|
178
231
|
|
|
232
|
+
if (iscrashSaveed && iscrashSaveed.length > 10 && allowCrashReport) {
|
|
179
233
|
try {
|
|
234
|
+
let data = JSON.parse(iscrashSaveed);
|
|
235
|
+
const formData = new FormData();
|
|
236
|
+
formData.append('method', 'addIssue');
|
|
237
|
+
formData.append('description', data['desc']);
|
|
238
|
+
formData.append('applicationsid', data['application_id']);
|
|
239
|
+
formData.append('session_id', data['session_id']);
|
|
240
|
+
formData.append('batteryLevel', data['batteryLevel']);
|
|
241
|
+
formData.append('image', '');
|
|
242
|
+
formData.append('memory', data['memory']);
|
|
243
|
+
formData.append('email', '');
|
|
244
|
+
formData.append('bugtypes', 'crashed');
|
|
245
|
+
formData.append('devicemodel', `${data['architecture']} -- ${data['model']}`);
|
|
246
|
+
formData.append('osversion', data['osversion']);
|
|
247
|
+
formData.append('internettype', data['internetType']);
|
|
248
|
+
formData.append('created', data['created']);
|
|
249
|
+
formData.append('isVideo', 0);
|
|
250
|
+
formData.append('appversion', data['appversion']);
|
|
251
|
+
formData.append('custom_user_id', Custom_User_Id || '');
|
|
252
|
+
formData.append('sdk_version', global.sdk_version);
|
|
253
|
+
|
|
180
254
|
const response = await fetch(BASE_URL, {
|
|
181
255
|
method: 'POST',
|
|
182
|
-
headers: {
|
|
183
|
-
'API-KEY': API_KEY
|
|
184
|
-
},
|
|
256
|
+
headers: { 'API-KEY': API_KEY },
|
|
185
257
|
body: formData,
|
|
186
258
|
});
|
|
187
259
|
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
ShakebugSDKSharedPreferencesModule.setString("iscrashSaveed", JSON.stringify({}))
|
|
193
|
-
} else {
|
|
194
|
-
|
|
260
|
+
const resData = await response.json();
|
|
261
|
+
if (resData.code === 200 && resData.success === true) {
|
|
262
|
+
log.info(resData.msg);
|
|
263
|
+
ShakebugSDKSharedPreferencesModule.setString('iscrashSaveed', JSON.stringify({}));
|
|
195
264
|
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
log.error("e", e)
|
|
265
|
+
} catch (e) {
|
|
266
|
+
log.error('Crash report send error', e);
|
|
199
267
|
}
|
|
200
268
|
}
|
|
201
|
-
|
|
202
269
|
}
|
|
203
|
-
|
|
270
|
+
fetchCrashData();
|
|
204
271
|
}, []);
|
|
205
272
|
|
|
206
|
-
|
|
273
|
+
// Stop screen recording
|
|
207
274
|
const Stop = () => {
|
|
208
|
-
RecordScreen.stopRecording()
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
275
|
+
RecordScreen.stopRecording()
|
|
276
|
+
.then((res) => {
|
|
277
|
+
global.isMic = false;
|
|
278
|
+
global.isRecordingStart = false;
|
|
279
|
+
global.IsBackground = 'true';
|
|
280
|
+
setIsShow(false);
|
|
281
|
+
setIsDraw(false);
|
|
282
|
+
global.isDraw = false;
|
|
283
|
+
global.isShow = false;
|
|
284
|
+
startTimeRef.current = null;
|
|
285
|
+
clearInterval(intervalId);
|
|
286
|
+
setIsLoading(false);
|
|
287
|
+
global.isRecording = false;
|
|
288
|
+
navigate('AddDetailsScreen', {
|
|
289
|
+
media: res.result.outputURL,
|
|
290
|
+
mediaType: 'Recordvideo',
|
|
291
|
+
themeColor: themeColor,
|
|
292
|
+
SDKScreenTitle: `${SDKScreenTitle}`,
|
|
293
|
+
});
|
|
225
294
|
})
|
|
226
|
-
|
|
295
|
+
.catch((e) => {
|
|
296
|
+
log.warn('Stop recording error', e);
|
|
297
|
+
});
|
|
298
|
+
};
|
|
227
299
|
|
|
228
300
|
useEffect(() => {
|
|
229
301
|
const handleAppStateChange = (nextAppState) => {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
302
|
+
if (nextAppState === 'background' || nextAppState === 'inactive') {
|
|
303
|
+
if (global.isRecording) {
|
|
304
|
+
Stop();
|
|
305
|
+
}
|
|
306
|
+
}
|
|
235
307
|
|
|
236
308
|
if (appState.current.match(/inactive|background/) && nextAppState === 'active') {
|
|
237
|
-
|
|
309
|
+
checkShakeDisabledStatus();
|
|
238
310
|
if (startTimeRef.current && global.isRecording) {
|
|
239
311
|
const elapsed = Math.floor((Date.now() - startTimeRef.current) / 1000);
|
|
240
312
|
updateTimer(elapsed);
|
|
241
313
|
}
|
|
242
|
-
|
|
243
314
|
}
|
|
244
315
|
appState.current = nextAppState;
|
|
245
316
|
};
|
|
246
317
|
|
|
247
318
|
const AppStateListener = AppState.addEventListener('change', handleAppStateChange);
|
|
248
|
-
|
|
249
|
-
// Start the interval initially
|
|
250
319
|
startTimer();
|
|
251
320
|
|
|
252
321
|
return () => {
|
|
253
|
-
|
|
254
|
-
AppStateListener.remove()
|
|
322
|
+
AppStateListener.remove();
|
|
255
323
|
clearInterval(intervalId);
|
|
256
324
|
};
|
|
257
325
|
}, []);
|
|
@@ -274,27 +342,26 @@ const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitl
|
|
|
274
342
|
const sec = parseInt(elapsed % 60);
|
|
275
343
|
const durationLimit = parseInt(global.videoDuration) || 20;
|
|
276
344
|
|
|
277
|
-
if (elapsed
|
|
345
|
+
if (elapsed === durationLimit) {
|
|
278
346
|
clearInterval(intervalId);
|
|
279
347
|
setTimeout(() => {
|
|
280
|
-
Stop()
|
|
281
|
-
}, 1000)
|
|
348
|
+
Stop();
|
|
349
|
+
}, 1000);
|
|
282
350
|
}
|
|
283
351
|
|
|
284
352
|
if (elapsed > durationLimit) {
|
|
285
|
-
RecordScreen.stopRecording()
|
|
286
|
-
.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
})
|
|
353
|
+
RecordScreen.stopRecording().then(() => {
|
|
354
|
+
global.isMic = false;
|
|
355
|
+
global.isRecordingStart = false;
|
|
356
|
+
global.IsBackground = 'true';
|
|
357
|
+
global.isRecording = false;
|
|
358
|
+
setIsShow(false);
|
|
359
|
+
setIsDraw(false);
|
|
360
|
+
global.isDraw = false;
|
|
361
|
+
global.isShow = false;
|
|
362
|
+
startTimeRef.current = null;
|
|
363
|
+
clearInterval(intervalId);
|
|
364
|
+
});
|
|
298
365
|
}
|
|
299
366
|
|
|
300
367
|
const minStr = min < 10 ? `0${min}` : min;
|
|
@@ -302,206 +369,404 @@ const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitl
|
|
|
302
369
|
setTime(`${minStr}:${secStr}`);
|
|
303
370
|
};
|
|
304
371
|
|
|
372
|
+
// Accelerometer subscription for shake detection
|
|
305
373
|
useEffect(() => {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
374
|
+
DeviceInfo.isEmulator().then((res) => {
|
|
375
|
+
if (!res && isRecordingStart === false && isBugReportingEnabled()) {
|
|
376
|
+
const subscription = accelerometer.subscribe(async ({ x, y, z }) => {
|
|
377
|
+
// Check if shake is temporarily disabled for 7 days
|
|
378
|
+
if (shakeDisabledUntilRef.current > 0) {
|
|
379
|
+
if (Date.now() < shakeDisabledUntilRef.current) {
|
|
380
|
+
return;
|
|
381
|
+
} else {
|
|
382
|
+
shakeDisabledUntilRef.current = 0;
|
|
383
|
+
setIsShakeDisabled(false);
|
|
384
|
+
if (ShakebugSDKSharedPreferencesModule && ShakebugSDKSharedPreferencesModule.setString) {
|
|
385
|
+
ShakebugSDKSharedPreferencesModule.setString(KEY_SHAKE_DISABLED_UNTIL, '');
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
313
389
|
|
|
314
390
|
let calculate = Math.sqrt(x * x + y * y + z * z);
|
|
315
391
|
|
|
316
|
-
if (global.isTrigger
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
setTimeout(() => {
|
|
320
|
-
OpenShakebug()
|
|
321
|
-
}, 200)
|
|
392
|
+
if (global.isTrigger === true && global.isShakebugOpen === false) {
|
|
393
|
+
global.isTrigger = false;
|
|
394
|
+
OpenShakebug(true);
|
|
322
395
|
}
|
|
323
396
|
|
|
324
|
-
if (
|
|
397
|
+
if (
|
|
398
|
+
Platform.OS === 'android' &&
|
|
399
|
+
global.isRecording === false &&
|
|
400
|
+
global.isTrigger === false &&
|
|
401
|
+
isBugReportingEnabled()
|
|
402
|
+
) {
|
|
325
403
|
if (calculate.toFixed(2) >= 18) {
|
|
326
|
-
if (
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
log.error("Failed to capture screenshot on shake", e);
|
|
333
|
-
}
|
|
334
|
-
if (!isShow) {
|
|
335
|
-
if (ImgUrl != undefined || ImgUrl != null) {
|
|
336
|
-
subscription.unsubscribe();
|
|
337
|
-
global.IsBackground = false
|
|
338
|
-
global.isShakebugSDKOpen = true
|
|
339
|
-
// navigate('TestScreen');
|
|
340
|
-
navigate("FirstScreen", { img: `${ImgUrl}`, themeColor: `${themeColor}`, SDKScreenTitle: `${SDKScreenTitle}` })
|
|
341
|
-
}
|
|
342
|
-
else {
|
|
343
|
-
setIsScreenShot(false)
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
xdata = 0;
|
|
347
|
-
ydata = 0;
|
|
348
|
-
zdata = 0;
|
|
404
|
+
if (
|
|
405
|
+
global.isAndroidValid === true &&
|
|
406
|
+
global.application_id &&
|
|
407
|
+
!isBottomSheetOpen
|
|
408
|
+
) {
|
|
409
|
+
captureAndOpenBottomSheet();
|
|
349
410
|
}
|
|
350
411
|
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
const filePath = await ShakebugSDKCustomScreenCapture.captureScreen();
|
|
365
|
-
ImgUrl = filePath
|
|
366
|
-
}
|
|
367
|
-
catch (e) {
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
if (ImgUrl != undefined || ImgUrl != null) {
|
|
371
|
-
subscription.unsubscribe();
|
|
372
|
-
global.isShakebugSDKOpen = true
|
|
373
|
-
navigate("FirstScreen", { img: `${ImgUrl}`, themeColor: `${themeColor}`, SDKScreenTitle: `${SDKScreenTitle}` })
|
|
374
|
-
}
|
|
375
|
-
else {
|
|
376
|
-
setIsScreenShot(false)
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
xdata = 0;
|
|
380
|
-
ydata = 0;
|
|
381
|
-
zdata = 0;
|
|
412
|
+
} else if (
|
|
413
|
+
Platform.OS === 'ios' &&
|
|
414
|
+
global.isRecording === false &&
|
|
415
|
+
global.isTrigger === false &&
|
|
416
|
+
isBugReportingEnabled()
|
|
417
|
+
) {
|
|
418
|
+
if (calculate.toFixed(2) >= 2.0) {
|
|
419
|
+
if (
|
|
420
|
+
global.isIOSValid === true &&
|
|
421
|
+
global.application_id &&
|
|
422
|
+
!isBottomSheetOpen
|
|
423
|
+
) {
|
|
424
|
+
captureAndOpenBottomSheet();
|
|
382
425
|
}
|
|
383
426
|
}
|
|
384
427
|
}
|
|
385
|
-
})
|
|
428
|
+
});
|
|
386
429
|
|
|
387
|
-
if (isFocused
|
|
388
|
-
subscription.unsubscribe()
|
|
389
|
-
|
|
390
|
-
ydata = 0;
|
|
391
|
-
zdata = 0;
|
|
392
|
-
setTime("00:00")
|
|
430
|
+
if (isFocused === false) {
|
|
431
|
+
subscription.unsubscribe();
|
|
432
|
+
setTime('00:00');
|
|
393
433
|
pan.setValue({ x: SCREEN_WIDTH * 0.55, y: SCREEN_HEIGHT * 0.85 });
|
|
394
434
|
}
|
|
395
435
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
if (global.isTrigger == true && global.isShakebugOpen == false && isBugReportingEnabled()) {
|
|
399
|
-
global.isShakebugOpen = true;
|
|
400
|
-
global.isTrigger = true;
|
|
401
|
-
OpenShakebug()
|
|
402
|
-
}
|
|
403
|
-
}, 1000)
|
|
404
|
-
}
|
|
405
|
-
})
|
|
406
|
-
|
|
407
|
-
}, [isFocused])
|
|
436
|
+
});
|
|
437
|
+
}, [isFocused, isBottomSheetOpen]);
|
|
408
438
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
439
|
+
// Capture screenshot and present Bottom Sheet
|
|
440
|
+
const captureAndOpenBottomSheet = async () => {
|
|
441
|
+
if (isBottomSheetOpen || global.isRecording) {
|
|
442
|
+
global.isShakebugOpen = false;
|
|
412
443
|
return;
|
|
413
444
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
445
|
+
|
|
446
|
+
setIsScreenShot(true);
|
|
447
|
+
let ImgUrl = null;
|
|
448
|
+
try {
|
|
449
|
+
if (ref.current && typeof ref.current.capture === 'function') {
|
|
450
|
+
ImgUrl = await ref.current.capture();
|
|
451
|
+
}
|
|
452
|
+
} catch (e) {
|
|
453
|
+
log.error('Failed to capture screenshot with ref', e);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if (!ImgUrl && Platform.OS === 'ios') {
|
|
457
|
+
try {
|
|
458
|
+
const filePath = await ShakebugSDKCustomScreenCapture.captureScreen();
|
|
459
|
+
if (filePath) ImgUrl = filePath;
|
|
460
|
+
} catch (e) {}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (!ImgUrl) {
|
|
417
464
|
try {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
465
|
+
const screenUri = await captureScreen({ format: 'jpg', quality: 1 });
|
|
466
|
+
if (screenUri) ImgUrl = screenUri;
|
|
467
|
+
} catch (e) {}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
setIsScreenShot(false);
|
|
471
|
+
|
|
472
|
+
if (!isShow) {
|
|
473
|
+
setCapturedScreenshot(ImgUrl || null);
|
|
474
|
+
setIsBottomSheetOpen(true);
|
|
475
|
+
global.isShakebugSDKOpen = true;
|
|
476
|
+
} else {
|
|
477
|
+
global.isShakebugOpen = false;
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
const OpenShakebug = async (bypassShakeCheck = false) => {
|
|
482
|
+
if (!bypassShakeCheck) {
|
|
483
|
+
if (global.allowBugReport === false || allowToReportBugByShaking === false) {
|
|
484
|
+
log.warn('OpenShakebug aborted: Shaking bug reporting is disabled.');
|
|
485
|
+
global.isShakebugOpen = false;
|
|
486
|
+
return;
|
|
421
487
|
}
|
|
422
|
-
if (
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
setTriggred(false)
|
|
427
|
-
global.isShakebugSDKOpen = true
|
|
428
|
-
navigate("FirstScreen", { img: `${ImgUrl}`, themeColor: `${themeColor}`, SDKScreenTitle: `${SDKScreenTitle}` })
|
|
429
|
-
} else {
|
|
430
|
-
log.warn("OpenShakebug aborted: Screenshot capture returned null.");
|
|
431
|
-
}
|
|
432
|
-
} else {
|
|
433
|
-
log.warn("OpenShakebug aborted: isShow is true (currently recording).");
|
|
488
|
+
if (shakeDisabledUntilRef.current > 0 && Date.now() < shakeDisabledUntilRef.current) {
|
|
489
|
+
log.warn('OpenShakebug aborted: Shake temporarily disabled by user.');
|
|
490
|
+
global.isShakebugOpen = false;
|
|
491
|
+
return;
|
|
434
492
|
}
|
|
435
493
|
} else {
|
|
436
|
-
|
|
494
|
+
if (global.allowBugReport === false) {
|
|
495
|
+
log.warn('OpenShakebug aborted: Bug reporting is globally disabled.');
|
|
496
|
+
global.isShakebugOpen = false;
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
437
499
|
}
|
|
438
|
-
}
|
|
439
500
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
501
|
+
if (isShow || isBottomSheetOpen || global.isRecording) {
|
|
502
|
+
global.isShakebugOpen = false;
|
|
503
|
+
return;
|
|
443
504
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
505
|
+
|
|
506
|
+
global.isShakebugOpen = true;
|
|
507
|
+
await captureAndOpenBottomSheet();
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
// Bottom Sheet Handlers
|
|
511
|
+
const handleReportIssue = () => {
|
|
512
|
+
setIsBottomSheetOpen(false);
|
|
513
|
+
global.IsBackground = 'false';
|
|
514
|
+
global.isScreenShotDetected = true;
|
|
515
|
+
global.isShakebugSDKOpen = true;
|
|
516
|
+
if (capturedScreenshot) {
|
|
517
|
+
navigate('FirstScreen', {
|
|
518
|
+
img: `${capturedScreenshot}`,
|
|
519
|
+
themeColor: `${themeColor}`,
|
|
520
|
+
SDKScreenTitle: `${SDKScreenTitle}`,
|
|
521
|
+
});
|
|
522
|
+
} else {
|
|
523
|
+
navigate('AddDetailsScreen', {
|
|
524
|
+
media: '',
|
|
525
|
+
mediaType: 'img',
|
|
526
|
+
themeColor: `${themeColor}`,
|
|
527
|
+
SDKScreenTitle: `${SDKScreenTitle}`,
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
const startRecordingProcess = (withMic = false) => {
|
|
533
|
+
setIsBottomSheetOpen(false);
|
|
534
|
+
setIsLoading(true);
|
|
535
|
+
global.isMic = withMic;
|
|
536
|
+
global.isRecordingStart = true;
|
|
537
|
+
try {
|
|
538
|
+
RecordScreen.startRecording({
|
|
539
|
+
mic: withMic,
|
|
540
|
+
fps: 30,
|
|
541
|
+
bitrate: 1024000,
|
|
542
|
+
})
|
|
543
|
+
.then((res) => {
|
|
544
|
+
setIsLoading(false);
|
|
545
|
+
if (res === 'started') {
|
|
546
|
+
setIsRecordingStart(true);
|
|
547
|
+
if (focusedScreen !== 'ShakebugHome') {
|
|
548
|
+
goToScreenAtIndex(0);
|
|
471
549
|
}
|
|
472
|
-
|
|
473
|
-
.
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
550
|
+
global.isRecording = true;
|
|
551
|
+
StatusBar.setHidden(false);
|
|
552
|
+
setIsShow(true);
|
|
553
|
+
global.minutes = 0;
|
|
554
|
+
global.Seconds = 0;
|
|
555
|
+
startTimeRef.current = null;
|
|
556
|
+
startTimer();
|
|
557
|
+
} else {
|
|
558
|
+
global.isMic = false;
|
|
559
|
+
global.isRecordingStart = false;
|
|
560
|
+
setIsAlertText('Unable to start screen recording. Please try again.');
|
|
561
|
+
setIsAlert(true);
|
|
562
|
+
}
|
|
563
|
+
})
|
|
564
|
+
.catch((e) => {
|
|
565
|
+
log.error('RecordScreen error', e);
|
|
566
|
+
setIsLoading(false);
|
|
567
|
+
});
|
|
568
|
+
} catch (e) {
|
|
569
|
+
log.error('RecordScreen start error', e);
|
|
570
|
+
setIsLoading(false);
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
const handleRecordIssue = () => {
|
|
575
|
+
if (global.AllowVideo === false) {
|
|
576
|
+
setIsAlertText(
|
|
577
|
+
`You have reached your max video limitation. \n\n Used Videos: ${global.used_video} \nAllowed Videos: ${global.total_video}\n\nPlease visit https://www.shakebug.com website and upgrade your plan.`
|
|
578
|
+
);
|
|
579
|
+
setIsAlert(true);
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
DeviceInfo.isEmulator().then((res) => {
|
|
584
|
+
if (res === true && Platform.OS === 'ios') {
|
|
585
|
+
setIsAlertText('Only real device is supported for recording video');
|
|
586
|
+
setIsAlert(true);
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
Alert.alert(
|
|
591
|
+
Localization[global.ShakebugLanguage]?.RecordAudio || 'Do you want to record Audio?',
|
|
592
|
+
'',
|
|
593
|
+
[
|
|
594
|
+
{
|
|
595
|
+
text: Localization[global.ShakebugLanguage]?.No || 'No',
|
|
596
|
+
style: 'cancel',
|
|
597
|
+
onPress: () => {
|
|
598
|
+
startRecordingProcess(false);
|
|
599
|
+
},
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
text: Localization[global.ShakebugLanguage]?.Yes || 'YES',
|
|
603
|
+
onPress: () => {
|
|
604
|
+
if (Platform.OS === 'android') {
|
|
605
|
+
PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.RECORD_AUDIO).then(
|
|
606
|
+
(permRes) => {
|
|
607
|
+
if (permRes === PermissionsAndroid.RESULTS.GRANTED) {
|
|
608
|
+
startRecordingProcess(true);
|
|
609
|
+
} else {
|
|
610
|
+
startRecordingProcess(false);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
);
|
|
614
|
+
} else {
|
|
615
|
+
if (RNCameraPermission && RNCameraPermission.checkCameraPermissionStatus) {
|
|
616
|
+
RNCameraPermission.checkCameraPermissionStatus().then((permRes) => {
|
|
617
|
+
if (permRes === 'granted') {
|
|
618
|
+
startRecordingProcess(true);
|
|
619
|
+
} else if (permRes === 'denied') {
|
|
620
|
+
Alert.alert(
|
|
621
|
+
'',
|
|
622
|
+
Localization[global.ShakebugLanguage]?.AudioPermission ||
|
|
623
|
+
'Audio permission required',
|
|
624
|
+
[
|
|
625
|
+
{
|
|
626
|
+
text: Localization[global.ShakebugLanguage]?.No || 'No',
|
|
627
|
+
style: 'cancel',
|
|
628
|
+
onPress: () => startRecordingProcess(false),
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
text: Localization[global.ShakebugLanguage]?.Yes || 'YES',
|
|
632
|
+
onPress: () => {
|
|
633
|
+
Linking.openSettings();
|
|
634
|
+
startRecordingProcess(false);
|
|
635
|
+
},
|
|
636
|
+
},
|
|
637
|
+
]
|
|
638
|
+
);
|
|
639
|
+
} else {
|
|
640
|
+
startRecordingProcess(false);
|
|
641
|
+
}
|
|
642
|
+
});
|
|
643
|
+
} else {
|
|
644
|
+
startRecordingProcess(true);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
},
|
|
648
|
+
},
|
|
649
|
+
]
|
|
650
|
+
);
|
|
651
|
+
});
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
const handleChooseMedia = () => {
|
|
655
|
+
setIsBottomSheetOpen(false);
|
|
656
|
+
setIsLoading(true);
|
|
657
|
+
|
|
658
|
+
const options = {
|
|
659
|
+
mediaType: 'mixed',
|
|
660
|
+
includeBase64: false,
|
|
661
|
+
selectionLimit: 1,
|
|
662
|
+
};
|
|
663
|
+
|
|
664
|
+
launchImageLibrary(options, async (response) => {
|
|
665
|
+
setIsLoading(false);
|
|
666
|
+
if (response.didCancel) {
|
|
667
|
+
handleDismissBottomSheet();
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
if (response.error || response.errorCode) {
|
|
671
|
+
handleDismissBottomSheet();
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
const asset = response.assets?.[0];
|
|
675
|
+
const mediaUri = (await response.uri) || asset?.uri;
|
|
676
|
+
if (!mediaUri) {
|
|
677
|
+
handleDismissBottomSheet();
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
const mediaType = asset?.type || '';
|
|
681
|
+
const isVideo =
|
|
682
|
+
mediaType.startsWith('video') ||
|
|
683
|
+
mediaUri.toLowerCase().endsWith('.mp4') ||
|
|
684
|
+
mediaUri.toLowerCase().endsWith('.mov') ||
|
|
685
|
+
mediaUri.toLowerCase().endsWith('.m4v');
|
|
686
|
+
|
|
687
|
+
if (isVideo) {
|
|
688
|
+
if (global.AllowVideo === false) {
|
|
689
|
+
setIsAlertText(
|
|
690
|
+
`You have reached your max video limitation. \n\n Used Videos: ${global.used_video} \nAllowed Videos: ${global.total_video}\n\nPlease visit https://www.shakebug.com website and upgrade your plan.`
|
|
691
|
+
);
|
|
692
|
+
setIsAlert(true);
|
|
693
|
+
return;
|
|
481
694
|
}
|
|
695
|
+
global.IsBackground = 'false';
|
|
696
|
+
global.isShakebugSDKOpen = true;
|
|
697
|
+
navigate('TrimVideoScreen', {
|
|
698
|
+
video: `${mediaUri}`,
|
|
699
|
+
Type: 'video',
|
|
700
|
+
themeColor: themeColor,
|
|
701
|
+
SDKScreenTitle: `${SDKScreenTitle}`,
|
|
702
|
+
UpdateStatusBar: () => StatusBar.setHidden(false),
|
|
703
|
+
updateParent: () => {},
|
|
704
|
+
});
|
|
705
|
+
} else {
|
|
706
|
+
global.IsBackground = 'false';
|
|
707
|
+
global.isShakebugSDKOpen = true;
|
|
708
|
+
navigate('FirstScreen', {
|
|
709
|
+
img: `${mediaUri}`,
|
|
710
|
+
themeColor: themeColor,
|
|
711
|
+
SDKScreenTitle: `${SDKScreenTitle}`,
|
|
712
|
+
});
|
|
482
713
|
}
|
|
483
|
-
}
|
|
714
|
+
});
|
|
715
|
+
};
|
|
484
716
|
|
|
485
|
-
|
|
717
|
+
const handleDismissBottomSheet = () => {
|
|
718
|
+
setIsBottomSheetOpen(false);
|
|
719
|
+
setCapturedScreenshot(null);
|
|
720
|
+
global.isTrigger = false;
|
|
721
|
+
global.isShakebugOpen = false;
|
|
722
|
+
global.isScreenShotDetected = false;
|
|
723
|
+
global.isScreeenShotTaken = false;
|
|
724
|
+
global.isShakebugSDKOpen = false;
|
|
725
|
+
setIsScreenShot(false);
|
|
726
|
+
setIsRecordingStart(false);
|
|
727
|
+
};
|
|
486
728
|
|
|
729
|
+
const handleDisableShake = async () => {
|
|
730
|
+
const disabledUntil = Date.now() + SEVEN_DAYS_MS;
|
|
731
|
+
shakeDisabledUntilRef.current = disabledUntil;
|
|
732
|
+
setIsShakeDisabled(true);
|
|
733
|
+
try {
|
|
734
|
+
if (ShakebugSDKSharedPreferencesModule && ShakebugSDKSharedPreferencesModule.setString) {
|
|
735
|
+
await ShakebugSDKSharedPreferencesModule.setString(
|
|
736
|
+
KEY_SHAKE_DISABLED_UNTIL,
|
|
737
|
+
disabledUntil.toString()
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
} catch (e) {
|
|
741
|
+
log.warn('Failed to save SHAKE_DISABLED_UNTIL', e);
|
|
742
|
+
}
|
|
743
|
+
};
|
|
487
744
|
|
|
488
|
-
const
|
|
745
|
+
const handleEnableShake = async () => {
|
|
746
|
+
shakeDisabledUntilRef.current = 0;
|
|
747
|
+
setIsShakeDisabled(false);
|
|
748
|
+
try {
|
|
749
|
+
if (ShakebugSDKSharedPreferencesModule && ShakebugSDKSharedPreferencesModule.setString) {
|
|
750
|
+
await ShakebugSDKSharedPreferencesModule.setString(KEY_SHAKE_DISABLED_UNTIL, '');
|
|
751
|
+
}
|
|
752
|
+
} catch (e) {
|
|
753
|
+
log.warn('Failed to clear SHAKE_DISABLED_UNTIL', e);
|
|
754
|
+
}
|
|
755
|
+
};
|
|
489
756
|
|
|
757
|
+
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get('window');
|
|
490
758
|
const pan = useRef(new Animated.ValueXY()).current;
|
|
491
|
-
|
|
492
759
|
const BOUNDARY_X_MIN = 0;
|
|
493
|
-
const BOUNDARY_X_MAX = Dimensions.get('window').width * 0.6;
|
|
760
|
+
const BOUNDARY_X_MAX = Dimensions.get('window').width * 0.6;
|
|
494
761
|
const BOUNDARY_Y_MIN = 0;
|
|
495
|
-
const BOUNDARY_Y_MAX = Dimensions.get('window').height * 0.98;
|
|
762
|
+
const BOUNDARY_Y_MAX = Dimensions.get('window').height * 0.98;
|
|
496
763
|
|
|
497
764
|
const panResponder = useRef(
|
|
498
765
|
PanResponder.create({
|
|
499
766
|
onStartShouldSetPanResponder: () => true,
|
|
500
767
|
onPanResponderMove: (event, gestureState) => {
|
|
501
|
-
// Calculate the new x and y values within the boundaries
|
|
502
768
|
let newX = Math.max(BOUNDARY_X_MIN, Math.min(BOUNDARY_X_MAX, gestureState.dx + pan.x._offset));
|
|
503
769
|
let newY = Math.max(BOUNDARY_Y_MIN, Math.min(BOUNDARY_Y_MAX, gestureState.dy + pan.y._offset));
|
|
504
|
-
|
|
505
770
|
pan.setValue({ x: newX - pan.x._offset, y: newY - pan.y._offset });
|
|
506
771
|
},
|
|
507
772
|
onPanResponderRelease: () => {
|
|
@@ -510,25 +775,17 @@ const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitl
|
|
|
510
775
|
onPanResponderGrant: () => {
|
|
511
776
|
pan.setOffset({
|
|
512
777
|
x: pan.x._value,
|
|
513
|
-
y: pan.y._value
|
|
778
|
+
y: pan.y._value,
|
|
514
779
|
});
|
|
515
780
|
pan.setValue({ x: SCREEN_WIDTH * 0.55, y: SCREEN_HEIGHT * 0.8 });
|
|
516
|
-
}
|
|
781
|
+
},
|
|
517
782
|
})
|
|
518
783
|
).current;
|
|
519
784
|
|
|
520
785
|
return (
|
|
521
|
-
<View
|
|
522
|
-
style={{
|
|
523
|
-
|
|
524
|
-
height: '100%'
|
|
525
|
-
}}
|
|
526
|
-
>
|
|
527
|
-
|
|
528
|
-
<ShakebugCapture ref={ref} options={{ format: "jpg", quality: 1, }} style={{ flex: 1 }}>
|
|
529
|
-
<View style={{ flex: 1 }}>
|
|
530
|
-
{children}
|
|
531
|
-
</View>
|
|
786
|
+
<View style={{ width: '100%', height: '100%' }}>
|
|
787
|
+
<ShakebugCapture ref={ref} options={{ format: 'jpg', quality: 1 }} style={{ flex: 1 }}>
|
|
788
|
+
<View style={{ flex: 1 }}>{children}</View>
|
|
532
789
|
{isDraw && (
|
|
533
790
|
<RNDrawingView
|
|
534
791
|
ref={canvasRef}
|
|
@@ -540,17 +797,15 @@ const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitl
|
|
|
540
797
|
bottom: 0,
|
|
541
798
|
width: '100%',
|
|
542
799
|
height: '100%',
|
|
543
|
-
zIndex: 999
|
|
800
|
+
zIndex: 999,
|
|
544
801
|
}}
|
|
545
802
|
color={'red'}
|
|
546
|
-
strokeWidth={Platform.OS
|
|
803
|
+
strokeWidth={Platform.OS === 'android' ? 5 : 3}
|
|
547
804
|
/>
|
|
548
805
|
)}
|
|
549
|
-
|
|
550
|
-
|
|
551
806
|
</ShakebugCapture>
|
|
552
807
|
|
|
553
|
-
|
|
808
|
+
{/* Floating Screen Recording Widget */}
|
|
554
809
|
{isShow ? (
|
|
555
810
|
<Animated.View
|
|
556
811
|
{...panResponder.panHandlers}
|
|
@@ -567,45 +822,81 @@ const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitl
|
|
|
567
822
|
position: 'absolute',
|
|
568
823
|
backgroundColor: themeColor,
|
|
569
824
|
flexDirection: 'row',
|
|
570
|
-
zIndex:
|
|
825
|
+
zIndex: 100,
|
|
571
826
|
}}
|
|
572
827
|
>
|
|
573
828
|
<TouchableOpacity
|
|
574
829
|
onPress={() => Stop()}
|
|
575
830
|
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
|
576
831
|
>
|
|
577
|
-
<Image
|
|
832
|
+
<Image
|
|
833
|
+
source={require('../Assets/images/stopButton.png')}
|
|
834
|
+
style={{ height: 30, width: 30 }}
|
|
835
|
+
/>
|
|
578
836
|
</TouchableOpacity>
|
|
579
837
|
|
|
580
|
-
<Text style={{ color:
|
|
838
|
+
<Text style={{ color: 'white', fontSize: 18, marginRight: 5, marginLeft: 5, fontWeight: '700' }}>
|
|
839
|
+
{time}
|
|
840
|
+
</Text>
|
|
581
841
|
|
|
582
|
-
{isDraw
|
|
842
|
+
{isDraw === false ? (
|
|
583
843
|
<TouchableOpacity
|
|
584
844
|
onPress={() => {
|
|
585
|
-
setIsDraw(true)
|
|
586
|
-
global.isDraw = true
|
|
845
|
+
setIsDraw(true);
|
|
846
|
+
global.isDraw = true;
|
|
587
847
|
}}
|
|
588
848
|
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
|
589
849
|
>
|
|
590
|
-
<Image
|
|
850
|
+
<Image
|
|
851
|
+
source={require('../Assets/images/OpenSketch.png')}
|
|
852
|
+
style={{ height: 25, width: 25 }}
|
|
853
|
+
/>
|
|
591
854
|
</TouchableOpacity>
|
|
592
855
|
) : (
|
|
593
856
|
<TouchableOpacity
|
|
594
857
|
onPress={() => {
|
|
595
|
-
setIsDraw(false)
|
|
596
|
-
global.isDraw = false
|
|
597
|
-
ClearCanvas(canvasRef)
|
|
858
|
+
setIsDraw(false);
|
|
859
|
+
global.isDraw = false;
|
|
860
|
+
ClearCanvas(canvasRef);
|
|
598
861
|
}}
|
|
599
862
|
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
|
600
863
|
>
|
|
601
|
-
<Image
|
|
864
|
+
<Image
|
|
865
|
+
source={require('../Assets/images/close.png')}
|
|
866
|
+
style={{ height: 30, width: 30 }}
|
|
867
|
+
/>
|
|
602
868
|
</TouchableOpacity>
|
|
603
869
|
)}
|
|
604
870
|
</Animated.View>
|
|
605
871
|
) : null}
|
|
872
|
+
|
|
873
|
+
{/* Bottom Sheet on Shake / Trigger */}
|
|
874
|
+
<ShakebugBottomSheet
|
|
875
|
+
visible={isBottomSheetOpen}
|
|
876
|
+
onClose={handleDismissBottomSheet}
|
|
877
|
+
onReportIssue={handleReportIssue}
|
|
878
|
+
onRecordIssue={handleRecordIssue}
|
|
879
|
+
onChooseMedia={handleChooseMedia}
|
|
880
|
+
themeColor={themeColor}
|
|
881
|
+
isShakeDisabled={isShakeDisabled}
|
|
882
|
+
onDisableShake={handleDisableShake}
|
|
883
|
+
onEnableShake={handleEnableShake}
|
|
884
|
+
screenshot={capturedScreenshot}
|
|
885
|
+
/>
|
|
886
|
+
|
|
887
|
+
<CustomeAlert
|
|
888
|
+
isVisible={isAlert}
|
|
889
|
+
text={isAlertText}
|
|
890
|
+
color={themeColor}
|
|
891
|
+
OnPrees={() => {
|
|
892
|
+
setIsAlert(false);
|
|
893
|
+
setIsAlertText('');
|
|
894
|
+
}}
|
|
895
|
+
/>
|
|
896
|
+
|
|
897
|
+
<LoadingModal visible={isLoading} color={themeColor} />
|
|
606
898
|
</View>
|
|
607
899
|
);
|
|
608
|
-
|
|
609
|
-
}
|
|
900
|
+
};
|
|
610
901
|
|
|
611
902
|
export default ShakeFunction;
|