shakebug-react-native 2.4.12 → 2.4.14

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shakebug-react-native",
3
3
  "title": "shakebug-react-native",
4
- "version": "2.4.12",
4
+ "version": "2.4.14",
5
5
  "description": "Shakebug allows users to report the bug from your mobile phone for your application. Here users just need to shake their mobile and all the data regarding bugs & crashes can be seen by developers through their log in panel easily",
6
6
  "main": "src/index.tsx",
7
7
  "types": "src/index.tsx",
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { View, Text, Button, StyleSheet, Modal, TouchableOpacity } from 'react-native';
3
3
 
4
- const CustomeAlert = ({color, isVisible, OnPrees, text}) => {
4
+ const CustomeAlert = ({color, isVisible, OnPrees, text = ""}) => {
5
5
 
6
6
  return (
7
7
  <Modal
@@ -13,7 +13,7 @@ const CustomeAlert = ({color, isVisible, OnPrees, text}) => {
13
13
  <View
14
14
  style={[
15
15
  styles.container, {
16
- height: text.length > 120 ? 300 : text.length < 50 ? 170 : 200
16
+ height: (text && text.length > 120) ? 300 : (text && text.length < 50) ? 170 : 200
17
17
  }]}
18
18
  >
19
19
  <Text style={styles.text}>
@@ -13,7 +13,7 @@ const ReviewModal = ({ visible, onClose, onSubmit, color }) => {
13
13
 
14
14
  const handleSubmit = () => {
15
15
  ShakebugSDKSharedPreferencesModule.setString("IS_REVIEW_SUBMITTED", "true");
16
- AddReviewApi(rating, feedback, global.application_id, global.session_id);
16
+ AddReviewApi(rating, feedback, global.application_id, global.session_id).catch(() => {});
17
17
  setRating(0);
18
18
  setFeedback('');
19
19
  onClose();
@@ -1,6 +1,6 @@
1
1
  export const Localization = {
2
2
  "ENGLISH": {
3
- InterNetConnetionError: "Please check you internet connection",
3
+ InterNetConnetionError: "Please check your internet connection",
4
4
  FirstScreenTitle: "Annotate your bug",
5
5
  SecondScreenTitle: "Add Details",
6
6
  RecordVideo: "Record Video?",
@@ -49,7 +49,7 @@ const AddDetailsScreen = ({ media, updateParent, mediaType, themeColor, SDKScree
49
49
  // For handel system back navigation
50
50
  useEffect(() => {
51
51
 
52
- NetInfo.addEventListener(stat => {
52
+ const unsubscribeNetInfo = NetInfo.addEventListener(stat => {
53
53
  setIsInternet(stat.isConnected)
54
54
  })
55
55
 
@@ -73,7 +73,12 @@ const AddDetailsScreen = ({ media, updateParent, mediaType, themeColor, SDKScree
73
73
 
74
74
  const backHandler = BackHandler.addEventListener('hardwareBackPress', backAction);
75
75
 
76
- return () => backHandler.remove(); // Clean up the event listener on unmount
76
+ return () => {
77
+ backHandler.remove();
78
+ if (unsubscribeNetInfo) {
79
+ unsubscribeNetInfo();
80
+ }
81
+ }; // Clean up the event listener on unmount
77
82
  }, []);
78
83
 
79
84
 
@@ -16,7 +16,7 @@ import FirstScreen from './FirstScreen';
16
16
  import AddDetailsScreen from './AddDetailsScreen';
17
17
  import TrimVideoScreen from './TrimVideoScreen'
18
18
  import DeviceInfo from '../../DeviceInfo';
19
- import { useEffect, useState } from 'react';
19
+ import { useEffect, useState, useRef } from 'react';
20
20
  import GetLocation from '../../GetLocation'
21
21
  import NetInfo from '../../NetInfo/src'
22
22
  import { SessionStartApi } from '../APIs/StartSession';
@@ -63,18 +63,18 @@ global.isScreeenShotTaken = false;
63
63
  global.restrictedViews = [];
64
64
  global.currentScreen = ""
65
65
  global.isShakebugSDKOpen = false;
66
- global.sdk_version = "2.4.12";
66
+ global.sdk_version = "2.4.14";
67
67
  global.app_lunch_count = 0;
68
68
  global.POPUP_LAUNCH_THRESHOLD = 3;
69
69
  global.POPUP_COOLDOWN_DAYS = 2;
70
70
  global.KEY_REVIEW_SUBMITTED = false;
71
- // Initialize feature flags with defaults (allow all)
71
+ // Initialize feature flags with defaults (allow core reporting; reviews disabled by default until verified)
72
72
  global.allowBugReport = true;
73
73
  global.allowCrashReport = true;
74
74
  global.allowEvent = true;
75
- global.allowReview = true;
75
+ global.allowReview = false;
76
76
  global.allowSession = true;
77
- global.shakebug_type = "1"; // default allow all
77
+ global.shakebug_type = "";
78
78
  global.sdk_platform = "react-native";
79
79
  try {
80
80
  global.sdk_platform_version = require("react-native/package.json").version;
@@ -190,27 +190,58 @@ const ShakeScreen = () => {
190
190
 
191
191
 
192
192
 
193
- function Shakebug({ children, Android_appkey, iOS_appkey, showTutorialScreenFirstTime, ShakebugThemeColor, changeSDKScreenTitle, allowToReportBugByShakingMobile, allowToReportBugByScreenCapture, allowCrashReport, ShakebugLanguage, makeLogEnabled, setShakebugSDKEndPointURL }) {
193
+ function Shakebug({
194
+ children,
195
+ Android_appkey,
196
+ iOS_appkey,
197
+ showTutorialScreenFirstTime = true,
198
+ ShakebugThemeColor = "#1dd3e3",
199
+ changeSDKScreenTitle = ['Annotate your bug', 'Add Details'],
200
+ allowToReportBugByShakingMobile = true,
201
+ allowToReportBugByScreenCapture = false,
202
+ allowCrashReport = true,
203
+ ShakebugLanguage = "ENGLISH",
204
+ makeLogEnabled = false,
205
+ setShakebugSDKEndPointURL = ["https://www.shakebug.com/api/v1.6/webservice.php/", "MarchShake2022", ""]
206
+ }) {
194
207
 
195
208
  const [allowBugReport, setAllowBugReport] = useState(true);
196
209
  const [allowCrashFlag, setAllowCrashFlag] = useState(true);
197
210
  const [allowEventFlag, setAllowEventFlag] = useState(true);
198
- const [allowReviewFlag, setAllowReviewFlag] = useState(true);
211
+ const [allowReviewFlag, setAllowReviewFlag] = useState(false);
199
212
  const [allowSessionFlag, setAllowSessionFlag] = useState(true);
200
213
 
201
214
  const { ShakebugSDKSharedPreferencesModule } = NativeModules;
202
215
 
216
+ const validLanguage = (ShakebugLanguage && Localization[ShakebugLanguage])
217
+ ? ShakebugLanguage
218
+ : (global.ShakebugLanguage && Localization[global.ShakebugLanguage])
219
+ ? global.ShakebugLanguage
220
+ : "ENGLISH";
221
+ global.ShakebugLanguage = validLanguage;
222
+
203
223
  const ThemeColor = ShakebugThemeColor ? ShakebugThemeColor : "#1dd3e3";
204
- const FirstScreenTitle = changeSDKScreenTitle ? changeSDKScreenTitle[0] != "" ? changeSDKScreenTitle[0] : Localization[ShakebugLanguage].FirstScreenTitle : Localization[ShakebugLanguage].FirstScreenTitle;
205
- const SecondScreenTitle = changeSDKScreenTitle ? changeSDKScreenTitle[1] != "" ? changeSDKScreenTitle[1] : Localization[ShakebugLanguage].SecondScreenTitle : Localization[ShakebugLanguage].SecondScreenTitle;
224
+ const FirstScreenTitle = (changeSDKScreenTitle && changeSDKScreenTitle[0] && changeSDKScreenTitle[0] !== "")
225
+ ? changeSDKScreenTitle[0]
226
+ : Localization[validLanguage]?.FirstScreenTitle || "Annotate your bug";
227
+ const SecondScreenTitle = (changeSDKScreenTitle && changeSDKScreenTitle[1] && changeSDKScreenTitle[1] !== "")
228
+ ? changeSDKScreenTitle[1]
229
+ : Localization[validLanguage]?.SecondScreenTitle || "Add Details";
206
230
  const [isAlert, setIsAlert] = useState(false)
207
231
  const [isAlertText, setAlertText] = useState("")
208
232
  const [showModal, setShowModal] = useState(false);
209
233
  const [focusedScreen, setFocusedScreen] = useState('');
210
- global.ShakebugLanguage = ShakebugLanguage;
211
234
  global.makeLogEnabled = makeLogEnabled;
212
- global.ShakebugSDKEndPointURL = setShakebugSDKEndPointURL[0].length > 0 ? setShakebugSDKEndPointURL[0] : "https://www.shakebug.com/api/v1.6/webservice.php/";
213
- global.ShakebugSDKEndPointURLheaderKey = setShakebugSDKEndPointURL[1].length > 0 ? setShakebugSDKEndPointURL[1] : "MarchShake2022";
235
+ global.ShakebugSDKEndPointURL = (setShakebugSDKEndPointURL && setShakebugSDKEndPointURL[0] && setShakebugSDKEndPointURL[0].length > 0)
236
+ ? setShakebugSDKEndPointURL[0]
237
+ : "https://www.shakebug.com/api/v1.6/webservice.php/";
238
+ global.ShakebugSDKEndPointURLheaderKey = (setShakebugSDKEndPointURL && setShakebugSDKEndPointURL[1] && setShakebugSDKEndPointURL[1].length > 0)
239
+ ? setShakebugSDKEndPointURL[1]
240
+ : "MarchShake2022";
241
+
242
+ const connectionAlertShownRef = useRef(false);
243
+ const isMatchingKeyRef = useRef(false);
244
+ const reviewTimeoutRef = useRef(null);
214
245
 
215
246
 
216
247
  // DefaulfConfig for log
@@ -259,116 +290,362 @@ function Shakebug({ children, Android_appkey, iOS_appkey, showTutorialScreenFirs
259
290
  fetchData();
260
291
  }, [Android_appkey, iOS_appkey])
261
292
 
262
- // For check mau limit, valid appkey and call MatchKeyFunc
263
- useEffect(() => {
264
- async function fetchData() {
293
+ // For call Startsesstion and get session id
294
+ const StartSession = async () => {
295
+ if (global.session_id == "") {
296
+ try {
297
+ const { success, session_id: newSessionId, message } = await SessionStartApi(global.latitude, global.longitude, global.application_id);
298
+ if (success) {
299
+ global.session_id = newSessionId
300
+ log.debug("------------------------------------------------------------------------------------------")
301
+ log.info('API response:', message);
302
+ log.debug("------------------------------------------------------------------------------------------")
303
+ } else {
304
+ log.debug("------------------------------------------------------------------------------------------")
305
+ log.warn(message);
306
+ log.debug("------------------------------------------------------------------------------------------")
307
+ global.session_id = ""
308
+ }
309
+ }
310
+ catch (err) {
311
+ log.error("err", err)
312
+ }
313
+ }
265
314
 
266
- const KEY_APP_LAUNCH_COUNT = await ShakebugSDKSharedPreferencesModule.getString("KEY_APP_LAUNCH_COUNT") ? parseInt(await ShakebugSDKSharedPreferencesModule.getString("KEY_APP_LAUNCH_COUNT")) : 0;
267
- const LAST_POPUP_TIME = await ShakebugSDKSharedPreferencesModule.getString("LAST_POPUP_TIME") ? parseInt(await ShakebugSDKSharedPreferencesModule.getString("LAST_POPUP_TIME")) : null;
268
- const IS_REVIEW_SUBMITTED = await ShakebugSDKSharedPreferencesModule.getString("IS_REVIEW_SUBMITTED") || "false";
315
+ DeviceInfo.isEmulator().then(res => {
316
+ if (res === true) {
317
+ log.info("Supports real device only");
318
+ }
319
+ })
320
+ }
269
321
 
270
- const SDK_VERSION = await ShakebugSDKSharedPreferencesModule.getString("SDK_VERSION")
322
+ // Set feature flags based on shakebug_type (supports comma‑separated codes)
323
+ const applyFeatureFlags = (type) => {
324
+ if (type === undefined || type === null || type === "") return;
325
+
326
+ // Reset all flags to false initially
327
+ global.allowBugReport = false;
328
+ global.allowCrashReport = false;
329
+ global.allowEvent = false;
330
+ global.allowReview = false;
331
+ global.allowSession = false;
332
+
333
+ // Helper to enable a specific flag
334
+ const enableFlag = (code) => {
335
+ switch (code) {
336
+ case "0":
337
+ // Disable all – already false
338
+ break;
339
+ case "1":
340
+ // Enable all
341
+ global.allowBugReport = true;
342
+ global.allowCrashReport = true;
343
+ global.allowEvent = true;
344
+ global.allowReview = true;
345
+ global.allowSession = true;
346
+ break;
347
+ case "2":
348
+ global.allowBugReport = true;
349
+ break;
350
+ case "3":
351
+ global.allowCrashReport = true;
352
+ break;
353
+ case "4":
354
+ global.allowEvent = true;
355
+ break;
356
+ case "5":
357
+ global.allowSession = true;
358
+ break;
359
+ case "6":
360
+ global.allowReview = true;
361
+ break;
362
+ default:
363
+ // ignore unknown codes
364
+ break;
365
+ }
366
+ };
271
367
 
272
- ShakebugSDKSharedPreferencesModule.setString("KEY_APP_LAUNCH_COUNT", (KEY_APP_LAUNCH_COUNT + 1).toString())
368
+ // Split the incoming string and enable flags for each code
369
+ const codes = String(type).split(',').map(c => c.trim());
370
+ codes.forEach(enableFlag);
273
371
 
274
- if (SDK_VERSION) {
275
- if (SDK_VERSION != global.sdk_version) {
276
- ShakebugSDKSharedPreferencesModule.setString("KEY_APP_LAUNCH_COUNT", "0")
277
- ShakebugSDKSharedPreferencesModule.setString("LAST_POPUP_TIME", "")
278
- ShakebugSDKSharedPreferencesModule.setString("IS_REVIEW_SUBMITTED", "false")
279
- ShakebugSDKSharedPreferencesModule.setString("SDK_VERSION", global.sdk_version)
280
- }
372
+ // Store raw type for reference
373
+ global.shakebug_type = type;
374
+
375
+ // Update React state so UI re‑renders with new flags
376
+ setAllowBugReport(global.allowBugReport);
377
+ setAllowCrashFlag(global.allowCrashReport);
378
+ setAllowEventFlag(global.allowEvent);
379
+ setAllowReviewFlag(global.allowReview);
380
+ setAllowSessionFlag(global.allowSession);
381
+ };
382
+
383
+ const checkAndScheduleReviewPopup = async () => {
384
+ try {
385
+ if (!global.allowReview || !global.application_id) {
386
+ return;
281
387
  }
282
- else {
283
- ShakebugSDKSharedPreferencesModule.setString("KEY_APP_LAUNCH_COUNT", "0")
284
- ShakebugSDKSharedPreferencesModule.setString("LAST_POPUP_TIME", "")
285
- ShakebugSDKSharedPreferencesModule.setString("IS_REVIEW_SUBMITTED", "false")
286
- ShakebugSDKSharedPreferencesModule.setString("SDK_VERSION", global.sdk_version)
388
+
389
+ const LAST_POPUP_TIME = (await ShakebugSDKSharedPreferencesModule.getString("LAST_POPUP_TIME"))
390
+ ? parseInt(await ShakebugSDKSharedPreferencesModule.getString("LAST_POPUP_TIME"))
391
+ : null;
392
+ const IS_REVIEW_SUBMITTED = (await ShakebugSDKSharedPreferencesModule.getString("IS_REVIEW_SUBMITTED")) || "false";
393
+
394
+ if (global.app_lunch_count >= global.POPUP_LAUNCH_THRESHOLD && global.allowReview) {
395
+ if (LAST_POPUP_TIME && LAST_POPUP_TIME != "" && IS_REVIEW_SUBMITTED != "true") {
396
+ const now = Date.now(); // current timestamp in milliseconds
397
+ const cooldownInMs = global.POPUP_COOLDOWN_DAYS * 24 * 60 * 60 * 1000;
398
+
399
+ if (now - parseInt(LAST_POPUP_TIME) >= cooldownInMs) {
400
+ if (reviewTimeoutRef.current) {
401
+ clearTimeout(reviewTimeoutRef.current);
402
+ }
403
+ reviewTimeoutRef.current = setTimeout(() => {
404
+ if (global.allowReview && global.application_id) {
405
+ setShowModal(true);
406
+ }
407
+ }, 15000);
408
+ }
409
+ } else if (IS_REVIEW_SUBMITTED != "true") {
410
+ if (reviewTimeoutRef.current) {
411
+ clearTimeout(reviewTimeoutRef.current);
412
+ }
413
+ reviewTimeoutRef.current = setTimeout(() => {
414
+ if (global.allowReview && global.application_id) {
415
+ setShowModal(true);
416
+ }
417
+ }, 15000);
418
+ }
287
419
  }
420
+ } catch (err) {
421
+ log.error("Error scheduling review popup", err);
422
+ }
423
+ };
424
+
425
+ // For call Match key app and get application id
426
+ const MatchKeyFunc = async (appkey) => {
427
+ try {
428
+ let BundleId = DeviceInfo.getBundleId();
429
+
430
+ const { success, application_id: newApplication_id, message, total_mau, used_mau, total_video, used_video, video_duration, shakebug_type } = await MatchKeyApi(appkey, BundleId);
431
+
432
+ global.videoDuration = video_duration;
433
+
434
+ if (success) {
435
+ if (total_video == "Unlimited") {
436
+ global.AllowVideo = true;
437
+ }
438
+ else if (used_video == null) {
439
+ global.AllowVideo = true;
440
+ }
441
+ else if (parseInt(total_video) > parseInt(used_video)) {
442
+ global.AllowVideo = true;
443
+ }
444
+ else {
445
+ global.AllowVideo = false;
446
+ global.total_video = total_video;
447
+ global.used_video = used_video;
448
+ }
288
449
 
289
- global.app_lunch_count = (parseInt(KEY_APP_LAUNCH_COUNT) + 1);
450
+ if (total_mau.toString() == used_mau.toString()) {
451
+ let date = new Date().getTime() + 6 * 60 * 60 * 1000
452
+ ShakebugSDKSharedPreferencesModule.setString("mauReachedTime", date.toString())
453
+ }
454
+ if (Platform.OS == "android") {
455
+ global.isAndroidValid = true
456
+ }
457
+ else {
458
+ global.isIOSValid = true
459
+ }
460
+ global.application_id = newApplication_id;
290
461
 
462
+ // Apply and persist feature flags
463
+ applyFeatureFlags(shakebug_type);
464
+ if (shakebug_type) {
465
+ ShakebugSDKSharedPreferencesModule.setString("SHAKEBUG_TYPE", String(shakebug_type));
466
+ }
467
+
468
+ log.debug("------------------------------------------------------------------------------------------");
469
+ log.info('API response:', message);
470
+ log.debug("------------------------------------------------------------------------------------------");
471
+ if (global.allowSession) { StartSession(); }
472
+
473
+ checkAndScheduleReviewPopup();
474
+ return true;
475
+ } else {
476
+ if (Platform.OS == "android") {
477
+ global.isAndroidValid = false
478
+ }
479
+ else {
480
+ global.isIOSValid = false
481
+ }
482
+ log.debug("------------------------------------------------------------------------------------------")
483
+ log.warn(message);
484
+ log.debug("------------------------------------------------------------------------------------------")
485
+ global.application_id = ""
486
+ return false;
487
+ }
488
+ }
489
+ catch (err) {
490
+ log.error("Err", err)
491
+ if (err === "Network request failed" || err?.message === "Network request failed") {
492
+ log.warn("Please check your internet connection")
493
+ }
494
+ return false;
495
+ }
496
+ }
497
+
498
+ const executeMatchKey = async () => {
499
+ if (global.application_id && global.application_id.trim().length > 0) {
500
+ return true;
501
+ }
502
+ if (isMatchingKeyRef.current) {
503
+ return false;
504
+ }
505
+ isMatchingKeyRef.current = true;
506
+ try {
291
507
  if (Platform.OS == 'android') {
292
508
  if (Android_appkey && Android_appkey.trim().length > 0) {
293
509
  try {
294
510
  const ismauReached = await ShakebugSDKSharedPreferencesModule.getString('mauReachedTime');
295
511
  if (!ismauReached) {
296
- await MatchKeyFunc(Android_appkey);
512
+ return await MatchKeyFunc(Android_appkey);
297
513
  } else if (parseInt(ismauReached) < new Date().getTime()) {
298
- await MatchKeyFunc(Android_appkey);
514
+ const res = await MatchKeyFunc(Android_appkey);
299
515
  ShakebugSDKSharedPreferencesModule.setString("mauReachedTime", "");
516
+ return res;
300
517
  } else {
301
518
  log.debug("------------------------------------------------------------------------------------------");
302
519
  log.warn('MAU limit is arrived, please try after', new Date(parseInt(ismauReached)).toLocaleString());
303
520
  log.debug("------------------------------------------------------------------------------------------");
521
+ return false;
304
522
  }
305
523
  } catch (err) {
306
524
  log.error("Err here", err);
525
+ return false;
307
526
  }
308
527
  } else {
309
528
  log.warn("Please provide valid android appkey");
529
+ return false;
310
530
  }
311
531
  } else if (Platform.OS == 'ios') {
312
532
  if (iOS_appkey && iOS_appkey.trim().length > 0) {
313
533
  try {
314
534
  const ismauReached = await ShakebugSDKSharedPreferencesModule.getString('mauReachedTime');
315
535
  if (!ismauReached) {
316
- await MatchKeyFunc(iOS_appkey);
536
+ return await MatchKeyFunc(iOS_appkey);
317
537
  } else if (parseInt(ismauReached) < new Date().getTime()) {
318
- await MatchKeyFunc(iOS_appkey);
538
+ const res = await MatchKeyFunc(iOS_appkey);
319
539
  ShakebugSDKSharedPreferencesModule.setString("mauReachedTime", "");
540
+ return res;
320
541
  } else {
321
542
  log.debug("------------------------------------------------------------------------------------------");
322
543
  log.warn('MAU limit is arrived, please try after', new Date(parseInt(ismauReached)).toLocaleString());
323
544
  log.debug("------------------------------------------------------------------------------------------");
545
+ return false;
324
546
  }
325
547
  } catch (err) {
326
548
  log.error("Err", err);
549
+ return false;
327
550
  }
328
551
  } else {
329
552
  log.warn("Please provide valid ios appkey");
553
+ return false;
330
554
  }
331
555
  }
556
+ return false;
557
+ } finally {
558
+ isMatchingKeyRef.current = false;
559
+ }
560
+ };
332
561
 
333
- if (global.app_lunch_count >= POPUP_LAUNCH_THRESHOLD && global.allowReview) {
334
- if (LAST_POPUP_TIME && LAST_POPUP_TIME != "" && IS_REVIEW_SUBMITTED != "true") {
335
- const now = Date.now(); // current timestamp in milliseconds
336
- const cooldownInMs = global.POPUP_COOLDOWN_DAYS * 24 * 60 * 60 * 1000;
562
+ // For check mau limit, valid appkey, handle connectivity, and call MatchKeyFunc
563
+ useEffect(() => {
564
+ let isMounted = true;
337
565
 
338
- if (now - parseInt(LAST_POPUP_TIME) >= cooldownInMs) {
339
- setTimeout(() => {
340
- if (global.allowReview) {
341
- setShowModal(true);
342
- }
343
- }, 15000);
566
+ async function initLaunchData() {
567
+ try {
568
+ const KEY_APP_LAUNCH_COUNT = (await ShakebugSDKSharedPreferencesModule.getString("KEY_APP_LAUNCH_COUNT"))
569
+ ? parseInt(await ShakebugSDKSharedPreferencesModule.getString("KEY_APP_LAUNCH_COUNT"))
570
+ : 0;
571
+ const SDK_VERSION = await ShakebugSDKSharedPreferencesModule.getString("SDK_VERSION");
572
+
573
+ if (SDK_VERSION) {
574
+ if (SDK_VERSION != global.sdk_version) {
575
+ await ShakebugSDKSharedPreferencesModule.setString("KEY_APP_LAUNCH_COUNT", "1");
576
+ await ShakebugSDKSharedPreferencesModule.setString("LAST_POPUP_TIME", "");
577
+ await ShakebugSDKSharedPreferencesModule.setString("IS_REVIEW_SUBMITTED", "false");
578
+ await ShakebugSDKSharedPreferencesModule.setString("SDK_VERSION", global.sdk_version);
579
+ global.app_lunch_count = 1;
580
+ } else {
581
+ const newCount = KEY_APP_LAUNCH_COUNT + 1;
582
+ await ShakebugSDKSharedPreferencesModule.setString("KEY_APP_LAUNCH_COUNT", newCount.toString());
583
+ global.app_lunch_count = newCount;
344
584
  }
345
-
585
+ } else {
586
+ await ShakebugSDKSharedPreferencesModule.setString("KEY_APP_LAUNCH_COUNT", "1");
587
+ await ShakebugSDKSharedPreferencesModule.setString("LAST_POPUP_TIME", "");
588
+ await ShakebugSDKSharedPreferencesModule.setString("IS_REVIEW_SUBMITTED", "false");
589
+ await ShakebugSDKSharedPreferencesModule.setString("SDK_VERSION", global.sdk_version);
590
+ global.app_lunch_count = 1;
346
591
  }
347
- else if (IS_REVIEW_SUBMITTED != "true") {
348
- setTimeout(() => {
349
- if (global.allowReview) {
350
- setShowModal(true);
351
- }
352
- }, 15000);
592
+
593
+ // Load cached feature flags from previous session if available
594
+ const cachedShakebugType = await ShakebugSDKSharedPreferencesModule.getString("SHAKEBUG_TYPE");
595
+ if (cachedShakebugType && cachedShakebugType.trim().length > 0) {
596
+ applyFeatureFlags(cachedShakebugType);
353
597
  }
598
+ } catch (err) {
599
+ log.error("Err initializing launch data", err);
354
600
  }
355
601
  }
356
602
 
357
- let i = 0;
358
- NetInfo.addEventListener(state => {
359
- if (i == 0) {
360
- if (state.isConnected == true) {
361
- fetchData()
603
+ initLaunchData();
604
+
605
+ const handleConnectivityChange = (state) => {
606
+ if (!isMounted || !state) return;
607
+
608
+ // Ignore unknown/null initial state until native connectivity is reported
609
+ if (state.isConnected === null) return;
610
+
611
+ const isConnected = state.isConnected === true;
612
+ const lang = (global.ShakebugLanguage && Localization[global.ShakebugLanguage])
613
+ ? global.ShakebugLanguage
614
+ : "ENGLISH";
615
+ const errorMsg = Localization[lang]?.InterNetConnetionError || "Please check your internet connection";
616
+
617
+ if (!isConnected) {
618
+ setAlertText(errorMsg);
619
+ setIsAlert(true);
620
+ connectionAlertShownRef.current = true;
621
+ } else {
622
+ if (connectionAlertShownRef.current || isAlert) {
623
+ setIsAlert(false);
624
+ setAlertText("");
625
+ connectionAlertShownRef.current = false;
362
626
  }
363
- else {
364
- setAlertText(Localization[global.ShakebugLanguage].InterNetConnetionError)
365
- setIsAlert(true)
627
+ if (!global.application_id || global.application_id === "") {
628
+ executeMatchKey();
366
629
  }
367
630
  }
368
- i++;
369
- })
370
- }, [Android_appkey, iOS_appkey])
631
+ };
632
+
633
+ // Check immediate connectivity on mount
634
+ NetInfo.fetch().then(handleConnectivityChange).catch(() => {});
371
635
 
636
+ // Listen to network changes (online <-> offline)
637
+ const unsubscribe = NetInfo.addEventListener(handleConnectivityChange);
638
+
639
+ return () => {
640
+ isMounted = false;
641
+ if (unsubscribe) {
642
+ unsubscribe();
643
+ }
644
+ if (reviewTimeoutRef.current) {
645
+ clearTimeout(reviewTimeoutRef.current);
646
+ }
647
+ };
648
+ }, [Android_appkey, iOS_appkey]);
372
649
 
373
650
  // For close or start session according app state
374
651
  useEffect(() => {
@@ -416,150 +693,6 @@ function Shakebug({ children, Android_appkey, iOS_appkey, showTutorialScreenFirs
416
693
  };
417
694
  }, [global.IsBackground]);
418
695
 
419
-
420
- // For call Match key app and get application id
421
- const MatchKeyFunc = async (appkey) => {
422
- try {
423
- let BundleId = DeviceInfo.getBundleId();
424
-
425
- const { success, application_id: newApplication_id, message, total_mau, used_mau, total_video, used_video, video_duration, shakebug_type } = await MatchKeyApi(appkey, BundleId);
426
-
427
- global.videoDuration = video_duration;
428
-
429
- if (success) {
430
- if (total_video == "Unlimited") {
431
- global.AllowVideo = true;
432
- }
433
- else if (used_video == null) {
434
- global.AllowVideo = true;
435
- }
436
- else if (parseInt(total_video) > parseInt(used_video)) {
437
- global.AllowVideo = true;
438
- }
439
- else {
440
- global.AllowVideo = false;
441
- global.total_video = total_video;
442
- global.used_video = used_video;
443
- }
444
-
445
- if (total_mau.toString() == used_mau.toString()) {
446
- let date = new Date().getTime() + 6 * 60 * 60 * 1000
447
- ShakebugSDKSharedPreferencesModule.setString("mauReachedTime", date.toString())
448
- }
449
- if (Platform.OS == "android") {
450
- global.isAndroidValid = true
451
- }
452
- else {
453
- global.isIOSValid = true
454
- }
455
- global.application_id = newApplication_id;
456
- // Set feature flags based on shakebug_type (supports comma‑separated codes)
457
- // Reset all flags to false initially
458
- global.allowBugReport = false;
459
- global.allowCrashReport = false;
460
- global.allowEvent = false;
461
- global.allowReview = false;
462
- global.allowSession = false;
463
- // Helper to enable a specific flag
464
- const enableFlag = (code) => {
465
- switch (code) {
466
- case "0":
467
- // Disable all – already false
468
- break;
469
- case "1":
470
- // Enable all
471
- global.allowBugReport = true;
472
- global.allowCrashReport = true;
473
- global.allowEvent = true;
474
- global.allowReview = true;
475
- global.allowSession = true;
476
- break;
477
- case "2":
478
- global.allowBugReport = true;
479
- break;
480
- case "3":
481
- global.allowCrashReport = true;
482
- break;
483
- case "4":
484
- global.allowEvent = true;
485
- break;
486
- case "5":
487
- global.allowReview = true;
488
- break;
489
- case "6":
490
- global.allowSession = true;
491
- break;
492
- default:
493
- // ignore unknown codes
494
- break;
495
- }
496
- };
497
- // Split the incoming string and enable flags for each code
498
- if (shakebug_type) {
499
- const codes = String(shakebug_type).split(',').map(c => c.trim());
500
- codes.forEach(enableFlag);
501
- }
502
- // Store raw type for reference
503
- global.shakebug_type = shakebug_type;
504
- // Update React state so UI re‑renders with new flags
505
- setAllowBugReport(global.allowBugReport);
506
- setAllowCrashFlag(global.allowCrashReport);
507
- setAllowEventFlag(global.allowEvent);
508
- setAllowReviewFlag(global.allowReview);
509
- setAllowSessionFlag(global.allowSession); log.debug("------------------------------------------------------------------------------------------");
510
- log.info('API response:', message);
511
- log.debug("------------------------------------------------------------------------------------------");
512
- if (global.allowSession) { StartSession(); }
513
- } else {
514
- if (Platform.OS == "android") {
515
- global.isAndroidValid = false
516
- }
517
- else {
518
- global.isIOSValid = false
519
- }
520
- log.debug("------------------------------------------------------------------------------------------")
521
- log.warn(message);
522
- log.debug("------------------------------------------------------------------------------------------")
523
- global.application_id = ""
524
- }
525
- }
526
- catch (err) {
527
- log.error("Err", err)
528
- if (err === "Network request failed" || err?.message === "Network request failed") {
529
- log.warn("Please check your internet connection")
530
- }
531
- }
532
- }
533
-
534
- // For call Startsesstion and get session id
535
- const StartSession = async () => {
536
- if (global.session_id == "") {
537
- try {
538
- const { success, session_id: newSessionId, message } = await SessionStartApi(global.latitude, global.longitude, global.application_id);
539
- if (success) {
540
- global.session_id = newSessionId
541
- log.debug("------------------------------------------------------------------------------------------")
542
- log.info('API response:', message);
543
- log.debug("------------------------------------------------------------------------------------------")
544
- } else {
545
- log.debug("------------------------------------------------------------------------------------------")
546
- log.warn(message);
547
- log.debug("------------------------------------------------------------------------------------------")
548
- global.session_id = ""
549
- }
550
- }
551
- catch (err) {
552
- log.error("err", err)
553
- }
554
- }
555
-
556
- DeviceInfo.isEmulator().then(res => {
557
- if (res === true) {
558
- log.info("Supports real device only");
559
- }
560
- })
561
- }
562
-
563
696
  // For handle error globally
564
697
  setGlobalErrorHandler()
565
698
 
@@ -605,10 +738,15 @@ function Shakebug({ children, Android_appkey, iOS_appkey, showTutorialScreenFirs
605
738
  OnPrees={() => {
606
739
  setAlertText("")
607
740
  setIsAlert(false)
741
+ connectionAlertShownRef.current = false;
608
742
  }}
609
743
  />
610
744
 
611
- <ReviewModal color={ThemeColor} visible={showModal && allowReviewFlag && global.allowReview} onClose={() => { setShowModal(false) }} />
745
+ <ReviewModal
746
+ color={ThemeColor}
747
+ visible={showModal && allowReviewFlag && global.allowReview && !!global.application_id}
748
+ onClose={() => { setShowModal(false) }}
749
+ />
612
750
  </View>
613
751
  </ShakebugContext.Provider>
614
752
  )