shakebug-react-native 2.4.9 → 2.4.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.
Files changed (51) hide show
  1. package/README.md +0 -12
  2. package/VideoPlayer/PlayVideo.tsx +4 -46
  3. package/VideoPlayer/index.js +6 -43
  4. package/android/src/main/java/com/shakebug/BaseUtils.java +7 -19
  5. package/android/src/main/java/com/shakebug/DeviceUtil.java +34 -21
  6. package/android/src/main/java/com/shakebug/ShakebugPackage.java +3 -3
  7. package/android/src/main/java/com/shakebug/UnitConverter.java +8 -8
  8. package/android/src/main/java/com/shakebug/VideoPlayerModule.java +81 -0
  9. package/android/src/main/java/com/shakebug/VideoTrimModule.java +387 -0
  10. package/android/src/main/java/com/shakebug/VideoTrimUtil.java +133 -0
  11. package/android/src/main/java/com/shakebug/adapters/VideoTrimmerAdapter.java +53 -0
  12. package/android/src/main/java/com/shakebug/callback/SingleCallback.java +0 -6
  13. package/android/src/main/java/com/shakebug/thread/BackgroundExecutor.java +1 -93
  14. package/android/src/main/java/com/shakebug/thread/UiThreadExecutor.java +0 -37
  15. package/android/src/main/java/com/shakebug/utils/StorageUtil.java +135 -0
  16. package/android/src/main/java/com/shakebug/utils/VideoTrimmerUtil.java +70 -0
  17. package/android/src/main/java/com/shakebug/widgets/RangeSeekBarView.java +534 -0
  18. package/android/src/main/java/com/shakebug/widgets/SpacesItemDecoration2.java +1 -2
  19. package/android/src/main/java/com/shakebug/widgets/VideoPlayerView.java +317 -0
  20. package/android/src/main/java/com/shakebug/widgets/VideoTrimmerView.java +520 -0
  21. package/android/src/main/res/drawable/ic_volume_off.xml +10 -0
  22. package/android/src/main/res/drawable/ic_volume_on.xml +10 -0
  23. package/android/src/main/res/layout/{video_player_view.xml → shakebug_video_player_view.xml} +29 -9
  24. package/ios/TrimVideo/ShakebugSDKVideoTrim.swift +389 -0
  25. package/ios/TrimVideo/VideoTrim-Bridging-Header.h +10 -0
  26. package/ios/TrimVideo/VideoTrim.m +23 -0
  27. package/ios/TrimVideo/VideoTrimmer.swift +810 -0
  28. package/ios/TrimVideo/VideoTrimmerThumb.swift +119 -0
  29. package/ios/TrimVideo/VideoTrimmerViewController.swift +322 -0
  30. package/ios/VideoPlayer/VideoPlayerModule.m +23 -7
  31. package/package.json +1 -1
  32. package/src/APIs/AddIssue.js +7 -5
  33. package/src/APIs/AddReview.js +5 -2
  34. package/src/APIs/CustomUserId.js +5 -2
  35. package/src/APIs/EndSession.js +3 -2
  36. package/src/APIs/Event.js +5 -2
  37. package/src/APIs/FetchRemoteCodeAPI.js +5 -2
  38. package/src/APIs/MatchKey.js +3 -2
  39. package/src/APIs/StartSession.js +44 -23
  40. package/src/Componanats/LoadingModal.js +59 -0
  41. package/src/Componanats/ShakeFunction.js +32 -14
  42. package/src/Screens/AddDetailsScreen.js +28 -31
  43. package/src/Screens/FirstScreen.js +15 -18
  44. package/src/Screens/Shakebug.js +11 -6
  45. package/src/Screens/TrimVideoScreen.js +37 -22
  46. package/src/index.tsx +7 -6
  47. package/trimVideo/src/index.tsx +12 -48
  48. package/Volumes:.fileloc +0 -8
  49. package/shakebug-react-native-2.4.8.tgz +0 -0
  50. /package/android/src/main/res/layout/{video_thumb_item_layout.xml → shakebug_video_thumb_item_layout.xml} +0 -0
  51. /package/android/src/main/res/layout/{video_trimmer_view.xml → shakebug_video_trimmer_view.xml} +0 -0
@@ -2,10 +2,10 @@ import { NativeModules } from "react-native";
2
2
  import DeviceInfo from "../../DeviceInfo";
3
3
  import { getLocales } from "../../GetLocals/src";
4
4
 
