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.
- package/RNRookSdk.podspec +1 -1
- package/android/build.gradle +6 -0
- package/android/src/main/java/com/rooksdk/RookSdkModule.kt +1850 -6
- package/android/src/main/java/com/rooksdk/broadcasts/AndroidPermissionsReceiverTransmitter.kt +62 -0
- package/android/src/main/java/com/rooksdk/broadcasts/HealthConnectPermissionsReceiverTransmitter.kt +64 -0
- package/android/src/main/java/com/rooksdk/broadcasts/SamsungHealthPermissionsReceiverTransmitter.kt +44 -0
- package/android/src/main/java/com/rooksdk/utils/DatasourceUtils.kt +35 -0
- package/android/src/main/java/com/rooksdk/utils/PermissionConvertions.kt +21 -0
- package/android/src/main/java/com/rooksdk/utils/ReadableToWritable.kt +144 -0
- package/android/src/main/java/com/rooksdk/utils/RookDateTime.kt +26 -0
- package/android/src/main/java/com/rooksdk/utils/RookGsonBuilder.kt +20 -0
- package/android/src/main/java/com/rooksdk/utils/SamsungAvailability.kt +22 -0
- package/android/src/main/java/com/rooksdk/utils/Source.kt +6 -0
- package/android/src/main/java/com/rooksdk/utils/StringToSyncType.kt +41 -0
- package/android/src/main/java/com/rooksdk/utils/serializers/InstantSerializer.kt +18 -0
- package/android/src/main/java/com/rooksdk/utils/serializers/LocalDateSerializer.kt +21 -0
- package/android/src/main/java/com/rooksdk/utils/serializers/ZoneDateTimeSerializer.kt +18 -0
- package/ios/EncodableSDKState.swift +95 -0
- package/ios/NutritionMapper.swift +114 -0
- package/ios/RookConfiguration.swift +13 -0
- package/ios/RookData.swift +29 -0
- package/ios/RookEntry.swift +5 -4
- package/ios/RookPermissions.swift +33 -9
- package/ios/RookSdk.h +1 -13
- package/ios/RookSdk.mm +44 -237
- package/lib/module/NativeRookSdk.js +98 -10
- package/lib/module/NativeRookSdk.js.map +1 -1
- package/lib/module/context/RookSyncGateProvider.js +29 -21
- package/lib/module/context/RookSyncGateProvider.js.map +1 -1
- package/lib/module/context/RookSyncGateReducer.js +12 -2
- package/lib/module/context/RookSyncGateReducer.js.map +1 -1
- package/lib/module/hooks/useRookConfiguration.js +20 -1
- package/lib/module/hooks/useRookConfiguration.js.map +1 -1
- package/lib/module/hooks/useRookData.js +13 -4
- package/lib/module/hooks/useRookData.js.map +1 -1
- package/lib/module/hooks/useRookPermissions.js +13 -1
- package/lib/module/hooks/useRookPermissions.js.map +1 -1
- package/lib/module/hooks/useRookSync.js +1 -1
- package/lib/module/hooks/useRookSync.js.map +1 -1
- package/lib/module/hooks/useRookVariables.js +16 -1
- package/lib/module/hooks/useRookVariables.js.map +1 -1
- package/lib/module/modules/components/RookStateManager.js +31 -0
- package/lib/module/modules/components/RookStateManager.js.map +1 -0
- package/lib/module/modules/hook/useRookAutoSync.js +5 -4
- package/lib/module/modules/hook/useRookAutoSync.js.map +1 -1
- package/lib/module/modules/hook/useRookEmitter.js +61 -0
- package/lib/module/modules/hook/useRookEmitter.js.map +1 -0
- package/lib/module/types/AppleHealthNutritionEvent.js +72 -0
- package/lib/module/types/AppleHealthNutritionEvent.js.map +1 -0
- package/lib/module/types/HCMealData.js +61 -0
- package/lib/module/types/HCMealData.js.map +1 -0
- package/lib/module/types/WriteNutrition.js +14 -0
- package/lib/module/types/WriteNutrition.js.map +1 -0
- package/lib/module/utils/isValidDate.js +20 -0
- package/lib/module/utils/isValidDate.js.map +1 -1
- package/lib/typescript/src/NativeRookSdk.d.ts +622 -33
- package/lib/typescript/src/NativeRookSdk.d.ts.map +1 -1
- package/lib/typescript/src/context/RookSyncGateProvider.d.ts.map +1 -1
- package/lib/typescript/src/context/RookSyncGateReducer.d.ts.map +1 -1
- package/lib/typescript/src/context/RookSyncGateTypes.d.ts +14 -4
- package/lib/typescript/src/context/RookSyncGateTypes.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useRookConfiguration.d.ts +3 -1
- package/lib/typescript/src/hooks/useRookConfiguration.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useRookData.d.ts +2 -2
- package/lib/typescript/src/hooks/useRookData.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useRookPermissions.d.ts +2 -0
- package/lib/typescript/src/hooks/useRookPermissions.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useRookVariables.d.ts +2 -0
- package/lib/typescript/src/hooks/useRookVariables.d.ts.map +1 -1
- package/lib/typescript/src/modules/components/RookStateManager.d.ts +10 -0
- package/lib/typescript/src/modules/components/RookStateManager.d.ts.map +1 -0
- package/lib/typescript/src/modules/hook/useRookAutoSync.d.ts.map +1 -1
- package/lib/typescript/src/modules/hook/useRookEmitter.d.ts +4 -0
- package/lib/typescript/src/modules/hook/useRookEmitter.d.ts.map +1 -0
- package/lib/typescript/src/types/AppleHealthNutritionEvent.d.ts +76 -0
- package/lib/typescript/src/types/AppleHealthNutritionEvent.d.ts.map +1 -0
- package/lib/typescript/src/types/HCMealData.d.ts +60 -0
- package/lib/typescript/src/types/HCMealData.d.ts.map +1 -0
- package/lib/typescript/src/types/WriteNutrition.d.ts +61 -0
- package/lib/typescript/src/types/WriteNutrition.d.ts.map +1 -0
- package/lib/typescript/src/utils/isValidDate.d.ts +8 -0
- package/lib/typescript/src/utils/isValidDate.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/NativeRookSdk.ts +682 -117
- package/src/context/RookSyncGateProvider.tsx +20 -16
- package/src/context/RookSyncGateReducer.ts +6 -2
- package/src/context/RookSyncGateTypes.ts +9 -3
- package/src/hooks/useRookConfiguration.ts +26 -2
- package/src/hooks/useRookData.ts +18 -7
- package/src/hooks/useRookPermissions.ts +16 -0
- package/src/hooks/useRookSync.ts +1 -1
- package/src/hooks/useRookVariables.ts +22 -1
- package/src/modules/components/RookStateManager.tsx +41 -0
- package/src/modules/hook/useRookAutoSync.ts +6 -4
- package/src/modules/hook/useRookEmitter.ts +94 -0
- package/src/types/AppleHealthNutritionEvent.ts +142 -0
- package/src/types/HCMealData.ts +114 -0
- package/src/types/WriteNutrition.ts +66 -0
- 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
|
+
|
package/android/src/main/java/com/rooksdk/broadcasts/HealthConnectPermissionsReceiverTransmitter.kt
ADDED
|
@@ -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
|
+
|
package/android/src/main/java/com/rooksdk/broadcasts/SamsungHealthPermissionsReceiverTransmitter.kt
ADDED
|
@@ -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,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
|
+
}
|