react-native-mytatva-rn-sdk 1.2.71 → 1.2.73
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/android/build.gradle +1 -0
- package/android/src/main/java/com/mytatvarnsdk/CgmTrackyLibModule.kt +76 -57
- package/android/src/main/java/com/mytatvarnsdk/activity/StartCGMActivity.kt +3 -0
- package/android/src/main/java/com/mytatvarnsdk/network/AuthenticateSDKService.kt +8 -0
- package/package.json +1 -1
package/android/build.gradle
CHANGED
|
@@ -131,6 +131,7 @@ dependencies {
|
|
|
131
131
|
implementation 'com.google.android.material:material:1.8.0'
|
|
132
132
|
implementation 'androidx.activity:activity:1.9.3'
|
|
133
133
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
|
134
|
+
implementation "io.sentry:sentry-android:7.11.0"
|
|
134
135
|
implementation 'com.github.bumptech.glide:glide:4.15.1'
|
|
135
136
|
implementation 'com.github.bumptech.glide:okhttp3-integration:4.15.1'
|
|
136
137
|
implementation 'androidx.multidex:multidex:2.0.1'
|
|
@@ -28,6 +28,8 @@ import com.facebook.react.module.annotations.ReactModule
|
|
|
28
28
|
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
29
29
|
import com.google.gson.Gson
|
|
30
30
|
import com.google.gson.GsonBuilder
|
|
31
|
+
import io.sentry.Sentry
|
|
32
|
+
import io.sentry.android.core.SentryAndroid
|
|
31
33
|
import com.mytatvarnsdk.activity.HelpActivity
|
|
32
34
|
import com.mytatvarnsdk.activity.StartCGMActivity
|
|
33
35
|
import com.mytatvarnsdk.model.AllCGMLogRequest
|
|
@@ -92,6 +94,19 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
92
94
|
ViewModelProvider.AndroidViewModelFactory.getInstance(reactContext.applicationContext as Application)
|
|
93
95
|
mModel = ViewModelProvider(viewModelStore, factory)[MainActivityModel::class.java]
|
|
94
96
|
authenticateSDKService = AuthenticateSDKService(scope = scope)
|
|
97
|
+
|
|
98
|
+
initSentryIfNeeded(reactContext)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private fun initSentryIfNeeded(context: ReactApplicationContext) {
|
|
102
|
+
if (sentryInitialized.compareAndSet(false, true)) {
|
|
103
|
+
SentryAndroid.init(context.applicationContext) { options ->
|
|
104
|
+
options.dsn = "https://8c1585c04b41a8bdf3271d89c7361530@o4509755819294720.ingest.us.sentry.io/4510520864735232"
|
|
105
|
+
options.isDebug = true // remove or toggle for production
|
|
106
|
+
options.tracesSampleRate = 1.0
|
|
107
|
+
}
|
|
108
|
+
Sentry.captureMessage("Goodflip SDK started")
|
|
109
|
+
}
|
|
95
110
|
}
|
|
96
111
|
|
|
97
112
|
|
|
@@ -99,6 +114,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
99
114
|
var mReactContext: ReactApplicationContext? = null
|
|
100
115
|
var userToken: String = ""
|
|
101
116
|
var env: String = ""
|
|
117
|
+
private val sentryInitialized = AtomicBoolean(false)
|
|
102
118
|
}
|
|
103
119
|
|
|
104
120
|
override fun getName(): String {
|
|
@@ -363,7 +379,9 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
363
379
|
fun startCgmTracky(token: String, envType: String) {
|
|
364
380
|
try {
|
|
365
381
|
userToken = token
|
|
382
|
+
env = envType.lowercase()
|
|
366
383
|
val intent = Intent(currentActivity, StartCGMActivity::class.java)
|
|
384
|
+
intent.putExtra("envType", env)
|
|
367
385
|
currentActivity?.startActivity(intent)
|
|
368
386
|
} catch (e: Exception) {
|
|
369
387
|
Log.e("startCgmTracky", "startCgmTracky: ${e.message}")
|
|
@@ -385,11 +403,12 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
385
403
|
fun reconnectCgmTracky(token: String, envType: String) {
|
|
386
404
|
try {
|
|
387
405
|
userToken = token
|
|
406
|
+
env = envType.lowercase()
|
|
388
407
|
currentActivity?.startActivity(
|
|
389
408
|
Intent(currentActivity, StartCGMActivity::class.java).putExtra(
|
|
390
409
|
"IsForReconnect",
|
|
391
410
|
true
|
|
392
|
-
)
|
|
411
|
+
).putExtra("envType", env)
|
|
393
412
|
)
|
|
394
413
|
} catch (e: Exception) {
|
|
395
414
|
Log.e("reconnectCgmTracky", "reconnectCgmTracky: ${e.message}")
|
|
@@ -495,7 +514,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
495
514
|
|
|
496
515
|
// Check for duplicate using glucoseId
|
|
497
516
|
val glucoseId = pocGlucose.glucoseId ?: continue
|
|
498
|
-
|
|
517
|
+
|
|
499
518
|
if (!processedGlucoseIds.add(glucoseId)) {
|
|
500
519
|
Log.d("triggerDataUpload", "Already processed: $glucoseId, skipping")
|
|
501
520
|
continue
|
|
@@ -518,7 +537,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
518
537
|
// Put it back in queue for batch to handle
|
|
519
538
|
pendingDataQueue.offer(pocGlucose)
|
|
520
539
|
Log.d("triggerDataUpload", "Old data detected, triggering batch: $glucoseId")
|
|
521
|
-
|
|
540
|
+
|
|
522
541
|
// Trigger batch process on main thread
|
|
523
542
|
withContext(Dispatchers.Main) {
|
|
524
543
|
observeAllGlucoseData(userToken, false, envType)
|
|
@@ -543,40 +562,40 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
543
562
|
Log.d("handleGlucoseData", "Processing glucose data: ${pocGlucose.glucoseId}")
|
|
544
563
|
|
|
545
564
|
if (pocGlucose.errorCode == enumError.NONE) {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
val request: GlucoseLogRequest =
|
|
552
|
-
GlucoseLogRequest(vendor = "GoodFlip", logs = logs)
|
|
553
|
-
val gson: Gson = GsonBuilder().create()
|
|
554
|
-
val json = gson.toJson(request)
|
|
555
|
-
|
|
556
|
-
Log.d("Glucose data 3 min==> ", "Glucose data 3 min==> final Json: $json")
|
|
557
|
-
|
|
558
|
-
authenticateSDKService.postCGMData(
|
|
559
|
-
environment = if (envType.lowercase() == "uat") TATVA_ENVIRONMENT.STAGE else TATVA_ENVIRONMENT.PROD,
|
|
560
|
-
data = json,
|
|
561
|
-
token = userToken,
|
|
562
|
-
responseListener = object : AuthenticateSDKService.ResponseListener {
|
|
563
|
-
override fun onResponseSuccess(response: String) {
|
|
564
|
-
updateSyncMetadata(pocGlucose)
|
|
565
|
-
Log.d("CGM Data", "Single glucose data uploaded successfully")
|
|
566
|
-
}
|
|
565
|
+
/* if (pocGlucose.showGlucoseMG > 0) { */
|
|
566
|
+
val dto: GlucoseLog = mapToDto(pocGlucose)
|
|
567
|
+
val logs: ArrayList<GlucoseLog> = ArrayList()
|
|
568
|
+
logs.add(dto)
|
|
567
569
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
570
|
+
val request: GlucoseLogRequest =
|
|
571
|
+
GlucoseLogRequest(vendor = "GoodFlip", logs = logs)
|
|
572
|
+
val gson: Gson = GsonBuilder().create()
|
|
573
|
+
val json = gson.toJson(request)
|
|
574
|
+
|
|
575
|
+
Log.d("Glucose data 3 min==> ", "Glucose data 3 min==> final Json: $json")
|
|
576
|
+
|
|
577
|
+
authenticateSDKService.postCGMData(
|
|
578
|
+
environment = if (envType.lowercase() == "uat") TATVA_ENVIRONMENT.STAGE else TATVA_ENVIRONMENT.PROD,
|
|
579
|
+
data = json,
|
|
580
|
+
token = userToken,
|
|
581
|
+
responseListener = object : AuthenticateSDKService.ResponseListener {
|
|
582
|
+
override fun onResponseSuccess(response: String) {
|
|
583
|
+
updateSyncMetadata(pocGlucose)
|
|
584
|
+
Log.d("CGM Data", "Single glucose data uploaded successfully")
|
|
571
585
|
}
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
586
|
+
|
|
587
|
+
override fun onResponseFail() {
|
|
588
|
+
Log.e("CGM Data", "Failed to upload single glucose data")
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
)
|
|
592
|
+
/* } */
|
|
593
|
+
/* else {
|
|
594
|
+
Log.d(
|
|
595
|
+
"handleGlucoseData",
|
|
596
|
+
"Glucose value is 0 or negative: ${pocGlucose.showGlucoseMG}"
|
|
597
|
+
)
|
|
598
|
+
} */
|
|
580
599
|
} else {
|
|
581
600
|
Log.d("handleGlucoseData", "Glucose data has error: ${pocGlucose.errorCode}")
|
|
582
601
|
handleGlucoseError(pocGlucose, envType)
|
|
@@ -653,7 +672,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
653
672
|
while (pendingDataQueue.isNotEmpty()) {
|
|
654
673
|
pendingDataQueue.poll()?.let { pendingData.add(it) }
|
|
655
674
|
}
|
|
656
|
-
|
|
675
|
+
|
|
657
676
|
if (pendingData.isNotEmpty()) {
|
|
658
677
|
Log.d("observeAllGlucoseData", "Found ${pendingData.size} items in pending queue")
|
|
659
678
|
}
|
|
@@ -668,7 +687,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
668
687
|
val glucoseData = mModel.getGlucoseBetweenTime(lastSyncData.timeInMillis)
|
|
669
688
|
|
|
670
689
|
Log.d("observeAllGlucoseData", "Retrieved ${glucoseData?.size ?: 0} records from DB")
|
|
671
|
-
|
|
690
|
+
|
|
672
691
|
// Combine database data with pending queue data
|
|
673
692
|
val allData = mutableListOf<PocGlucose>()
|
|
674
693
|
glucoseData?.let { allData.addAll(it) }
|
|
@@ -687,7 +706,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
687
706
|
sortedGlucoseData.take(5).forEachIndexed { i, data ->
|
|
688
707
|
Log.d("AFTER Sort [$i]", "timeInMillis: ${data.timeInMillis}, glucoseId: ${data.glucoseId}")
|
|
689
708
|
}
|
|
690
|
-
|
|
709
|
+
|
|
691
710
|
if (sortedGlucoseData.isNotEmpty()) {
|
|
692
711
|
Log.d("observeAllGlucoseData", "✅ Sorted ${sortedGlucoseData.size} records chronologically")
|
|
693
712
|
Log.d("observeAllGlucoseData", "Oldest: ${sortedGlucoseData.first().timeInMillis}")
|
|
@@ -722,7 +741,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
722
741
|
}
|
|
723
742
|
}
|
|
724
743
|
}
|
|
725
|
-
|
|
744
|
+
|
|
726
745
|
withContext(Dispatchers.Main) {
|
|
727
746
|
if (!isObserving) {
|
|
728
747
|
observeGlucoseData(userToken, isForClear, envType)
|
|
@@ -760,7 +779,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
760
779
|
}
|
|
761
780
|
|
|
762
781
|
// Don't reset flag here - it's reset in observeAllGlucoseData's finally block
|
|
763
|
-
|
|
782
|
+
|
|
764
783
|
// Ensure we're on main thread and not already observing
|
|
765
784
|
withContext(Dispatchers.Main) {
|
|
766
785
|
if (!isObserving) {
|
|
@@ -813,7 +832,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
813
832
|
// Cancel all coroutines
|
|
814
833
|
debounceJob?.cancel()
|
|
815
834
|
debounceJob = null
|
|
816
|
-
|
|
835
|
+
|
|
817
836
|
uploadJob?.cancel()
|
|
818
837
|
uploadJob = null
|
|
819
838
|
|
|
@@ -826,7 +845,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
826
845
|
// Clear processed IDs and pending queue
|
|
827
846
|
processedGlucoseIds.clear()
|
|
828
847
|
pendingDataQueue.clear()
|
|
829
|
-
|
|
848
|
+
|
|
830
849
|
// Reset batch processing flag
|
|
831
850
|
isBatchProcessing.set(false)
|
|
832
851
|
|
|
@@ -847,20 +866,20 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
847
866
|
try {
|
|
848
867
|
val context = reactApplicationContext
|
|
849
868
|
val logFiles = mutableListOf<String>()
|
|
850
|
-
|
|
869
|
+
|
|
851
870
|
// Get the primary log folder path
|
|
852
871
|
val externalFilesDir = context.getExternalFilesDir(android.os.Environment.DIRECTORY_DOCUMENTS)
|
|
853
872
|
val primaryFolder = externalFilesDir?.absolutePath
|
|
854
|
-
|
|
873
|
+
|
|
855
874
|
// Get the fallback log folder path
|
|
856
|
-
val fallbackFolder = android.os.Environment.getExternalStorageDirectory().absolutePath +
|
|
857
|
-
|
|
858
|
-
|
|
875
|
+
val fallbackFolder = android.os.Environment.getExternalStorageDirectory().absolutePath +
|
|
876
|
+
File.separatorChar + "PocData" + File.separatorChar + "logger"
|
|
877
|
+
|
|
859
878
|
// Check primary folder
|
|
860
879
|
if (primaryFolder != null) {
|
|
861
880
|
val primaryDir = File(primaryFolder)
|
|
862
881
|
if (primaryDir.exists() && primaryDir.isDirectory) {
|
|
863
|
-
val files = primaryDir.listFiles { file ->
|
|
882
|
+
val files = primaryDir.listFiles { file ->
|
|
864
883
|
file.isFile && file.name.endsWith(".csv")
|
|
865
884
|
}
|
|
866
885
|
files?.forEach { file ->
|
|
@@ -868,11 +887,11 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
868
887
|
}
|
|
869
888
|
}
|
|
870
889
|
}
|
|
871
|
-
|
|
890
|
+
|
|
872
891
|
// Check fallback folder
|
|
873
892
|
val fallbackDir = File(fallbackFolder)
|
|
874
893
|
if (fallbackDir.exists() && fallbackDir.isDirectory) {
|
|
875
|
-
val files = fallbackDir.listFiles { file ->
|
|
894
|
+
val files = fallbackDir.listFiles { file ->
|
|
876
895
|
file.isFile && file.name.endsWith(".csv")
|
|
877
896
|
}
|
|
878
897
|
files?.forEach { file ->
|
|
@@ -882,17 +901,17 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
882
901
|
}
|
|
883
902
|
}
|
|
884
903
|
}
|
|
885
|
-
|
|
904
|
+
|
|
886
905
|
Log.d("getCgmLogFiles", "Found ${logFiles.size} log files")
|
|
887
|
-
|
|
906
|
+
|
|
888
907
|
// Convert list to WritableArray
|
|
889
908
|
val resultArray = Arguments.createArray()
|
|
890
909
|
logFiles.forEach { path ->
|
|
891
910
|
resultArray.pushString(path)
|
|
892
911
|
}
|
|
893
|
-
|
|
912
|
+
|
|
894
913
|
promise.resolve(resultArray)
|
|
895
|
-
|
|
914
|
+
|
|
896
915
|
} catch (e: Exception) {
|
|
897
916
|
Log.e("getCgmLogFiles", "Error getting log files: ${e.message}")
|
|
898
917
|
promise.reject("ERROR_GET_LOG_FILES", e.message, e)
|
|
@@ -1035,7 +1054,7 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
1035
1054
|
fun stopObservingGlucoseData() {
|
|
1036
1055
|
stopObservingGlucoseDataInternal()
|
|
1037
1056
|
}
|
|
1038
|
-
|
|
1057
|
+
|
|
1039
1058
|
// Internal method that doesn't clear the queue (used during restarts)
|
|
1040
1059
|
private fun stopObservingGlucoseDataInternal() {
|
|
1041
1060
|
Log.d("stopObservingGlucoseData", "Stopping glucose data observation")
|
|
@@ -1110,10 +1129,10 @@ class CgmTrackyLibModule(reactContext: ReactApplicationContext) :
|
|
|
1110
1129
|
it.glucoseId
|
|
1111
1130
|
)
|
|
1112
1131
|
prefsHelper?.lastSyncData = syncData
|
|
1113
|
-
|
|
1132
|
+
|
|
1114
1133
|
// Mark this glucose ID as processed
|
|
1115
1134
|
it.glucoseId?.let { id -> processedGlucoseIds.add(id) }
|
|
1116
|
-
|
|
1135
|
+
|
|
1117
1136
|
Log.d(
|
|
1118
1137
|
"Sync Metadata",
|
|
1119
1138
|
"Sync metadata updated: glucoseId=${it.glucoseId}, time=${it.timeInMillis}"
|
|
@@ -54,6 +54,9 @@ class StartCGMActivity : AppCompatActivity() {
|
|
|
54
54
|
|
|
55
55
|
private fun init() {
|
|
56
56
|
isForReconnect = intent.getBooleanExtra("IsForReconnect", false)
|
|
57
|
+
val envType = intent.getStringExtra("envType") ?: "prod"
|
|
58
|
+
|
|
59
|
+
// Use envType as needed
|
|
57
60
|
|
|
58
61
|
sendDataToRN("", "cgm_start_connection_landing")
|
|
59
62
|
|
|
@@ -19,6 +19,7 @@ import kotlinx.coroutines.CoroutineScope
|
|
|
19
19
|
import kotlinx.coroutines.launch
|
|
20
20
|
import okhttp3.MediaType.Companion.toMediaType
|
|
21
21
|
import okhttp3.RequestBody.Companion.toRequestBody
|
|
22
|
+
import retrofit2.HttpException
|
|
22
23
|
|
|
23
24
|
class AuthenticateSDKService(val scope: CoroutineScope) {
|
|
24
25
|
|
|
@@ -158,6 +159,13 @@ class AuthenticateSDKService(val scope: CoroutineScope) {
|
|
|
158
159
|
|
|
159
160
|
Log.d("API Response", "API response: $decryptedResponse")
|
|
160
161
|
|
|
162
|
+
} catch (e: HttpException) {
|
|
163
|
+
if (e.code() == 401) {
|
|
164
|
+
Log.d("API Error", "401 Unauthorized - Token: $token")
|
|
165
|
+
// Further handling if necessary
|
|
166
|
+
} else {
|
|
167
|
+
throw e
|
|
168
|
+
}
|
|
161
169
|
} catch (e: Exception) {
|
|
162
170
|
e.printStackTrace()
|
|
163
171
|
Log.d("API Response", "Exception: ${e.message}")
|