diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-appleMain.cinteropLibraries b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-appleMain.cinteropLibraries
new file mode 100644
index 00000000..060dde8b
--- /dev/null
+++ b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-appleMain.cinteropLibraries
@@ -0,0 +1,3 @@
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-nativeMain-cinterop/org.jetbrains.kotlinx_atomicfu-cinterop-interop-wFq7cg.klib
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-nativeDarwin-cinterop/io.realm.kotlin_cinterop-cinterop-realm_wrapper-nt9oMQ.klib
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.ktor-ktor-utils-2.3.12-iosMain-cinterop/io.ktor_ktor-utils-cinterop-threadUtils-TE4abA.klib
\ No newline at end of file
diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-appleTest.cinteropLibraries b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-appleTest.cinteropLibraries
new file mode 100644
index 00000000..060dde8b
--- /dev/null
+++ b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-appleTest.cinteropLibraries
@@ -0,0 +1,3 @@
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-nativeMain-cinterop/org.jetbrains.kotlinx_atomicfu-cinterop-interop-wFq7cg.klib
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-nativeDarwin-cinterop/io.realm.kotlin_cinterop-cinterop-realm_wrapper-nt9oMQ.klib
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.ktor-ktor-utils-2.3.12-iosMain-cinterop/io.ktor_ktor-utils-cinterop-threadUtils-TE4abA.klib
\ No newline at end of file
diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-iosMain.cinteropLibraries b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-iosMain.cinteropLibraries
new file mode 100644
index 00000000..060dde8b
--- /dev/null
+++ b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-iosMain.cinteropLibraries
@@ -0,0 +1,3 @@
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-nativeMain-cinterop/org.jetbrains.kotlinx_atomicfu-cinterop-interop-wFq7cg.klib
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-nativeDarwin-cinterop/io.realm.kotlin_cinterop-cinterop-realm_wrapper-nt9oMQ.klib
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.ktor-ktor-utils-2.3.12-iosMain-cinterop/io.ktor_ktor-utils-cinterop-threadUtils-TE4abA.klib
\ No newline at end of file
diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-iosTest.cinteropLibraries b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-iosTest.cinteropLibraries
new file mode 100644
index 00000000..060dde8b
--- /dev/null
+++ b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-iosTest.cinteropLibraries
@@ -0,0 +1,3 @@
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-nativeMain-cinterop/org.jetbrains.kotlinx_atomicfu-cinterop-interop-wFq7cg.klib
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-nativeDarwin-cinterop/io.realm.kotlin_cinterop-cinterop-realm_wrapper-nt9oMQ.klib
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.ktor-ktor-utils-2.3.12-iosMain-cinterop/io.ktor_ktor-utils-cinterop-threadUtils-TE4abA.klib
\ No newline at end of file
diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-nativeMain.cinteropLibraries b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-nativeMain.cinteropLibraries
new file mode 100644
index 00000000..060dde8b
--- /dev/null
+++ b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-nativeMain.cinteropLibraries
@@ -0,0 +1,3 @@
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-nativeMain-cinterop/org.jetbrains.kotlinx_atomicfu-cinterop-interop-wFq7cg.klib
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-nativeDarwin-cinterop/io.realm.kotlin_cinterop-cinterop-realm_wrapper-nt9oMQ.klib
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.ktor-ktor-utils-2.3.12-iosMain-cinterop/io.ktor_ktor-utils-cinterop-threadUtils-TE4abA.klib
\ No newline at end of file
diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-nativeTest.cinteropLibraries b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-nativeTest.cinteropLibraries
new file mode 100644
index 00000000..060dde8b
--- /dev/null
+++ b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.shared-nativeTest.cinteropLibraries
@@ -0,0 +1,3 @@
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-nativeMain-cinterop/org.jetbrains.kotlinx_atomicfu-cinterop-interop-wFq7cg.klib
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-nativeDarwin-cinterop/io.realm.kotlin_cinterop-cinterop-realm_wrapper-nt9oMQ.klib
+/Users/jancortiel/Documents/More/LBI/more-multiplatform-app/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.ktor-ktor-utils-2.3.12-iosMain-cinterop/io.ktor_ktor-utils-cinterop-threadUtils-TE4abA.klib
\ No newline at end of file
diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.ktor-ktor-utils-2.3.12-iosMain-cinterop/io.ktor_ktor-utils-cinterop-threadUtils-TE4abA.klib b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.ktor-ktor-utils-2.3.12-iosMain-cinterop/io.ktor_ktor-utils-cinterop-threadUtils-TE4abA.klib
new file mode 100644
index 00000000..ca651ddb
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.ktor-ktor-utils-2.3.12-iosMain-cinterop/io.ktor_ktor-utils-cinterop-threadUtils-TE4abA.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-nativeDarwin-cinterop/io.realm.kotlin_cinterop-cinterop-realm_wrapper-nt9oMQ.klib b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-nativeDarwin-cinterop/io.realm.kotlin_cinterop-cinterop-realm_wrapper-nt9oMQ.klib
new file mode 100644
index 00000000..729c60ea
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-nativeDarwin-cinterop/io.realm.kotlin_cinterop-cinterop-realm_wrapper-nt9oMQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-nativeMain-cinterop/org.jetbrains.kotlinx_atomicfu-cinterop-interop-wFq7cg.klib b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-nativeMain-cinterop/org.jetbrains.kotlinx_atomicfu-cinterop-interop-wFq7cg.klib
new file mode 100644
index 00000000..15d6a208
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-nativeMain-cinterop/org.jetbrains.kotlinx_atomicfu-cinterop-interop-wFq7cg.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/dev.tmapps-konnection-1.4.1-commonMain-1qj7aA.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/dev.tmapps-konnection-1.4.1-commonMain-1qj7aA.klib
new file mode 100644
index 00000000..52e41176
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/dev.tmapps-konnection-1.4.1-commonMain-1qj7aA.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/dev.tmapps-konnection-1.4.1-ios-BePiUw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/dev.tmapps-konnection-1.4.1-ios-BePiUw.klib
new file mode 100644
index 00000000..8b847fe8
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/dev.tmapps-konnection-1.4.1-ios-BePiUw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.github.aakira-napier-2.7.1-commonMain-UpJokw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.github.aakira-napier-2.7.1-commonMain-UpJokw.klib
new file mode 100644
index 00000000..5a2f649c
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.github.aakira-napier-2.7.1-commonMain-UpJokw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.github.aakira-napier-2.7.1-darwinMain-EnitAw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.github.aakira-napier-2.7.1-darwinMain-EnitAw.klib
new file mode 100644
index 00000000..4ba5570d
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.github.aakira-napier-2.7.1-darwinMain-EnitAw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-auth-2.3.12-commonMain-tgNnVQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-auth-2.3.12-commonMain-tgNnVQ.klib
new file mode 100644
index 00000000..98da7559
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-auth-2.3.12-commonMain-tgNnVQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-content-negotiation-2.3.12-commonMain-jI37cw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-content-negotiation-2.3.12-commonMain-jI37cw.klib
new file mode 100644
index 00000000..745c2195
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-content-negotiation-2.3.12-commonMain-jI37cw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-content-negotiation-2.3.12-posixMain-jI37cw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-content-negotiation-2.3.12-posixMain-jI37cw.klib
new file mode 100644
index 00000000..47bfdb02
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-content-negotiation-2.3.12-posixMain-jI37cw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-core-2.3.12-commonMain-FU-9lg.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-core-2.3.12-commonMain-FU-9lg.klib
new file mode 100644
index 00000000..d5eb44a3
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-core-2.3.12-commonMain-FU-9lg.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-core-2.3.12-posixMain-FU-9lg.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-core-2.3.12-posixMain-FU-9lg.klib
new file mode 100644
index 00000000..f33f7f85
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-core-2.3.12-posixMain-FU-9lg.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-darwin-2.3.12-darwinMain-CnRCQQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-darwin-2.3.12-darwinMain-CnRCQQ.klib
new file mode 100644
index 00000000..27421f95
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-darwin-2.3.12-darwinMain-CnRCQQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-logging-2.3.12-commonMain-grxlVw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-logging-2.3.12-commonMain-grxlVw.klib
new file mode 100644
index 00000000..1a0f4bd9
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-logging-2.3.12-commonMain-grxlVw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-logging-2.3.12-posixMain-grxlVw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-logging-2.3.12-posixMain-grxlVw.klib
new file mode 100644
index 00000000..a3e08f24
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-client-logging-2.3.12-posixMain-grxlVw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-events-2.3.12-commonMain-Q6-xkw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-events-2.3.12-commonMain-Q6-xkw.klib
new file mode 100644
index 00000000..d9a2627a
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-events-2.3.12-commonMain-Q6-xkw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-http-2.3.12-commonMain-W5sIeA.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-http-2.3.12-commonMain-W5sIeA.klib
new file mode 100644
index 00000000..be50fd4d
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-http-2.3.12-commonMain-W5sIeA.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-http-2.3.12-posixMain-W5sIeA.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-http-2.3.12-posixMain-W5sIeA.klib
new file mode 100644
index 00000000..8dcf145e
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-http-2.3.12-posixMain-W5sIeA.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-io-2.3.12-commonMain-3YsjwQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-io-2.3.12-commonMain-3YsjwQ.klib
new file mode 100644
index 00000000..4a89b145
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-io-2.3.12-commonMain-3YsjwQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-io-2.3.12-darwinMain-sbySvA.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-io-2.3.12-darwinMain-sbySvA.klib
new file mode 100644
index 00000000..b45daa05
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-io-2.3.12-darwinMain-sbySvA.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-io-2.3.12-posixMain-3YsjwQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-io-2.3.12-posixMain-3YsjwQ.klib
new file mode 100644
index 00000000..635a72f6
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-io-2.3.12-posixMain-3YsjwQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-2.3.12-commonMain-NxrIfg.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-2.3.12-commonMain-NxrIfg.klib
new file mode 100644
index 00000000..265f7193
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-2.3.12-commonMain-NxrIfg.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-kotlinx-2.3.12-commonMain-s53Slg.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-kotlinx-2.3.12-commonMain-s53Slg.klib
new file mode 100644
index 00000000..9e5d8b52
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-kotlinx-2.3.12-commonMain-s53Slg.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-kotlinx-2.3.12-posixMain-s53Slg.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-kotlinx-2.3.12-posixMain-s53Slg.klib
new file mode 100644
index 00000000..9d87792e
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-kotlinx-2.3.12-posixMain-s53Slg.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-kotlinx-json-2.3.12-commonMain-sJ8SDA.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-kotlinx-json-2.3.12-commonMain-sJ8SDA.klib
new file mode 100644
index 00000000..45f1885b
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-kotlinx-json-2.3.12-commonMain-sJ8SDA.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-kotlinx-json-2.3.12-posixMain-sJ8SDA.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-kotlinx-json-2.3.12-posixMain-sJ8SDA.klib
new file mode 100644
index 00000000..a327a028
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-serialization-kotlinx-json-2.3.12-posixMain-sJ8SDA.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-utils-2.3.12-commonMain-kEcFvw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-utils-2.3.12-commonMain-kEcFvw.klib
new file mode 100644
index 00000000..8eb66ad6
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-utils-2.3.12-commonMain-kEcFvw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-utils-2.3.12-darwinMain-TE4abA.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-utils-2.3.12-darwinMain-TE4abA.klib
new file mode 100644
index 00000000..6deb9542
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-utils-2.3.12-darwinMain-TE4abA.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-utils-2.3.12-nixMain-kEcFvw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-utils-2.3.12-nixMain-kEcFvw.klib
new file mode 100644
index 00000000..cd74f993
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-utils-2.3.12-nixMain-kEcFvw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-utils-2.3.12-posixMain-kEcFvw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-utils-2.3.12-posixMain-kEcFvw.klib
new file mode 100644
index 00000000..a464aafc
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-utils-2.3.12-posixMain-kEcFvw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-websocket-serialization-2.3.12-commonMain-8xBQEg.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-websocket-serialization-2.3.12-commonMain-8xBQEg.klib
new file mode 100644
index 00000000..160024bc
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-websocket-serialization-2.3.12-commonMain-8xBQEg.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-websockets-2.3.12-commonMain-8-9-_g.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-websockets-2.3.12-commonMain-8-9-_g.klib
new file mode 100644
index 00000000..6217010f
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-websockets-2.3.12-commonMain-8-9-_g.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-websockets-2.3.12-posixMain-8-9-_g.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-websockets-2.3.12-posixMain-8-9-_g.klib
new file mode 100644
index 00000000..a3799471
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.ktor-ktor-websockets-2.3.12-posixMain-8-9-_g.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-commonMain-zZQVnw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-commonMain-zZQVnw.klib
new file mode 100644
index 00000000..dee97933
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-commonMain-zZQVnw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-nativeDarwin-nt9oMQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-nativeDarwin-nt9oMQ.klib
new file mode 100644
index 00000000..9e495c50
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-cinterop-1.13.0-nativeDarwin-nt9oMQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-library-base-1.13.0-commonMain-0LVaVg.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-library-base-1.13.0-commonMain-0LVaVg.klib
new file mode 100644
index 00000000..05ca0842
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-library-base-1.13.0-commonMain-0LVaVg.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-library-base-1.13.0-nativeDarwin-RwRULA.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-library-base-1.13.0-nativeDarwin-RwRULA.klib
new file mode 100644
index 00000000..629031e4
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-library-base-1.13.0-nativeDarwin-RwRULA.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-library-base-1.13.0-nativeIos-RwRULA.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-library-base-1.13.0-nativeIos-RwRULA.klib
new file mode 100644
index 00000000..0b80091e
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/io.realm.kotlin-library-base-1.13.0-nativeIos-RwRULA.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-stdlib-2.0.0-commonMain-2bbUHA.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-stdlib-2.0.0-commonMain-2bbUHA.klib
new file mode 100644
index 00000000..ed256742
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-stdlib-2.0.0-commonMain-2bbUHA.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-test-2.0.0-annotationsCommonMain-24eTFQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-test-2.0.0-annotationsCommonMain-24eTFQ.klib
new file mode 100644
index 00000000..250ee082
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-test-2.0.0-annotationsCommonMain-24eTFQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-test-2.0.0-assertionsCommonMain-24eTFQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-test-2.0.0-assertionsCommonMain-24eTFQ.klib
new file mode 100644
index 00000000..75ffad47
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-test-2.0.0-assertionsCommonMain-24eTFQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-commonMain-wFq7cg.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-commonMain-wFq7cg.klib
new file mode 100644
index 00000000..7a42bd23
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-commonMain-wFq7cg.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-nativeMain-wFq7cg.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-nativeMain-wFq7cg.klib
new file mode 100644
index 00000000..3c54c5c3
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-atomicfu-0.23.1-nativeMain-wFq7cg.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.8.1-commonMain-XanZ2w.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.8.1-commonMain-XanZ2w.klib
new file mode 100644
index 00000000..7d489eb0
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.8.1-commonMain-XanZ2w.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.8.1-concurrentMain-XanZ2w.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.8.1-concurrentMain-XanZ2w.klib
new file mode 100644
index 00000000..04231f8d
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.8.1-concurrentMain-XanZ2w.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.8.1-nativeDarwinMain-sy5nKg.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.8.1-nativeDarwinMain-sy5nKg.klib
new file mode 100644
index 00000000..0ea2d1c9
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.8.1-nativeDarwinMain-sy5nKg.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.8.1-nativeMain-XanZ2w.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.8.1-nativeMain-XanZ2w.klib
new file mode 100644
index 00000000..9273ad95
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.8.1-nativeMain-XanZ2w.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-datetime-0.4.0-commonMain-k5yUlQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-datetime-0.4.0-commonMain-k5yUlQ.klib
new file mode 100644
index 00000000..7fea36f1
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-datetime-0.4.0-commonMain-k5yUlQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-datetime-0.4.0-darwinMain-bPkWaQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-datetime-0.4.0-darwinMain-bPkWaQ.klib
new file mode 100644
index 00000000..7073571c
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-datetime-0.4.0-darwinMain-bPkWaQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-datetime-0.4.0-nativeMain-k5yUlQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-datetime-0.4.0-nativeMain-k5yUlQ.klib
new file mode 100644
index 00000000..36477fc6
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-datetime-0.4.0-nativeMain-k5yUlQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-serialization-core-1.7.1-commonMain-8gwKMQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-serialization-core-1.7.1-commonMain-8gwKMQ.klib
new file mode 100644
index 00000000..ea79905d
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-serialization-core-1.7.1-commonMain-8gwKMQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-serialization-core-1.7.1-nativeMain-8gwKMQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-serialization-core-1.7.1-nativeMain-8gwKMQ.klib
new file mode 100644
index 00000000..514eaa94
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-serialization-core-1.7.1-nativeMain-8gwKMQ.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-serialization-json-1.7.1-commonMain-Ii3AMw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-serialization-json-1.7.1-commonMain-Ii3AMw.klib
new file mode 100644
index 00000000..0ad0396e
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-serialization-json-1.7.1-commonMain-Ii3AMw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-serialization-json-1.7.1-nativeMain-Ii3AMw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-serialization-json-1.7.1-nativeMain-Ii3AMw.klib
new file mode 100644
index 00000000..6b5b966c
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlinx-kotlinx-serialization-json-1.7.1-nativeMain-Ii3AMw.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.mongodb.kbson-kbson-0.3.0-commonMain-eKbbTg.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.mongodb.kbson-kbson-0.3.0-commonMain-eKbbTg.klib
new file mode 100644
index 00000000..36a82e5f
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.mongodb.kbson-kbson-0.3.0-commonMain-eKbbTg.klib differ
diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.mongodb.kbson-kbson-0.3.0-iosMain-l8A9Sw.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.mongodb.kbson-kbson-0.3.0-iosMain-l8A9Sw.klib
new file mode 100644
index 00000000..84046587
Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.mongodb.kbson-kbson-0.3.0-iosMain-l8A9Sw.klib differ
diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts
index 8608272d..38c58e0e 100644
--- a/androidApp/build.gradle.kts
+++ b/androidApp/build.gradle.kts
@@ -13,8 +13,8 @@ android {
applicationId = "ac.at.lbg.dhp.more"
minSdk = 29
targetSdk = 34
- versionCode = 10
- versionName = "4.0.12"
+ versionCode = 12
+ versionName = "4.0.14"
}
buildFeatures {
compose = true
@@ -50,7 +50,7 @@ android {
val composeVersion = "1.6.8"
val workVersion = "2.9.0"
val navVersion = "2.7.7"
-val polarSDKVersion = "5.5.0"
+val polarSDKVersion = "5.6.0"
dependencies {
implementation(project(":shared"))
@@ -61,8 +61,8 @@ dependencies {
implementation("androidx.compose.material:material:$composeVersion")
implementation("androidx.compose.material:material-icons-core:$composeVersion")
implementation("androidx.compose.material:material-icons-extended:$composeVersion")
- implementation("androidx.fragment:fragment:1.8.1")
- implementation("androidx.activity:activity-compose:1.9.0")
+ implementation("androidx.fragment:fragment:1.8.2")
+ implementation("androidx.activity:activity-compose:1.9.1")
implementation("io.realm.kotlin:library-base:1.13.0")
implementation("androidx.navigation:navigation-compose:$navVersion")
implementation("androidx.work:work-runtime-ktx:$workVersion")
@@ -80,5 +80,5 @@ dependencies {
implementation("com.google.firebase:firebase-inappmessaging-display-ktx")
implementation("com.google.code.gson:gson:2.10.1")
implementation("com.github.acsbendi:Android-Request-Inspector-WebView:1.0.3")
- implementation("androidx.lifecycle:lifecycle-process:2.8.3")
+ implementation("androidx.lifecycle:lifecycle-process:2.8.4")
}
diff --git a/androidApp/src/main/java/io/redlink/more/app/android/observations/HR/PolarObserverCallback.kt b/androidApp/src/main/java/io/redlink/more/app/android/observations/HR/PolarObserverCallback.kt
index b6bbc3d8..80b2e514 100644
--- a/androidApp/src/main/java/io/redlink/more/app/android/observations/HR/PolarObserverCallback.kt
+++ b/androidApp/src/main/java/io/redlink/more/app/android/observations/HR/PolarObserverCallback.kt
@@ -11,6 +11,7 @@
package io.redlink.more.app.android.observations.HR
+import com.polar.androidcommunications.api.ble.model.DisInfo
import com.polar.sdk.api.PolarBleApi
import com.polar.sdk.api.PolarBleApiCallback
import com.polar.sdk.api.model.PolarDeviceInfo
@@ -45,35 +46,60 @@ class PolarObserverCallback : PolarBleApiCallback() {
override fun deviceConnected(polarDeviceInfo: PolarDeviceInfo) {
super.deviceConnected(polarDeviceInfo)
- Napier.d("CONNECTED: ${polarDeviceInfo.deviceId}", tag = "PolarObserverCallback::deviceConnected")
+ Napier.d(
+ "CONNECTED: ${polarDeviceInfo.deviceId}",
+ tag = "PolarObserverCallback::deviceConnected"
+ )
connectionListener?.onDeviceConnected(polarDeviceInfo)
}
override fun deviceConnecting(polarDeviceInfo: PolarDeviceInfo) {
super.deviceConnecting(polarDeviceInfo)
- Napier.d("CONNECTING: ${polarDeviceInfo.deviceId}", tag = "PolarObserverCallback::deviceConnecting")
+ Napier.d(
+ "CONNECTING: ${polarDeviceInfo.deviceId}",
+ tag = "PolarObserverCallback::deviceConnecting"
+ )
connectionListener?.onDeviceConnecting(polarDeviceInfo)
}
override fun deviceDisconnected(polarDeviceInfo: PolarDeviceInfo) {
super.deviceDisconnected(polarDeviceInfo)
- Napier.i("Device disconnected: ${polarDeviceInfo.name}", tag = "PolarObserverCallback::deviceDisconnected")
+ Napier.i(
+ "Device disconnected: ${polarDeviceInfo.name}",
+ tag = "PolarObserverCallback::deviceDisconnected"
+ )
connectionListener?.onDeviceDisconnected(polarDeviceInfo)
}
override fun bleSdkFeatureReady(identifier: String, feature: PolarBleApi.PolarBleSdkFeature) {
super.bleSdkFeatureReady(identifier, feature)
- Napier.i("SDK Feature ready: ${feature.name}, identifier: $identifier", tag = "PolarObserverCallback::bleSdkFeatureReady")
+ Napier.i(
+ "SDK Feature ready: ${feature.name}, identifier: $identifier",
+ tag = "PolarObserverCallback::bleSdkFeatureReady"
+ )
connectionListener?.onPolarFeatureReady(feature)
}
override fun disInformationReceived(identifier: String, uuid: UUID, value: String) {
super.disInformationReceived(identifier, uuid, value)
- Napier.i("Disinformation: $identifier, UUID: $uuid, Value: $value", tag = "PolarObserverCallback::disInformationReceived")
+ Napier.i(
+ "Disinformation: $identifier, UUID: $uuid, Value: $value",
+ tag = "PolarObserverCallback::disInformationReceived"
+ )
+ }
+
+ override fun disInformationReceived(identifier: String, disInfo: DisInfo) {
+ Napier.i(
+ "Disinformation: $identifier, DisInfo: $disInfo",
+ tag = "PolarObserverCallback::disInformationReceived"
+ )
}
override fun batteryLevelReceived(identifier: String, level: Int) {
super.batteryLevelReceived(identifier, level)
- Napier.i( "Battery Level Received: $level", tag = "PolarObserverCallback::batteryLevelReceived")
+ Napier.i(
+ "Battery Level Received: $level",
+ tag = "PolarObserverCallback::batteryLevelReceived"
+ )
}
}
\ No newline at end of file
diff --git a/androidApp/src/main/java/io/redlink/more/app/android/services/bluetooth/PolarConnector.kt b/androidApp/src/main/java/io/redlink/more/app/android/services/bluetooth/PolarConnector.kt
index bf0cb600..98cc6b2f 100644
--- a/androidApp/src/main/java/io/redlink/more/app/android/services/bluetooth/PolarConnector.kt
+++ b/androidApp/src/main/java/io/redlink/more/app/android/services/bluetooth/PolarConnector.kt
@@ -124,7 +124,7 @@ class PolarConnector(context: Context) : BluetoothConnector, PolarConnectorListe
override fun onPolarFeatureReady(feature: PolarBleApi.PolarBleSdkFeature) {
if (feature == PolarBleApi.PolarBleSdkFeature.FEATURE_HR) {
Napier.i(tag = "PolarConnector::onPolarFeatureReady") { "HR ready!" }
- PolarHeartRateObservation.setHRFeature(false)
+ PolarHeartRateObservation.setHRFeature(true)
}
}
diff --git a/androidApp/src/main/res/values-de/bluetooth-strings.xml b/androidApp/src/main/res/values-de/bluetooth-strings.xml
index 21f5d44b..cf92099f 100644
--- a/androidApp/src/main/res/values-de/bluetooth-strings.xml
+++ b/androidApp/src/main/res/values-de/bluetooth-strings.xml
@@ -13,7 +13,7 @@
Manche Aufgaben benötigen Bluetooth Geräte um abgeschlossen zu werden. Stelle sicher, dass folgende Geräte verbunden sind
Sie können sich jederzeit mit Geräten verbinden in: Info > Geräte
Setup überspringen
- Bluetooth ist deaktiviert. Bitte aktivieren zum verbinden!
+ Bluetooth oder GPS deaktiviert! Bitte aktivieren Sie beides für die Nutzung!
Verbinde ein Gerät, indem du es aus der Liste auswählst, nachdem du dieses mit deinem Smartphone gekoppelt hast.
Bitte verbinde das geforderte Gerät mit deinem Smartphone, um es mit der App zu verbinden.
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index d1cc58c6..97133f66 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,7 +1,7 @@
buildscript {
dependencies {
- classpath("com.google.gms:google-services:4.4.1")
- classpath("com.google.firebase:firebase-crashlytics-gradle:2.9.9")
+ classpath("com.google.gms:google-services:4.4.2")
+ classpath("com.google.firebase:firebase-crashlytics-gradle:3.0.2")
}
repositories {
google() // Google's Maven repository
@@ -13,7 +13,7 @@ plugins {
//trick: for the same plugin versions in all sub-modules
id("com.android.application").version("8.2.2").apply(false)
id("com.android.library").version("8.2.2").apply(false)
- kotlin("android").version("1.9.22").apply(false)
+ kotlin("android").version("1.9.23").apply(false)
kotlin("multiplatform").version("1.9.23").apply(false)
kotlin("plugin.serialization").version("1.9.23").apply(false)
}
diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj
index 9afab252..e2744f02 100644
--- a/iosApp/iosApp.xcodeproj/project.pbxproj
+++ b/iosApp/iosApp.xcodeproj/project.pbxproj
@@ -1798,7 +1798,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 4.0.12;
+ MARKETING_VERSION = 4.0.14;
OTHER_LDFLAGS = (
"$(inherited)",
"-framework",
@@ -1838,7 +1838,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 4.0.12;
+ MARKETING_VERSION = 4.0.14;
OTHER_LDFLAGS = (
"$(inherited)",
"-framework",
diff --git a/iosApp/iosApp/AppDelegate.swift b/iosApp/iosApp/AppDelegate.swift
index 94a3f94d..db72fd24 100644
--- a/iosApp/iosApp/AppDelegate.swift
+++ b/iosApp/iosApp/AppDelegate.swift
@@ -52,7 +52,7 @@ class AppDelegate: NSObject, UIApplicationDelegate {
fcmService.register()
AppDelegate.registerForNotifications()
- registerBackgroundTasks()
+ DataUploadBackgroundTask.setupBackgroundTasks()
AppDelegate.shared.deeplinkManager.addAvailableDeepLinks(deepLinks: Set(NavigationScreen.allCases.map { $0.values.navigationLink }))
@@ -78,14 +78,6 @@ class AppDelegate: NSObject, UIApplicationDelegate {
print("App did fail to register for remote notifications: \(error)")
}
- private func registerBackgroundTasks() {
- BGTaskScheduler.shared.register(forTaskWithIdentifier: DataUploadBackgroundTask.taskID, using: nil) { task in
- if let task = task as? BGProcessingTask {
- DataUploadBackgroundTask().handleProcessingTask(task: task)
- }
- }
- }
-
func cancelBackgroundTasks() {
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: DataUploadBackgroundTask.taskID)
}
diff --git a/iosApp/iosApp/BackgroundTasks/DataUploadBackgroundTask.swift b/iosApp/iosApp/BackgroundTasks/DataUploadBackgroundTask.swift
index 8c2e2a2b..49543ae0 100644
--- a/iosApp/iosApp/BackgroundTasks/DataUploadBackgroundTask.swift
+++ b/iosApp/iosApp/BackgroundTasks/DataUploadBackgroundTask.swift
@@ -1,26 +1,15 @@
-//
-// DataUploadBackgroundTask.swift
-// iosApp
-//
-// Created by Jan Cortiel on 23.03.23.
-// Copyright © 2023 Ludwig Boltzmann Institute for
-// Digital Health and Prevention - A research institute
-// of the Ludwig Boltzmann Gesellschaft,
-// Oesterreichische Vereinigung zur Foerderung
-// der wissenschaftlichen Forschung
-// Licensed under the Apache 2.0 license with Commons Clause
-// (see https://www.apache.org/licenses/LICENSE-2.0 and
-// https://commonsclause.com/).
-//
-
import BackgroundTasks
-import Foundation
class DataUploadBackgroundTask {
static let taskID = "io.redlink.more.app.multiplatform.data-upload"
- static func schedule() {
+
+ static func schedule(earliestBeginDate: Date? = nil) {
let request = BGProcessingTaskRequest(identifier: taskID)
- request.earliestBeginDate = Calendar.current.date(byAdding: .minute, value: 15, to: Date())
+ if let earliestDate = earliestBeginDate {
+ request.earliestBeginDate = earliestDate
+ } else {
+ request.earliestBeginDate = Calendar.current.date(byAdding: .minute, value: 15, to: Date())
+ }
request.requiresNetworkConnectivity = true
request.requiresExternalPower = false
@@ -28,12 +17,12 @@ class DataUploadBackgroundTask {
try BGTaskScheduler.shared.submit(request)
print("DataUploadBackgroundTask::schedule - Background Task scheduled")
} catch {
- print("DataUploadBackgroundTask:schedule - Error requesting for a background task")
+ print("DataUploadBackgroundTask::schedule - Error requesting a background task: \(error.localizedDescription)")
}
}
private let dataCollector = ObservationDataCollector()
-
+
private func collectRecordedData(completion: @escaping () -> Void) {
print("DataUploadBackgroundTask::collectRecordedData - \(Date()): Collecting recorded data...")
dataCollector.collectData { dataCollected in
@@ -45,8 +34,9 @@ class DataUploadBackgroundTask {
completion()
}
}
-
+
private func close() {
+ print("DataUploadBackgroundTask::close - Cleaning up resources")
}
}
@@ -54,6 +44,7 @@ extension DataUploadBackgroundTask: BackgroundTaskHandler {
@MainActor
func handleProcessingTask(task: BGProcessingTask) {
print("DataUploadBackgroundTask::handleProcessingTask - Starting Background Processing Task")
+
task.expirationHandler = {
print("\(Date()): Task will soon expire! Cleaning up...")
self.close()
@@ -63,24 +54,35 @@ extension DataUploadBackgroundTask: BackgroundTaskHandler {
task.setTaskCompleted(success: false)
}
}
+
collectRecordedData { [weak self] in
guard let strongSelf = self else {
DataUploadBackgroundTask.schedule()
task.setTaskCompleted(success: false)
return
}
-
+
strongSelf.close()
DataUploadBackgroundTask.schedule()
DispatchQueue.main.async {
task.setTaskCompleted(success: true)
}
}
-
}
func handleRefreshTask(task: BGAppRefreshTask) {
+ print("DataUploadBackgroundTask::handleRefreshTask - Handling Refresh Task")
task.setTaskCompleted(success: true)
}
-
+
+ static func setupBackgroundTasks() {
+ BGTaskScheduler.shared.register(forTaskWithIdentifier: DataUploadBackgroundTask.taskID, using: nil) { task in
+ if let processingTask = task as? BGProcessingTask {
+ let backgroundTaskHandler = DataUploadBackgroundTask()
+ Task {
+ await backgroundTaskHandler.handleProcessingTask(task: processingTask)
+ }
+ }
+ }
+ }
}
diff --git a/iosApp/iosApp/Info.plist b/iosApp/iosApp/Info.plist
index efb75cbe..4a0878f0 100644
--- a/iosApp/iosApp/Info.plist
+++ b/iosApp/iosApp/Info.plist
@@ -19,7 +19,7 @@
CFBundlePackageType
$(PRODUCT_BUNDLE_PACKAGE_TYPE)
CFBundleShortVersionString
- 4.0.12
+ 4.0.14
CFBundleURLTypes
@@ -36,7 +36,7 @@
CFBundleVersion
- 4.0.12
+ 4.0.14
FirebaseAppDelegateProxyEnabled
ITSAppUsesNonExemptEncryption
diff --git a/iosApp/iosApp/Observations/AccelerometerBackgroundObservation.swift b/iosApp/iosApp/Observations/AccelerometerBackgroundObservation.swift
index 5142c1bb..4b72ecd2 100644
--- a/iosApp/iosApp/Observations/AccelerometerBackgroundObservation.swift
+++ b/iosApp/iosApp/Observations/AccelerometerBackgroundObservation.swift
@@ -7,14 +7,14 @@
// Digital Health and Prevention - A research institute
// of the Ludwig Boltzmann Gesellschaft,
// Oesterreichische Vereinigung zur Foerderung
-// der wissenschaftlichen Forschung
-// Licensed under the Apache 2.0 license with Commons Clause
+// der wissenschaftlichen Forschung
+// Licensed under the Apache 2.0 license with Commons Clause
// (see https://www.apache.org/licenses/LICENSE-2.0 and
// https://commonsclause.com/).
//
-import Foundation
import CoreMotion
+import Foundation
import shared
import UIKit
@@ -22,21 +22,21 @@ class AccelerometerBackgroundObservation: Observation_ {
private var recordForDurationInSec: Double = 60 * 10
private let recorder = CMSensorRecorder()
private var startRecording: Date = Date()
-
+
private var timer: Timer?
private let semaphore = Semaphore()
private let observationRepository: ObservationRepository = {
ObservationRepository()
}()
-
+
init(sensorPermissions: Set) {
super.init(observationType: AccelerometerType(sensorPermissions: sensorPermissions))
}
-
+
override func start() -> Bool {
if observerAccessible() {
recorder.recordAccelerometer(forDuration: recordForDurationInSec)
- self.startRecording = Date()
+ startRecording = Date()
print("CMSensorRecorder started recording accelerometer data for the next \(recordForDurationInSec)s...")
DispatchQueue.main.async { [weak self] in
self?.timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { [weak self] timer in
@@ -51,41 +51,40 @@ class AccelerometerBackgroundObservation: Observation_ {
}
}
}
-
+
return true
}
return false
}
-
+
override func stop(onCompletion: @escaping () -> Void) {
timer?.invalidate()
- self.collectData(start: Date(timeIntervalSince1970: TimeInterval(self.lastCollectionTimestamp.epochSeconds)), end: Date(), completion: onCompletion)
+ collectData(start: Date(timeIntervalSince1970: TimeInterval(lastCollectionTimestamp.epochSeconds)), end: Date(), completion: onCompletion)
}
-
+
override func store(start: Int64, end: Int64, onCompletion: @escaping () -> Void) {
- self.collectData(start: Date(timeIntervalSince1970: TimeInterval(start)), end: Date(timeIntervalSince1970: TimeInterval(end))) {
+ collectData(start: Date(timeIntervalSince1970: TimeInterval(start)), end: Date(timeIntervalSince1970: TimeInterval(end))) {
print("\(Date()): Data collected")
super.store(start: start, end: end, onCompletion: {})
print("\(Date()): Returning from store function")
onCompletion()
}
}
-
- override func applyObservationConfig(settings: [String : Any]) {
+
+ override func applyObservationConfig(settings: [String: Any]) {
if var start = settings[Observation_.Companion().CONFIG_TASK_START] as? Int64,
let end = settings[Observation_.Companion().CONFIG_TASK_STOP] as? Int64,
- Date(timeIntervalSince1970: TimeInterval(end)) > Date()
- {
+ Date(timeIntervalSince1970: TimeInterval(end)) > Date() {
let startDate = Date(timeIntervalSince1970: TimeInterval(start))
let endDate = Date(timeIntervalSince1970: TimeInterval(end))
if startDate < Date() {
start = Int64(Date().timeIntervalSince1970)
}
print("Recording time from \(startDate) to \(endDate); \(Double(end - start))s")
- self.recordForDurationInSec = Double(end - start)
+ recordForDurationInSec = Double(end - start)
}
}
-
+
override func observerErrors() -> Set {
var errors: Set = []
if !CMSensorRecorder.isAccelerometerRecordingAvailable() {
@@ -102,23 +101,25 @@ class AccelerometerBackgroundObservation: Observation_ {
extension AccelerometerBackgroundObservation: ObservationCollector {
func collectData(start: Date, end: Date, completion: @escaping () -> Void) {
if start < end {
- DispatchQueue.global(qos: .background).async {
- if let sensorData = self.recorder.accelerometerData(from: start, to: end) {
- self.collectionTimestampToNow()
- let data = sensorData.compactMap { data in
- if let accDatum = data as? CMRecordedAccelerometerData {
- let accel = accDatum.acceleration
- let timestamp = accDatum.startDate.timeIntervalSince1970
- let dict = ["x": accel.x, "y": accel.y, "z": accel.z]
- return ObservationBulkModel(data: dict, timestamp: Int64(timestamp))
+ DispatchQueue.global(qos: .background).async { [weak self] in
+ if let self {
+ if let sensorData = self.recorder.accelerometerData(from: start, to: end) {
+ self.collectionTimestampToNow()
+ let data = sensorData.enumerated().compactMap { index, data -> ObservationBulkModel? in
+ if index % 2 == 0, let accDatum = data as? CMRecordedAccelerometerData {
+ let accel = accDatum.acceleration
+ let timestamp = accDatum.startDate.timeIntervalSince1970
+ let dict = ["x": accel.x, "y": accel.y, "z": accel.z]
+ return ObservationBulkModel(data: dict, timestamp: Int64(timestamp))
+ }
+ return nil
}
- return nil
- }
- self.storeData(data: data) {
+ self.storeData(data: data) {
+ completion()
+ }
+ } else {
completion()
}
- } else {
- completion()
}
}
} else {
diff --git a/iosApp/iosApp/Services/DataUploadManager.swift b/iosApp/iosApp/Services/DataUploadManager.swift
index 41b39760..5b0a9f74 100644
--- a/iosApp/iosApp/Services/DataUploadManager.swift
+++ b/iosApp/iosApp/Services/DataUploadManager.swift
@@ -17,16 +17,16 @@ import Foundation
import shared
class DataUploadManager {
- private let observationDataRepository = ObservationDataRepository()
private let semaphore = Semaphore()
private var currentlyUploading = false
func uploadData(completion: @escaping (Bool) -> Void) {
if !currentlyUploading {
currentlyUploading = true
- DispatchQueue.global(qos: .background).async {
+ DispatchQueue.global(qos: .background).async { [weak self] in
print("Fetching Data Bulk...")
- self.observationDataRepository.allAsBulk { [weak self] dataBulk in
+ let observationDataRepository = ObservationDataRepository()
+ observationDataRepository.allAsBulk { dataBulk in
if let dataBulk, !dataBulk.dataPoints.isEmpty {
print("Sending data to backend...")
AppDelegate.shared.networkService.iosSendData(data: dataBulk) { pair in
@@ -36,7 +36,7 @@ class DataUploadManager {
completion(false)
} else if let self, let idSet = pair.first as? Set {
print("Sent data! Deleting local data...")
- self.observationDataRepository.deleteAllWithId(idSet: idSet)
+ observationDataRepository.deleteAllWithId(idSet: idSet)
print("Deleted data!")
self.currentlyUploading = false
completion(true)
diff --git a/iosApp/iosApp/iosApp.entitlements b/iosApp/iosApp/iosApp.entitlements
index 39b021ea..c686016d 100644
--- a/iosApp/iosApp/iosApp.entitlements
+++ b/iosApp/iosApp/iosApp.entitlements
@@ -4,6 +4,8 @@
aps-environment
development
+ com.apple.developer.kernel.extended-virtual-addressing
+
com.apple.developer.kernel.increased-memory-limit
com.apple.developer.usernotifications.time-sensitive
diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts
index 824ae9df..a3fc65b3 100644
--- a/shared/build.gradle.kts
+++ b/shared/build.gradle.kts
@@ -14,8 +14,8 @@ val mobileAppApiOutputDir = "$openApiOutputDir/mobile_app_api"
val mobileAppApiPackage = "io.redlink.more.more_app_multiplatform.openapi"
val openapiIgnore = "$openApiInputDir/openapi-ignore"
-val coroutinesVersion = "1.7.3"
-val ktorVersion = "2.3.10"
+val coroutinesVersion = "1.8.1"
+val ktorVersion = "2.3.12"
val napierVersion = "2.7.1"
val serializationVersion = "1.6.0"
val gsonVersion = "2.10.1"
@@ -52,6 +52,7 @@ kotlin {
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
implementation("io.ktor:ktor-client-auth:$ktorVersion")
implementation("io.ktor:ktor-client-logging:$ktorVersion")
+ implementation("dev.tmapps:konnection:1.4.1")
}
commonTest.dependencies {
diff --git a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/RealmDatabase.kt b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/RealmDatabase.kt
index 3309a80a..4f172b50 100644
--- a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/RealmDatabase.kt
+++ b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/RealmDatabase.kt
@@ -20,12 +20,10 @@ import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.TypedRealmObject
import io.redlink.more.more_app_mutliplatform.extensions.asMappedFlow
import io.redlink.more.more_app_mutliplatform.extensions.firstAsFlow
-import io.redlink.more.more_app_mutliplatform.util.Scope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.sync.Mutex
-import kotlinx.coroutines.sync.withLock
import kotlin.reflect.KClass
private const val DB_SCHEMA_VERSION: Long = 4
@@ -54,23 +52,23 @@ object RealmDatabase {
fun store(
realmObjects: Collection,
- updatePolicy: UpdatePolicy = UpdatePolicy.ALL
- ) {
+ updatePolicy: UpdatePolicy = UpdatePolicy.ALL,
+ ): Int {
if (realmObjects.isNotEmpty()) {
- Scope.launch {
- mutex.withLock {
- realm?.write {
- realmObjects.forEach {
- try {
- copyToRealm(it, updatePolicy)
- } catch (e: Exception) {
- Napier.i { "Copy to Realm exception: $e" }
- }
- }
+ var storedObjects = realmObjects.size
+ realm?.writeBlocking {
+ realmObjects.forEach {
+ try {
+ copyToRealm(it, updatePolicy)
+ } catch (e: Exception) {
+ Napier.i { "Copy to Realm exception: $e" }
+ storedObjects--;
}
}
}
+ return storedObjects
}
+ return 0
}
inline fun count(): Flow {
diff --git a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/DataPointCountRepository.kt b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/DataPointCountRepository.kt
index b77e05bc..2d690e2b 100644
--- a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/DataPointCountRepository.kt
+++ b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/DataPointCountRepository.kt
@@ -13,38 +13,65 @@ package io.redlink.more.more_app_mutliplatform.database.repository
import io.realm.kotlin.ext.query
import io.redlink.more.more_app_mutliplatform.database.schemas.DataPointCountSchema
import io.redlink.more.more_app_mutliplatform.util.StudyScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.IO
+import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
class DataPointCountRepository : Repository() {
private val mutex = Mutex()
+ private val countQueue = mutableMapOf()
+ private var storeJob: Job? = null
+
override fun count(): Flow {
return realmDatabase().count()
}
fun incrementCount(scheduleIdSet: Set, addCount: Long = 1) {
if (scheduleIdSet.isNotEmpty()) {
- StudyScope.launch {
+ StudyScope.launch(Dispatchers.IO) {
mutex.withLock {
- realm()?.write {
- val dataPointCounts = this.query()
- .find()
- .filter { it.scheduleId in scheduleIdSet }
- val dataPointScheduleIds = dataPointCounts.map { it.scheduleId }.toSet()
- val (existing, nonExisting) = scheduleIdSet.partition { it in dataPointScheduleIds }
- existing.map { id ->
- dataPointCounts.firstOrNull { it.scheduleId == id }?.let {
- it.count += addCount
- }
- }
- nonExisting.map { id ->
- this.copyToRealm(DataPointCountSchema().apply {
- count = addCount
- this.scheduleId = id
- })
+ scheduleIdSet.forEach { scheduleId ->
+ countQueue[scheduleId] = countQueue.getOrElse(scheduleId) { 0 } + addCount
+ }
+ }
+ if (storeJob == null || storeJob?.isActive == false) {
+ storeJob = StudyScope.repeatedLaunch(5000L) {
+ storeCounts()
+ }.second
+ storeJob?.invokeOnCompletion {
+ storeJob = null
+ }
+ }
+ }
+ }
+ }
+
+ private suspend fun storeCounts() {
+ val countsToStore: Map
+ mutex.withLock {
+ countsToStore = countQueue.toMap()
+ countQueue.clear()
+ }
+ if (countsToStore.isNotEmpty()) {
+ StudyScope.launch {
+ realm()?.write {
+ val dataPointCounts = this.query().find()
+ val dataPointScheduleIds = dataPointCounts.map { it.scheduleId }.toSet()
+ val (existing, nonExisting) = countsToStore.keys.partition { it in dataPointScheduleIds }
+ existing.forEach { id ->
+ dataPointCounts.firstOrNull { it.scheduleId == id }?.let {
+ it.count += countsToStore[id] ?: 0
}
}
+ nonExisting.forEach { id ->
+ this.copyToRealm(DataPointCountSchema().apply {
+ count = countsToStore[id] ?: 0
+ this.scheduleId = id
+ })
+ }
}
}
}
diff --git a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/ObservationDataRepository.kt b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/ObservationDataRepository.kt
index f67bbded..017e2b61 100644
--- a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/ObservationDataRepository.kt
+++ b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/ObservationDataRepository.kt
@@ -16,6 +16,7 @@ import io.realm.kotlin.ext.query
import io.redlink.more.more_app_mutliplatform.database.schemas.ObservationDataSchema
import io.redlink.more.more_app_mutliplatform.extensions.mapAsBulkData
import io.redlink.more.more_app_mutliplatform.services.network.openapi.model.DataBulk
+import io.redlink.more.more_app_mutliplatform.util.Scope
import io.redlink.more.more_app_mutliplatform.util.StudyScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
@@ -28,14 +29,20 @@ class ObservationDataRepository : Repository() {
private var queue = mutableSetOf()
private val mutex = Mutex()
+
+ init {
+ Scope.repeatedLaunch(10000L) {
+ if (queue.isNotEmpty()) {
+ store()
+ }
+ }
+ }
+
fun addData(dataList: List) {
StudyScope.launch {
mutex.withLock {
queue.addAll(dataList)
}
- if (queue.size > QUEUE_THRESHOLD) {
- store()
- }
}
}
@@ -44,7 +51,7 @@ class ObservationDataRepository : Repository() {
StudyScope.launch {
val queueCopy = mutex.withLock {
val queueCopy = queue.toSet()
- queue = mutableSetOf()
+ queue.clear()
queueCopy
}
realmDatabase().store(queueCopy, UpdatePolicy.ERROR)
@@ -54,9 +61,8 @@ class ObservationDataRepository : Repository() {
override fun count() = realmDatabase().count()
-
suspend fun allAsBulk(): DataBulk? {
- return mutex().withLock {
+ return mutex.withLock {
realmDatabase().query(limit = 5000).firstOrNull()
?.mapAsBulkData()
}
@@ -71,14 +77,13 @@ class ObservationDataRepository : Repository() {
fun deleteAllWithId(idSet: Set) {
Napier.i { "Deleting ${idSet.size} elements..." }
val objectIdSet = idSet.map { ObjectId(it) }.toSet()
- StudyScope.launch {
- mutex().withLock {
+ StudyScope.launch(Dispatchers.IO) {
+ mutex.withLock {
realm()?.write {
this.query().find().filter { it.dataId in objectIdSet }
- .forEach {
- delete(it)
- }
+ .forEach { delete(it) }
}
+
}
}
}
diff --git a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/ObservationRepository.kt b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/ObservationRepository.kt
index a7232777..bd1ce9aa 100644
--- a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/ObservationRepository.kt
+++ b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/ObservationRepository.kt
@@ -16,6 +16,7 @@ import io.realm.kotlin.types.RealmInstant
import io.redlink.more.more_app_mutliplatform.database.schemas.ObservationSchema
import io.redlink.more.more_app_mutliplatform.database.schemas.ScheduleSchema
import io.redlink.more.more_app_mutliplatform.extensions.asClosure
+import io.redlink.more.more_app_mutliplatform.util.Scope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.firstOrNull
@@ -34,12 +35,21 @@ class ObservationRepository : Repository() {
}
fun lastCollection(type: String, timestamp: Long) {
+ Scope.launch {
+ realm()?.write {
+ this.query("observationType == $0", type)
+ .find()
+ .forEach {
+ it.collectionTimestamp = RealmInstant.from(timestamp, 0)
+ }
+ }
+ }
+ }
+
+ fun lastCollection(type: Set, timestamp: Long) {
realm()?.writeBlocking {
- this.query("observationType == $0", type)
- .find()
- .forEach {
- it.collectionTimestamp = RealmInstant.from(timestamp, 0)
- }
+ this.query("observationType IN $0", type).find()
+ .forEach { it.collectionTimestamp = RealmInstant.from(timestamp, 0) }
}
}
@@ -55,6 +65,17 @@ class ObservationRepository : Repository() {
fun collectAllTimestamps() =
observations().transform { emit(it.associate { it.observationType to it.collectionTimestamp }) }
+ fun collectTimestampForObservationIds(observationIds: Set) =
+ realmDatabase().queryAllWhereFieldInList(
+ "observationType",
+ observationIds
+ ).transform {
+ emit(
+ it.maxByOrNull { it.collectionTimestamp }?.collectionTimestamp
+ ?: RealmInstant.now()
+ )
+ }
+
fun collectTimestampOfType(type: String, newState: (RealmInstant?) -> Unit): Closeable {
return collectionTimestamp(type).asClosure(newState)
}
diff --git a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/ScheduleRepository.kt b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/ScheduleRepository.kt
index 971530d4..60fd7bd2 100644
--- a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/ScheduleRepository.kt
+++ b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/database/repository/ScheduleRepository.kt
@@ -20,14 +20,18 @@ import io.redlink.more.more_app_mutliplatform.extensions.areAllNamesIn
import io.redlink.more.more_app_mutliplatform.extensions.asClosure
import io.redlink.more.more_app_mutliplatform.extensions.asMappedFlow
import io.redlink.more.more_app_mutliplatform.extensions.firstAsFlow
+import io.redlink.more.more_app_mutliplatform.extensions.localDateTime
+import io.redlink.more.more_app_mutliplatform.extensions.toLocalDate
import io.redlink.more.more_app_mutliplatform.models.ScheduleState
import io.redlink.more.more_app_mutliplatform.observations.DataRecorder
import io.redlink.more.more_app_mutliplatform.observations.ObservationFactory
+import io.redlink.more.more_app_mutliplatform.observations.observationTypes.ObservationType
import io.redlink.more.more_app_mutliplatform.services.bluetooth.BluetoothDeviceManager
import io.redlink.more.more_app_mutliplatform.util.StudyScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.firstOrNull
+import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.transform
import kotlinx.datetime.Clock
import org.mongodb.kbson.ObjectId
@@ -66,6 +70,19 @@ class ScheduleRepository : Repository() {
} ?: emptyFlow()
}
+ fun allSchedulesToday(observationType: ObservationType): Flow> {
+ val today = Clock.System.now().localDateTime().date
+ return realm()?.query(
+ "observationType = $0",
+ observationType.observationType
+ )
+ ?.asMappedFlow()?.transform { list ->
+ emit(list.filter {
+ !it.getState().completed()
+ && (it.start?.toLocalDate() == today || it.end?.toLocalDate() == today)
+ })
+ } ?: flow { emit(emptyList()) }
+ }
fun firstScheduleIdAvailableForObservationId(observationId: String): Flow =
firstScheduleAvailableForObservationId(observationId).transform { it?.scheduleId?.toHexString() }
@@ -157,13 +174,14 @@ class ScheduleRepository : Repository() {
if (scheduleSchema.getState() != newState) {
Napier.i { "State update for Schema: $scheduleSchema; ${scheduleSchema.getState()} -> $newState" }
}
- if (autoStartingObservations.isNotEmpty()
- && scheduleSchema.hidden
- && newState.active()
- && scheduleSchema.observationType in autoStartingObservations
- && observationFactory.observation(scheduleSchema.observationType)
+ if (newState == ScheduleState.RUNNING
+ || (autoStartingObservations.isNotEmpty()
+ && scheduleSchema.hidden
+ && newState.active()
+ && scheduleSchema.observationType in autoStartingObservations
+ && observationFactory.observation(scheduleSchema.observationType)
?.bleDevicesNeeded()
- ?.areAllNamesIn(BluetoothDeviceManager.connectedDevices.value) != false
+ ?.areAllNamesIn(BluetoothDeviceManager.connectedDevices.value) != false)
) {
scheduleSchema.scheduleId.toHexString()
} else {
diff --git a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/extensions/RealmExtensions.kt b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/extensions/RealmExtensions.kt
index b50f6895..52478f14 100644
--- a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/extensions/RealmExtensions.kt
+++ b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/extensions/RealmExtensions.kt
@@ -11,14 +11,18 @@
package io.redlink.more.more_app_mutliplatform.extensions
import io.realm.kotlin.query.RealmQuery
+import io.realm.kotlin.types.RealmInstant
import io.realm.kotlin.types.TypedRealmObject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.transform
+import kotlinx.datetime.LocalDate
-fun RealmQuery.asMappedFlow(): Flow> {
+fun RealmQuery.asMappedFlow(): Flow> {
return asFlow().transform { emit(it.list) }
}
-fun RealmQuery.firstAsFlow(): Flow {
+fun RealmQuery.firstAsFlow(): Flow {
return first().asFlow().transform { emit(it.obj) }
-}
\ No newline at end of file
+}
+
+fun RealmInstant.toLocalDate(): LocalDate = this.toInstant().localDateTime().date
\ No newline at end of file
diff --git a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/observations/Observation.kt b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/observations/Observation.kt
index 0cc4ff45..bed41362 100644
--- a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/observations/Observation.kt
+++ b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/observations/Observation.kt
@@ -11,6 +11,7 @@
package io.redlink.more.more_app_mutliplatform.observations
import io.github.aakira.napier.Napier
+import io.redlink.more.more_app_mutliplatform.database.repository.ObservationRepository
import io.redlink.more.more_app_mutliplatform.database.repository.ScheduleRepository
import io.redlink.more.more_app_mutliplatform.database.schemas.NotificationSchema
import io.redlink.more.more_app_mutliplatform.database.schemas.ObservationDataSchema
@@ -20,10 +21,12 @@ import io.redlink.more.more_app_mutliplatform.services.notification.Notification
import io.redlink.more.more_app_mutliplatform.util.StudyScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
+import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.withContext
import kotlinx.datetime.Clock
@@ -33,6 +36,7 @@ abstract class Observation(val observationType: ObservationType) {
private val scheduleRepository = ScheduleRepository()
private var dataManager: ObservationDataManager? = null
private var notificationManager: NotificationManager? = null
+ private val observationRepository = ObservationRepository()
private var running = false
private val observationIds = mutableSetOf()
@@ -43,6 +47,8 @@ abstract class Observation(val observationType: ObservationType) {
protected var lastCollectionTimestamp: Instant = Clock.System.now()
+ var timestampCollectionJob: Job? = null
+
private val _observationErrors = MutableStateFlow>>(
Pair(
this.observationType.observationType,
@@ -53,6 +59,16 @@ abstract class Observation(val observationType: ObservationType) {
fun start(observationId: String, scheduleId: String, notificationId: String? = null): Boolean {
observationIds.add(observationId)
+ timestampCollectionJob?.cancel()
+ timestampCollectionJob = StudyScope.launch {
+ observationRepository.collectTimestampForObservationIds(observationIds).collect {
+ lastCollectionTimestamp = Instant.fromEpochSeconds(it.epochSeconds)
+ Napier.d(tag = "Observation::start") { "Last collection $lastCollectionTimestamp" }
+ }
+ }.second
+ timestampCollectionJob?.invokeOnCompletion {
+ timestampCollectionJob = null
+ }
scheduleIds[scheduleId] = observationId
notificationId?.let {
notificationIds[scheduleId] = notificationId
@@ -73,6 +89,7 @@ abstract class Observation(val observationType: ObservationType) {
Napier.i(tag = "Observation::stop") { "Stopping observation of type ${observationType.observationType} for schedule $scheduleId." }
if (observationIds.size <= 1) {
stop {
+ timestampCollectionJob?.cancel()
saveAndSend()
observationShutdown(scheduleId)
}
@@ -115,7 +132,12 @@ abstract class Observation(val observationType: ObservationType) {
}
protected fun collectionTimestampToNow() {
- this.lastCollectionTimestamp = Clock.System.now()
+ Napier.d(tag = "Observation::collectionTimeStampToNow") { "Collecting timestamp" }
+ lastCollectionTimestamp = Clock.System.now()
+ observationRepository.lastCollection(
+ observationIds.toSet(),
+ lastCollectionTimestamp.epochSeconds
+ )
}
protected abstract fun start(): Boolean
@@ -125,7 +147,7 @@ abstract class Observation(val observationType: ObservationType) {
fun observerAccessible(): Boolean {
val errors = observerErrors()
Napier.d(tag = "Observation::observerAccessible") { errors.toString() }
- this._observationErrors.update { Pair(observationType.observationType, errors) }
+ updateObservationErrors()
return errors.isEmpty()
}
@@ -133,8 +155,18 @@ abstract class Observation(val observationType: ObservationType) {
fun updateObservationErrors() {
StudyScope.launch(Dispatchers.IO) {
- Napier.d(tag = "Observation::updateObservationErrors") { "ObservationErrors for ${observationType.observationType}" }
- _observationErrors.update { Pair(observationType.observationType, observerErrors()) }
+ scheduleRepository.allSchedulesToday(observationType).firstOrNull()?.let {
+ if (it.isNotEmpty()) {
+ Napier.d(tag = "Observation::updateObservationErrors") { "ObservationErrors for ${observationType.observationType}" }
+
+ _observationErrors.update {
+ Pair(
+ observationType.observationType,
+ observerErrors()
+ )
+ }
+ }
+ }
}
}
@@ -164,6 +196,7 @@ abstract class Observation(val observationType: ObservationType) {
fun stopAndFinish(scheduleId: String) {
Napier.i(tag = "Observation::stopAndFinish") { "Stopping and finishing observation ${observationType.observationType} for observationIds: $observationIds" }
stop {
+ timestampCollectionJob?.cancel()
saveAndSend()
observationShutdown(scheduleId)
}
@@ -173,6 +206,7 @@ abstract class Observation(val observationType: ObservationType) {
fun stopAndSetState(state: ScheduleState = ScheduleState.ACTIVE, scheduleId: String?) {
Napier.d(tag = "Observation::stopAndSetState") { "Stopping observation of type ${observationType.observationType} and setting state to $state for schedule $scheduleId." }
stop {
+ timestampCollectionJob?.cancel()
saveAndSend()
scheduleIds.keys.forEach { scheduleRepository.setRunningStateFor(it, state) }
scheduleId?.let {
@@ -185,6 +219,7 @@ abstract class Observation(val observationType: ObservationType) {
fun stopAndSetDone(scheduleId: String) {
Napier.d(tag = "Observation::stopAndSetDone") { "Stopping observation of type ${observationType.observationType} and setting done for schedule $scheduleId." }
stop {
+ timestampCollectionJob?.cancel()
saveAndSend()
scheduleIds.keys.forEach { scheduleRepository.setCompletionStateFor(it, true) }
observationShutdown(scheduleId)
diff --git a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/observations/ObservationDataManager.kt b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/observations/ObservationDataManager.kt
index 50bc59b1..20f9d17c 100644
--- a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/observations/ObservationDataManager.kt
+++ b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/observations/ObservationDataManager.kt
@@ -10,33 +10,26 @@
*/
package io.redlink.more.more_app_mutliplatform.observations
+import dev.tmapps.konnection.Konnection
import io.github.aakira.napier.Napier
import io.redlink.more.more_app_mutliplatform.database.repository.DataPointCountRepository
import io.redlink.more.more_app_mutliplatform.database.repository.ObservationDataRepository
-import io.redlink.more.more_app_mutliplatform.database.repository.ObservationRepository
import io.redlink.more.more_app_mutliplatform.database.schemas.ObservationDataSchema
import io.redlink.more.more_app_mutliplatform.util.Scope
-import io.redlink.more.more_app_mutliplatform.util.StudyScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
-import kotlinx.coroutines.flow.cancellable
+import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.firstOrNull
-import kotlinx.coroutines.sync.Mutex
-import kotlinx.coroutines.sync.withLock
-import kotlinx.datetime.Clock
abstract class ObservationDataManager {
- private val mutex = Mutex()
- private val timeStampMutex = Mutex()
private val observationDataRepository = ObservationDataRepository()
- private val observationRepository = ObservationRepository()
private val dataPointCountRepository = DataPointCountRepository()
- private var countJob: String? = null
- private var scheduleCountJob: String? = null
- private var observationTimestampJob: String? = null
+ private var countJob: Job? = null
private var scheduleCount = mutableMapOf()
- private var observationCollectionTimestamp = mutableMapOf()
+ private val konnection = Konnection.instance
+
+ private var uploadJob: Job? = null
init {
Napier.i(tag = "ObservationDataManager::init") { "ObservationDataManager init!" }
@@ -46,123 +39,58 @@ abstract class ObservationDataManager {
if (dataList.isNotEmpty()) {
Napier.i(tag = "ObservationDataManager::add") { "Adding ${dataList.size} observations for schedule IDs: $scheduleIdList" }
observationDataRepository.addData(dataList)
- if (scheduleCountJob == null) {
- listenToDatapointCountChanges()
- }
- StudyScope.launch(Dispatchers.IO) {
- mutex.withLock {
- if (countJob == null) {
- listenToDatapointCountChanges()
- }
- scheduleIdList.forEach {
- scheduleCount[it] = scheduleCount.getOrElse(it) { 0 } + dataList.size
- }
- }
- }
- StudyScope.launch {
- val now = Clock.System.now().epochSeconds
- val ids = dataList.map { it.observationId }.toSet()
- if (observationTimestampJob == null) {
- listenToDatapointCountChanges()
- }
- timeStampMutex.withLock {
- ids.forEach {
- observationCollectionTimestamp[it] = now
- }
- }
- }
+ dataPointCountRepository.incrementCount(scheduleIdList, dataList.size.toLong())
}
}
fun saveAndSend() {
Napier.i(tag = "ObservationDataManager::saveAndSend") { "Saving and sending observations" }
- StudyScope.launch {
- observationDataRepository.store()
- observationDataRepository.count().firstOrNull()?.let {
- if (it in 1 until DATA_COUNT_THRESHOLD) {
- sendData()
- }
- }
- }
+ observationDataRepository.store()
}
fun store() {
Napier.i(tag = "ObservationDataManager::store") { "Storing observations" }
observationDataRepository.store()
- storeCount()
- storeTimestamps()
- }
-
- private fun storeCount() {
- if (scheduleCount.isNotEmpty()) {
- Napier.i(tag = "ObservationDataManager::storeCount") { "Storing count of observations" }
- StudyScope.launch {
- val copiedScheduleCount = mutex.withLock {
- val copiedScheduleCount = scheduleCount.toMap()
- scheduleCount = mutableMapOf()
- copiedScheduleCount
- }
- copiedScheduleCount.forEach {
- dataPointCountRepository.incrementCount(setOf(it.key), it.value)
- }
- }
- }
- }
-
- private fun storeTimestamps() {
- if (observationCollectionTimestamp.isNotEmpty()) {
- Napier.d(tag = "ObservationDataManager::storeTimestamps") { "Storing timestamps of observations" }
- StudyScope.launch {
- val copiedMap = timeStampMutex.withLock {
- val copiedMap = observationCollectionTimestamp.toMap()
- observationCollectionTimestamp = mutableMapOf()
- copiedMap
- }
- copiedMap.forEach {
- observationRepository.lastCollection(it.key, it.value)
- }
- }
- }
}
fun removeDataPointCount(scheduleId: String) {
Napier.d(tag = "ObservationDataManager::removeDataPointCount") { "Removing datapoint count for schedule ID: $scheduleId" }
scheduleCount.remove(scheduleId)
- observationCollectionTimestamp.remove(scheduleId)
}
abstract fun sendData(onCompletion: (Boolean) -> Unit = {})
fun listenToDatapointCountChanges() {
- Napier.d(tag = "ObservationDataManager::listenToDatapointCountChanges") { "Starting to listen for changes in datapoint counts" }
- if (countJob == null || Scope.isActive(countJob!!)) {
+ if (countJob == null) {
+ Napier.d(tag = "ObservationDataManager::listenToDatapointCountChanges") { "Starting to listen for changes in datapoint counts" }
countJob = Scope.repeatedLaunch(10000) {
- observationDataRepository.count().cancellable().firstOrNull()?.let {
- if (it > 0) {
- Napier.d(tag = "ObservationDataManager::listenToDatapointCountChanges") { "Observation data count: $it! Sending data..." }
- sendData()
+ if (konnection.isConnected() && (uploadJob == null || uploadJob?.isActive == false)) {
+ observationDataRepository.count().firstOrNull()?.let {
+ if (it > 0) {
+ Napier.d(tag = "ObservationDataManager::listenToDatapointCountChanges") { "Observation data count: $it! Sending data..." }
+ uploadJob = Scope.launch(Dispatchers.IO) {
+ sendData()
+ }.second
+ uploadJob?.invokeOnCompletion {
+ uploadJob = null
+ }
+ }
}
+ } else {
+ Napier.d(tag = "ObservationDataManager::listenToDatapointCountChanges") { "No conncetion" }
+ uploadJob?.cancel()
}
- }.first
- }
- if (scheduleCountJob == null || Scope.isActive(scheduleCountJob!!)) {
- scheduleCountJob = Scope.repeatedLaunch(5000) {
- storeCount()
- }.first
- }
- if (observationTimestampJob == null || Scope.isActive(observationTimestampJob!!)) {
- observationTimestampJob = Scope.repeatedLaunch(15000) {
- storeTimestamps()
- }.first
+ }.second
+ countJob?.invokeOnCompletion {
+ countJob = null
+ }
}
}
fun stopListeningToCountChanges() {
Napier.d(tag = "ObservationDataManager::stopListeningToCountChanges") { "Stopped listening for changes in datapoint counts" }
- Scope.cancel(setOf(countJob, scheduleCountJob, observationTimestampJob).filterNotNull())
+ countJob?.cancel()
countJob = null
- scheduleCountJob = null
- observationTimestampJob = null
}
private fun deleteAll(idSet: Set) {
diff --git a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/observations/ObservationManager.kt b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/observations/ObservationManager.kt
index 177ee448..152dd99e 100644
--- a/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/observations/ObservationManager.kt
+++ b/shared/src/commonMain/kotlin/io/redlink/more/more_app_mutliplatform/observations/ObservationManager.kt
@@ -244,7 +244,7 @@ class ObservationManager(
onCompletion(true)
}
}
- } ?: kotlin.run {
+ } ?: run {
if (++counter == runningObservations.size) {
onCompletion(true)
}
diff --git a/shared/src/iosMain/kotlin/io/redlink/more/more_app_mutliplatform/services/network/HttpClientReceiver.kt b/shared/src/iosMain/kotlin/io/redlink/more/more_app_mutliplatform/services/network/HttpClientReceiver.kt
index b5b5d7d3..48e00bf4 100644
--- a/shared/src/iosMain/kotlin/io/redlink/more/more_app_mutliplatform/services/network/HttpClientReceiver.kt
+++ b/shared/src/iosMain/kotlin/io/redlink/more/more_app_mutliplatform/services/network/HttpClientReceiver.kt
@@ -10,16 +10,20 @@
*/
package io.redlink.more.more_app_mutliplatform.services.network
-import io.ktor.client.*
-import io.ktor.client.engine.darwin.*
-import io.ktor.client.plugins.*
-import io.ktor.client.plugins.auth.*
-import io.ktor.client.plugins.auth.providers.*
-import io.ktor.client.plugins.contentnegotiation.*
-import io.ktor.client.plugins.logging.*
-import io.ktor.client.request.*
-import io.ktor.http.*
-import io.ktor.serialization.kotlinx.json.*
+import io.ktor.client.HttpClient
+import io.ktor.client.engine.darwin.Darwin
+import io.ktor.client.plugins.auth.Auth
+import io.ktor.client.plugins.auth.providers.basic
+import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
+import io.ktor.client.plugins.defaultRequest
+import io.ktor.client.plugins.logging.LogLevel
+import io.ktor.client.plugins.logging.Logger
+import io.ktor.client.plugins.logging.Logging
+import io.ktor.client.plugins.retry
+import io.ktor.client.request.request
+import io.ktor.http.ContentType
+import io.ktor.http.contentType
+import io.ktor.serialization.kotlinx.json.json
actual fun getHttpClient(customLogger: Logger): HttpClient = HttpClient(Darwin) {
install(ContentNegotiation) {
@@ -29,6 +33,9 @@ actual fun getHttpClient(customLogger: Logger): HttpClient = HttpClient(Darwin)
}
request {
contentType(ContentType.Application.Json)
+ retry {
+ maxRetries = 3
+ }
}
Logging {
logger = customLogger