5
- const BASE_URL = global.ShakebugSDKEndPointURL;
6
- const API_KEY = global.ShakebugSDKEndPointURLheaderKey;
7
-
8
5
  async function SessionStartApi(latitude, longitude, application_id) {
6
+ const BASE_URL = global.ShakebugSDKEndPointURL || "https://www.shakebug.com/api/v1.6/webservice.php/";
7
+ const API_KEY = global.ShakebugSDKEndPointURLheaderKey || "MarchShake2022";
8
+
9
9
 
10
10
  let city = "";
11
11
  let state = ""
@@ -57,24 +57,35 @@ async function SessionStartApi(latitude, longitude, application_id) {
57
57
 
58
58
  let architecture = await DeviceInfo.supportedAbis()
59
59
 
60
+ const requestPayload = {
61
+ method: "startSession",
62
+ uuid: uuid || "",
63
+ applicationsid: application_id || "",
64
+ systemversion: system_version || "",
65
+ os: os || "",
66
+ language: (locals && locals[0]) ? locals[0].languageCode : "",
67
+ country: (locals && locals[0]) ? locals[0].countryCode : "",
68
+ phonename: (device_name || "").replace(/'/g, ""),
69
+ devicemodel: (architecture && architecture[0]) ? architecture[0] : "",
70
+ city: city || "",
71
+ state: state || "",
72
+ latitude: latitude === undefined || latitude === null ? "" : latitude,
73
+ longitude: longitude === undefined || longitude === null ? "" : longitude,
74
+ phonecarrier: phone_carrier || "",
75
+ appversion: app_version || "",
76
+ custom_user_id: Custom_User_Id || "",
77
+ sdk_version: global.sdk_version || "",
78
+ sdk_platform: global.sdk_platform || "",
79
+ sdk_platform_version: global.sdk_platform_version || ""
80
+ };
81
+
82
+ console.log("➡️ [Shakebug] SessionStartApi Request URL:", BASE_URL);
83
+ console.log("➡️ [Shakebug] SessionStartApi Payload:", requestPayload);
84
+
60
85
  const formData = new FormData();
61
- formData.append("method", "startSession")
62
- formData.append("uuid", uuid)
63
- formData.append("applicationsid", application_id)
64
- formData.append("systemversion", system_version)
65
- formData.append("os", os)
66
- formData.append("language", locals[0].languageCode)
67
- formData.append("country", locals[0].countryCode)
68
- formData.append("phonename", device_name)
69
- formData.append("devicemodel", architecture[0])
70
- formData.append("city", city)
71
- formData.append("state", state)
72
- formData.append("latitude", latitude)
73
- formData.append("longitude", longitude)
74
- formData.append("phonecarrier", phone_carrier)
75
- formData.append("appversion", app_version)
76
- formData.append("custom_user_id", Custom_User_Id || "")
77
- formData.append("sdk_version", global.sdk_version)
86
+ Object.keys(requestPayload).forEach(key => {
87
+ formData.append(key, requestPayload[key]);
88
+ });
78
89
 
79
90
  try {
80
91
  const response = await fetch(BASE_URL, {
@@ -85,7 +96,17 @@ async function SessionStartApi(latitude, longitude, application_id) {
85
96
  body: formData,
86
97
  });
87
98
 
88
- const data = await response.json();
99
+ const responseText = await response.text();
100
+ console.log("⬅️ [Shakebug] SessionStartApi Raw Response:", responseText);
101
+
102
+ let data;
103
+ try {
104
+ data = JSON.parse(responseText);
105
+ } catch (parseError) {
106
+ console.error("❌ [Shakebug] Server returned invalid JSON. Could not parse:", responseText);
107
+ return { success: false, message: "Invalid server response" };
108
+ }
109
+
89
110
  if (data.code === 200 && data.success === true) {
90
111
  const session_id = data.response_data.session_id;
91
112
  return { success: true, session_id, message: data.msg };
@@ -93,8 +114,8 @@ async function SessionStartApi(latitude, longitude, application_id) {
93
114
  return { success: false, message: data.msg };
94
115
  }
95
116
  } catch (error) {
96
- // console.error('Error fetching data:', error);
97
- // throw error;
117
+ console.error('❌ [Shakebug] Error fetching data:', error);
118
+ return { success: false, message: "Network error" };
98
119
  }
99
120
  }
100
121
 
@@ -0,0 +1,59 @@
1
+ import React from 'react';
2
+ import { View, ActivityIndicator, StyleSheet, Text } from 'react-native';
3
+
4
+ const LoadingModal = ({ visible, color = '#1dd3e3', text = '' }) => {
5
+ if (!visible) return null;
6
+
7
+ return (
8
+ <View style={styles.overlay} pointerEvents="auto">
9
+ <View style={styles.backdrop} />
10
+ <View style={styles.indicatorContainer}>
11
+ <ActivityIndicator size="large" color={color} />
12
+ {text ? <Text style={styles.text}>{text}</Text> : null}
13
+ </View>
14
+ </View>
15
+ );
16
+ };
17
+
18
+ const styles = StyleSheet.create({
19
+ overlay: {
20
+ position: 'absolute',
21
+ top: 0,
22
+ bottom: 0,
23
+ left: 0,
24
+ right: 0,
25
+ zIndex: 99999,
26
+ elevation: 999,
27
+ justifyContent: 'center',
28
+ alignItems: 'center',
29
+ },
30
+ backdrop: {
31
+ position: 'absolute',
32
+ top: 0,
33
+ bottom: 0,
34
+ left: 0,
35
+ right: 0,
36
+ backgroundColor: 'rgba(0, 0, 0, 0.65)',
37
+ },
38
+ indicatorContainer: {
39
+ padding: 24,
40
+ backgroundColor: '#ffffff',
41
+ borderRadius: 16,
42
+ alignItems: 'center',
43
+ justifyContent: 'center',
44
+ shadowColor: '#000',
45
+ shadowOffset: { width: 0, height: 4 },
46
+ shadowOpacity: 0.35,
47
+ shadowRadius: 8,
48
+ elevation: 10,
49
+ zIndex: 100000,
50
+ },
51
+ text: {
52
+ marginTop: 12,
53
+ fontSize: 14,
54
+ color: '#333333',
55
+ fontWeight: '500',
56
+ },
57
+ });
58
+
59
+ export default LoadingModal;
@@ -13,9 +13,11 @@ console.ignoredYellowBox = ["Warning: Each", "Warning: Failed", "Possible", "WAR
13
13
  import { logger, consoleTransport } from "react-native-logs";
14
14
  import { ActivityIndicator } from 'react-native';
15
15
  import { useGlobalState } from './GlobalStateContext';
16
+ import LoadingModal from './LoadingModal';
16
17
 
17
18
  LogBox.ignoreAllLogs()
18
19
 
20
+ let intervalId = null;
19
21
  const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitle, allowToReportBugByShaking, allowToReportBugByScreenCapture, allowCrashReport }) => {
20
22
 
21
23
  const { ShakebugSDKScreenShotDetector, ShakebugSDKSharedPreferencesModule, ShakebugSDKCustomScreenCapture} = NativeModules;
@@ -104,6 +106,20 @@ const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitl
104
106
  return global.allowBugReport !== false && allowToReportBugByShaking !== false;
105
107
  };
106
108
 
109
+ useEffect(() => {
110
+ const triggerSubscription = DeviceEventEmitter.addListener('TriggerBugReportingEvent', () => {
111
+ log.info("TriggerBugReportingEvent received. global.isShakebugOpen:", global.isShakebugOpen);
112
+ if (!global.isShakebugOpen) {
113
+ setTriggred(true);
114
+ global.isShakebugOpen = true;
115
+ setTimeout(() => {
116
+ OpenShakebug(true); // Pass true to bypass shake checks
117
+ }, 200);
118
+ }
119
+ });
120
+ return () => triggerSubscription.remove();
121
+ }, []);
122
+
107
123
  setUpdateIntervalForType(SensorTypes.accelerometer, 200);
108
124
 
109
125
  let iscrashSaveed = ""
@@ -241,6 +257,9 @@ const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitl
241
257
  }, []);
242
258
 
243
259
  const startTimer = () => {
260
+ if (intervalId) {
261
+ clearInterval(intervalId);
262
+ }
244
263
  startTimeRef.current = Date.now();
245
264
  intervalId = setInterval(() => {
246
265
  if (global.isRecording) {
@@ -253,15 +272,16 @@ const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitl
253
272
  const updateTimer = (elapsed) => {
254
273
  const min = Math.floor(elapsed / 60);
255
274
  const sec = parseInt(elapsed % 60);
275
+ const durationLimit = parseInt(global.videoDuration) || 20;
256
276
 
257
- if (elapsed == global.videoDuration) {
277
+ if (elapsed == durationLimit) {
258
278
  clearInterval(intervalId);
259
279
  setTimeout(() => {
260
280
  Stop()
261
281
  }, 1000)
262
282
  }
263
283
 
264
- if (elapsed > global.videoDuration) {
284
+ if (elapsed > durationLimit) {
265
285
  RecordScreen.stopRecording()
266
286
  .then(() => {
267
287
  global.isMic = false;
@@ -386,8 +406,9 @@ const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitl
386
406
 
387
407
  }, [isFocused])
388
408
 
389
- const OpenShakebug = async () => {
390
- if (!isBugReportingEnabled()) {
409
+ const OpenShakebug = async (bypassShakeCheck = false) => {
410
+ if (!bypassShakeCheck && !isBugReportingEnabled()) {
411
+ log.warn("OpenShakebug aborted: Bug reporting is disabled.");
391
412
  return;
392
413
  }
393
414
  setIsScreenShot(true)
@@ -405,8 +426,14 @@ const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitl
405
426
  setTriggred(false)
406
427
  global.isShakebugSDKOpen = true
407
428
  navigate("FirstScreen", { img: `${ImgUrl}`, themeColor: `${themeColor}`, SDKScreenTitle: `${SDKScreenTitle}` })
429
+ } else {
430
+ log.warn("OpenShakebug aborted: Screenshot capture returned null.");
408
431
  }
432
+ } else {
433
+ log.warn("OpenShakebug aborted: isShow is true (currently recording).");
409
434
  }
435
+ } else {
436
+ log.warn("OpenShakebug aborted: Missing application_id or session_id. App_Id:", global.application_id, "Session_Id:", global.session_id);
410
437
  }
411
438
  }
412
439
 
@@ -523,16 +550,7 @@ const ShakeFunction = ({ children, themeColor, showTutorialScreen, SDKScreenTitl
523
550
 
524
551
  </ShakebugCapture>
525
552
 
526
- {isLoading &&
527
- <View
528
- style={{
529
- ...StyleSheet.absoluteFillObject,
530
- backgroundColor: 'rgba(0, 0, 0, 0.4)',
531
- }}
532
- />
533
- }
534
-
535
- {isLoading && <ActivityIndicator size={'large'} color={themeColor} collapsable={true} style={{ position: 'absolute', top: 0, bottom: 0, left: 0, right: 0, elevation: 2 }} />}
553
+ <LoadingModal visible={isLoading} color={themeColor} />
536
554
  {isShow ? (
537
555
  <Animated.View
538
556
  {...panResponder.panHandlers}
@@ -12,6 +12,7 @@ import { ScrollView } from 'react-native';
12
12
  import KeyboardAvoidingWrapper from '../Componanats/KeyboardAvoidingWrapper';
13
13
  import { useGlobalState } from '../Componanats/GlobalStateContext';
14
14
  import CustomeAlert from '../Componanats/CustomAlert';
15
+ import LoadingModal from '../Componanats/LoadingModal';
15
16
  import NetInfo from '../../NetInfo/src';
16
17
  import DeviceInfo from '../../DeviceInfo';
17
18
 
@@ -92,10 +93,11 @@ const AddDetailsScreen = ({ media, updateParent, mediaType, themeColor, SDKScree
92
93
  try {
93
94
 
94
95
  const { create: createThumbnail } = CreateThumbnail;
96
+ const cleanVideoPath = path ? path.replace('file://', '') : '';
95
97
 
96
98
  const thumbnail = await createThumbnail({
97
- url: `file://${path}`,
98
- timeStamp: 10000,
99
+ url: `file://${cleanVideoPath}`,
100
+ timeStamp: 1000,
99
101
  })
100
102
 
101
103
  if (thumbnail) {
@@ -145,6 +147,7 @@ const AddDetailsScreen = ({ media, updateParent, mediaType, themeColor, SDKScree
145
147
  // For open Video picker
146
148
  const openVideoPicker = () => {
147
149
  global.IsBackground = "false"
150
+ setIsLoading(true)
148
151
 
149
152
  const options = {
150
153
  mediaType: 'video',
@@ -153,26 +156,26 @@ const AddDetailsScreen = ({ media, updateParent, mediaType, themeColor, SDKScree
153
156
  };
154
157
 
155
158
  launchImageLibrary(options, async (response) => {
156
- setIsLoading(true)
157
159
  if (response.didCancel) {
158
160
  setIsLoading(false)
159
- global.IsBackground = "fa"
161
+ global.IsBackground = "false"
160
162
  // console.log('User cancelled image picker');
161
- } else if (response.error) {
163
+ } else if (response.error || response.errorCode) {
162
164
  setIsLoading(false)
163
165
  global.IsBackground = "true"
164
166
  // console.log('Image picker error: ', response.error);
165
167
  } else {
166
- setIsLoading(false)
167
168
  global.IsBackground = "true"
168
169
  let videoUri = await response.uri || response.assets?.[0]?.uri;
169
- if (response.assets?.[0]?.type.slice(0, 5).trim() == "video") {
170
+ if (response.assets?.[0]?.type?.slice(0, 5).trim() == "video") {
170
171
  if (mediaType == "img")
171
172
  navigate("TrimVideoScreen", { video: `${videoUri}`, Type: "imgReplacedWithVideo", themeColor: ThemeColor, SDKScreenTitle: SDKScreenTitle, UpdateStatusBar: UpdateStatusBar, updateParent: updateParent })
172
173
  else
173
174
  navigate("TrimVideoScreen", { video: `${videoUri}`, Type: "videoReplacedWithVideo", themeColor: ThemeColor, SDKScreenTitle: SDKScreenTitle, UpdateStatusBar: UpdateStatusBar, updateParent: updateParent })
175
+ setIsLoading(false)
174
176
  }
175
177
  else {
178
+ setIsLoading(false)
176
179
  setAPIMessage("Invalid selection, Please choose a valid video file")
177
180
  setErrorInAPI(true)
178
181
  }
@@ -184,25 +187,24 @@ const AddDetailsScreen = ({ media, updateParent, mediaType, themeColor, SDKScree
184
187
  // For open image picker
185
188
  const openImagePicker = () => {
186
189
  global.IsBackground = "false"
190
+ setIsLoading(true)
187
191
  const options = {
188
192
  mediaType: 'photo',
189
193
  includeBase64: false,
190
194
  selectionLimit: 1
191
195
  };
192
196
  launchImageLibrary(options, async (response) => {
193
- setIsLoading(true)
194
197
  if (response.didCancel) {
195
198
  setIsLoading(false)
196
199
  global.IsBackground = "true"
197
200
  // console.log('User cancelled image picker');
198
- } else if (response.error) {
201
+ } else if (response.error || response.errorCode) {
199
202
  setIsLoading(false)
200
203
  global.IsBackground = "true"
201
204
  // console.log('Image picker error: ', response.error);
202
205
  } else {
203
-
204
206
  global.IsBackground = "true"
205
- if (response.assets?.[0]?.type.slice(0, 5).trim() == "image") {
207
+ if (response.assets?.[0]?.type?.slice(0, 5).trim() == "image") {
206
208
  let imageuri = await response.uri || response.assets?.[0]?.uri;
207
209
  setIsLoading(false)
208
210
  if (imageuri != "" || imageuri != undefined) {
@@ -217,6 +219,7 @@ const AddDetailsScreen = ({ media, updateParent, mediaType, themeColor, SDKScree
217
219
  }
218
220
  }
219
221
  else {
222
+ setIsLoading(false)
220
223
  setAPIMessage("Invalid selection, Please choose a valid image file")
221
224
  setErrorInAPI(true)
222
225
  }
@@ -285,13 +288,18 @@ const AddDetailsScreen = ({ media, updateParent, mediaType, themeColor, SDKScree
285
288
  }
286
289
 
287
290
  return (
288
- <SafeAreaView style={{ flex: 1, backgroundColor: ThemeColor, paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0 }}>
291
+ <View style={{ flex: 1, backgroundColor: '#fff' }}>
289
292
  <StatusBar backgroundColor={ThemeColor} hidden={false} barStyle="dark-content" />
290
- <View style={{
291
- flex: 1,
292
- backgroundColor: "#fff",
293
- paddingBottom: Platform.OS === 'android' ? 48 : 0 // Standard bottom navigation bar height
294
- }}>
293
+ <SafeAreaView style={{ flex: 0, backgroundColor: ThemeColor }} />
294
+ {Platform.OS === 'android' && StatusBar.currentHeight ? (
295
+ <View style={{ height: StatusBar.currentHeight, backgroundColor: ThemeColor }} />
296
+ ) : null}
297
+ <SafeAreaView style={{ flex: 1, backgroundColor: '#fff' }}>
298
+ <View style={{
299
+ flex: 1,
300
+ backgroundColor: "#fff",
301
+ paddingBottom: Platform.OS === 'android' ? 48 : 0 // Standard bottom navigation bar height
302
+ }}>
295
303
  <KeyboardAvoidingWrapper>
296
304
  <>
297
305
  <View style={{ height: '6%', padding: 5, paddingHorizontal: 15, backgroundColor: ThemeColor, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
@@ -436,7 +444,7 @@ const AddDetailsScreen = ({ media, updateParent, mediaType, themeColor, SDKScree
436
444
  <CustomeAlert
437
445
  isVisible={isErrorInAPI || isBugReported}
438
446
  text={apiMessage}
439
- color={themeColor}
447
+ color={ThemeColor}
440
448
  OnPrees={() => {
441
449
  if (isBugReported) {
442
450
  global.isScreenShotDetected = false;
@@ -449,24 +457,13 @@ const AddDetailsScreen = ({ media, updateParent, mediaType, themeColor, SDKScree
449
457
  setIsLoading(false)
450
458
  }}
451
459
  />
452
-
453
-
454
- {isLoading &&
455
- <View
456
- style={{
457
- ...StyleSheet.absoluteFillObject,
458
- backgroundColor: 'rgba(0, 0, 0, 0.4)',
459
- }}
460
- />
461
- }
462
-
463
- {isLoading &&
464
- <ActivityIndicator size={'large'} color={themeColor} collapsable={true} style={{ position: 'absolute', top: 0, bottom: 0, left: 0, right: 0, elevation: 2 }} />}
465
460
  </>
466
461
  </KeyboardAvoidingWrapper>
467
462
  </View>
468
463
 
469
464
  </SafeAreaView>
465
+ <LoadingModal visible={isLoading} color={ThemeColor} />
466
+ </View>
470
467
  )
471
468
  }
472
469
 
@@ -11,6 +11,7 @@ import { ActivityIndicator } from 'react-native';
11
11
  import DeviceInfo from '../../DeviceInfo';
12
12
  import { useGlobalState } from '../Componanats/GlobalStateContext.js';
13
13
  import CustomeAlert from '../Componanats/CustomAlert.js';
14
+ import LoadingModal from '../Componanats/LoadingModal.js';
14
15
 
15
16
  console.disableYellowBox = true;
16
17
  console.ignoredYellowBox = ["Warning: Each", "Warning: Failed", "Possible"];
@@ -108,6 +109,7 @@ const FirstScreen = ({ img, themeColor, SDKScreenTitle }) => {
108
109
 
109
110
  // open Video picker to choose video
110
111
  const openVideoPicker = () => {
112
+ setIsLoading(true)
111
113
  const options = {
112
114
  mediaType: 'video',
113
115
  includeBase64: false,
@@ -115,19 +117,19 @@ const FirstScreen = ({ img, themeColor, SDKScreenTitle }) => {
115
117
  };
116
118
 
117
119
  launchImageLibrary(options, async (response) => {
118
- setIsLoading(true)
119
120
  if (response.didCancel) {
120
121
  setIsLoading(false)
121
- } else if (response.error) {
122
+ } else if (response.error || response.errorCode) {
122
123
  setIsLoading(false)
123
124
  // console.log('Image picker error: ', response.error);
124
125
  } else {
125
126
  let vedioUri = await response.uri || response.assets?.[0]?.uri;
126
- if (response.assets?.[0]?.type.slice(0, 5).trim() == "video") {
127
+ if (response.assets?.[0]?.type?.slice(0, 5).trim() == "video") {
127
128
  setIsLoading(false)
128
129
  navigate("TrimVideoScreen", { video: `${vedioUri}`, Type: "video", themeColor: `${ThemeColor}`, SDKScreenTitle: `${SDKScreenTitle}`, UpdateStatusBar: UpdateStatusBar, updateParent: updateImage })
129
130
  }
130
131
  else {
132
+ setIsLoading(false)
131
133
  setIsAlertText("Invalid selection, Please choose a valid video file")
132
134
  setIsAlert(true)
133
135
  }
@@ -310,9 +312,13 @@ const FirstScreen = ({ img, themeColor, SDKScreenTitle }) => {
310
312
  // backgroundColor: "#181818"
311
313
 
312
314
  return (
313
- <SafeAreaView style={{ flex: 1, backgroundColor: ThemeColor, paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0 }}>
314
- <StatusBar backgroundColor={ThemeColor} barStyle="dark-content" />
315
-
315
+ <View style={{ flex: 1, backgroundColor: '#fff' }}>
316
+ <StatusBar backgroundColor={ThemeColor} barStyle="dark-content" />
317
+ <SafeAreaView style={{ flex: 0, backgroundColor: ThemeColor }} />
318
+ {Platform.OS === 'android' && StatusBar.currentHeight ? (
319
+ <View style={{ height: StatusBar.currentHeight, backgroundColor: ThemeColor }} />
320
+ ) : null}
321
+ <SafeAreaView style={{ flex: 1, backgroundColor: '#fff' }}>
316
322
  <View style={{
317
323
  flex: 1,
318
324
  backgroundColor: "#e4fdfd",
@@ -547,28 +553,19 @@ const FirstScreen = ({ img, themeColor, SDKScreenTitle }) => {
547
553
  </KeyboardAvoidingView>
548
554
  </View>) : null}
549
555
 
550
- {isLoading &&
551
- <View
552
- style={{
553
- ...StyleSheet.absoluteFillObject,
554
- backgroundColor: 'rgba(0, 0, 0, 0.4)',
555
- }}
556
- />
557
- }
558
-
559
556
  <CustomeAlert
560
557
  isVisible={isAlert}
561
558
  text={isAlertText}
562
- color={themeColor}
559
+ color={ThemeColor}
563
560
  OnPrees={() => {
564
561
  setIsAlert(false)
565
562
  setIsAlertText("")
566
563
  }}
567
564
  />
568
565
 
569
- {isLoading && <ActivityIndicator size={'large'} color={themeColor} collapsable={true} style={{ position: 'absolute', top: 0, bottom: 0, left: 0, right: 0, elevation: 2 }} />}
570
-
571
566
  </SafeAreaView>
567
+ <LoadingModal visible={isLoading} color={ThemeColor} />
568
+ </View>
572
569
  )
573
570
  }
574
571
 
@@ -49,7 +49,7 @@ global.isRecording = false
49
49
  global.isScreenShotDetected = false
50
50
  global.ShakebugLanguage = "ENGLISH"
51
51
  global.makeLogEnabled = false
52
- global.ShakebugSDKEndPointURL = "https://www.shakebug.com/api/v1.5/webservice.php/";
52
+ global.ShakebugSDKEndPointURL = "https://www.shakebug.com/api/v1.6/webservice.php/";
53
53
  global.ShakebugSDKEndPointURLheaderKey = 'MarchShake2022';
54
54
  global.AllowVideo = false;
55
55
  global.total_video = 0;
@@ -63,7 +63,7 @@ global.isScreeenShotTaken = false;
63
63
  global.restrictedViews = [];
64
64
  global.currentScreen = ""
65
65
  global.isShakebugSDKOpen = false;
66
- global.sdk_version = "2.4.9";
66
+ global.sdk_version = "2.4.11";
67
67
  global.app_lunch_count = 0;
68
68
  global.POPUP_LAUNCH_THRESHOLD = 3;
69
69
  global.POPUP_COOLDOWN_DAYS = 2;
@@ -75,7 +75,12 @@ global.allowEvent = true;
75
75
  global.allowReview = true;
76
76
  global.allowSession = true;
77
77
  global.shakebug_type = "1"; // default allow all
78
-
78
+ global.sdk_platform = "react-native";
79
+ try {
80
+ global.sdk_platform_version = require("react-native/package.json").version;
81
+ } catch (error) {
82
+ global.sdk_platform_version = "";
83
+ }
79
84
 
80
85
  const ShakebugContext = React.createContext();
81
86
 
@@ -204,7 +209,7 @@ function Shakebug({ children, Android_appkey, iOS_appkey, showTutorialScreenFirs
204
209
  const [focusedScreen, setFocusedScreen] = useState('');
205
210
  global.ShakebugLanguage = ShakebugLanguage;
206
211
  global.makeLogEnabled = makeLogEnabled;
207
- global.ShakebugSDKEndPointURL = setShakebugSDKEndPointURL[0].length > 0 ? setShakebugSDKEndPointURL[0] : "https://www.shakebug.com/api/v1.5/webservice.php/";
212
+ global.ShakebugSDKEndPointURL = setShakebugSDKEndPointURL[0].length > 0 ? setShakebugSDKEndPointURL[0] : "https://www.shakebug.com/api/v1.6/webservice.php/";
208
213
  global.ShakebugSDKEndPointURLheaderKey = setShakebugSDKEndPointURL[1].length > 0 ? setShakebugSDKEndPointURL[1] : "MarchShake2022";
209
214
 
210
215
 
@@ -291,12 +296,12 @@ function Shakebug({ children, Android_appkey, iOS_appkey, showTutorialScreenFirs
291
296
  const afterDaysTimestamp = now + sevenDaysInMs;
292
297
 
293
298
  if (LAST_POPUP_TIME > afterDaysTimestamp) {
294
- setShowModal(true)
299
+ setTimeout(() => { setShowModal(true) }, 15000);
295
300
  }
296
301
 
297
302
  }
298
303
  else if (IS_REVIEW_SUBMITTED != "true") {
299
- setShowModal(true)
304
+ setTimeout(() => { setShowModal(true) }, 15000);
300
305
  }
301
306
  }
302
307
 
@@ -1,26 +1,27 @@
1
- import { NativeEventEmitter, NativeModules, Platform, SafeAreaView, StatusBar } from 'react-native'
1
+ import { DeviceEventEmitter, NativeEventEmitter, NativeModules, Platform, SafeAreaView, StatusBar, View } from 'react-native'
2
2
  import React, { useEffect, useState } from 'react'
3
- import { showEditor } from 'react-native-video-trim';
3
+ import { showEditor } from '../../trimVideo/src/index';
4
4
  import { useNavigation } from '../Componanats/NavigationContext';
5
5
  import { Localization } from '../Componanats/localization';
6
+ import LoadingModal from '../Componanats/LoadingModal';
6
7
 
7
8
  console.ignoredYellowBox = ["Warning: Each", "Warning: Failed"];
8
9
 
9
-
10
-
11
10
  const TrimVideoScreen = ({ video, themeColor, SDKScreenTitle, Type, UpdateStatusBar, updateParent }) => {
12
11
 
13
12
  const { goToScreenAtIndex, navigate, goBack } = useNavigation();
13
+ const [loading, setLoading] = useState(true);
14
14
 
15
+ const ThemeColor = themeColor ? themeColor : "#1dd3e3";
15
16
 
16
17
  // For display video trimmer
17
18
  useEffect(() => {
18
19
  StatusBar.setHidden(true)
19
20
 
20
21
  const uri = video; // your path
21
- const trimmedUri = uri.replace('file://', '');
22
+ const cleanUri = uri.replace('file://', '');
22
23
 
23
- showEditor(Platform.OS == 'android' ? trimmedUri : video, {
24
+ showEditor(cleanUri, {
24
25
  saveButtonText: Localization[global.ShakebugLanguage].Choose,
25
26
  cancelButtonText: Localization[global.ShakebugLanguage].Cancel,
26
27
  trimmingText: Localization[global.ShakebugLanguage].TrimmingText,
@@ -38,50 +39,64 @@ const TrimVideoScreen = ({ video, themeColor, SDKScreenTitle, Type, UpdateStatus
38
39
  saveDialogConfirmText: Localization[global.ShakebugLanguage].Yes
39
40
  });
40
41
 
41
- const eventEmitter = new NativeEventEmitter(NativeModules.VideoTrim);
42
- const subscription = eventEmitter.addListener('VideoTrim', (event) => {
42
+ const handleVideoTrimEvent = (event) => {
43
43
  switch (event.name) {
44
44
  case 'onShow': {
45
+ setLoading(false);
45
46
  break;
46
47
  }
47
48
  case 'onHide': {
48
49
  break;
49
50
  }
50
51
  case 'onStartTrimming': {
52
+ // The native side displays "Trimming video..." dialog, so we don't need a React Native loader here
51
53
  break;
52
54
  }
53
55
  case 'onFinishTrimming': {
54
- global.IsBackground = 'true'
55
- UpdateStatusBar()
56
+ global.IsBackground = 'true';
57
+ UpdateStatusBar();
56
58
  navigate("AddDetailsScreen", { media: `${event.outputPath}`, mediaType: 'video', themeColor: themeColor, SDKScreenTitle: SDKScreenTitle, updateParent: updateParent });
57
59
  return;
58
60
  }
59
61
  case 'onCancel': {
60
- UpdateStatusBar()
62
+ UpdateStatusBar();
61
63
  if (Type == "video") {
62
- goToScreenAtIndex(1)
63
- }
64
- else if (Type == "imgReplacedWithVideo") {
65
- goBack()
66
- }
67
- else if (Type == "videoReplacedWithVideo") {
68
- goToScreenAtIndex(3)
64
+ goToScreenAtIndex(1);
65
+ } else if (Type == "imgReplacedWithVideo") {
66
+ goBack();
67
+ } else if (Type == "videoReplacedWithVideo") {
68
+ goToScreenAtIndex(3);
69
69
  }
70
70
  return;
71
- break;
72
71
  }
73
72
  case 'onError': {
73
+ setLoading(false);
74
74
  break;
75
75
  }
76
76
  }
77
- });
77
+ };
78
+
79
+ let subscription;
80
+ if (Platform.OS === 'android') {
81
+ subscription = DeviceEventEmitter.addListener('VideoTrim', handleVideoTrimEvent);
82
+ } else {
83
+ const videoTrimModule = NativeModules.ShakebugSDKVideoTrim || NativeModules.VideoTrim;
84
+ const eventEmitter = new NativeEventEmitter(videoTrimModule);
85
+ subscription = eventEmitter.addListener('VideoTrim', handleVideoTrimEvent);
86
+ }
78
87
 
79
88
  return () => {
80
- subscription.remove();
89
+ if (subscription && subscription.remove) {
90
+ subscription.remove();
91
+ }
81
92
  };
82
93
  }, [])
83
94
 
84
- return;
95
+ return (
96
+ <View style={{ flex: 1, backgroundColor: '#000', justifyContent: 'center', alignItems: 'center' }}>
97
+ <LoadingModal visible={loading} color={ThemeColor} />
98
+ </View>
99
+ );
85
100
  }
86
101
 
87
102
  export default TrimVideoScreen;