react-native-rook-sdk 4.0.0-beta.2 → 5.0.0-beta.0

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 (99) hide show
  1. package/RNRookSdk.podspec +1 -1
  2. package/android/build.gradle +6 -0
  3. package/android/src/main/java/com/rooksdk/RookSdkModule.kt +1850 -6
  4. package/android/src/main/java/com/rooksdk/broadcasts/AndroidPermissionsReceiverTransmitter.kt +62 -0
  5. package/android/src/main/java/com/rooksdk/broadcasts/HealthConnectPermissionsReceiverTransmitter.kt +64 -0
  6. package/android/src/main/java/com/rooksdk/broadcasts/SamsungHealthPermissionsReceiverTransmitter.kt +44 -0
  7. package/android/src/main/java/com/rooksdk/utils/DatasourceUtils.kt +35 -0
  8. package/android/src/main/java/com/rooksdk/utils/PermissionConvertions.kt +21 -0
  9. package/android/src/main/java/com/rooksdk/utils/ReadableToWritable.kt +144 -0
  10. package/android/src/main/java/com/rooksdk/utils/RookDateTime.kt +26 -0
  11. package/android/src/main/java/com/rooksdk/utils/RookGsonBuilder.kt +20 -0
  12. package/android/src/main/java/com/rooksdk/utils/SamsungAvailability.kt +22 -0
  13. package/android/src/main/java/com/rooksdk/utils/Source.kt +6 -0
  14. package/android/src/main/java/com/rooksdk/utils/StringToSyncType.kt +41 -0
  15. package/android/src/main/java/com/rooksdk/utils/serializers/InstantSerializer.kt +18 -0
  16. package/android/src/main/java/com/rooksdk/utils/serializers/LocalDateSerializer.kt +21 -0
  17. package/android/src/main/java/com/rooksdk/utils/serializers/ZoneDateTimeSerializer.kt +18 -0
  18. package/ios/EncodableSDKState.swift +95 -0
  19. package/ios/NutritionMapper.swift +114 -0
  20. package/ios/RookConfiguration.swift +13 -0
  21. package/ios/RookData.swift +29 -0
  22. package/ios/RookEntry.swift +5 -4
  23. package/ios/RookPermissions.swift +33 -9
  24. package/ios/RookSdk.h +1 -13
  25. package/ios/RookSdk.mm +44 -237
  26. package/lib/module/NativeRookSdk.js +98 -10
  27. package/lib/module/NativeRookSdk.js.map +1 -1
  28. package/lib/module/context/RookSyncGateProvider.js +29 -21
  29. package/lib/module/context/RookSyncGateProvider.js.map +1 -1
  30. package/lib/module/context/RookSyncGateReducer.js +12 -2
  31. package/lib/module/context/RookSyncGateReducer.js.map +1 -1
  32. package/lib/module/hooks/useRookConfiguration.js +20 -1
  33. package/lib/module/hooks/useRookConfiguration.js.map +1 -1
  34. package/lib/module/hooks/useRookData.js +13 -4
  35. package/lib/module/hooks/useRookData.js.map +1 -1
  36. package/lib/module/hooks/useRookPermissions.js +13 -1
  37. package/lib/module/hooks/useRookPermissions.js.map +1 -1
  38. package/lib/module/hooks/useRookSync.js +1 -1
  39. package/lib/module/hooks/useRookSync.js.map +1 -1
  40. package/lib/module/hooks/useRookVariables.js +16 -1
  41. package/lib/module/hooks/useRookVariables.js.map +1 -1
  42. package/lib/module/modules/components/RookStateManager.js +31 -0
  43. package/lib/module/modules/components/RookStateManager.js.map +1 -0
  44. package/lib/module/modules/hook/useRookAutoSync.js +5 -4
  45. package/lib/module/modules/hook/useRookAutoSync.js.map +1 -1
  46. package/lib/module/modules/hook/useRookEmitter.js +61 -0
  47. package/lib/module/modules/hook/useRookEmitter.js.map +1 -0
  48. package/lib/module/types/AppleHealthNutritionEvent.js +72 -0
  49. package/lib/module/types/AppleHealthNutritionEvent.js.map +1 -0
  50. package/lib/module/types/HCMealData.js +61 -0
  51. package/lib/module/types/HCMealData.js.map +1 -0
  52. package/lib/module/types/WriteNutrition.js +14 -0
  53. package/lib/module/types/WriteNutrition.js.map +1 -0
  54. package/lib/module/utils/isValidDate.js +20 -0
  55. package/lib/module/utils/isValidDate.js.map +1 -1
  56. package/lib/typescript/src/NativeRookSdk.d.ts +622 -33
  57. package/lib/typescript/src/NativeRookSdk.d.ts.map +1 -1
  58. package/lib/typescript/src/context/RookSyncGateProvider.d.ts.map +1 -1
  59. package/lib/typescript/src/context/RookSyncGateReducer.d.ts.map +1 -1
  60. package/lib/typescript/src/context/RookSyncGateTypes.d.ts +14 -4
  61. package/lib/typescript/src/context/RookSyncGateTypes.d.ts.map +1 -1
  62. package/lib/typescript/src/hooks/useRookConfiguration.d.ts +3 -1
  63. package/lib/typescript/src/hooks/useRookConfiguration.d.ts.map +1 -1
  64. package/lib/typescript/src/hooks/useRookData.d.ts +2 -2
  65. package/lib/typescript/src/hooks/useRookData.d.ts.map +1 -1
  66. package/lib/typescript/src/hooks/useRookPermissions.d.ts +2 -0
  67. package/lib/typescript/src/hooks/useRookPermissions.d.ts.map +1 -1
  68. package/lib/typescript/src/hooks/useRookVariables.d.ts +2 -0
  69. package/lib/typescript/src/hooks/useRookVariables.d.ts.map +1 -1
  70. package/lib/typescript/src/modules/components/RookStateManager.d.ts +10 -0
  71. package/lib/typescript/src/modules/components/RookStateManager.d.ts.map +1 -0
  72. package/lib/typescript/src/modules/hook/useRookAutoSync.d.ts.map +1 -1
  73. package/lib/typescript/src/modules/hook/useRookEmitter.d.ts +4 -0
  74. package/lib/typescript/src/modules/hook/useRookEmitter.d.ts.map +1 -0
  75. package/lib/typescript/src/types/AppleHealthNutritionEvent.d.ts +76 -0
  76. package/lib/typescript/src/types/AppleHealthNutritionEvent.d.ts.map +1 -0
  77. package/lib/typescript/src/types/HCMealData.d.ts +60 -0
  78. package/lib/typescript/src/types/HCMealData.d.ts.map +1 -0
  79. package/lib/typescript/src/types/WriteNutrition.d.ts +61 -0
  80. package/lib/typescript/src/types/WriteNutrition.d.ts.map +1 -0
  81. package/lib/typescript/src/utils/isValidDate.d.ts +8 -0
  82. package/lib/typescript/src/utils/isValidDate.d.ts.map +1 -1
  83. package/package.json +1 -1
  84. package/src/NativeRookSdk.ts +682 -117
  85. package/src/context/RookSyncGateProvider.tsx +20 -16
  86. package/src/context/RookSyncGateReducer.ts +6 -2
  87. package/src/context/RookSyncGateTypes.ts +9 -3
  88. package/src/hooks/useRookConfiguration.ts +26 -2
  89. package/src/hooks/useRookData.ts +18 -7
  90. package/src/hooks/useRookPermissions.ts +16 -0
  91. package/src/hooks/useRookSync.ts +1 -1
  92. package/src/hooks/useRookVariables.ts +22 -1
  93. package/src/modules/components/RookStateManager.tsx +41 -0
  94. package/src/modules/hook/useRookAutoSync.ts +6 -4
  95. package/src/modules/hook/useRookEmitter.ts +94 -0
  96. package/src/types/AppleHealthNutritionEvent.ts +142 -0
  97. package/src/types/HCMealData.ts +114 -0
  98. package/src/types/WriteNutrition.ts +66 -0
  99. package/src/utils/isValidDate.ts +24 -0
