react-native-rook-sdk 2.0.3 → 2.1.0-rc.1
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/src/main/java/com/rooksdk/RookSdkPackage.kt +3 -1
- package/android/src/main/java/com/rooksdk/modules/RookLocalData.kt +247 -0
- package/android/src/main/java/com/rooksdk/modules/RookSyncModule.kt +17 -1
- package/android/src/main/java/com/rooksdk/utils/serializers/InstantSerializer.kt +19 -0
- package/android/src/main/java/com/rooksdk/utils/serializers/LocalDateSerializer.kt +21 -0
- package/ios/EncodableDataSource.swift +32 -0
- package/ios/EncodableDataSourceAuthorizer.swift +32 -0
- package/ios/EncodableRookDataSource.swift +36 -0
- package/ios/EncodableStatusDataSources.swift +47 -0
- package/ios/RookExternalModule.h +5 -0
- package/ios/RookExternalModule.m +27 -0
- package/ios/RookLocalData.swift +152 -0
- package/ios/RookSdk.mm +1 -0
- package/ios/RookSources.swift +148 -0
- package/ios/RookSourcesModule.mm +29 -98
- package/ios/RookSync.h +5 -0
- package/ios/RookSync.m +27 -0
- package/ios/RookSync.swift +135 -0
- package/ios/RookSyncModule.h +1 -1
- package/ios/RookSyncModule.mm +10 -5
- package/ios/SwiftTest.swift +18 -0
- package/ios/react-native-rook-sdk-Bridging-Header.h +12 -0
- package/lib/commonjs/hooks/index.js +7 -0
- package/lib/commonjs/hooks/index.js.map +1 -1
- package/lib/commonjs/hooks/useRookData.js +100 -0
- package/lib/commonjs/hooks/useRookData.js.map +1 -0
- package/lib/commonjs/hooks/useRookDataSources.js +17 -6
- package/lib/commonjs/hooks/useRookDataSources.js.map +1 -1
- package/lib/commonjs/hooks/useRookSync.js +1 -1
- package/lib/commonjs/hooks/useRookSync.js.map +1 -1
- package/lib/commonjs/types/ActivityEvent.js +6 -0
- package/lib/commonjs/types/ActivityEvent.js.map +1 -0
- package/lib/commonjs/types/BodySummary.js +6 -0
- package/lib/commonjs/types/BodySummary.js.map +1 -0
- package/lib/commonjs/types/PhysicalSummary.js +6 -0
- package/lib/commonjs/types/PhysicalSummary.js.map +1 -0
- package/lib/commonjs/types/SleepSummary.js +6 -0
- package/lib/commonjs/types/SleepSummary.js.map +1 -0
- package/lib/commonjs/types/SummaryTypes.js +2 -0
- package/lib/commonjs/types/SummaryTypes.js.map +1 -0
- package/lib/commonjs/utils/getNativeModule.js +1 -1
- package/lib/commonjs/utils/getNativeModule.js.map +1 -1
- package/lib/commonjs/utils/nativeModules.js +5 -2
- package/lib/commonjs/utils/nativeModules.js.map +1 -1
- package/lib/module/hooks/index.js +1 -0
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/hooks/useRookData.js +92 -0
- package/lib/module/hooks/useRookData.js.map +1 -0
- package/lib/module/hooks/useRookDataSources.js +17 -6
- package/lib/module/hooks/useRookDataSources.js.map +1 -1
- package/lib/module/hooks/useRookSync.js +1 -1
- package/lib/module/hooks/useRookSync.js.map +1 -1
- package/lib/module/types/ActivityEvent.js +2 -0
- package/lib/module/types/ActivityEvent.js.map +1 -0
- package/lib/module/types/BodySummary.js +2 -0
- package/lib/module/types/BodySummary.js.map +1 -0
- package/lib/module/types/PhysicalSummary.js +2 -0
- package/lib/module/types/PhysicalSummary.js.map +1 -0
- package/lib/module/types/SleepSummary.js +2 -0
- package/lib/module/types/SleepSummary.js.map +1 -0
- package/lib/module/types/SummaryTypes.js +2 -0
- package/lib/module/types/SummaryTypes.js.map +1 -0
- package/lib/module/utils/getNativeModule.js +1 -1
- package/lib/module/utils/getNativeModule.js.map +1 -1
- package/lib/module/utils/nativeModules.js +5 -2
- package/lib/module/utils/nativeModules.js.map +1 -1
- package/lib/typescript/src/hooks/index.d.ts +1 -0
- package/lib/typescript/src/hooks/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useRookData.d.ts +18 -0
- package/lib/typescript/src/hooks/useRookData.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useRookDataSources.d.ts +2 -1
- package/lib/typescript/src/hooks/useRookDataSources.d.ts.map +1 -1
- package/lib/typescript/src/types/ActivityEvent.d.ts +137 -0
- package/lib/typescript/src/types/ActivityEvent.d.ts.map +1 -0
- package/lib/typescript/src/types/AuthorizedSources.d.ts +5 -0
- package/lib/typescript/src/types/AuthorizedSources.d.ts.map +1 -1
- package/lib/typescript/src/types/BodySummary.d.ts +99 -0
- package/lib/typescript/src/types/BodySummary.d.ts.map +1 -0
- package/lib/typescript/src/types/PhysicalSummary.d.ts +70 -0
- package/lib/typescript/src/types/PhysicalSummary.d.ts.map +1 -0
- package/lib/typescript/src/types/SleepSummary.d.ts +57 -0
- package/lib/typescript/src/types/SleepSummary.d.ts.map +1 -0
- package/lib/typescript/src/types/SummaryTypes.d.ts +59 -0
- package/lib/typescript/src/types/SummaryTypes.d.ts.map +1 -0
- package/lib/typescript/src/utils/nativeModules.d.ts +3 -0
- package/lib/typescript/src/utils/nativeModules.d.ts.map +1 -1
- package/package.json +22 -22
- package/react-native-rook-sdk.podspec +5 -3
|
@@ -8,6 +8,7 @@ import com.facebook.react.uimanager.ViewManager
|
|
|
8
8
|
import com.rookmotion.rook.sdk.RookConfigurationManager
|
|
9
9
|
import com.rooksdk.modules.RookBackgroundSyncModule
|
|
10
10
|
import com.rooksdk.modules.RookConfigurationModule
|
|
11
|
+
import com.rooksdk.modules.RookLocalData
|
|
11
12
|
import com.rooksdk.modules.RookPermissionsModule
|
|
12
13
|
import com.rooksdk.modules.RookStepsModule
|
|
13
14
|
import io.tryrook.sdk.samsung.RookSamsung
|
|
@@ -30,7 +31,8 @@ class RookSdkPackage : ReactPackage {
|
|
|
30
31
|
RookConfigurationModule(reactContext, rookConfigurationManager!!, rookSamsung!!),
|
|
31
32
|
RookSyncModule(reactContext, rookSamsung!!),
|
|
32
33
|
RookBackgroundSyncModule(reactContext),
|
|
33
|
-
RookStepsModule(reactContext)
|
|
34
|
+
RookStepsModule(reactContext),
|
|
35
|
+
RookLocalData(reactContext, rookSamsung!!)
|
|
34
36
|
)
|
|
35
37
|
}
|
|
36
38
|
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
package com.rooksdk.modules
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Promise
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
6
|
+
import com.facebook.react.bridge.ReactMethod
|
|
7
|
+
import com.google.gson.Gson
|
|
8
|
+
import com.google.gson.GsonBuilder
|
|
9
|
+
import com.rookmotion.rook.sdk.RookSyncManager
|
|
10
|
+
import com.rookmotion.rook.sdk.domain.model.HCActivityEvent
|
|
11
|
+
import com.rookmotion.rook.sdk.domain.model.HCBodySummary
|
|
12
|
+
import com.rookmotion.rook.sdk.domain.model.HCPhysicalSummary
|
|
13
|
+
import com.rookmotion.rook.sdk.domain.model.HCSleepSummary
|
|
14
|
+
import com.rookmotion.rook.sdk.domain.model.SyncStatusWithData
|
|
15
|
+
import com.rooksdk.utils.serializers.InstantSerializer
|
|
16
|
+
import com.rooksdk.utils.RookDateTime
|
|
17
|
+
import com.rooksdk.utils.serializers.LocalDateSerializer
|
|
18
|
+
import io.tryrook.sdk.samsung.RookSamsung
|
|
19
|
+
import io.tryrook.sdk.samsung.domain.model.SHActivityEvent
|
|
20
|
+
import io.tryrook.sdk.samsung.domain.model.SHBodySummary
|
|
21
|
+
import io.tryrook.sdk.samsung.domain.model.SHPhysicalSummary
|
|
22
|
+
import io.tryrook.sdk.samsung.domain.model.SHSleepSummary
|
|
23
|
+
import io.tryrook.sdk.samsung.domain.model.SHSyncStatusWithData
|
|
24
|
+
import kotlinx.coroutines.CoroutineScope
|
|
25
|
+
import kotlinx.coroutines.Dispatchers
|
|
26
|
+
import kotlinx.coroutines.SupervisorJob
|
|
27
|
+
import kotlinx.coroutines.launch
|
|
28
|
+
import java.time.Instant
|
|
29
|
+
import java.time.LocalDate
|
|
30
|
+
|
|
31
|
+
class RookLocalData (
|
|
32
|
+
reactContext: ReactApplicationContext,
|
|
33
|
+
private val rookSamsung: RookSamsung,
|
|
34
|
+
): ReactContextBaseJavaModule(reactContext){
|
|
35
|
+
|
|
36
|
+
private val scope: CoroutineScope by lazy {
|
|
37
|
+
CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private val rookHealthConnect by lazy {
|
|
41
|
+
RookSyncManager(reactContext)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private val gsonBuilder: Gson by lazy {
|
|
45
|
+
GsonBuilder()
|
|
46
|
+
.registerTypeAdapter(Instant::class.java, InstantSerializer())
|
|
47
|
+
.registerTypeAdapter(LocalDate::class.java, LocalDateSerializer())
|
|
48
|
+
.create()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@ReactMethod
|
|
52
|
+
fun getSamsungSleepSummary(date: String, promise: Promise) {
|
|
53
|
+
val localDate = RookDateTime.stringToLocalDate(date)
|
|
54
|
+
|
|
55
|
+
scope.launch {
|
|
56
|
+
rookSamsung.getSleepSummary(localDate).fold(
|
|
57
|
+
{
|
|
58
|
+
when (it) {
|
|
59
|
+
SHSyncStatusWithData.RecordsNotFound -> {
|
|
60
|
+
promise.reject("SamsungSleepSummary", "Records Not Found For Date: $date")
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
is SHSyncStatusWithData.Synced<List<SHSleepSummary>> -> {
|
|
64
|
+
promise.resolve(gsonBuilder.toJson(it.data))
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
promise.reject(it)
|
|
70
|
+
},
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@ReactMethod
|
|
76
|
+
fun getSamsungPhysicalSummary(date: String, promise: Promise) {
|
|
77
|
+
val localDate = RookDateTime.stringToLocalDate(date)
|
|
78
|
+
|
|
79
|
+
scope.launch {
|
|
80
|
+
rookSamsung.getPhysicalSummary(localDate).fold(
|
|
81
|
+
{
|
|
82
|
+
when (it) {
|
|
83
|
+
SHSyncStatusWithData.RecordsNotFound -> {
|
|
84
|
+
promise.reject("SamsungPhysicalSummary", "Records Not Found For Date: $date")
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
is SHSyncStatusWithData.Synced<SHPhysicalSummary> -> {
|
|
88
|
+
promise.resolve(gsonBuilder.toJson(it.data))
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
promise.reject(it)
|
|
94
|
+
},
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@ReactMethod
|
|
100
|
+
fun getSamsungBodySummary(date: String, promise: Promise) {
|
|
101
|
+
val localDate = RookDateTime.stringToLocalDate(date)
|
|
102
|
+
|
|
103
|
+
scope.launch {
|
|
104
|
+
rookSamsung.getBodySummary(localDate).fold(
|
|
105
|
+
{
|
|
106
|
+
when (it) {
|
|
107
|
+
SHSyncStatusWithData.RecordsNotFound -> {
|
|
108
|
+
promise.reject("SamsungBodySummary", "Records Not Found For Date: $date")
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
is SHSyncStatusWithData.Synced<SHBodySummary> -> {
|
|
112
|
+
promise.resolve(gsonBuilder.toJson(it.data))
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
promise.reject(it)
|
|
118
|
+
},
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@ReactMethod
|
|
124
|
+
fun getSamsungActivityEvents(date: String, promise: Promise) {
|
|
125
|
+
val localDate = RookDateTime.stringToLocalDate(date)
|
|
126
|
+
|
|
127
|
+
scope.launch {
|
|
128
|
+
rookSamsung.getActivityEvents(localDate).fold(
|
|
129
|
+
{
|
|
130
|
+
when (it) {
|
|
131
|
+
SHSyncStatusWithData.RecordsNotFound -> {
|
|
132
|
+
promise.reject("SamsungBodySummary", "Records Not Found For Date: $date")
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
is SHSyncStatusWithData.Synced<List<SHActivityEvent>> -> {
|
|
136
|
+
promise.resolve(gsonBuilder.toJson(it.data))
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
promise.reject(it)
|
|
142
|
+
},
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Health Connect
|
|
148
|
+
@ReactMethod
|
|
149
|
+
fun getHealthConnectSleepSummary(date: String, promise: Promise) {
|
|
150
|
+
val localDate = RookDateTime.stringToLocalDate(date)
|
|
151
|
+
|
|
152
|
+
scope.launch {
|
|
153
|
+
rookHealthConnect.getSleepSummary(localDate).fold(
|
|
154
|
+
{
|
|
155
|
+
when (it) {
|
|
156
|
+
SyncStatusWithData.RecordsNotFound -> {
|
|
157
|
+
promise.reject("HealthConnectSleepSummary", "Records Not Found For Date: $date")
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
is SyncStatusWithData.Synced<List<HCSleepSummary>> -> {
|
|
161
|
+
promise.resolve(gsonBuilder.toJson(it.data))
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
promise.reject(it)
|
|
167
|
+
},
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@ReactMethod
|
|
173
|
+
fun getHealthConnectPhysicalSummary(date: String, promise: Promise) {
|
|
174
|
+
val localDate = RookDateTime.stringToLocalDate(date)
|
|
175
|
+
|
|
176
|
+
scope.launch {
|
|
177
|
+
rookHealthConnect.getPhysicalSummary(localDate).fold(
|
|
178
|
+
{
|
|
179
|
+
when (it) {
|
|
180
|
+
SyncStatusWithData.RecordsNotFound -> {
|
|
181
|
+
promise.reject("HealthConnectSleepSummary", "Records Not Found For Date: $date")
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
is SyncStatusWithData.Synced<HCPhysicalSummary> -> {
|
|
185
|
+
promise.resolve(gsonBuilder.toJson(it.data))
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
promise.reject(it)
|
|
191
|
+
},
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@ReactMethod
|
|
197
|
+
fun getHealthConnectBodySummary(date: String, promise: Promise) {
|
|
198
|
+
val localDate = RookDateTime.stringToLocalDate(date)
|
|
199
|
+
|
|
200
|
+
scope.launch {
|
|
201
|
+
rookHealthConnect.getBodySummary(localDate).fold(
|
|
202
|
+
{
|
|
203
|
+
when (it) {
|
|
204
|
+
SyncStatusWithData.RecordsNotFound -> {
|
|
205
|
+
promise.reject("HealthConnectBodySummary", "Records Not Found For Date: $date")
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
is SyncStatusWithData.Synced<HCBodySummary> -> {
|
|
209
|
+
promise.resolve(gsonBuilder.toJson(it.data))
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
promise.reject(it)
|
|
215
|
+
},
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
@ReactMethod
|
|
221
|
+
fun getHealthConnectActivityEvents(date: String, promise: Promise) {
|
|
222
|
+
val localDate = RookDateTime.stringToLocalDate(date)
|
|
223
|
+
|
|
224
|
+
scope.launch {
|
|
225
|
+
rookHealthConnect.getActivityEvents(localDate).fold(
|
|
226
|
+
{
|
|
227
|
+
when (it) {
|
|
228
|
+
SyncStatusWithData.RecordsNotFound -> {
|
|
229
|
+
promise.reject("HealthConnectActivityEvents", "Records Not Found For Date: $date")
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
is SyncStatusWithData.Synced<List<HCActivityEvent>> -> {
|
|
233
|
+
promise.resolve(gsonBuilder.toJson(it.data))
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
promise.reject(it)
|
|
239
|
+
},
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
override fun getName(): String {
|
|
245
|
+
return "RookLocalData"
|
|
246
|
+
}
|
|
247
|
+
}
|
|
@@ -22,6 +22,7 @@ import kotlinx.coroutines.CoroutineScope
|
|
|
22
22
|
import kotlinx.coroutines.Dispatchers
|
|
23
23
|
import kotlinx.coroutines.SupervisorJob
|
|
24
24
|
import kotlinx.coroutines.launch
|
|
25
|
+
import org.jetbrains.annotations.Debug
|
|
25
26
|
|
|
26
27
|
class RookSyncModule(
|
|
27
28
|
reactContext: ReactApplicationContext,
|
|
@@ -145,6 +146,7 @@ class RookSyncModule(
|
|
|
145
146
|
|
|
146
147
|
|
|
147
148
|
/**
|
|
149
|
+
* @deprecated
|
|
148
150
|
* Retrieves the available data sources that can be connected to the app.
|
|
149
151
|
* This method fetches data sources such as Garmin, Fitbit, Oura, etc.,
|
|
150
152
|
* that the user can authorize to sync their health data.
|
|
@@ -233,7 +235,21 @@ class RookSyncModule(
|
|
|
233
235
|
}
|
|
234
236
|
}
|
|
235
237
|
|
|
236
|
-
@ReactMethod
|
|
238
|
+
@ReactMethod
|
|
239
|
+
fun getAuthorizedDataSourcesV2(promise: Promise) {
|
|
240
|
+
scope.launch {
|
|
241
|
+
rookDataSources.getAuthorizedDataSourcesV2().fold(
|
|
242
|
+
{
|
|
243
|
+
val gson = Gson()
|
|
244
|
+
promise.resolve(gson.toJson(it))
|
|
245
|
+
}, {
|
|
246
|
+
promise.reject(it)
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
@ReactMethod
|
|
237
253
|
fun getDataSourceAuthorizer(options: ReadableMap, promise: Promise) {
|
|
238
254
|
|
|
239
255
|
val source = options.getString("dataSource") ?: ""
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
}
|
|
19
|
+
|
|
@@ -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,32 @@
|
|
|
1
|
+
//
|
|
2
|
+
// EncodableDataSource.swift
|
|
3
|
+
// react-native-rook-sdk
|
|
4
|
+
//
|
|
5
|
+
// Created by Javier Villanueva on 09/10/25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import RookSDK
|
|
10
|
+
|
|
11
|
+
struct EncodableDataSource: Encodable {
|
|
12
|
+
|
|
13
|
+
private let dataSource: RookSDK.DataSourceStatus
|
|
14
|
+
|
|
15
|
+
init(_ dataSource: RookSDK.DataSourceStatus) {
|
|
16
|
+
self.dataSource = dataSource
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private enum CodingKeys: String, CodingKey {
|
|
20
|
+
case source
|
|
21
|
+
case status
|
|
22
|
+
case imageURL
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func encode(to encoder: Encoder) throws {
|
|
26
|
+
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
27
|
+
|
|
28
|
+
try container.encode(dataSource.source, forKey: .source)
|
|
29
|
+
try container.encode(dataSource.status, forKey: .status)
|
|
30
|
+
try container.encode(dataSource.imageURL, forKey: .imageURL)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//
|
|
2
|
+
// EncodableDataSourceAuthorizer.swift
|
|
3
|
+
// react-native-rook-sdk
|
|
4
|
+
//
|
|
5
|
+
// Created by Javier Villanueva on 08/10/25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import RookSDK
|
|
9
|
+
import Foundation
|
|
10
|
+
|
|
11
|
+
struct EncodableDataSourceAuthorizer: Encodable {
|
|
12
|
+
|
|
13
|
+
private let authorizer: RookSDK.DataSourceAuthorizer
|
|
14
|
+
|
|
15
|
+
init(_ authorizer: RookSDK.DataSourceAuthorizer) {
|
|
16
|
+
self.authorizer = authorizer
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private enum CodingKeys: String, CodingKey {
|
|
20
|
+
case dataSource
|
|
21
|
+
case authorized
|
|
22
|
+
case authorizationURL
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func encode(to encoder: Encoder) throws {
|
|
26
|
+
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
27
|
+
|
|
28
|
+
try container.encode(authorizer.dataSource, forKey: .dataSource)
|
|
29
|
+
try container.encode(authorizer.authorized, forKey: .authorized)
|
|
30
|
+
try container.encode(authorizer.authorizationURL, forKey: .authorizationURL)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//
|
|
2
|
+
// EncodableRookDataSource.swift
|
|
3
|
+
// Pods
|
|
4
|
+
//
|
|
5
|
+
// Created by Javier Villanueva on 08/10/25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import RookSDK
|
|
10
|
+
|
|
11
|
+
struct EncodableRookDataSource: Encodable {
|
|
12
|
+
|
|
13
|
+
private let dataSource: RookSDK.RookDataSource
|
|
14
|
+
|
|
15
|
+
init(_ dataSource: RookSDK.RookDataSource) {
|
|
16
|
+
self.dataSource = dataSource
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private enum CodingKeys: String, CodingKey {
|
|
20
|
+
case name
|
|
21
|
+
case description
|
|
22
|
+
case imageUrl
|
|
23
|
+
case connected
|
|
24
|
+
case authorizationURL
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
func encode(to encoder: Encoder) throws {
|
|
28
|
+
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
29
|
+
|
|
30
|
+
try container.encode(dataSource.name, forKey: .name)
|
|
31
|
+
try container.encode(dataSource.description, forKey: .description)
|
|
32
|
+
try container.encode(dataSource.imageUrl, forKey: .imageUrl)
|
|
33
|
+
try container.encode(dataSource.connected, forKey: .connected)
|
|
34
|
+
try container.encode(dataSource.authorizationURL, forKey: .authorizationURL)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//
|
|
2
|
+
// EncodableStatusDataSources.swift
|
|
3
|
+
// react-native-rook-sdk
|
|
4
|
+
//
|
|
5
|
+
// Created by Javier Villanueva on 08/10/25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import RookSDK
|
|
10
|
+
|
|
11
|
+
struct EncodableStatusDataSources: Encodable {
|
|
12
|
+
private let status: RookSDK.StatusDataSources
|
|
13
|
+
|
|
14
|
+
init(_ status: RookSDK.StatusDataSources) {
|
|
15
|
+
self.status = status
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private enum CodingKeys: String, CodingKey {
|
|
19
|
+
case oura
|
|
20
|
+
case polar
|
|
21
|
+
case whoop
|
|
22
|
+
case fitbit
|
|
23
|
+
case garmin
|
|
24
|
+
case withings
|
|
25
|
+
case googleFit
|
|
26
|
+
case appleHealth
|
|
27
|
+
case healthConnect
|
|
28
|
+
case android
|
|
29
|
+
case dexcom
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
func encode(to encoder: Encoder) throws {
|
|
33
|
+
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
34
|
+
|
|
35
|
+
try container.encode(status.oura, forKey: .oura)
|
|
36
|
+
try container.encode(status.polar, forKey: .polar)
|
|
37
|
+
try container.encode(status.whoop, forKey: .whoop)
|
|
38
|
+
try container.encode(status.fitbit, forKey: .fitbit)
|
|
39
|
+
try container.encode(status.garmin, forKey: .garmin)
|
|
40
|
+
try container.encode(status.withings, forKey: .withings)
|
|
41
|
+
try container.encode(status.googleFit, forKey: .googleFit)
|
|
42
|
+
try container.encode(status.appleHealth, forKey: .appleHealth)
|
|
43
|
+
try container.encode(status.healthConnect, forKey: .healthConnect)
|
|
44
|
+
try container.encode(status.android, forKey: .android)
|
|
45
|
+
try container.encode(status.dexcom, forKey: .dexcom)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RookExternalModule.m
|
|
3
|
+
// react-native-rook-sdk
|
|
4
|
+
//
|
|
5
|
+
// Created by Javier Villanueva on 10/09/25.
|
|
6
|
+
//
|
|
7
|
+
#import <Foundation/Foundation.h>
|
|
8
|
+
#import <React/RCTBridgeModule.h>
|
|
9
|
+
|
|
10
|
+
@interface RCT_EXTERN_MODULE(RookLocalData, NSObject)
|
|
11
|
+
|
|
12
|
+
RCT_EXTERN_METHOD(getAppleHealthSleepSummary: (NSString *) date
|
|
13
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
14
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
15
|
+
|
|
16
|
+
RCT_EXTERN_METHOD(getAppleHealthPhysicalSummary: (NSString *) date
|
|
17
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
18
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
19
|
+
|
|
20
|
+
RCT_EXTERN_METHOD(getAppleHealthBodySummary: (NSString *) date
|
|
21
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
22
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
23
|
+
|
|
24
|
+
RCT_EXTERN_METHOD(getAppleHealthActivityEvents: (NSString *) date
|
|
25
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
26
|
+
reject:(RCTPromiseRejectBlock)reject)
|
|
27
|
+
@end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RookLocalData.swift
|
|
3
|
+
// react-native-rook-sdk
|
|
4
|
+
//
|
|
5
|
+
// Created by Javier Villanueva on 10/09/25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import RookSDK
|
|
9
|
+
|
|
10
|
+
@objc(RookLocalData)
|
|
11
|
+
public class RookLocalData: NSObject {
|
|
12
|
+
|
|
13
|
+
lazy var summaryManager: RookSummaryManager = {
|
|
14
|
+
return RookSummaryManager()
|
|
15
|
+
}()
|
|
16
|
+
|
|
17
|
+
lazy var eventManager: RookEventsManager = {
|
|
18
|
+
return RookEventsManager()
|
|
19
|
+
}()
|
|
20
|
+
|
|
21
|
+
func parseStringToDate(_ input: String) -> Date? {
|
|
22
|
+
let dateFormatter = DateFormatter()
|
|
23
|
+
dateFormatter.dateFormat = "yyyy-MM-dd"
|
|
24
|
+
return dateFormatter.date(from: input)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@objc(getAppleHealthSleepSummary:resolve:reject:)
|
|
28
|
+
public func getAppleHealthSleepSummary(
|
|
29
|
+
_ date: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock
|
|
30
|
+
) {
|
|
31
|
+
Task {
|
|
32
|
+
do {
|
|
33
|
+
guard let parsed = parseStringToDate(date) else {
|
|
34
|
+
reject("AppleHealthGetSleepSummaryError", "Invalid date format", nil)
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let sleepSummaries = try await summaryManager.getSleepSummary(date: parsed)
|
|
39
|
+
let dic = sleepSummaries.map { $0.toDictionary() }
|
|
40
|
+
|
|
41
|
+
DispatchQueue.main.async {
|
|
42
|
+
resolve(dic)
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
|
|
46
|
+
DispatchQueue.main.async {
|
|
47
|
+
reject("AppleHealthGetSleepSummaryError", error.localizedDescription, error as NSError)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@objc(getAppleHealthPhysicalSummary:resolve:reject:)
|
|
54
|
+
public func getAppleHealthPhysicalSummary(
|
|
55
|
+
_ date: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock
|
|
56
|
+
) {
|
|
57
|
+
Task {
|
|
58
|
+
do {
|
|
59
|
+
guard let parsed = parseStringToDate(date) else {
|
|
60
|
+
reject("AppleHealthGetPhysicalSummaryError", "Invalid date format", nil)
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let physicalSummaries = try await summaryManager.getPhysicalSummary(date: parsed)
|
|
65
|
+
let dic = physicalSummaries.toDictionary()
|
|
66
|
+
|
|
67
|
+
DispatchQueue.main.async {
|
|
68
|
+
resolve(dic)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
} catch {
|
|
72
|
+
|
|
73
|
+
DispatchQueue.main.async {
|
|
74
|
+
reject("AppleHealthGetBodySummaryError", error.localizedDescription, error as NSError)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@objc(getAppleHealthBodySummary:resolve:reject:)
|
|
81
|
+
public func getAppleHealthBodySummary(
|
|
82
|
+
_ date: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock
|
|
83
|
+
) {
|
|
84
|
+
Task {
|
|
85
|
+
do {
|
|
86
|
+
guard let parsed = parseStringToDate(date) else {
|
|
87
|
+
reject("AppleHealthGetBodySummaryError", "Invalid date format", nil)
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
let bodySummaries = try await summaryManager.getBodySummary(date: parsed)
|
|
91
|
+
let dic = bodySummaries.toDictionary()
|
|
92
|
+
|
|
93
|
+
DispatchQueue.main.async {
|
|
94
|
+
resolve(dic)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
} catch {
|
|
98
|
+
|
|
99
|
+
DispatchQueue.main.async {
|
|
100
|
+
reject("AppleHealthGetBodySummaryError", error.localizedDescription, error as NSError)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@objc(getAppleHealthActivityEvents:resolve:reject:)
|
|
107
|
+
public func getAppleHealthActivityEvents(
|
|
108
|
+
_ date: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock
|
|
109
|
+
) {
|
|
110
|
+
Task {
|
|
111
|
+
do {
|
|
112
|
+
guard let parsed = parseStringToDate(date) else {
|
|
113
|
+
reject("AppleHealthGetActivityEventsError", "Invalid date format", nil)
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
let activityEvents = try await eventManager.getActivityEvents(date: parsed)
|
|
118
|
+
let dic = activityEvents.map { $0.toDictionary() }
|
|
119
|
+
|
|
120
|
+
DispatchQueue.main.async {
|
|
121
|
+
resolve(dic)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
} catch {
|
|
125
|
+
|
|
126
|
+
DispatchQueue.main.async {
|
|
127
|
+
reject("AppleHealthGetActivityEvents", error.localizedDescription, error as NSError)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
extension Encodable {
|
|
136
|
+
func toDictionary() -> [String: Any] {
|
|
137
|
+
let encoder = JSONEncoder()
|
|
138
|
+
|
|
139
|
+
let dateFormatter = DateFormatter()
|
|
140
|
+
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
|
|
141
|
+
|
|
142
|
+
encoder.dateEncodingStrategy = .formatted(dateFormatter)
|
|
143
|
+
|
|
144
|
+
guard let data = try? encoder.encode(self),
|
|
145
|
+
let dictionary = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any]
|
|
146
|
+
else {
|
|
147
|
+
return [:]
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return dictionary
|
|
151
|
+
}
|
|
152
|
+
}
|