Refactoring to improve legibility and compose stability of FhirResources
This commit is contained in:
@@ -20,8 +20,14 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.note
|
package com.vitorpamplona.amethyst.ui.note
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import com.fasterxml.jackson.annotation.JsonSubTypes
|
import com.fasterxml.jackson.annotation.JsonSubTypes
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeInfo
|
import com.fasterxml.jackson.annotation.JsonTypeInfo
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||||
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
|
import kotlinx.collections.immutable.ImmutableMap
|
||||||
|
import kotlinx.collections.immutable.persistentMapOf
|
||||||
|
import kotlinx.collections.immutable.toImmutableMap
|
||||||
|
|
||||||
@JsonTypeInfo(
|
@JsonTypeInfo(
|
||||||
use = JsonTypeInfo.Id.NAME,
|
use = JsonTypeInfo.Id.NAME,
|
||||||
@@ -110,6 +116,11 @@ class Reference(
|
|||||||
var reference: String? = null,
|
var reference: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class FhirElementDatabase(
|
||||||
|
var baseResource: Resource? = null,
|
||||||
|
var localDb: ImmutableMap<String, Resource> = persistentMapOf(),
|
||||||
|
)
|
||||||
|
|
||||||
fun findReferenceInDb(
|
fun findReferenceInDb(
|
||||||
it: String,
|
it: String,
|
||||||
db: Map<String, Resource>,
|
db: Map<String, Resource>,
|
||||||
@@ -121,3 +132,30 @@ fun findReferenceInDb(
|
|||||||
db.get(it.removePrefix("#"))
|
db.get(it.removePrefix("#"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun parseResourceBundleOrNull(json: String): FhirElementDatabase? {
|
||||||
|
val mapper =
|
||||||
|
jacksonObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||||
|
|
||||||
|
return try {
|
||||||
|
val resource = mapper.readValue(json, Resource::class.java)
|
||||||
|
|
||||||
|
val db =
|
||||||
|
when (resource) {
|
||||||
|
is Bundle -> {
|
||||||
|
resource.entry.associateBy { it.id }.toImmutableMap()
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
persistentMapOf(resource.id to resource)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FhirElementDatabase(
|
||||||
|
localDb = db,
|
||||||
|
baseResource = resource,
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("RenderEyeGlassesPrescription", "Parser error", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -99,8 +99,6 @@ import androidx.lifecycle.map
|
|||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import coil.compose.AsyncImagePainter
|
import coil.compose.AsyncImagePainter
|
||||||
import coil.request.SuccessResult
|
import coil.request.SuccessResult
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
|
||||||
import com.fonfon.kgeohash.toGeoHash
|
import com.fonfon.kgeohash.toGeoHash
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.commons.BaseMediaContent
|
import com.vitorpamplona.amethyst.commons.BaseMediaContent
|
||||||
@@ -131,7 +129,6 @@ import com.vitorpamplona.amethyst.ui.components.VideoView
|
|||||||
import com.vitorpamplona.amethyst.ui.components.ZoomableContentView
|
import com.vitorpamplona.amethyst.ui.components.ZoomableContentView
|
||||||
import com.vitorpamplona.amethyst.ui.components.ZoomableImageDialog
|
import com.vitorpamplona.amethyst.ui.components.ZoomableImageDialog
|
||||||
import com.vitorpamplona.amethyst.ui.components.measureSpaceWidth
|
import com.vitorpamplona.amethyst.ui.components.measureSpaceWidth
|
||||||
import com.vitorpamplona.amethyst.ui.components.mockAccountViewModel
|
|
||||||
import com.vitorpamplona.amethyst.ui.elements.AddButton
|
import com.vitorpamplona.amethyst.ui.elements.AddButton
|
||||||
import com.vitorpamplona.amethyst.ui.elements.DisplayFollowingCommunityInPost
|
import com.vitorpamplona.amethyst.ui.elements.DisplayFollowingCommunityInPost
|
||||||
import com.vitorpamplona.amethyst.ui.elements.DisplayFollowingHashtagsInPost
|
import com.vitorpamplona.amethyst.ui.elements.DisplayFollowingHashtagsInPost
|
||||||
@@ -244,6 +241,7 @@ import com.vitorpamplona.quartz.events.VideoVerticalEvent
|
|||||||
import com.vitorpamplona.quartz.events.WikiNoteEvent
|
import com.vitorpamplona.quartz.events.WikiNoteEvent
|
||||||
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.ImmutableMap
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -4430,12 +4428,9 @@ fun CreateImageHeader(
|
|||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun RenderEyeGlassesPrescriptionPreview() {
|
fun RenderEyeGlassesPrescriptionPreview() {
|
||||||
val accountViewModel = mockAccountViewModel()
|
|
||||||
val nav: (String) -> Unit = {}
|
|
||||||
|
|
||||||
val prescriptionEvent = Event.fromJson("{\"id\":\"0c15d2bc6f7dcc42fa4426d35d30d09840c9afa5b46d100415006e41d6471416\",\"pubkey\":\"bcd4715cc34f98dce7b52fddaf1d826e5ce0263479b7e110a5bd3c3789486ca8\",\"created_at\":1709074097,\"kind\":82,\"tags\":[],\"content\":\"{\\\"resourceType\\\":\\\"Bundle\\\",\\\"id\\\":\\\"bundle-vision-test\\\",\\\"type\\\":\\\"document\\\",\\\"entry\\\":[{\\\"resourceType\\\":\\\"Practitioner\\\",\\\"id\\\":\\\"2\\\",\\\"active\\\":true,\\\"name\\\":[{\\\"use\\\":\\\"official\\\",\\\"family\\\":\\\"Careful\\\",\\\"given\\\":[\\\"Adam\\\"]}],\\\"gender\\\":\\\"male\\\"},{\\\"resourceType\\\":\\\"Patient\\\",\\\"id\\\":\\\"1\\\",\\\"active\\\":true,\\\"name\\\":[{\\\"use\\\":\\\"official\\\",\\\"family\\\":\\\"Duck\\\",\\\"given\\\":[\\\"Donald\\\"]}],\\\"gender\\\":\\\"male\\\"},{\\\"resourceType\\\":\\\"VisionPrescription\\\",\\\"status\\\":\\\"active\\\",\\\"created\\\":\\\"2014-06-15\\\",\\\"patient\\\":{\\\"reference\\\":\\\"#1\\\"},\\\"dateWritten\\\":\\\"2014-06-15\\\",\\\"prescriber\\\":{\\\"reference\\\":\\\"#2\\\"},\\\"lensSpecification\\\":[{\\\"eye\\\":\\\"right\\\",\\\"sphere\\\":-2,\\\"prism\\\":[{\\\"amount\\\":0.5,\\\"base\\\":\\\"down\\\"}],\\\"add\\\":2},{\\\"eye\\\":\\\"left\\\",\\\"sphere\\\":-1,\\\"cylinder\\\":-0.5,\\\"axis\\\":180,\\\"prism\\\":[{\\\"amount\\\":0.5,\\\"base\\\":\\\"up\\\"}],\\\"add\\\":2}]}]}\",\"sig\":\"dc58f6109111ca06920c0c711aeaf8e2ee84975afa60d939828d4e01e2edea738f735fb5b1fcadf6d5496e36ac429abf7020a55fd1e4ed215738afc8d07cb950\"}") as FhirResourceEvent
|
val prescriptionEvent = Event.fromJson("{\"id\":\"0c15d2bc6f7dcc42fa4426d35d30d09840c9afa5b46d100415006e41d6471416\",\"pubkey\":\"bcd4715cc34f98dce7b52fddaf1d826e5ce0263479b7e110a5bd3c3789486ca8\",\"created_at\":1709074097,\"kind\":82,\"tags\":[],\"content\":\"{\\\"resourceType\\\":\\\"Bundle\\\",\\\"id\\\":\\\"bundle-vision-test\\\",\\\"type\\\":\\\"document\\\",\\\"entry\\\":[{\\\"resourceType\\\":\\\"Practitioner\\\",\\\"id\\\":\\\"2\\\",\\\"active\\\":true,\\\"name\\\":[{\\\"use\\\":\\\"official\\\",\\\"family\\\":\\\"Careful\\\",\\\"given\\\":[\\\"Adam\\\"]}],\\\"gender\\\":\\\"male\\\"},{\\\"resourceType\\\":\\\"Patient\\\",\\\"id\\\":\\\"1\\\",\\\"active\\\":true,\\\"name\\\":[{\\\"use\\\":\\\"official\\\",\\\"family\\\":\\\"Duck\\\",\\\"given\\\":[\\\"Donald\\\"]}],\\\"gender\\\":\\\"male\\\"},{\\\"resourceType\\\":\\\"VisionPrescription\\\",\\\"status\\\":\\\"active\\\",\\\"created\\\":\\\"2014-06-15\\\",\\\"patient\\\":{\\\"reference\\\":\\\"#1\\\"},\\\"dateWritten\\\":\\\"2014-06-15\\\",\\\"prescriber\\\":{\\\"reference\\\":\\\"#2\\\"},\\\"lensSpecification\\\":[{\\\"eye\\\":\\\"right\\\",\\\"sphere\\\":-2,\\\"prism\\\":[{\\\"amount\\\":0.5,\\\"base\\\":\\\"down\\\"}],\\\"add\\\":2},{\\\"eye\\\":\\\"left\\\",\\\"sphere\\\":-1,\\\"cylinder\\\":-0.5,\\\"axis\\\":180,\\\"prism\\\":[{\\\"amount\\\":0.5,\\\"base\\\":\\\"up\\\"}],\\\"add\\\":2}]}]}\",\"sig\":\"dc58f6109111ca06920c0c711aeaf8e2ee84975afa60d939828d4e01e2edea738f735fb5b1fcadf6d5496e36ac429abf7020a55fd1e4ed215738afc8d07cb950\"}") as FhirResourceEvent
|
||||||
|
|
||||||
RenderFhirResource(prescriptionEvent, accountViewModel, nav)
|
RenderFhirResource(prescriptionEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -4446,45 +4441,30 @@ fun RenderFhirResource(
|
|||||||
) {
|
) {
|
||||||
val event = baseNote.event as? FhirResourceEvent ?: return
|
val event = baseNote.event as? FhirResourceEvent ?: return
|
||||||
|
|
||||||
RenderFhirResource(event, accountViewModel, nav)
|
RenderFhirResource(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RenderFhirResource(
|
fun RenderFhirResource(event: FhirResourceEvent) {
|
||||||
event: FhirResourceEvent,
|
val state by produceState(initialValue = FhirElementDatabase(), key1 = event) {
|
||||||
accountViewModel: AccountViewModel,
|
withContext(Dispatchers.Default) {
|
||||||
nav: (String) -> Unit,
|
parseResourceBundleOrNull(event.content)?.let {
|
||||||
) {
|
value = it
|
||||||
var baseResource: Resource? by remember(event) {
|
|
||||||
mutableStateOf(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(key1 = event) {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
val mapper =
|
|
||||||
jacksonObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
|
||||||
|
|
||||||
try {
|
|
||||||
baseResource = mapper.readValue(event.content, Resource::class.java)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e("RenderEyeGlassesPrescription", "Parser error", e)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
baseResource?.let { resource ->
|
state.baseResource?.let { resource ->
|
||||||
when (resource) {
|
when (resource) {
|
||||||
is Bundle -> {
|
is Bundle -> {
|
||||||
val db = resource.entry.associate { it.id to it }
|
|
||||||
val vision = resource.entry.filterIsInstance(VisionPrescription::class.java)
|
val vision = resource.entry.filterIsInstance(VisionPrescription::class.java)
|
||||||
|
|
||||||
vision.firstOrNull()?.let {
|
vision.firstOrNull()?.let {
|
||||||
RenderEyeGlassesPrescription(it, db, accountViewModel, nav)
|
RenderEyeGlassesPrescription(it, state.localDb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is VisionPrescription -> {
|
is VisionPrescription -> {
|
||||||
val db = mapOf(resource.id to resource)
|
RenderEyeGlassesPrescription(resource, state.localDb)
|
||||||
RenderEyeGlassesPrescription(resource, db, accountViewModel, nav)
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
}
|
}
|
||||||
@@ -4495,9 +4475,7 @@ fun RenderFhirResource(
|
|||||||
@Composable
|
@Composable
|
||||||
fun RenderEyeGlassesPrescription(
|
fun RenderEyeGlassesPrescription(
|
||||||
visionPrescription: VisionPrescription,
|
visionPrescription: VisionPrescription,
|
||||||
db: Map<String, Resource>,
|
db: ImmutableMap<String, Resource>,
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: (String) -> Unit,
|
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier =
|
modifier =
|
||||||
|
|||||||
Reference in New Issue
Block a user