@@ -0,0 +1,62 @@
1
+ package com.rooksdk.broadcasts
2
+
3
+ import android.content.BroadcastReceiver
4
+ import android.content.Context
5
+ import android.content.Intent
6
+ import com.facebook.react.bridge.Arguments
7
+ import com.facebook.react.bridge.ReactApplicationContext
8
+ import com.facebook.react.bridge.ReadableMap
9
+ import com.rookmotion.rook.sdk.RookPermissionsManager
10
+
11
+ /**
12
+ * AndroidPermissionsReceiverTransmitter is a custom BroadcastReceiver used to listen for updates
13
+ * on Android permission changes and transmit them back to the React Native layer.
14
+ * It listens for a broadcast containing permission status, then emits a corresponding event to JavaScript.
15
+ */
16
+ class AndroidPermissionsReceiverTransmitter: BroadcastReceiver() {
17
+ var onActionReceived: ((ReadableMap) -> Unit)? = null
18
+ private var reactApplicationContext: ReactApplicationContext? = null
19
+
20
+ /**
21
+ * This method is called when a broadcast is received.
22
+ * It checks whether the broadcast includes the permission status and emits an event to the React Native
23
+ * JavaScript layer with the results.
24
+ *
25
+ * @param context The context in which the receiver is running.
26
+ * @param intent The intent containing permission-related data.
27
+ */
28
+ override fun onReceive(context: Context?, intent: Intent?) {
29
+ val permissionsGranted = intent?.getBooleanExtra(
30
+ /* name = */ RookPermissionsManager.EXTRA_ANDROID_PERMISSIONS_GRANTED,
31
+ /* defaultValue = */ false
32
+ ) ?: false
33
+
34
+ val dialogDisplayed = intent?.getBooleanExtra(
35
+ RookPermissionsManager.EXTRA_ANDROID_PERMISSIONS_DIALOG_DISPLAYED,
36
+ false
37
+ ) ?: false
38
+
39
+ if (reactApplicationContext == null || reactApplicationContext?.hasReactInstance() == false)
40
+ return
41
+
42
+ val events = listOf(
43
+ "ROOK_BACKGROUND_ANDROID_PERMISSIONS" to permissionsGranted,
44
+ "ROOK_BACKGROUND_ANDROID_PERMISSIONS_DIALOG_DISPLAYED" to dialogDisplayed
45
+ )
46
+
47
+ events.forEach { (type, value) ->
48
+ Arguments.createMap().apply {
49
+ putString("type", type)
50
+ putBoolean("value", value)
51
+ onActionReceived?.invoke(this)
52
+ }
53
+ }
54
+ }
55
+
56
+ fun setConfig(ctx: ReactApplicationContext, emit: (ReadableMap) -> Unit) {
57
+ this.reactApplicationContext = ctx
58
+ this.onActionReceived = emit
59
+ }
60
+
61
+ }
62
+
@@ -0,0 +1,64 @@
1
+ package com.rooksdk.broadcasts
2
+
3
+ import android.content.BroadcastReceiver
4
+ import android.content.Context
5
+ import android.content.Intent
6
+ import com.facebook.react.bridge.Arguments
7
+ import com.facebook.react.bridge.ReactApplicationContext
8
+ import com.facebook.react.bridge.ReadableMap
9
+ import com.rookmotion.rook.sdk.RookPermissionsManager
10
+
11
+ /**
12
+ * HealthConnectPermissionsReceiverTransmitter is a custom BroadcastReceiver used to listen for updates
13
+ * on Android permission changes and transmit them back to the React Native layer.
14
+ * It listens for a broadcast containing permission status, then emits a corresponding event to JavaScript.
15
+ */
16
+ class HealthConnectPermissionsReceiverTransmitter: BroadcastReceiver() {
17
+ var onActionReceived: ((ReadableMap) -> Unit)? = null
18
+ private var reactApplicationContext: ReactApplicationContext? = null
19
+
20
+ /**
21
+ * This method is called when a broadcast is received.
22
+ * It checks whether the broadcast includes the permission status and emits an event to the React Native
23
+ * JavaScript layer with the results.
24
+ *
25
+ * @param context The context in which the receiver is running.
26
+ * @param intent The intent containing permission-related data.
27
+ */
28
+ override fun onReceive(context: Context?, intent: Intent?) {
29
+ val permissionsGranted = intent?.getBooleanExtra(
30
+ /* name = */ RookPermissionsManager.EXTRA_HEALTH_CONNECT_PERMISSIONS_GRANTED,
31
+ /* defaultValue = */ false
32
+ ) ?: false
33
+
34
+ val partiallyGranted = intent?.getBooleanExtra(
35
+ RookPermissionsManager.EXTRA_HEALTH_CONNECT_PERMISSIONS_PARTIALLY_GRANTED,
36
+ false
37
+ ) ?: false
38
+
39
+ val backgroundReadStatus = intent?.getBooleanExtra(
40
+ RookPermissionsManager.EXTRA_HEALTH_CONNECT_BACKGROUND_PERMISSION_GRANTED,
41
+ false
42
+ ) ?: false
43
+
44
+ val events = listOf(
45
+ "ROOK_HEALTH_CONNECT_PERMISSIONS" to permissionsGranted,
46
+ "ROOK_HEALTH_CONNECT_PERMISSIONS_PARTIALLY_GRANTED" to partiallyGranted,
47
+ "ROOK_HEALTH_CONNECT_BACKGROUND_PERMISSIONS" to backgroundReadStatus,
48
+ )
49
+
50
+ events.forEach { (type, value) ->
51
+ Arguments.createMap().apply {
52
+ putString("type", type)
53
+ putBoolean("value", value)
54
+ onActionReceived?.invoke(this)
55
+ }
56
+ }
57
+ }
58
+
59
+ fun setConfig(ctx: ReactApplicationContext,emit: (ReadableMap) -> Unit) {
60
+ this.reactApplicationContext = ctx
61
+ this.onActionReceived = emit
62
+ }
63
+ }
64
+
@@ -0,0 +1,44 @@
1
+ package com.rooksdk.broadcasts
2
+
3
+ import android.content.BroadcastReceiver
4
+ import android.content.Context
5
+ import android.content.Intent
6
+ import com.facebook.react.bridge.Arguments
7
+ import com.facebook.react.bridge.ReactApplicationContext
8
+ import com.facebook.react.bridge.ReadableMap
9
+ import io.tryrook.sdk.samsung.domain.enums.SamsungHealthPermission
10
+ class SamsungHealthPermissionsReceiverTransmitter: BroadcastReceiver() {
11
+ var onActionReceived: ((ReadableMap) -> Unit)? = null
12
+ private var reactApplicationContext: ReactApplicationContext? = null
13
+
14
+ override fun onReceive(conext: Context?, intent: Intent?) {
15
+ val allPermissionsGranted = intent?.getBooleanExtra(
16
+ /* name = */ SamsungHealthPermission.EXTRA_SAMSUNG_HEALTH_PERMISSIONS_GRANTED,
17
+ /* defaultValue = */ false
18
+ ) ?: false
19
+
20
+ val permissionsPartiallyGranted = intent?.getBooleanExtra(
21
+ /* name = */ SamsungHealthPermission.EXTRA_SAMSUNG_HEALTH_PERMISSIONS_PARTIALLY_GRANTED,
22
+ /* defaultValue = */ false
23
+ ) ?: false
24
+
25
+ val events = listOf(
26
+ "ROOK_SAMSUNG_HEALTH_PERMISSIONS" to allPermissionsGranted,
27
+ "ROOK_SAMSUNG_HEALTH_PERMISSIONS_PARTIALLY_GRANTED" to permissionsPartiallyGranted,
28
+ )
29
+
30
+ events.forEach { (type, value) ->
31
+ Arguments.createMap().apply {
32
+ putString("type", type)
33
+ putBoolean("value", value)
34
+ onActionReceived?.invoke(this)
35
+ }
36
+ }
37
+ }
38
+
39
+ fun setConfig(ctx: ReactApplicationContext, emit: (ReadableMap) -> Unit) {
40
+ this.reactApplicationContext = ctx
41
+ this.onActionReceived = emit
42
+ }
43
+ }
44
+
@@ -0,0 +1,35 @@
1
+ package com.rooksdk.utils
2
+
3
+ import com.facebook.react.bridge.ReadableArray
4
+ import io.tryrook.api.sources.domain.enums.DataSourceType
5
+
6
+ object DatasourceUtils {
7
+
8
+ /**
9
+ * Maps a data source string to its corresponding DataSourceType enum.
10
+ * @param source The data source name as a string (e.g., "Garmin", "Fitbit").
11
+ * @return The corresponding DataSourceType enum or null if the string does not match.
12
+ */
13
+ fun mapToDataSourceType(source: String): DataSourceType? {
14
+ return try {
15
+ DataSourceType.valueOf(source.uppercase())
16
+ } catch (e: IllegalArgumentException) {
17
+ null
18
+ }
19
+ }
20
+
21
+ fun readableArrayToSourceList(sources: ReadableArray): List<Source> {
22
+ val rawList = sources.toArrayList()
23
+
24
+ return rawList
25
+ .mapNotNull { it as? String }
26
+ .mapNotNull {
27
+ try {
28
+ Source.valueOf(it)
29
+ } catch (e: IllegalArgumentException) {
30
+ null
31
+ }
32
+ }
33
+ }
34
+ }
35
+
@@ -0,0 +1,21 @@
1
+ package com.rooksdk.utils
2
+
3
+ import com.facebook.react.bridge.ReadableArray
4
+ import io.tryrook.sdk.samsung.domain.enums.SamsungHealthPermission
5
+
6
+ object PermissionConversion {
7
+
8
+ fun parseSamsungPermissions(rawPermissions: ReadableArray): Set<SamsungHealthPermission> {
9
+ val rawList = rawPermissions.toArrayList()
10
+
11
+ return rawList
12
+ .mapNotNull { it as? String }
13
+ .mapNotNull {
14
+ try {
15
+ SamsungHealthPermission.valueOf(it)
16
+ } catch (e: IllegalArgumentException) {
17
+ null
18
+ }
19
+ }.toSet()
20
+ }
21
+ }
@@ -0,0 +1,144 @@
1
+ package com.rooksdk.utils
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.ReadableMap
5
+ import com.facebook.react.bridge.ReadableType
6
+ import com.facebook.react.bridge.WritableMap
7
+ import com.rookmotion.rook.sdk.domain.enums.HCNutritionInsertionEventType
8
+ import com.rookmotion.rook.sdk.domain.model.HCNutritionInsertionEvent
9
+ import java.time.ZonedDateTime
10
+
11
+ /**
12
+ * ReadableToWritable is a utility object that provides methods to convert between
13
+ * React Native's ReadableMap and WritableMap, and Kotlin's HashMap.
14
+ * This is useful when you need to transform data between JavaScript and native code.
15
+ */
16
+ object ReadableToWritable {
17
+
18
+ /**
19
+ * Converts a ReadableMap (from JavaScript/React Native) to a HashMap (native Kotlin data structure).
20
+ * It iterates through all the keys in the ReadableMap and converts its values based on their type.
21
+ *
22
+ * @param readableMap The ReadableMap to convert.
23
+ * @return A HashMap<String, Any> with equivalent values.
24
+ */
25
+ fun readableMapToHashMap(readableMap: ReadableMap): HashMap<String, Any> {
26
+ val map = HashMap<String, Any>()
27
+ val iterator = readableMap.keySetIterator()
28
+
29
+ while (iterator.hasNextKey()) {
30
+ val key = iterator.nextKey()
31
+ when (readableMap.getType(key)) {
32
+ ReadableType.Boolean -> map[key] = readableMap.getBoolean(key)
33
+ ReadableType.Number -> map[key] = readableMap.getDouble(key)
34
+ ReadableType.String -> map[key] = readableMap.getString(key) ?: ""
35
+ ReadableType.Map -> map[key] = readableMapToHashMap(readableMap.getMap(key)!!)
36
+ ReadableType.Array -> map[key] = readableMap.getArray(key)!!.toArrayList()
37
+ else -> {} // Manejar otros tipos si es necesario
38
+ }
39
+ }
40
+
41
+ return map
42
+ }
43
+
44
+ /**
45
+ * Converts a HashMap (native Kotlin data structure) to a WritableMap (to be sent to JavaScript/React Native).
46
+ * It iterates through all the entries in the HashMap and converts its values based on their type.
47
+ *
48
+ * @param hashMap The HashMap<String, Any> to convert.
49
+ * @return A WritableMap with equivalent values.
50
+ */
51
+ fun hashMapToWritableMap(hashMap: HashMap<String, Any>): WritableMap {
52
+ val writableMap = Arguments.createMap()
53
+
54
+ for ((key, value) in hashMap) {
55
+ when (value) {
56
+ is Boolean -> writableMap.putBoolean(key, value)
57
+ is Double -> writableMap.putDouble(key, value)
58
+ is String -> writableMap.putString(key, value)
59
+ is HashMap<*, *> -> writableMap.putMap(key, hashMapToWritableMap(value as HashMap<String, Any>))
60
+ is ArrayList<*> -> writableMap.putArray(key, Arguments.fromArray(value))
61
+ }
62
+ }
63
+
64
+ return writableMap
65
+ }
66
+
67
+ fun mapReadableMapToHCMealData(map: ReadableMap): HCNutritionInsertionEvent {
68
+ // Helper for micro-nutrients: range [0.0, 100.0]
69
+ fun getGramValue(key: String): Double? {
70
+ return if (map.hasKey(key) && !map.isNull(key)) {
71
+ map.getDouble(key).takeIf { it in 0.0..100.0 }
72
+ } else null
73
+ }
74
+
75
+ // Helper for energy and macronutrients: range [0.0, 100,000.0]
76
+ fun getLargeValue(key: String): Double? {
77
+ return if (map.hasKey(key) && !map.isNull(key)) {
78
+ map.getDouble(key).takeIf { it in 0.0..100000.0 }
79
+ } else null
80
+ }
81
+
82
+ val typeString = if (map.hasKey("type")) map.getString("type") else null
83
+ val mealType = when (typeString?.uppercase()) {
84
+ "BREAKFAST" -> HCNutritionInsertionEventType.BREAKFAST
85
+ "LUNCH" -> HCNutritionInsertionEventType.LUNCH
86
+ "DINNER" -> HCNutritionInsertionEventType.DINNER
87
+ "SNACK" -> HCNutritionInsertionEventType.SNACK
88
+ else -> HCNutritionInsertionEventType.SNACK // Default fallback
89
+ }
90
+
91
+ return HCNutritionInsertionEvent(
92
+ startDateTime = ZonedDateTime.parse(map.getString("startDateTime")),
93
+ endDateTime = ZonedDateTime.parse(map.getString("endDateTime")),
94
+ name = map.getString("name") ?: "Meal",
95
+ type = mealType,
96
+
97
+ // Energy & Macros (0 to 100,000 range)
98
+ energyKcal = getLargeValue("energyKcal"),
99
+ energyFromFatKcal = getLargeValue("energyFromFatKcal"),
100
+ dietaryFiberGrams = getLargeValue("dietaryFiberGrams"),
101
+ monounsaturatedFatGrams = getLargeValue("monounsaturatedFatGrams"),
102
+ polyunsaturatedFatGrams = getLargeValue("polyunsaturatedFatGrams"),
103
+ proteinGrams = getLargeValue("proteinGrams"),
104
+ saturatedFatGrams = getLargeValue("saturatedFatGrams"),
105
+ sugarGrams = getLargeValue("sugarGrams"),
106
+ totalCarbohydrateGrams = getLargeValue("totalCarbohydrateGrams"),
107
+ totalFatGrams = getLargeValue("totalFatGrams"),
108
+ transFatGrams = getLargeValue("transFatGrams"),
109
+ unsaturatedFatGrams = getLargeValue("unsaturatedFatGrams"),
110
+
111
+ // Micro-nutrients & Minerals (0 to 100 range)
112
+ biotinGrams = getGramValue("biotinGrams"),
113
+ caffeineGrams = getGramValue("caffeineGrams"),
114
+ calciumGrams = getGramValue("calciumGrams"),
115
+ chlorideGrams = getGramValue("chlorideGrams"),
116
+ cholesterolGrams = getGramValue("cholesterolGrams"),
117
+ chromiumGrams = getGramValue("chromiumGrams"),
118
+ copperGrams = getGramValue("copperGrams"),
119
+ folateGrams = getGramValue("folateGrams"),
120
+ folicAcidGrams = getGramValue("folicAcidGrams"),
121
+ iodineGrams = getGramValue("iodineGrams"),
122
+ ironGrams = getGramValue("ironGrams"),
123
+ magnesiumGrams = getGramValue("magnesiumGrams"),
124
+ manganeseGrams = getGramValue("manganeseGrams"),
125
+ molybdenumGrams = getGramValue("molybdenumGrams"),
126
+ niacinGrams = getGramValue("niacinGrams"),
127
+ pantothenicAcidGrams = getGramValue("pantothenicAcidGrams"),
128
+ phosphorusGrams = getGramValue("phosphorusGrams"),
129
+ potassiumGrams = getGramValue("potassiumGrams"),
130
+ riboflavinGrams = getGramValue("riboflavinGrams"),
131
+ seleniumGrams = getGramValue("seleniumGrams"),
132
+ sodiumGrams = getGramValue("sodiumGrams"),
133
+ thiaminGrams = getGramValue("thiaminGrams"),
134
+ vitaminAGrams = getGramValue("vitaminAGrams"),
135
+ vitaminB12Grams = getGramValue("vitaminB12Grams"),
136
+ vitaminB6Grams = getGramValue("vitaminB6Grams"),
137
+ vitaminCGrams = getGramValue("vitaminCGrams"),
138
+ vitaminDGrams = getGramValue("vitaminDGrams"),
139
+ vitaminEGrams = getGramValue("vitaminEGrams"),
140
+ vitaminKGrams = getGramValue("vitaminKGrams"),
141
+ zincGrams = getGramValue("zincGrams")
142
+ )
143
+ }
144
+ }
@@ -0,0 +1,26 @@
1
+ package com.rooksdk.utils
2
+
3
+ import java.time.LocalDate
4
+ import java.time.ZonedDateTime
5
+ import java.time.format.DateTimeFormatter
6
+
7
+ /**
8
+ * RookDateTime is a utility object for handling date-related operations.
9
+ * It provides methods to format and parse dates using the ISO_LOCAL_DATE format.
10
+ */
11
+ object RookDateTime {
12
+ private val rookDateFormatter: DateTimeFormatter get() = DateTimeFormatter.ISO_LOCAL_DATE
13
+ private val rookZonedDateTimeFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME
14
+
15
+ /**
16
+ * A DateTimeFormatter using the ISO_LOCAL_DATE pattern (e.g., "YYYY-MM-DD").
17
+ * It formats or parses dates in the standard ISO 8601 format.
18
+ */
19
+ fun stringToLocalDate(string: String): LocalDate {
20
+ return LocalDate.parse(string, rookDateFormatter)
21
+ }
22
+
23
+ fun stringToZonedDateTime(string: String): ZonedDateTime {
24
+ return ZonedDateTime.parse(string, rookZonedDateTimeFormatter)
25
+ }
26
+ }
@@ -0,0 +1,20 @@
1
+ package com.rooksdk.utils
2
+
3
+ import com.google.gson.Gson
4
+ import com.google.gson.GsonBuilder
5
+ import com.rooksdk.utils.serializers.InstantSerializer
6
+ import com.rooksdk.utils.serializers.LocalDateSerializer
7
+ import com.rooksdk.utils.serializers.ZonedDateTimeAdapter
8
+ import java.time.Instant
9
+ import java.time.LocalDate
10
+ import java.time.ZonedDateTime
11
+
12
+ object RookGsonBuilder {
13
+ fun getGsonBuilder(): Gson {
14
+ return GsonBuilder()
15
+ .registerTypeAdapter(Instant::class.java, InstantSerializer())
16
+ .registerTypeAdapter(LocalDate::class.java, LocalDateSerializer())
17
+ .registerTypeAdapter(ZonedDateTime::class.java, ZonedDateTimeAdapter())
18
+ .create()
19
+ }
20
+ }
@@ -0,0 +1,22 @@
1
+ package com.rooksdk.utils
2
+
3
+ import io.tryrook.sdk.samsung.RookSamsung
4
+ import io.tryrook.sdk.samsung.domain.enums.SamsungHealthAvailability
5
+
6
+ object SamsungAvailability {
7
+ suspend fun getSamsungHealthAvailabilityOrDefault(rookSamsung: RookSamsung): SamsungHealthAvailability {
8
+ val result = rookSamsung.checkSamsungHealthAvailability()
9
+ val defaultValue = SamsungHealthAvailability.NOT_INSTALLED
10
+
11
+ return result.getOrDefault(defaultValue)
12
+ }
13
+ suspend fun isSamsungAvailable(rookSamsung: RookSamsung): Boolean {
14
+ val result = rookSamsung.checkSamsungHealthAvailability()
15
+ val defaultValue = SamsungHealthAvailability.NOT_INSTALLED
16
+
17
+ val availability = result.getOrDefault(defaultValue)
18
+
19
+ return availability == SamsungHealthAvailability.INSTALLED
20
+ }
21
+ }
22
+
@@ -0,0 +1,6 @@
1
+ package com.rooksdk.utils
2
+
3
+ enum class Source{
4
+ HEALTH_CONNECT,
5
+ SAMSUNG_HEALTH
6
+ }
@@ -0,0 +1,41 @@
1
+ package com.rooksdk.utils
2
+
3
+ import com.rookmotion.rook.sdk.domain.model.SyncType
4
+ import io.tryrook.sdk.samsung.domain.model.SHSyncType
5
+
6
+ object StringToSyncType {
7
+
8
+ fun stringToSummary(type: String): SyncType.Summary {
9
+ return when(type.lowercase()) {
10
+ "sleep" -> SyncType.Summary.SLEEP
11
+ "body" -> SyncType.Summary.BODY
12
+ "physical" -> SyncType.Summary.PHYSICAL
13
+ else -> SyncType.Summary.BODY
14
+ }
15
+ }
16
+
17
+ fun stringToEvent(value: String): SyncType.Event {
18
+ return try {
19
+ SyncType.Event.valueOf(value)
20
+ } catch (e: IllegalArgumentException) {
21
+ SyncType.Event.STEPS
22
+ }
23
+ }
24
+
25
+ fun stringToSamsungPillar(value: String): SHSyncType.Summary {
26
+ return when(value.lowercase()) {
27
+ "sleep" -> SHSyncType.Summary.SLEEP
28
+ "body" -> SHSyncType.Summary.BODY
29
+ "physical" -> SHSyncType.Summary.PHYSICAL
30
+ else -> SHSyncType.Summary.BODY
31
+ }
32
+ }
33
+
34
+ fun stringToSamsungEvent(value: String): SHSyncType.Event {
35
+ return try {
36
+ SHSyncType.Event.valueOf(value)
37
+ } catch (e: IllegalArgumentException) {
38
+ SHSyncType.Event.STEPS
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,18 @@
1
+ package com.rooksdk.utils.serializers
2
+
3
+ import com.google.gson.JsonElement
4
+ import com.google.gson.JsonPrimitive
5
+ import com.google.gson.JsonSerializationContext
6
+ import com.google.gson.JsonSerializer
7
+ import java.time.Instant
8
+ import java.lang.reflect.Type
9
+
10
+ class InstantSerializer : JsonSerializer<Instant> {
11
+ override fun serialize(
12
+ src: Instant?,
13
+ typeOfSrc: Type?,
14
+ context: JsonSerializationContext?
15
+ ): JsonElement {
16
+ return JsonPrimitive(src?.toString())
17
+ }
18
+ }
@@ -0,0 +1,21 @@
1
+ package com.rooksdk.utils.serializers
2
+
3
+ import com.google.gson.JsonElement
4
+ import com.google.gson.JsonPrimitive
5
+ import com.google.gson.JsonSerializationContext
6
+ import com.google.gson.JsonSerializer
7
+ import java.lang.reflect.Type
8
+ import java.time.LocalDate
9
+ import java.time.format.DateTimeFormatter
10
+
11
+ class LocalDateSerializer : JsonSerializer<LocalDate> {
12
+ private val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
13
+
14
+ override fun serialize(
15
+ src: LocalDate?,
16
+ typeOfSrc: Type?,
17
+ context: JsonSerializationContext?
18
+ ): JsonElement {
19
+ return JsonPrimitive(src?.format(formatter))
20
+ }
21
+ }
@@ -0,0 +1,18 @@
1
+ package com.rooksdk.utils.serializers
2
+
3
+ import com.google.gson.*
4
+ import java.lang.reflect.Type
5
+ import java.time.ZonedDateTime
6
+ import java.time.format.DateTimeFormatter
7
+
8
+ class ZonedDateTimeAdapter : JsonSerializer<ZonedDateTime>, JsonDeserializer<ZonedDateTime> {
9
+ private val formatter = DateTimeFormatter.ISO_ZONED_DATE_TIME
10
+
11
+ override fun serialize(src: ZonedDateTime, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
12
+ return JsonPrimitive(formatter.format(src))
13
+ }
14
+
15
+ override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): ZonedDateTime {
16
+ return ZonedDateTime.parse(json.asString, formatter)
17
+ }
18
+ }
@@ -0,0 +1,95 @@
1
+ //
2
+ // EncodableSDKState.swift
3
+ // RNRookSdk
4
+ //
5
+ // Created by Javier Villanueva on 07/04/26.
6
+ //
7
+
8
+ import Foundation
9
+ import RookSDK
10
+
11
+ private struct DateTransformer {
12
+ static let localFormatter: DateFormatter = {
13
+ let formatter = DateFormatter()
14
+ // Use a standard ISO-like format or customize as needed
15
+ formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
16
+ formatter.timeZone = .current // Explicitly set to the device's local timezone
17
+ return formatter
18
+ }()
19
+
20
+ static func string(from date: Date?) -> String? {
21
+ guard let date = date else { return nil }
22
+ return localFormatter.string(from: date)
23
+ }
24
+ }
25
+
26
+ public struct EncodableSDKState: Encodable {
27
+
28
+ private let state: RookSDK.SDKState
29
+
30
+ public init(_ state: RookSDK.SDKState) {
31
+ self.state = state
32
+ }
33
+
34
+ private enum CodingKeys: String, CodingKey {
35
+ case isConfigured
36
+ case userIdentified
37
+ case permissions
38
+ case backgroundSync
39
+ case manualSync
40
+ }
41
+
42
+ public func encode(to encoder: Encoder) throws {
43
+ var container = encoder.container(keyedBy: CodingKeys.self)
44
+
45
+ try container.encode(state.isConfigured, forKey: .isConfigured)
46
+ try container.encode(state.userIdentified, forKey: .userIdentified)
47
+ try container.encode(state.permissions, forKey: .permissions)
48
+
49
+ // Wrap nested structs to ensure they use their own encoding logic
50
+ try container.encode(EncodableSDKBackgroundState(state.backgroundSync), forKey: .backgroundSync)
51
+ try container.encode(EncodableSDKManualSyncState(state.manualSync), forKey: .manualSync)
52
+ }
53
+ }
54
+
55
+ // MARK: - Nested Wrappers
56
+
57
+ struct EncodableSDKBackgroundState: Encodable {
58
+ private let backgroundState: RookSDK.SDKBackgroundState
59
+ private let formatter = ISO8601DateFormatter()
60
+
61
+ init(_ backgroundState: RookSDK.SDKBackgroundState) {
62
+ self.backgroundState = backgroundState
63
+ }
64
+
65
+ private enum CodingKeys: String, CodingKey {
66
+ case enabled, lastSync
67
+ }
68
+
69
+ func encode(to encoder: Encoder) throws {
70
+ var container = encoder.container(keyedBy: CodingKeys.self)
71
+ try container.encode(backgroundState.enabled, forKey: .enabled)
72
+
73
+ try container.encode(DateTransformer.string(from: backgroundState.lastSync), forKey: .lastSync)
74
+ }
75
+ }
76
+
77
+ struct EncodableSDKManualSyncState: Encodable {
78
+ private let manualState: RookSDK.SDKManualSyncState
79
+ private let formatter = ISO8601DateFormatter()
80
+
81
+ init(_ manualState: RookSDK.SDKManualSyncState) {
82
+ self.manualState = manualState
83
+ }
84
+
85
+ private enum CodingKeys: String, CodingKey {
86
+ case enabled, lastSync
87
+ }
88
+
89
+ func encode(to encoder: Encoder) throws {
90
+ var container = encoder.container(keyedBy: CodingKeys.self)
91
+ try container.encode(manualState.enabled, forKey: .enabled)
92
+
93
+ try container.encode(DateTransformer.string(from: manualState.lastSync), forKey: .lastSync)
94
+ }
95
+ }