diff --git a/data/src/commonMain/kotlin/ca/gosyer/jui/data/DataComponent.kt b/data/src/commonMain/kotlin/ca/gosyer/jui/data/DataComponent.kt index 36558ce3..26d62562 100644 --- a/data/src/commonMain/kotlin/ca/gosyer/jui/data/DataComponent.kt +++ b/data/src/commonMain/kotlin/ca/gosyer/jui/data/DataComponent.kt @@ -26,10 +26,10 @@ import me.tatarka.inject.annotations.Provides interface DataComponent { @Provides - fun ktorfit(http: Http, serverPreferences: ServerPreferences) = Ktorfit + fun ktorfit(http: Http, serverPreferences: ServerPreferences, flowIOResponseConverter: FlowIOResponseConverter) = Ktorfit .Builder() .httpClient(http) - .responseConverter(FlowIOResponseConverter()) + .responseConverter(flowIOResponseConverter) .baseUrl(serverPreferences.serverUrl().get().toString().addSuffix('/')) .build() diff --git a/data/src/commonMain/kotlin/ca/gosyer/jui/data/FlowIOResponseConverter.kt b/data/src/commonMain/kotlin/ca/gosyer/jui/data/FlowIOResponseConverter.kt index 61cabac2..7dee634a 100644 --- a/data/src/commonMain/kotlin/ca/gosyer/jui/data/FlowIOResponseConverter.kt +++ b/data/src/commonMain/kotlin/ca/gosyer/jui/data/FlowIOResponseConverter.kt @@ -10,14 +10,15 @@ import ca.gosyer.jui.core.lang.IO import de.jensklingenberg.ktorfit.Ktorfit import de.jensklingenberg.ktorfit.converter.request.ResponseConverter import de.jensklingenberg.ktorfit.internal.TypeData -import io.ktor.client.call.body import io.ktor.client.statement.HttpResponse import io.ktor.util.reflect.TypeInfo import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn +import kotlinx.serialization.json.Json +import me.tatarka.inject.annotations.Inject -class FlowIOResponseConverter : ResponseConverter { +class FlowIOResponseConverter @Inject constructor(private val json: Json) : ResponseConverter { override fun supportedType(typeData: TypeData, isSuspend: Boolean): Boolean { return typeData.qualifiedName == "kotlinx.coroutines.flow.Flow" @@ -34,7 +35,7 @@ class FlowIOResponseConverter : ResponseConverter { if (info.type == HttpResponse::class) { emit(response!!) } else { - emit(response!!.body(info)) + emit(decodeType(response!!, info, json)) } } catch (exception: Exception) { throw exception @@ -42,3 +43,5 @@ class FlowIOResponseConverter : ResponseConverter { }.flowOn(Dispatchers.IO) } } + +expect suspend fun decodeType(response: HttpResponse, typeInfo: TypeInfo, json: Json): Any \ No newline at end of file diff --git a/data/src/iosMain/kotlin/ca/gosyer/jui/data/IosFlowIOResponseConverter.kt b/data/src/iosMain/kotlin/ca/gosyer/jui/data/IosFlowIOResponseConverter.kt new file mode 100644 index 00000000..9e2df7c6 --- /dev/null +++ b/data/src/iosMain/kotlin/ca/gosyer/jui/data/IosFlowIOResponseConverter.kt @@ -0,0 +1,17 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package ca.gosyer.jui.data + +import io.ktor.client.statement.HttpResponse +import io.ktor.client.statement.bodyAsText +import io.ktor.util.reflect.TypeInfo +import kotlinx.serialization.json.Json +import kotlinx.serialization.serializer + +actual suspend fun decodeType(response: HttpResponse, typeInfo: TypeInfo, json: Json): Any { + return json.decodeFromString(serializer(typeInfo.kotlinType!!), response.bodyAsText())!! +} \ No newline at end of file diff --git a/data/src/jvmMain/kotlin/ca/gosyer/jui/data/JvmFlowIOResponseConverter.kt b/data/src/jvmMain/kotlin/ca/gosyer/jui/data/JvmFlowIOResponseConverter.kt new file mode 100644 index 00000000..3d7980bf --- /dev/null +++ b/data/src/jvmMain/kotlin/ca/gosyer/jui/data/JvmFlowIOResponseConverter.kt @@ -0,0 +1,16 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package ca.gosyer.jui.data + +import io.ktor.client.call.body +import io.ktor.client.statement.HttpResponse +import io.ktor.util.reflect.TypeInfo +import kotlinx.serialization.json.Json + +actual suspend fun decodeType(response: HttpResponse, typeInfo: TypeInfo, json: Json): Any { + return response.body(typeInfo) +} \ No newline at end of file diff --git a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/SharedDomainComponent.kt b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/SharedDomainComponent.kt index 601739be..75a7fa12 100644 --- a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/SharedDomainComponent.kt +++ b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/SharedDomainComponent.kt @@ -22,6 +22,7 @@ import ca.gosyer.jui.domain.source.service.CatalogPreferences import ca.gosyer.jui.domain.ui.service.UiPreferences import ca.gosyer.jui.domain.updates.interactor.UpdateChecker import ca.gosyer.jui.domain.updates.service.UpdatePreferences +import kotlinx.serialization.json.Json import me.tatarka.inject.annotations.Provides interface SharedDomainComponent : CoreComponent { @@ -58,6 +59,8 @@ interface SharedDomainComponent : CoreComponent { val serverListeners: ServerListeners + val json: Json + @get:AppScope @get:Provides val serverPreferencesFactory: ServerPreferences @@ -103,7 +106,7 @@ interface SharedDomainComponent : CoreComponent { @get:AppScope @get:Provides val httpFactory: Http - get() = httpProvider.get(serverPreferences) + get() = httpProvider.get() @get:AppScope @get:Provides @@ -119,4 +122,14 @@ interface SharedDomainComponent : CoreComponent { @get:Provides val serverListenersFactory: ServerListeners get() = ServerListeners() + + @get:AppScope + @get:Provides + val jsonFactory: Json + get() = Json { + isLenient = false + ignoreUnknownKeys = true + allowSpecialFloatingPointValues = true + useArrayPolymorphism = false + } } diff --git a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/server/HttpClient.kt b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/server/HttpClient.kt index cabd004f..a9b29877 100644 --- a/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/server/HttpClient.kt +++ b/domain/src/commonMain/kotlin/ca/gosyer/jui/domain/server/HttpClient.kt @@ -41,8 +41,11 @@ expect val Engine: HttpClientEngineFactory expect fun HttpClientConfig.configurePlatform() -class HttpProvider @Inject constructor() { - fun get(serverPreferences: ServerPreferences): Http { +class HttpProvider @Inject constructor( + private val serverPreferences: ServerPreferences, + private val json: Json +) { + fun get(): Http { return HttpClient(Engine) { configurePlatform() @@ -95,14 +98,7 @@ class HttpProvider @Inject constructor() { socketTimeoutMillis = 2.minutes.inWholeMilliseconds } install(ContentNegotiation) { - json( - Json { - isLenient = false - ignoreUnknownKeys = true - allowSpecialFloatingPointValues = true - useArrayPolymorphism = false - } - ) + json(json) } install(WebSockets) install(Logging) {