From 4a334c91d3b401c802503cafd2c327f63c60af8b Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sat, 18 Nov 2023 14:53:48 +0100 Subject: [PATCH 01/38] Update all dependencies. --- gradle/libs.versions.toml | 86 ++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 50 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 75f718b49..cb32e8463 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,89 +1,72 @@ [versions] accompanist = "0.33.2-alpha" -agp = "8.1.2" -appauth = "0.8.1" -atomicfu = "0.21.0" - +agp = "8.1.3" androidx-activity = "1.8.0" -androidx-appCompat = "1.5.1" androidx-browser = "1.6.0" androidx-core = "1.12.0" androidx-core-splashscreen = "1.0.1" -androidx-datastore = "1.1.0-alpha05" +androidx-datastore = "1.1.0-alpha06" androidx-lifecycle = "2.6.2" androidx-material3 = "1.1.2" -androidx-navigation = "2.7.4" +androidx-navigation = "2.7.5" androidx-palette = "1.0.0" -androidx-paging = "3.2.1" androidx-work = "2.8.1" - +appauth = "0.11.1" +atomicfu = "0.22.0" coil = "2.4.0" compose-bom = "2023.10.01" -compose-constraintlayout= "1.0.1" +compose-constraintlayout = "1.0.1" compose-paging = "3.2.1" -compose-material = "1.5.4" -composecompiler = "1.5.3" +composecompiler = "1.5.4" coroutines = "1.7.3" -datetime = "0.4.0" -detekt = "1.22.0" -dependency-analysis = "1.13.1" -dependency-check = "0.44.0" -desugar = "2.0.3" +datetime = "0.4.1" +dependency-analysis = "1.25.0" +dependency-check = "0.49.0" +desugar = "2.0.4" +detekt = "1.23.0" flowredux = "1.2.0" -junit = "4.13.2" kenburns = "1.0.7" -kermit = "1.2.2" +kermit = "1.2.3" kmmbridge = "0.3.7" kotest = "5.5.4" -kotlin = "1.9.10" -kotlinx-collections = "0.3.5" -kotlininject = "0.6.1" -ktor = "2.3.2" -ksp = "1.9.10-1.0.13" +kotlin = "1.9.20" +kotlininject = "0.6.3" +kotlinx-collections = "0.3.6" +ksp = "1.9.20-1.0.14" +ktor = "2.3.5" lint = "1.2.0" +moko-resources = "0.23.0" shared-module-version = "0.8.0" snapper = "0.3.0" -sqldelight = "2.0.0-rc01" -store5 = "5.0.0-beta01" +sqldelight = "2.0.0" +store5 = "5.0.0" turbine = "1.0.0" yamlkt = "0.12.0" youtubePlayer = "11.0.1" -android-compileSdk = "34" -android-minSdk = "21" - [libraries] -android-desugarJdkLibs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "desugar" } -android-gradle-tools = { group = "com.android.tools.build", name = "gradle", version.ref = "agp" } -kotlin-gradle = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } - accompanist-navigation-material = { module = "com.google.accompanist:accompanist-navigation-material", version.ref = "accompanist" } androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } androidx-compose-foundation = { module = "androidx.compose.foundation:foundation" } androidx-compose-material-icons = { module = "androidx.compose.material:material-icons-extended" } +androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } androidx-compose-ui-ui = { module = "androidx.compose.ui:ui" } -androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling"} -androidx-compose-ui-util = { module = "androidx.compose.ui:ui-util"} - +androidx-compose-ui-util = { module = "androidx.compose.ui:ui-util" } androidx-activity = { module = "androidx.activity:activity-ktx", version.ref = "androidx-activity" } -androidx-browser = { module = "androidx.browser:browser", version.ref = "androidx-browser" } - +androidx-browser = { module = "androidx.browser:browser", version.ref = "androidx-browser" } androidx-compose-activity = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" } androidx-compose-constraintlayout = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "compose-constraintlayout" } androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "androidx-material3" } -androidx-compose-material3-windowSizeClass = { group = "androidx.compose.material3", name = "material3-window-size-class", version.ref = "androidx-material3" } androidx-compose-paging = { module = "androidx.paging:paging-compose", version.ref = "compose-paging" } androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" } androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "androidx-core-splashscreen" } androidx-datastore-preference = { module = "androidx.datastore:datastore-preferences-core", version.ref = "androidx-datastore" } androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" } androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" } -androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle" } -androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" } androidx-navigation-common = { module = "androidx.navigation:navigation-common", version.ref = "androidx-navigation" } +androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" } androidx-navigation-runtime = { module = "androidx.navigation:navigation-runtime", version.ref = "androidx-navigation" } -androidx-paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "androidx-paging" } androidx-palette = { module = "androidx.palette:palette-ktx", version.ref = "androidx-palette" } androidx-work-runtime = { module = "androidx.work:work-runtime-ktx", version.ref = "androidx-work" } @@ -97,12 +80,8 @@ coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", ve coroutines-jvm = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", version.ref = "coroutines" } coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" } -desugar = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar" } - flowredux = { module = "com.freeletics.flowredux:flowredux", version.ref = "flowredux" } -junit = { module = "junit:junit", version.ref = "junit" } - kenburns = { module = "com.flaviofaria:kenburnsview", version.ref = "kenburns" } kermit = { module = "co.touchlab:kermit", version.ref = "kermit" } kotest-assertions = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" } @@ -123,12 +102,14 @@ ktor-serialization-json = { module = "io.ktor:ktor-serialization-kotlinx-json", lint-compose = { module = "com.slack.lint.compose:compose-lint-checks", version.ref = "lint" } +moko-core = { module = "dev.icerock.moko:resources", version.ref = "moko-resources" } + snapper = { module = "dev.chrisbanes.snapper:snapper", version.ref = "snapper" } -sqldelight-extensions = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } sqldelight-driver-jvm = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" } sqldelight-driver-native = { module = "app.cash.sqldelight:native-driver", version.ref = "sqldelight" } +sqldelight-extensions = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqldelight" } sqldelight-primitive-adapters = { module = "app.cash.sqldelight:primitive-adapters", version.ref = "sqldelight" } store5 = { module = "org.mobilenativefoundation.store:store5", version.ref = "store5" } @@ -136,16 +117,21 @@ turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" } yamlkt = { module = "net.mamoe.yamlkt:yamlkt", version.ref = "yamlkt" } youtubePlayer = { module = "com.pierfrancescosoffritti.androidyoutubeplayer:core", version.ref = "youtubePlayer" } +# Build logic dependencies +android-desugarJdkLibs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar" } +android-gradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "agp" } +kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } + [plugins] android-application = { id = "com.android.application", version.ref = "agp" } android-library = { id = "com.android.library", version.ref = "agp" } -dependency-check = { id = "com.github.ben-manes.versions", version.ref = "dependency-check" } dependency-analysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependency-analysis" } +dependency-check = { id = "com.github.ben-manes.versions", version.ref = "dependency-check" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } kmmbridge = { id = "co.touchlab.faktory.kmmbridge", version.ref = "kmmbridge" } +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +moko-resources = { id = "dev.icerock.mobile.multiplatform-resources", version.ref = "moko-resources" } multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } -kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } -kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" } From adb34f846341a87f23a44190ec8c6d4261ca7ef2 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sat, 18 Nov 2023 15:04:46 +0100 Subject: [PATCH 02/38] Remove store5 dependency from domain api module. --- data/profile/api/build.gradle.kts | 2 - .../tvmaniac/profile/api/ProfileRepository.kt | 5 +- .../profile/testing/FakeProfileRepository.kt | 9 +-- data/profilestats/api/build.gradle.kts | 2 - .../profilestats/api/StatsRepository.kt | 5 +- .../profile/testing/FakeStatsRepository.kt | 5 +- data/seasondetails/api/build.gradle.kts | 2 - .../api/SeasonDetailsRepository.kt | 2 +- .../testing/FakeSeasonDetailsRepository.kt | 26 ++++--- .../seasondetails/testing/MockData.kt | 2 +- data/seasons/api/build.gradle.kts | 2 - .../tvmaniac/seasons/api/SeasonsRepository.kt | 5 +- .../seasons/testing/FakeSeasonsRepository.kt | 29 +++++--- data/shows/api/build.gradle.kts | 2 - .../tvmaniac/shows/api/DiscoverRepository.kt | 20 +++--- .../shows/testing/FakeDiscoverRepository.kt | 70 +++++++------------ data/similar/api/build.gradle.kts | 2 - .../similar/api/SimilarShowsRepository.kt | 5 +- .../testing/FakeSimilarShowsRepository.kt | 9 +-- data/trailers/api/build.gradle.kts | 2 - .../TrailerRepository.kt | 5 +- .../trailers/testing/FakeTrailerRepository.kt | 26 +++---- 22 files changed, 109 insertions(+), 128 deletions(-) diff --git a/data/profile/api/build.gradle.kts b/data/profile/api/build.gradle.kts index 978bdc459..f24a4da61 100644 --- a/data/profile/api/build.gradle.kts +++ b/data/profile/api/build.gradle.kts @@ -11,8 +11,6 @@ kotlin { api(projects.core.util) api(libs.coroutines.core) - api(libs.kotlinx.atomicfu) - api(libs.store5) } } } diff --git a/data/profile/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/api/ProfileRepository.kt b/data/profile/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/api/ProfileRepository.kt index b385f9fe1..ce6396347 100644 --- a/data/profile/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/api/ProfileRepository.kt +++ b/data/profile/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/api/ProfileRepository.kt @@ -1,10 +1,11 @@ package com.thomaskioko.tvmaniac.profile.api import com.thomaskioko.tvmaniac.core.db.User +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import kotlinx.coroutines.flow.Flow -import org.mobilenativefoundation.store.store5.StoreReadResponse interface ProfileRepository { - fun observeProfile(slug: String): Flow> + fun observeProfile(slug: String): Flow> suspend fun clearProfile() } diff --git a/data/profile/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeProfileRepository.kt b/data/profile/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeProfileRepository.kt index d27162001..577b28d27 100644 --- a/data/profile/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeProfileRepository.kt +++ b/data/profile/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeProfileRepository.kt @@ -1,21 +1,22 @@ package com.thomaskioko.tvmaniac.trakt.profile.testing import com.thomaskioko.tvmaniac.core.db.User +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.profile.api.ProfileRepository import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.receiveAsFlow -import org.mobilenativefoundation.store.store5.StoreReadResponse class FakeProfileRepository : ProfileRepository { - private val userFlow: Channel> = Channel(Channel.UNLIMITED) + private val userFlow: Channel> = Channel(Channel.UNLIMITED) - suspend fun setUserData(response: StoreReadResponse) { + suspend fun setUserData(response: Either) { userFlow.send(response) } - override fun observeProfile(slug: String): Flow> = + override fun observeProfile(slug: String): Flow> = userFlow.receiveAsFlow() override suspend fun clearProfile() { diff --git a/data/profilestats/api/build.gradle.kts b/data/profilestats/api/build.gradle.kts index 978bdc459..f24a4da61 100644 --- a/data/profilestats/api/build.gradle.kts +++ b/data/profilestats/api/build.gradle.kts @@ -11,8 +11,6 @@ kotlin { api(projects.core.util) api(libs.coroutines.core) - api(libs.kotlinx.atomicfu) - api(libs.store5) } } } diff --git a/data/profilestats/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/api/StatsRepository.kt b/data/profilestats/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/api/StatsRepository.kt index 1f2cb32a2..c1c9c340d 100644 --- a/data/profilestats/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/api/StatsRepository.kt +++ b/data/profilestats/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/api/StatsRepository.kt @@ -1,9 +1,10 @@ package com.thomaskioko.tvmaniac.profilestats.api import com.thomaskioko.tvmaniac.core.db.Stats +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import kotlinx.coroutines.flow.Flow -import org.mobilenativefoundation.store.store5.StoreReadResponse interface StatsRepository { - fun observeStats(slug: String): Flow> + fun observeStats(slug: String): Flow> } diff --git a/data/profilestats/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeStatsRepository.kt b/data/profilestats/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeStatsRepository.kt index 4b03efbfb..da4409af3 100644 --- a/data/profilestats/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeStatsRepository.kt +++ b/data/profilestats/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeStatsRepository.kt @@ -1,12 +1,13 @@ package com.thomaskioko.tvmaniac.trakt.profile.testing import com.thomaskioko.tvmaniac.core.db.Stats +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.profilestats.api.StatsRepository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf -import org.mobilenativefoundation.store.store5.StoreReadResponse class FakeStatsRepository : StatsRepository { - override fun observeStats(slug: String): Flow> = + override fun observeStats(slug: String): Flow> = flowOf() } diff --git a/data/seasondetails/api/build.gradle.kts b/data/seasondetails/api/build.gradle.kts index 3702698fc..59e60b379 100644 --- a/data/seasondetails/api/build.gradle.kts +++ b/data/seasondetails/api/build.gradle.kts @@ -10,8 +10,6 @@ kotlin { api(projects.core.networkutil) api(libs.coroutines.core) - api(libs.kotlinx.atomicfu) - api(libs.store5) } } } diff --git a/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsRepository.kt b/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsRepository.kt index 2d8e9b530..3ddaa2701 100644 --- a/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsRepository.kt +++ b/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsRepository.kt @@ -9,5 +9,5 @@ interface SeasonDetailsRepository { fun observeSeasonDetailsStream(traktId: Long): Flow>> - fun observeSeasonDetails(traktId: Long): Flow>> + fun observeCachedSeasonDetails(traktId: Long): Flow>> } diff --git a/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/FakeSeasonDetailsRepository.kt b/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/FakeSeasonDetailsRepository.kt index c2f7a12fd..d25663e67 100644 --- a/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/FakeSeasonDetailsRepository.kt +++ b/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/FakeSeasonDetailsRepository.kt @@ -1,33 +1,31 @@ package com.thomaskioko.tvmaniac.seasondetails.testing import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes -import com.thomaskioko.tvmaniac.core.db.Seasons import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.seasondetails.api.SeasonDetailsRepository +import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.flowOf -import org.mobilenativefoundation.store.store5.StoreReadResponse +import kotlinx.coroutines.flow.receiveAsFlow class FakeSeasonDetailsRepository : SeasonDetailsRepository { - private var seasonsResult = flowOf>>() + private val seasonsResult: Channel>> = Channel(Channel.UNLIMITED) + private val cachedResult: Channel>> = Channel(Channel.UNLIMITED) - private var seasonEpisodesResult = flowOf>>() - - suspend fun setSeasonsResult(result: StoreReadResponse>) { - seasonsResult = flow { emit(result) } + suspend fun setSeasonsResult(result: Either>) { + seasonsResult.send(result) } - suspend fun setSeasonDetails(result: Either>) { - seasonEpisodesResult = flow { emit(result) } + suspend fun setCachedResults(result: Either>) { + cachedResult.send(result) } - override fun observeSeasonDetails(traktId: Long): Flow>> = - seasonEpisodesResult + override fun observeCachedSeasonDetails( + traktId: Long, + ): Flow>> = cachedResult.receiveAsFlow() override fun observeSeasonDetailsStream( traktId: Long, - ): Flow>> = seasonEpisodesResult + ): Flow>> = seasonsResult.receiveAsFlow() } diff --git a/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/MockData.kt b/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/MockData.kt index f83ccbae7..0b80394d6 100644 --- a/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/MockData.kt +++ b/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/MockData.kt @@ -2,7 +2,7 @@ package com.thomaskioko.tvmaniac.seasondetails.testing import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes -val seasonDetails = listOf( +val SeasonWithEpisodeList = listOf( SeasonWithEpisodes( trakt_id = 84958, tmdb_id = 849583, diff --git a/data/seasons/api/build.gradle.kts b/data/seasons/api/build.gradle.kts index 3702698fc..59e60b379 100644 --- a/data/seasons/api/build.gradle.kts +++ b/data/seasons/api/build.gradle.kts @@ -10,8 +10,6 @@ kotlin { api(projects.core.networkutil) api(libs.coroutines.core) - api(libs.kotlinx.atomicfu) - api(libs.store5) } } } diff --git a/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsRepository.kt b/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsRepository.kt index ebeb06def..edfdf7abf 100644 --- a/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsRepository.kt +++ b/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsRepository.kt @@ -1,11 +1,12 @@ package com.thomaskioko.tvmaniac.seasons.api import com.thomaskioko.tvmaniac.core.db.Seasons +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import kotlinx.coroutines.flow.Flow -import org.mobilenativefoundation.store.store5.StoreReadResponse interface SeasonsRepository { suspend fun getSeasons(traktId: Long): List - fun observeSeasonsStoreResponse(traktId: Long): Flow>> + fun observeSeasonsStoreResponse(traktId: Long): Flow>> } diff --git a/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/FakeSeasonsRepository.kt b/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/FakeSeasonsRepository.kt index 413e0d877..7eb3f74be 100644 --- a/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/FakeSeasonsRepository.kt +++ b/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/FakeSeasonsRepository.kt @@ -5,26 +5,33 @@ import com.thomaskioko.tvmaniac.core.db.Seasons import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.seasons.api.SeasonsRepository +import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.flowOf -import org.mobilenativefoundation.store.store5.StoreReadResponse +import kotlinx.coroutines.flow.receiveAsFlow class FakeSeasonsRepository : SeasonsRepository { - private var seasonsResult = flowOf>>() + private var seasonsList: Channel> = Channel(Channel.UNLIMITED) + private var seasonsResult: Channel>> = Channel(Channel.UNLIMITED) - private var seasonEpisodesResult = flowOf>>() + private var seasonEpisodesResult: Channel>> = + Channel(Channel.UNLIMITED) - suspend fun setSeasonsResult(result: StoreReadResponse>) { - seasonsResult = flow { emit(result) } + suspend fun setSeasonWithEpisodes(result: Either>) { + seasonEpisodesResult.send(result) } - suspend fun setSeasonDetails(result: Either>) { - seasonEpisodesResult = flow { emit(result) } + suspend fun setSeasons(result: List) { + seasonsList.send(result) } - override suspend fun getSeasons(traktId: Long): List = emptyList() + suspend fun setSeasonsResult(result: Either>) { + seasonsResult.send(result) + } + + override suspend fun getSeasons(traktId: Long): List = seasonsList.receive() - override fun observeSeasonsStoreResponse(traktId: Long): Flow>> = seasonsResult + override fun observeSeasonsStoreResponse( + traktId: Long, + ): Flow>> = seasonsResult.receiveAsFlow() } diff --git a/data/shows/api/build.gradle.kts b/data/shows/api/build.gradle.kts index 1437f8489..bb8a6543a 100644 --- a/data/shows/api/build.gradle.kts +++ b/data/shows/api/build.gradle.kts @@ -11,8 +11,6 @@ kotlin { api(projects.data.category.api) api(libs.coroutines.core) - api(libs.kotlinx.atomicfu) - api(libs.store5) } } } diff --git a/data/shows/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/DiscoverRepository.kt b/data/shows/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/DiscoverRepository.kt index 928891f5d..2c569e28c 100644 --- a/data/shows/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/DiscoverRepository.kt +++ b/data/shows/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/DiscoverRepository.kt @@ -3,22 +3,20 @@ package com.thomaskioko.tvmaniac.shows.api import com.thomaskioko.tvmaniac.category.api.model.Category import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.ShowsByCategory +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import kotlinx.coroutines.flow.Flow -import org.mobilenativefoundation.store.store5.StoreReadResponse +import kotlin.time.Duration +import kotlin.time.Duration.Companion.days interface DiscoverRepository { - fun observeShow(traktId: Long): Flow> + fun observeShow(traktId: Long): Flow> - fun observeShowsByCategory(categoryId: Long): Flow>> - - fun observeTrendingShows(): Flow>> - - fun observePopularShows(): Flow>> - - fun observeAnticipatedShows(): Flow>> - - fun observeRecommendedShows(): Flow>> + fun observeShowCategory( + category: Category, + duration: Duration = 3.days, + ): Flow>> suspend fun fetchDiscoverShows() diff --git a/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/FakeDiscoverRepository.kt b/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/FakeDiscoverRepository.kt index dafc7c483..ef6382f32 100644 --- a/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/FakeDiscoverRepository.kt +++ b/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/FakeDiscoverRepository.kt @@ -3,71 +3,53 @@ package com.thomaskioko.tvmaniac.shows.testing import com.thomaskioko.tvmaniac.category.api.model.Category import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.ShowsByCategory +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.shows.api.DiscoverRepository +import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.flowOf -import org.mobilenativefoundation.store.store5.StoreReadResponse +import kotlinx.coroutines.flow.receiveAsFlow +import kotlin.time.Duration class FakeDiscoverRepository : DiscoverRepository { - private var featuredResult = flowOf>>() + private var showById: Channel = Channel(Channel.UNLIMITED) + private var updatedShowCategoryResult: Channel>> = + Channel(Channel.UNLIMITED) - private var anticipatedResult = flowOf>>() + private var showCategoryResult: Channel> = Channel(Channel.UNLIMITED) - private var popularResult = flowOf>>() + private var showByIdResult: Channel> = + Channel(Channel.UNLIMITED) - private var trendingResult = flowOf>>() - - private var showResult = flowOf>() - - suspend fun setFeaturedResult(result: StoreReadResponse>) { - featuredResult = flow { emit(result) } - } - - suspend fun setAnticipatedResult(result: StoreReadResponse>) { - anticipatedResult = flow { emit(result) } - } - - suspend fun setPopularResult(result: StoreReadResponse>) { - popularResult = flow { emit(result) } + suspend fun setShowCategory(result: List) { + showCategoryResult.send(result) } - suspend fun setTrendingResult(result: StoreReadResponse>) { - trendingResult = flow { emit(result) } + suspend fun setShowById(result: ShowById) { + showById.send(result) } - suspend fun setShowResult(result: StoreReadResponse) { - showResult = flow { emit(result) } + suspend fun setTrendingResult(result: Either>) { + updatedShowCategoryResult.send(result) } - override fun observeShow(traktId: Long): Flow> = showResult - - override fun observeShowsByCategory( - categoryId: Long, - ): Flow>> = featuredResult - - override fun observeTrendingShows(): Flow>> { - return trendingResult - } - - override fun observePopularShows(): Flow>> { - return popularResult + suspend fun setShowResult(result: Either) { + showByIdResult.send(result) } - override fun observeAnticipatedShows(): Flow>> { - return anticipatedResult - } + override fun observeShow(traktId: Long): Flow> = showByIdResult.receiveAsFlow() - override fun observeRecommendedShows(): Flow>> { - return featuredResult - } + override fun observeShowCategory( + category: Category, + duration: Duration, + ): Flow>> = updatedShowCategoryResult.receiveAsFlow() override suspend fun fetchDiscoverShows() {} - override suspend fun fetchShows(category: Category): List = emptyList() + override suspend fun fetchShows(category: Category): List = showCategoryResult.receive() - override suspend fun getShowById(traktId: Long): ShowById = selectedShow + override suspend fun getShowById(traktId: Long): ShowById = showById.receive() } val selectedShow = ShowById( diff --git a/data/similar/api/build.gradle.kts b/data/similar/api/build.gradle.kts index cc0798de1..c02395d78 100644 --- a/data/similar/api/build.gradle.kts +++ b/data/similar/api/build.gradle.kts @@ -13,8 +13,6 @@ kotlin { implementation(projects.data.shows.api) api(libs.coroutines.core) - api(libs.kotlinx.atomicfu) - api(libs.store5) } } } diff --git a/data/similar/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/api/SimilarShowsRepository.kt b/data/similar/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/api/SimilarShowsRepository.kt index 111ff57c7..3ac79d614 100644 --- a/data/similar/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/api/SimilarShowsRepository.kt +++ b/data/similar/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/api/SimilarShowsRepository.kt @@ -1,12 +1,13 @@ package com.thomaskioko.tvmaniac.similar.api import com.thomaskioko.tvmaniac.core.db.SimilarShows +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import kotlinx.coroutines.flow.Flow -import org.mobilenativefoundation.store.store5.StoreReadResponse interface SimilarShowsRepository { suspend fun fetchSimilarShows(traktId: Long): List - fun observeSimilarShows(traktId: Long): Flow>> + fun observeSimilarShows(traktId: Long): Flow>> } diff --git a/data/similar/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/testing/FakeSimilarShowsRepository.kt b/data/similar/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/testing/FakeSimilarShowsRepository.kt index 9797886d5..3036aa5f8 100644 --- a/data/similar/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/testing/FakeSimilarShowsRepository.kt +++ b/data/similar/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/testing/FakeSimilarShowsRepository.kt @@ -1,22 +1,23 @@ package com.thomaskioko.tvmaniac.similar.testing import com.thomaskioko.tvmaniac.core.db.SimilarShows +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.similar.api.SimilarShowsRepository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf -import org.mobilenativefoundation.store.store5.StoreReadResponse class FakeSimilarShowsRepository : SimilarShowsRepository { - private var similarShowsResult: Flow>> = flowOf() + private var similarShowsResult: Flow>> = flowOf() - suspend fun setSimilarShowsResult(result: StoreReadResponse>) { + suspend fun setSimilarShowsResult(result: Either>) { similarShowsResult = flow { emit(result) } } override suspend fun fetchSimilarShows(traktId: Long): List = emptyList() - override fun observeSimilarShows(traktId: Long): Flow>> = + override fun observeSimilarShows(traktId: Long): Flow>> = similarShowsResult } diff --git a/data/trailers/api/build.gradle.kts b/data/trailers/api/build.gradle.kts index 694d850e9..ea55b9cd9 100644 --- a/data/trailers/api/build.gradle.kts +++ b/data/trailers/api/build.gradle.kts @@ -10,8 +10,6 @@ kotlin { api(projects.core.networkutil) api(libs.coroutines.core) - api(libs.kotlinx.atomicfu) - api(libs.store5) } } } diff --git a/data/trailers/api/src/commonMain/kotlin/com.thomaskioko.tvmaniac.data.trailers.implementation/TrailerRepository.kt b/data/trailers/api/src/commonMain/kotlin/com.thomaskioko.tvmaniac.data.trailers.implementation/TrailerRepository.kt index ca393b993..2e83a7f45 100644 --- a/data/trailers/api/src/commonMain/kotlin/com.thomaskioko.tvmaniac.data.trailers.implementation/TrailerRepository.kt +++ b/data/trailers/api/src/commonMain/kotlin/com.thomaskioko.tvmaniac.data.trailers.implementation/TrailerRepository.kt @@ -1,11 +1,12 @@ package com.thomaskioko.tvmaniac.data.trailers.implementation import com.thomaskioko.tvmaniac.core.db.Trailers +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import kotlinx.coroutines.flow.Flow -import org.mobilenativefoundation.store.store5.StoreReadResponse interface TrailerRepository { fun isYoutubePlayerInstalled(): Flow - fun observeTrailersStoreResponse(traktId: Long): Flow>> + fun observeTrailersStoreResponse(traktId: Long): Flow>> suspend fun fetchTrailersByShowId(traktId: Long): List } diff --git a/data/trailers/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trailers/testing/FakeTrailerRepository.kt b/data/trailers/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trailers/testing/FakeTrailerRepository.kt index ffd250948..5530995c0 100644 --- a/data/trailers/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trailers/testing/FakeTrailerRepository.kt +++ b/data/trailers/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trailers/testing/FakeTrailerRepository.kt @@ -1,29 +1,31 @@ package com.thomaskioko.tvmaniac.trailers.testing import com.thomaskioko.tvmaniac.core.db.Trailers +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.data.trailers.implementation.TrailerRepository +import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf -import org.mobilenativefoundation.store.store5.StoreReadResponse +import kotlinx.coroutines.flow.receiveAsFlow class FakeTrailerRepository : TrailerRepository { - private var trailerList = mutableListOf() - private var trailersStoreResponse: Flow>> = flowOf() + private var trailerList: Channel> = Channel(Channel.UNLIMITED) + private var trailersStoreResponse: Channel>> = + Channel(Channel.UNLIMITED) - suspend fun setTrailerResult(result: StoreReadResponse>) { - trailersStoreResponse = flow { emit(result) } + suspend fun setTrailerResult(result: Either>) { + trailersStoreResponse.send(result) } - fun setTrailerList(list: List) { - trailerList.clear() - trailerList.addAll(list.toMutableList()) + suspend fun setTrailerList(list: List) { + trailerList.send(list) } override fun isYoutubePlayerInstalled(): Flow = flowOf() - override fun observeTrailersStoreResponse(traktId: Long): Flow>> = - trailersStoreResponse + override fun observeTrailersStoreResponse(traktId: Long): Flow>> = + trailersStoreResponse.receiveAsFlow() - override suspend fun fetchTrailersByShowId(traktId: Long): List = trailerList + override suspend fun fetchTrailersByShowId(traktId: Long): List = trailerList.receive() } From d94fbe57a8a5384586fcb2b4409c801d2ba406c8 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sat, 18 Nov 2023 15:07:11 +0100 Subject: [PATCH 03/38] cleanup domain implementation module and map result to Either implementation. --- .../implementation/ProfileRepositoryImpl.kt | 25 +++- .../implementation/build.gradle.kts | 2 + .../implementation/StatsRepositoryImpl.kt | 20 ++- .../implementation/build.gradle.kts | 3 +- .../SeasonDetailsRepositoryImpl.kt | 2 +- data/seasons/implementation/build.gradle.kts | 3 +- .../implementation/SeasonsRepositoryImpl.kt | 20 ++- .../ShowImagesRepositoryImpl.kt | 59 ++++----- data/shows/implementation/build.gradle.kts | 2 + .../implementation/DiscoverRepositoryImpl.kt | 124 +++++++----------- data/similar/implementation/build.gradle.kts | 2 + .../SimilarShowsRepositoryImpl.kt | 20 ++- data/trailers/implementation/build.gradle.kts | 2 + .../implementation/TrailerRepositoryImpl.kt | 20 ++- 14 files changed, 178 insertions(+), 126 deletions(-) diff --git a/data/profile/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/implementation/ProfileRepositoryImpl.kt b/data/profile/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/implementation/ProfileRepositoryImpl.kt index 12b7122e0..166c5645b 100644 --- a/data/profile/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/implementation/ProfileRepositoryImpl.kt +++ b/data/profile/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/implementation/ProfileRepositoryImpl.kt @@ -1,10 +1,17 @@ package com.thomaskioko.tvmaniac.profile.implementation import com.thomaskioko.tvmaniac.core.db.User +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.profile.api.ProfileRepository import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import me.tatarka.inject.annotations.Inject import org.mobilenativefoundation.store.store5.ExperimentalStoreApi @@ -12,7 +19,7 @@ import org.mobilenativefoundation.store.store5.StoreReadRequest import org.mobilenativefoundation.store.store5.StoreReadResponse import kotlin.time.Duration.Companion.days -@OptIn(ExperimentalStoreApi::class) +@OptIn(ExperimentalStoreApi::class, ExperimentalCoroutinesApi::class) @Inject class ProfileRepositoryImpl constructor( private val store: ProfileStore, @@ -20,7 +27,7 @@ class ProfileRepositoryImpl constructor( private val dispatchers: AppCoroutineDispatchers, ) : ProfileRepository { - override fun observeProfile(slug: String): Flow> = + override fun observeProfile(slug: String): Flow> = store.stream( StoreReadRequest.cached( key = slug, @@ -31,9 +38,21 @@ class ProfileRepositoryImpl constructor( ), ), ) - .flowOn(dispatchers.io) + .mapResult() override suspend fun clearProfile() { store.clear() } + + private fun Flow>.mapResult(): Flow> = + distinctUntilChanged() + .flatMapLatest { + val data = it.dataOrNull() + if (data != null) { + flowOf(Either.Right(data)) + } else { + emptyFlow() + } + } + .flowOn(dispatchers.io) } diff --git a/data/profilestats/implementation/build.gradle.kts b/data/profilestats/implementation/build.gradle.kts index 1f6a9d195..120f5b655 100644 --- a/data/profilestats/implementation/build.gradle.kts +++ b/data/profilestats/implementation/build.gradle.kts @@ -14,6 +14,8 @@ kotlin { implementation(libs.kotlinInject.runtime) implementation(libs.sqldelight.extensions) + implementation(libs.kotlinx.atomicfu) + implementation(libs.store5) } } } diff --git a/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsRepositoryImpl.kt b/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsRepositoryImpl.kt index e67679454..3ea597767 100644 --- a/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsRepositoryImpl.kt +++ b/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsRepositoryImpl.kt @@ -1,16 +1,23 @@ package com.thomaskioko.tvmaniac.profilestats.implementation import com.thomaskioko.tvmaniac.core.db.Stats +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.profilestats.api.StatsRepository import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import me.tatarka.inject.annotations.Inject import org.mobilenativefoundation.store.store5.StoreReadRequest -import org.mobilenativefoundation.store.store5.StoreReadResponse import kotlin.time.Duration.Companion.days +@OptIn(ExperimentalCoroutinesApi::class) @Inject class StatsRepositoryImpl( private val store: StatsStore, @@ -18,7 +25,7 @@ class StatsRepositoryImpl( private val dispatchers: AppCoroutineDispatchers, ) : StatsRepository { - override fun observeStats(slug: String): Flow> = + override fun observeStats(slug: String): Flow> = store.stream( StoreReadRequest.cached( key = slug, @@ -29,5 +36,14 @@ class StatsRepositoryImpl( ), ), ) + .distinctUntilChanged() + .flatMapLatest { + val data = it.dataOrNull() + if (data != null) { + flowOf(Either.Right(data)) + } else { + emptyFlow() + } + } .flowOn(dispatchers.io) } diff --git a/data/seasondetails/implementation/build.gradle.kts b/data/seasondetails/implementation/build.gradle.kts index 742fe3df8..8987cc386 100644 --- a/data/seasondetails/implementation/build.gradle.kts +++ b/data/seasondetails/implementation/build.gradle.kts @@ -18,7 +18,8 @@ kotlin { implementation(libs.kotlinInject.runtime) implementation(libs.sqldelight.extensions) - + implementation(libs.kotlinx.atomicfu) + implementation(libs.store5) } } diff --git a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsRepositoryImpl.kt b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsRepositoryImpl.kt index 5d3e3bec8..c9a0cb781 100644 --- a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsRepositoryImpl.kt +++ b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsRepositoryImpl.kt @@ -41,7 +41,7 @@ class SeasonDetailsRepositoryImpl( coroutineDispatcher = dispatcher.io, ) - override fun observeSeasonDetails(traktId: Long): Flow>> = + override fun observeCachedSeasonDetails(traktId: Long): Flow>> = seasonCache.observeShowEpisodes(traktId) .catch { Either.Left(DefaultError(exceptionHandler.resolveError(it))) } .map { Either.Right(it) } diff --git a/data/seasons/implementation/build.gradle.kts b/data/seasons/implementation/build.gradle.kts index 54722660a..27f02d9ec 100644 --- a/data/seasons/implementation/build.gradle.kts +++ b/data/seasons/implementation/build.gradle.kts @@ -19,7 +19,8 @@ kotlin { implementation(libs.kotlinInject.runtime) implementation(libs.sqldelight.extensions) - + implementation(libs.kotlinx.atomicfu) + implementation(libs.store5) } } diff --git a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsRepositoryImpl.kt b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsRepositoryImpl.kt index 111e35373..3367dcb2b 100644 --- a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsRepositoryImpl.kt +++ b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsRepositoryImpl.kt @@ -1,17 +1,24 @@ package com.thomaskioko.tvmaniac.seasons.implementation import com.thomaskioko.tvmaniac.core.db.Seasons +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.seasons.api.SeasonsRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import me.tatarka.inject.annotations.Inject import org.mobilenativefoundation.store.store5.StoreReadRequest -import org.mobilenativefoundation.store.store5.StoreReadResponse import org.mobilenativefoundation.store.store5.impl.extensions.get import kotlin.time.Duration.Companion.days +@OptIn(ExperimentalCoroutinesApi::class) @Inject class SeasonsRepositoryImpl( private val seasonsStore: SeasonsStore, @@ -22,7 +29,7 @@ class SeasonsRepositoryImpl( override suspend fun getSeasons(traktId: Long): List = seasonsStore.get(traktId) - override fun observeSeasonsStoreResponse(traktId: Long): Flow>> = + override fun observeSeasonsStoreResponse(traktId: Long): Flow>> = seasonsStore.stream( StoreReadRequest.cached( key = traktId, @@ -33,5 +40,14 @@ class SeasonsRepositoryImpl( ), ), ) + .distinctUntilChanged() + .flatMapLatest { + val data = it.dataOrNull() + if (data != null) { + flowOf(Either.Right(data)) + } else { + emptyFlow() + } + } .flowOn(dispatcher.io) } diff --git a/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesRepositoryImpl.kt b/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesRepositoryImpl.kt index 67ae3ef6d..8ffa4af07 100644 --- a/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesRepositoryImpl.kt +++ b/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesRepositoryImpl.kt @@ -19,7 +19,6 @@ import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import me.tatarka.inject.annotations.Inject -import kotlin.time.Duration.Companion.days @Inject class ShowImagesRepositoryImpl( @@ -36,41 +35,33 @@ class ShowImagesRepositoryImpl( imageCache.observeShowImages() .map { shows -> shows.forEach { show -> - val shouldFetch = requestManagerRepository.isRequestExpired( - entityId = show.trakt_id, - requestType = "SHOW_ARTWORK", - threshold = 1.days, - ) - if (shouldFetch) { - show.tmdb_id?.let { tmdbId -> - - when (val response = networkDataSource.getTvShowDetails(tmdbId)) { - is ApiResponse.Error -> { - logger.error("updateShowArtWork", "$response") - } + show.tmdb_id?.let { tmdbId -> + when (val response = networkDataSource.getTvShowDetails(tmdbId)) { + is ApiResponse.Error -> { + logger.error("updateShowArtWork", "$response") + } - is ApiResponse.Success -> { - imageCache.insert( - Show_image( - trakt_id = show.trakt_id, - tmdb_id = tmdbId, - poster_url = response.body.posterPath?.let { - formatterUtil.formatTmdbPosterPath(it) - }, - backdrop_url = response.body.backdropPath?.let { - formatterUtil.formatTmdbPosterPath(it) - }, - ), - ) + is ApiResponse.Success -> { + imageCache.insert( + Show_image( + trakt_id = show.trakt_id, + tmdb_id = tmdbId, + poster_url = response.body.posterPath?.let { + formatterUtil.formatTmdbPosterPath(it) + }, + backdrop_url = response.body.backdropPath?.let { + formatterUtil.formatTmdbPosterPath(it) + }, + ), + ) - requestManagerRepository.insert( - LastRequest( - id = tmdbId, - entityId = show.trakt_id, - requestType = "SHOW_ARTWORK", - ), - ) - } + requestManagerRepository.insert( + LastRequest( + id = tmdbId, + entityId = show.trakt_id, + requestType = "SHOW_ARTWORK", + ), + ) } } } diff --git a/data/shows/implementation/build.gradle.kts b/data/shows/implementation/build.gradle.kts index fb0c55523..40aeabdf2 100644 --- a/data/shows/implementation/build.gradle.kts +++ b/data/shows/implementation/build.gradle.kts @@ -17,6 +17,8 @@ kotlin { implementation(libs.kotlinInject.runtime) implementation(libs.sqldelight.extensions) + implementation(libs.kotlinx.atomicfu) + implementation(libs.store5) } } diff --git a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverRepositoryImpl.kt b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverRepositoryImpl.kt index b28e4c47c..1f661fde2 100644 --- a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverRepositoryImpl.kt +++ b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverRepositoryImpl.kt @@ -5,111 +5,67 @@ import com.thomaskioko.tvmaniac.category.api.model.Category.ANTICIPATED import com.thomaskioko.tvmaniac.category.api.model.Category.POPULAR import com.thomaskioko.tvmaniac.category.api.model.Category.RECOMMENDED import com.thomaskioko.tvmaniac.category.api.model.Category.TRENDING -import com.thomaskioko.tvmaniac.category.api.model.getCategory import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.ShowsByCategory +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.shows.api.DiscoverRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import me.tatarka.inject.annotations.Inject import org.mobilenativefoundation.store.store5.StoreReadRequest import org.mobilenativefoundation.store.store5.StoreReadResponse import org.mobilenativefoundation.store.store5.impl.extensions.get +import kotlin.time.Duration import kotlin.time.Duration.Companion.days +@OptIn(ExperimentalCoroutinesApi::class) @Inject -class DiscoverRepositoryImpl constructor( +class DiscoverRepositoryImpl( private val showStore: ShowStore, private val discoverShowsStore: DiscoverShowsStore, private val requestManagerRepository: RequestManagerRepository, private val dispatchers: AppCoroutineDispatchers, ) : DiscoverRepository { - override suspend fun getShowById(traktId: Long): ShowById = - showStore.get(key = traktId) + override suspend fun getShowById(traktId: Long): ShowById = showStore.get(key = traktId) - override fun observeShow(traktId: Long): Flow> = - showStore.stream( - StoreReadRequest.cached( - key = traktId, - refresh = requestManagerRepository.isRequestExpired( - entityId = traktId, - requestType = "SHOW_DETAILS", - threshold = 6.days, - ), + override fun observeShow(traktId: Long): Flow> = showStore.stream( + StoreReadRequest.cached( + key = traktId, + refresh = requestManagerRepository.isRequestExpired( + entityId = traktId, + requestType = "SHOW_DETAILS", + threshold = 6.days, ), - ) - .flowOn(dispatchers.io) + ), + ) + .mapResult() override suspend fun fetchShows(category: Category): List = discoverShowsStore.get(key = category) - override fun observeShowsByCategory(categoryId: Long): Flow>> = - discoverShowsStore.stream( - StoreReadRequest.cached( - key = categoryId.getCategory(), - refresh = requestManagerRepository.isRequestExpired( - entityId = categoryId, - requestType = categoryId.getCategory().title, - threshold = 3.days, - ), - ), - ) - .flowOn(dispatchers.io) - - override fun observeTrendingShows(): Flow>> = - discoverShowsStore.stream( - StoreReadRequest.cached( - key = TRENDING, - refresh = requestManagerRepository.isRequestExpired( - entityId = TRENDING.id, - requestType = TRENDING.title, - threshold = 3.days, - ), - ), - ) - .flowOn(dispatchers.io) - - override fun observePopularShows(): Flow>> = - discoverShowsStore.stream( - StoreReadRequest.cached( - key = POPULAR, - refresh = requestManagerRepository.isRequestExpired( - entityId = POPULAR.id, - requestType = POPULAR.title, - threshold = 3.days, - ), - ), - ) - .flowOn(dispatchers.io) - - override fun observeAnticipatedShows(): Flow>> = - discoverShowsStore.stream( - StoreReadRequest.cached( - key = ANTICIPATED, - refresh = requestManagerRepository.isRequestExpired( - entityId = ANTICIPATED.id, - requestType = ANTICIPATED.title, - threshold = 3.days, - ), - ), - ) - .flowOn(dispatchers.io) - - override fun observeRecommendedShows(): Flow>> = - discoverShowsStore.stream( - StoreReadRequest.cached( - key = RECOMMENDED, - refresh = requestManagerRepository.isRequestExpired( - entityId = RECOMMENDED.id, - requestType = RECOMMENDED.title, - threshold = 1.days, - ), + override fun observeShowCategory( + category: Category, + duration: Duration, + ): Flow>> = discoverShowsStore.stream( + StoreReadRequest.cached( + key = category, + refresh = requestManagerRepository.isRequestExpired( + entityId = category.id, + requestType = category.title, + threshold = duration, ), - ) - .flowOn(dispatchers.io) + ), + ) + .mapResult() override suspend fun fetchDiscoverShows() { val categories = listOf(TRENDING, POPULAR, ANTICIPATED, RECOMMENDED) @@ -118,4 +74,16 @@ class DiscoverRepositoryImpl constructor( discoverShowsStore.get(category) } } + + private fun Flow>.mapResult(): Flow> = + distinctUntilChanged() + .flatMapLatest { + val data = it.dataOrNull() + if (data != null) { + flowOf(Either.Right(data)) + } else { + emptyFlow() + } + } + .flowOn(dispatchers.io) } diff --git a/data/similar/implementation/build.gradle.kts b/data/similar/implementation/build.gradle.kts index c3bd775d3..788559a46 100644 --- a/data/similar/implementation/build.gradle.kts +++ b/data/similar/implementation/build.gradle.kts @@ -16,6 +16,8 @@ kotlin { implementation(libs.kotlinInject.runtime) implementation(libs.sqldelight.extensions) + implementation(libs.kotlinx.atomicfu) + implementation(libs.store5) } } diff --git a/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowsRepositoryImpl.kt b/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowsRepositoryImpl.kt index 9582d267c..d37dd5681 100644 --- a/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowsRepositoryImpl.kt +++ b/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowsRepositoryImpl.kt @@ -1,17 +1,24 @@ package com.thomaskioko.tvmaniac.similar.implementation import com.thomaskioko.tvmaniac.core.db.SimilarShows +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.similar.api.SimilarShowsRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import me.tatarka.inject.annotations.Inject import org.mobilenativefoundation.store.store5.StoreReadRequest -import org.mobilenativefoundation.store.store5.StoreReadResponse import org.mobilenativefoundation.store.store5.impl.extensions.get import kotlin.time.Duration.Companion.days +@OptIn(ExperimentalCoroutinesApi::class) @Inject class SimilarShowsRepositoryImpl( private val store: SimilarShowStore, @@ -21,7 +28,7 @@ class SimilarShowsRepositoryImpl( override suspend fun fetchSimilarShows(traktId: Long): List = store.get(traktId) - override fun observeSimilarShows(traktId: Long): Flow>> = + override fun observeSimilarShows(traktId: Long): Flow>> = store.stream( StoreReadRequest.cached( key = traktId, @@ -32,5 +39,14 @@ class SimilarShowsRepositoryImpl( ), ), ) + .distinctUntilChanged() + .flatMapLatest { + val data = it.dataOrNull() + if (data != null) { + flowOf(Either.Right(data)) + } else { + emptyFlow() + } + } .flowOn(dispatchers.io) } diff --git a/data/trailers/implementation/build.gradle.kts b/data/trailers/implementation/build.gradle.kts index b3df2065e..dfc9cba1d 100644 --- a/data/trailers/implementation/build.gradle.kts +++ b/data/trailers/implementation/build.gradle.kts @@ -16,6 +16,8 @@ kotlin { implementation(libs.kermit) implementation(libs.kotlinInject.runtime) implementation(libs.sqldelight.extensions) + implementation(libs.kotlinx.atomicfu) + implementation(libs.store5) } } } diff --git a/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerRepositoryImpl.kt b/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerRepositoryImpl.kt index 14680fa13..3a6b20fe3 100644 --- a/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerRepositoryImpl.kt +++ b/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerRepositoryImpl.kt @@ -1,17 +1,24 @@ package com.thomaskioko.tvmaniac.data.trailers.implementation import com.thomaskioko.tvmaniac.core.db.Trailers +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.util.AppUtils import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import me.tatarka.inject.annotations.Inject import org.mobilenativefoundation.store.store5.StoreReadRequest -import org.mobilenativefoundation.store.store5.StoreReadResponse import org.mobilenativefoundation.store.store5.impl.extensions.get import kotlin.time.Duration.Companion.days +@OptIn(ExperimentalCoroutinesApi::class) @Inject class TrailerRepositoryImpl( private val store: TrailerStore, @@ -25,7 +32,7 @@ class TrailerRepositoryImpl( override suspend fun fetchTrailersByShowId(traktId: Long): List = store.get(traktId) - override fun observeTrailersStoreResponse(traktId: Long): Flow>> = + override fun observeTrailersStoreResponse(traktId: Long): Flow>> = store.stream( StoreReadRequest.cached( key = traktId, @@ -36,5 +43,14 @@ class TrailerRepositoryImpl( ), ), ) + .distinctUntilChanged() + .flatMapLatest { + val data = it.dataOrNull() + if (data != null) { + flowOf(Either.Right(data)) + } else { + emptyFlow() + } + } .flowOn(dispatchers.io) } From 25031960599e5e52b97e1d4d239090ae4763218b Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sat, 18 Nov 2023 15:11:34 +0100 Subject: [PATCH 04/38] update presentation implementation result mapping. --- .../discover/DiscoverShowsMapper.kt | 39 ++-- .../discover/DiscoverShowsState.kt | 13 +- .../discover/DiscoverStateMachine.kt | 23 ++- .../discover/DiscoverStateMachineTest.kt | 74 +------- .../presentation/discover/MockData.kt | 25 +++ .../profile/ProfileStateMachine.kt | 33 +--- .../profile/ProfileStateMachineTest.kt | 23 +-- .../SeasonDetailsStateMachine.kt | 40 +++-- .../SeasonDetailsStateMachineTest.kt | 8 +- .../settings/SettingsStateMachine.kt | 36 ++-- .../settings/SettingsStateMachineTest.kt | 25 +-- .../showdetails/ShowDetailsStateMachine.kt | 169 ++++++------------ .../ShowDetailsStateMachineTest.kt | 169 ++++-------------- .../tvmaniac/presentation/trailers/Mapper.kt | 6 +- .../presentation/trailers/TrailersState.kt | 2 +- .../trailers/TrailersStateMachine.kt | 81 ++++----- .../trailers/TrailerStateMachineTest.kt | 45 ++++- 17 files changed, 286 insertions(+), 525 deletions(-) diff --git a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsMapper.kt b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsMapper.kt index 92f6a8131..7a80a1ddd 100644 --- a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsMapper.kt +++ b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsMapper.kt @@ -1,11 +1,12 @@ package com.thomaskioko.tvmaniac.presentation.discover import com.thomaskioko.tvmaniac.core.db.ShowsByCategory +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.presentation.discover.model.TvShow import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList -import org.mobilenativefoundation.store.store5.StoreReadResponse fun List?.toTvShowList(): ImmutableList = this?.map { it.toTvShow() }?.toImmutableList() ?: persistentListOf() @@ -25,26 +26,18 @@ fun ShowsByCategory.toTvShow(): TvShow = TvShow( status = status, ) -fun toShowResultState( - trending: StoreReadResponse>, - popular: StoreReadResponse>, - anticipated: StoreReadResponse>, - recommended: StoreReadResponse>, -): DataLoaded = DataLoaded( - trendingShows = trending.dataOrNull().toTvShowList(), - popularShows = popular.dataOrNull().toTvShowList(), - anticipatedShows = anticipated.dataOrNull().toTvShowList(), - recommendedShows = recommended.dataOrNull()?.take(5).toTvShowList(), - errorMessage = getErrorMessage(trending, popular, anticipated, recommended), - isContentEmpty = trending.dataOrNull().isNullOrEmpty() && - popular.dataOrNull().isNullOrEmpty() && anticipated.dataOrNull().isNullOrEmpty() && - recommended.dataOrNull().isNullOrEmpty(), -) +fun getErrorMessage( + trending: Either>, + popular: Either>, + anticipated: Either>, + recommended: Either>, +) = trending.getErrorOrNull()?.errorMessage ?: popular.getErrorOrNull()?.errorMessage + ?: anticipated.getErrorOrNull()?.errorMessage ?: recommended.getErrorOrNull()?.errorMessage -private fun getErrorMessage( - trending: StoreReadResponse>, - popular: StoreReadResponse>, - anticipated: StoreReadResponse>, - recommended: StoreReadResponse>, -) = trending.errorMessageOrNull() ?: popular.errorMessageOrNull() - ?: anticipated.errorMessageOrNull() ?: recommended.errorMessageOrNull() +fun getIsContentEmpty( + trending: Either>, + popular: Either>, + anticipated: Either>, + recommended: Either>, +) = trending.getOrNull().isNullOrEmpty() && popular.getOrNull().isNullOrEmpty() && + anticipated.getOrNull().isNullOrEmpty() && recommended.getOrNull().isNullOrEmpty() diff --git a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsState.kt b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsState.kt index 702172175..9582e3b59 100644 --- a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsState.kt +++ b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsState.kt @@ -2,16 +2,17 @@ package com.thomaskioko.tvmaniac.presentation.discover import com.thomaskioko.tvmaniac.presentation.discover.model.TvShow import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf sealed interface DiscoverState -object Loading : DiscoverState +data object Loading : DiscoverState +data class ErrorState(val errorMessage: String?) : DiscoverState data class DataLoaded( - val recommendedShows: ImmutableList? = null, - val trendingShows: ImmutableList? = null, - val popularShows: ImmutableList? = null, - val anticipatedShows: ImmutableList? = null, + val recommendedShows: ImmutableList = persistentListOf(), + val trendingShows: ImmutableList = persistentListOf(), + val popularShows: ImmutableList = persistentListOf(), + val anticipatedShows: ImmutableList = persistentListOf(), val errorMessage: String? = null, - val isContentEmpty: Boolean = true, ) : DiscoverState diff --git a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachine.kt b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachine.kt index dc8ebb7b5..7d5a8bd02 100644 --- a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachine.kt +++ b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachine.kt @@ -8,6 +8,7 @@ import com.thomaskioko.tvmaniac.showimages.api.ShowImagesRepository import com.thomaskioko.tvmaniac.shows.api.DiscoverRepository import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine import me.tatarka.inject.annotations.Inject @@ -35,7 +36,6 @@ class DiscoverStateMachine( popularShows = result.popularShows, anticipatedShows = result.anticipatedShows, errorMessage = result.errorMessage, - isContentEmpty = result.isContentEmpty, ) } } @@ -52,7 +52,9 @@ class DiscoverStateMachine( on { _, state -> state.override { Loading } } + } + inState { on { _, state -> state.mutate { copy(errorMessage = null) @@ -80,11 +82,18 @@ class DiscoverStateMachine( private fun observeShowData(): Flow = combine( - discoverRepository.observeTrendingShows(), - discoverRepository.observePopularShows(), - discoverRepository.observeAnticipatedShows(), - discoverRepository.observeRecommendedShows(), - ) { trending, popular, anticipated, featured -> - toShowResultState(trending, popular, anticipated, featured) + discoverRepository.observeShowCategory(Category.TRENDING), + discoverRepository.observeShowCategory(Category.POPULAR), + discoverRepository.observeShowCategory(Category.ANTICIPATED), + discoverRepository.observeShowCategory(Category.RECOMMENDED), + ) { trending, popular, anticipated, recommended -> + DataLoaded( + trendingShows = trending.getOrNull().toTvShowList(), + popularShows = popular.getOrNull().toTvShowList(), + anticipatedShows = anticipated.getOrNull().toTvShowList(), + recommendedShows = recommended.getOrNull()?.take(5).toTvShowList(), + errorMessage = getErrorMessage(trending, popular, anticipated, recommended), + ) } + .catch { ErrorState(errorMessage = it.message) } } diff --git a/presentation/discover/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachineTest.kt b/presentation/discover/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachineTest.kt index cfea3517f..ff0ea5355 100644 --- a/presentation/discover/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachineTest.kt +++ b/presentation/discover/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachineTest.kt @@ -5,84 +5,24 @@ import com.thomaskioko.tvmaniac.shows.testing.FakeDiscoverRepository import com.thomaskioko.tvmaniac.tmdb.testing.FakeShowImagesRepository import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest -import org.mobilenativefoundation.store.store5.StoreReadResponse -import org.mobilenativefoundation.store.store5.StoreReadResponseOrigin -import kotlin.test.Ignore import kotlin.test.Test -@Ignore internal class DiscoverStateMachineTest { - private val traktRepository = FakeDiscoverRepository() + private val discoverRepository = FakeDiscoverRepository() private val imagesRepository = FakeShowImagesRepository() - private val stateMachine = DiscoverStateMachine( - traktRepository, - imagesRepository, - ) + private val stateMachine = DiscoverStateMachine(discoverRepository, imagesRepository) @Test - fun initial_state_emits_expected_result() = runTest { - traktRepository.setTrendingResult( - StoreReadResponse.Data( - value = categoryResult(1), - origin = StoreReadResponseOrigin.Cache, - ), - ) - traktRepository.setPopularResult( - StoreReadResponse.Data( - value = categoryResult(2), - origin = StoreReadResponseOrigin.Cache, - ), - ) - traktRepository.setAnticipatedResult( - StoreReadResponse.Data( - value = categoryResult(3), - origin = StoreReadResponseOrigin.Cache, - ), - ) - traktRepository.setFeaturedResult( - StoreReadResponse.Data( - value = categoryResult(4), - origin = StoreReadResponseOrigin.Cache, - ), - ) + fun `given an result is loaded then correct state is emitted`() = runTest { + discoverRepository.setShowCategory(categoryResult(1)) + discoverRepository.setShowCategory(categoryResult(2)) + discoverRepository.setShowCategory(categoryResult(3)) + discoverRepository.setShowCategory(categoryResult(4)) stateMachine.state.test { awaitItem() shouldBe Loading awaitItem() shouldBe discoverContent } } - - @Test - fun on_category_error_emits_expected_result() = runTest { - traktRepository.setFeaturedResult( - StoreReadResponse.Error.Message( - message = "Something went wrong", - origin = StoreReadResponseOrigin.Cache, - ), - ) - traktRepository.setAnticipatedResult( - StoreReadResponse.Error.Message( - message = "Something went wrong", - origin = StoreReadResponseOrigin.Cache, - ), - ) - traktRepository.setPopularResult( - StoreReadResponse.Error.Message( - message = "Something went wrong", - origin = StoreReadResponseOrigin.Cache, - ), - ) - traktRepository.setTrendingResult( - StoreReadResponse.Error.Message( - message = "Something went wrong", - origin = StoreReadResponseOrigin.Cache, - ), - ) - - stateMachine.state.test { - awaitItem() shouldBe Loading - awaitItem() shouldBe DataLoaded() - } - } } diff --git a/presentation/discover/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/discover/MockData.kt b/presentation/discover/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/discover/MockData.kt index d316a7a23..c62d54b90 100644 --- a/presentation/discover/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/discover/MockData.kt +++ b/presentation/discover/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/discover/MockData.kt @@ -55,3 +55,28 @@ fun categoryResult(categoryId: Long) = listOf( aired_episodes = null, ), ) + +fun updateCategoryResult(categoryId: Long, size: Int = 1) = List(size) { + ShowsByCategory( + trakt_id = 84958, + tmdb_id = 849583, + title = "Loki", + overview = "After stealing the Tesseract during the events of “Avengers: Endgame,” " + + "an alternate version of Loki is brought to the mysterious Time Variance " + + "Authority, a bureaucratic organization that exists outside of time and " + + "space and monitors the timeline. They give Loki a choice: face being " + + "erased from existence due to being a “time variant”or help fix " + + "the timeline and stop a greater threat.", + language = "en", + votes = 4958, + rating = 8.1, + genres = listOf("Horror", "Action"), + status = "Returning Series", + year = "2024", + runtime = 45, + poster_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", + backdrop_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", + category_id = categoryId, + aired_episodes = null, + ) +} diff --git a/presentation/profile/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachine.kt b/presentation/profile/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachine.kt index d08011fff..940efd877 100644 --- a/presentation/profile/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachine.kt +++ b/presentation/profile/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachine.kt @@ -1,13 +1,13 @@ package com.thomaskioko.tvmaniac.presentation.profile import com.freeletics.flowredux.dsl.FlowReduxStateMachine +import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.datastore.api.DatastoreRepository import com.thomaskioko.tvmaniac.profile.api.ProfileRepository import com.thomaskioko.tvmaniac.traktauth.api.TraktAuthRepository import com.thomaskioko.tvmaniac.traktauth.api.TraktAuthState import kotlinx.coroutines.ExperimentalCoroutinesApi import me.tatarka.inject.annotations.Inject -import org.mobilenativefoundation.store.store5.StoreReadResponse @OptIn(ExperimentalCoroutinesApi::class) @Inject @@ -72,38 +72,23 @@ class ProfileStateMachine( collectWhileInState(profileRepository.observeProfile("me")) { response, state -> when (response) { - is StoreReadResponse.NoNewData -> state.noChange() - is StoreReadResponse.Loading -> state.mutate { + is Either.Left -> state.mutate { copy( - isLoading = true, + isLoading = false, + errorMessage = response.error.errorMessage, ) } - - is StoreReadResponse.Data -> state.mutate { + is Either.Right -> state.mutate { copy( isLoading = false, userInfo = UserInfo( - slug = response.requireData().slug, - userName = response.requireData().user_name, - fullName = response.requireData().full_name, - userPicUrl = response.requireData().profile_picture, + slug = response.data.slug, + userName = response.data.user_name, + fullName = response.data.full_name, + userPicUrl = response.data.profile_picture, ), ) } - - is StoreReadResponse.Error.Exception -> state.mutate { - copy( - isLoading = false, - errorMessage = response.error.message, - ) - } - - is StoreReadResponse.Error.Message -> state.mutate { - copy( - isLoading = false, - errorMessage = response.message, - ) - } } } diff --git a/presentation/profile/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachineTest.kt b/presentation/profile/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachineTest.kt index 0d2898fa3..920803907 100644 --- a/presentation/profile/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachineTest.kt +++ b/presentation/profile/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachineTest.kt @@ -1,6 +1,8 @@ package com.thomaskioko.tvmaniac.presentation.profile import app.cash.turbine.test +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.ServerError import com.thomaskioko.tvmaniac.datastore.testing.FakeDatastoreRepository import com.thomaskioko.tvmaniac.datastore.testing.authenticatedAuthState import com.thomaskioko.tvmaniac.trakt.profile.testing.FakeProfileRepository @@ -9,8 +11,6 @@ import com.thomaskioko.tvmaniac.traktauth.api.TraktAuthState import com.thomaskioko.tvmaniac.traktauth.testing.FakeTraktAuthRepository import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest -import org.mobilenativefoundation.store.store5.StoreReadResponse -import org.mobilenativefoundation.store.store5.StoreReadResponseOrigin import kotlin.test.Test class ProfileStateMachineTest { @@ -53,12 +53,7 @@ class ProfileStateMachineTest { traktAuthRepository.setAuthState(TraktAuthState.LOGGED_IN) datastoreRepository.setAuthState(authenticatedAuthState) - profileRepository.setUserData( - StoreReadResponse.Data( - value = user, - origin = StoreReadResponseOrigin.Cache, - ), - ) + profileRepository.setUserData(Either.Right(user)) awaitItem() shouldBe LoggedInContent() awaitItem() shouldBe LoggedInContent() @@ -96,10 +91,7 @@ class ProfileStateMachineTest { traktAuthRepository.setAuthState(TraktAuthState.LOGGED_IN) datastoreRepository.setAuthState(authenticatedAuthState) profileRepository.setUserData( - StoreReadResponse.Error.Exception( - error = Throwable(errorMessage), - origin = StoreReadResponseOrigin.Cache, - ), + Either.Left(ServerError(errorMessage)), ) awaitItem() shouldBe LoggedInContent() @@ -117,12 +109,7 @@ class ProfileStateMachineTest { traktAuthRepository.setAuthState(TraktAuthState.LOGGED_IN) datastoreRepository.setAuthState(authenticatedAuthState) - profileRepository.setUserData( - StoreReadResponse.Data( - value = user, - origin = StoreReadResponseOrigin.Cache, - ), - ) + profileRepository.setUserData(Either.Right(user)) awaitItem() shouldBe LoggedInContent() awaitItem() shouldBe LoggedInContent() diff --git a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsStateMachine.kt b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsStateMachine.kt index bde1c8bff..f4c1e9dca 100644 --- a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsStateMachine.kt +++ b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsStateMachine.kt @@ -3,7 +3,6 @@ package com.thomaskioko.tvmaniac.presentation.seasondetails import com.freeletics.flowredux.dsl.ChangedState import com.freeletics.flowredux.dsl.FlowReduxStateMachine import com.freeletics.flowredux.dsl.State -import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageRepository import com.thomaskioko.tvmaniac.seasondetails.api.SeasonDetailsRepository import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -12,7 +11,7 @@ import me.tatarka.inject.annotations.Inject @OptIn(ExperimentalCoroutinesApi::class) @Inject -class SeasonDetailsStateMachine constructor( +class SeasonDetailsStateMachine( @Assisted private val traktId: Long, private val seasonDetailsRepository: SeasonDetailsRepository, private val episodeImageRepository: EpisodeImageRepository, @@ -24,10 +23,28 @@ class SeasonDetailsStateMachine constructor( onEnter { state -> fetchSeasonDetails(state) } + + untilIdentityChanges({ state -> state }) { + collectWhileInState(seasonDetailsRepository.observeSeasonDetailsStream(traktId)) { result, state -> + result.fold( + { + state.override { LoadingError(it.errorMessage) } + }, + { + state.override { + SeasonDetailsLoaded( + showTitle = it.getTitle(), + seasonDetailsList = it.toSeasonWithEpisodes(), + ) + } + }, + ) + } + } } inState { - collectWhileInState(seasonDetailsRepository.observeSeasonDetails(traktId)) { result, state -> + collectWhileInState(seasonDetailsRepository.observeSeasonDetailsStream(traktId)) { result, state -> result.fold( { state.override { LoadingError(it.errorMessage) } @@ -46,19 +63,7 @@ class SeasonDetailsStateMachine constructor( } inState { - on { action, state -> - var nextState: SeasonDetailsState = state.snapshot - - seasonDetailsRepository.observeSeasonDetailsStream(traktId = action.showId) - .collect { result -> - nextState = when (result) { - is Either.Left -> LoadingError(result.error.errorMessage) - is Either.Right -> SeasonDetailsLoaded( - showTitle = result.getTitle(), - seasonDetailsList = result.toSeasonWithEpisodes(), - ) - } - } + on { _, state -> state.override { Loading } } @@ -69,9 +74,8 @@ class SeasonDetailsStateMachine constructor( private suspend fun fetchSeasonDetails(state: State): ChangedState { var nextState: SeasonDetailsState = Loading - seasonDetailsRepository.observeSeasonDetailsStream(traktId) + seasonDetailsRepository.observeCachedSeasonDetails(traktId) .collect { result -> - nextState = result.fold( { LoadingError(it.errorMessage) }, { diff --git a/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt b/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt index bdd7d2c1e..40da3c454 100644 --- a/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt +++ b/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt @@ -8,13 +8,11 @@ import com.thomaskioko.tvmaniac.presentation.seasondetails.Loading import com.thomaskioko.tvmaniac.presentation.seasondetails.LoadingError import com.thomaskioko.tvmaniac.presentation.seasondetails.SeasonDetailsStateMachine import com.thomaskioko.tvmaniac.seasondetails.testing.FakeSeasonDetailsRepository -import com.thomaskioko.tvmaniac.seasondetails.testing.seasonDetails +import com.thomaskioko.tvmaniac.seasondetails.testing.SeasonWithEpisodeList import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest -import kotlin.test.Ignore import kotlin.test.Test -@Ignore // TODO:: Fix test class SeasonDetailsStateMachineTest { private val seasonDetailsRepository = FakeSeasonDetailsRepository() @@ -28,7 +26,7 @@ class SeasonDetailsStateMachineTest { @Test fun onLoadSeasonDetails_correct_state_is_emitted() = runTest { stateMachine.state.test { - seasonDetailsRepository.setSeasonDetails(Either.Right(seasonDetails)) + seasonDetailsRepository.setSeasonsResult(Either.Right(SeasonWithEpisodeList)) awaitItem() shouldBe Loading awaitItem() shouldBe seasonDetailsLoaded @@ -39,7 +37,7 @@ class SeasonDetailsStateMachineTest { fun onLoadSeasonDetails_andErrorOccurs_correctStateIsEmitted() = runTest { stateMachine.state.test { val errorMessage = "Something went wrong" - seasonDetailsRepository.setSeasonDetails(Either.Left(DefaultError(errorMessage))) + seasonDetailsRepository.setSeasonsResult(Either.Left(DefaultError(errorMessage))) awaitItem() shouldBe Loading awaitItem() shouldBe LoadingError(errorMessage) diff --git a/presentation/settings/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachine.kt b/presentation/settings/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachine.kt index 362897de8..5bc119ecd 100644 --- a/presentation/settings/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachine.kt +++ b/presentation/settings/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachine.kt @@ -1,16 +1,15 @@ package com.thomaskioko.tvmaniac.presentation.settings import com.freeletics.flowredux.dsl.FlowReduxStateMachine +import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.datastore.api.DatastoreRepository import com.thomaskioko.tvmaniac.profile.api.ProfileRepository import com.thomaskioko.tvmaniac.traktauth.api.TraktAuthRepository import com.thomaskioko.tvmaniac.traktauth.api.TraktAuthState import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.FlowPreview import me.tatarka.inject.annotations.Inject -import org.mobilenativefoundation.store.store5.StoreReadResponse -@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class) +@OptIn(ExperimentalCoroutinesApi::class) @Inject class SettingsStateMachine( private val datastoreRepository: DatastoreRepository, @@ -109,39 +108,24 @@ class SettingsStateMachine( } collectWhileInState(profileRepository.observeProfile("me")) { response, state -> - when (response) { - is StoreReadResponse.NoNewData -> state.noChange() - is StoreReadResponse.Loading -> state.mutate { + is Either.Left -> state.mutate { copy( - isLoading = true, + isLoading = false, + errorMessage = response.error.errorMessage, ) } - is StoreReadResponse.Data -> state.mutate { + is Either.Right -> state.mutate { copy( isLoading = false, userInfo = UserInfo( - slug = response.requireData().slug, - userName = response.requireData().user_name, - fullName = response.requireData().full_name, - userPicUrl = response.requireData().profile_picture, + slug = response.data.slug, + userName = response.data.user_name, + fullName = response.data.full_name, + userPicUrl = response.data.profile_picture, ), ) } - - is StoreReadResponse.Error.Exception -> state.mutate { - copy( - isLoading = false, - errorMessage = response.error.message, - ) - } - - is StoreReadResponse.Error.Message -> state.mutate { - copy( - isLoading = false, - errorMessage = response.message, - ) - } } } diff --git a/presentation/settings/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachineTest.kt b/presentation/settings/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachineTest.kt index cfd44776e..418584b18 100644 --- a/presentation/settings/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachineTest.kt +++ b/presentation/settings/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachineTest.kt @@ -1,6 +1,8 @@ package com.thomaskioko.tvmaniac.presentation.settings import app.cash.turbine.test +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.ServerError import com.thomaskioko.tvmaniac.datastore.api.Theme import com.thomaskioko.tvmaniac.datastore.testing.FakeDatastoreRepository import com.thomaskioko.tvmaniac.datastore.testing.authenticatedAuthState @@ -10,8 +12,6 @@ import com.thomaskioko.tvmaniac.traktauth.api.TraktAuthState import com.thomaskioko.tvmaniac.traktauth.testing.FakeTraktAuthRepository import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest -import org.mobilenativefoundation.store.store5.StoreReadResponse -import org.mobilenativefoundation.store.store5.StoreReadResponseOrigin import kotlin.test.Test class SettingsStateMachineTest { @@ -115,12 +115,7 @@ class SettingsStateMachineTest { traktAuthRepository.setAuthState(TraktAuthState.LOGGED_IN) datastoreRepository.setAuthState(authenticatedAuthState) - profileRepository.setUserData( - StoreReadResponse.Data( - value = user, - origin = StoreReadResponseOrigin.Cache, - ), - ) + profileRepository.setUserData(Either.Right(user)) awaitItem() shouldBe LoggedInContent.DEFAULT_STATE awaitItem() shouldBe LoggedInContent.DEFAULT_STATE @@ -157,12 +152,7 @@ class SettingsStateMachineTest { traktAuthRepository.setAuthState(TraktAuthState.LOGGED_IN) datastoreRepository.setAuthState(authenticatedAuthState) - profileRepository.setUserData( - StoreReadResponse.Error.Exception( - error = Throwable(errorMessage), - origin = StoreReadResponseOrigin.Cache, - ), - ) + profileRepository.setUserData(Either.Left(ServerError(errorMessage))) awaitItem() shouldBe LoggedInContent.DEFAULT_STATE awaitItem() shouldBe LoggedInContent.DEFAULT_STATE @@ -179,12 +169,7 @@ class SettingsStateMachineTest { traktAuthRepository.setAuthState(TraktAuthState.LOGGED_IN) datastoreRepository.setAuthState(authenticatedAuthState) - profileRepository.setUserData( - StoreReadResponse.Data( - value = user, - origin = StoreReadResponseOrigin.Cache, - ), - ) + profileRepository.setUserData(Either.Right(user)) awaitItem() shouldBe LoggedInContent.DEFAULT_STATE awaitItem() shouldBe LoggedInContent.DEFAULT_STATE diff --git a/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachine.kt b/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachine.kt index 58c5b7657..f1d1152b1 100644 --- a/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachine.kt +++ b/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachine.kt @@ -4,8 +4,11 @@ import com.freeletics.flowredux.dsl.ChangedState import com.freeletics.flowredux.dsl.FlowReduxStateMachine import com.freeletics.flowredux.dsl.State import com.thomaskioko.tvmaniac.core.db.Seasons +import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.SimilarShows import com.thomaskioko.tvmaniac.core.db.Trailers +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.data.trailers.implementation.TrailerRepository import com.thomaskioko.tvmaniac.presentation.showdetails.ShowDetailsLoaded.TrailersContent.Companion.playerErrorMessage import com.thomaskioko.tvmaniac.seasons.api.SeasonsRepository @@ -15,11 +18,10 @@ import com.thomaskioko.tvmaniac.similar.api.SimilarShowsRepository import kotlinx.coroutines.ExperimentalCoroutinesApi import me.tatarka.inject.annotations.Assisted import me.tatarka.inject.annotations.Inject -import org.mobilenativefoundation.store.store5.StoreReadResponse @OptIn(ExperimentalCoroutinesApi::class) @Inject -class ShowDetailsStateMachine constructor( +class ShowDetailsStateMachine( @Assisted private val traktShowId: Long, private val discoverRepository: DiscoverRepository, private val similarShowsRepository: SimilarShowsRepository, @@ -39,37 +41,16 @@ class ShowDetailsStateMachine constructor( fetchShowDetails(state) } - collectWhileInState(discoverRepository.observeShow(traktShowId)) { response, state -> - when (response) { - is StoreReadResponse.NoNewData -> state.noChange() - is StoreReadResponse.Loading -> state.mutate { - copy(isLoading = true) - } - - is StoreReadResponse.Data -> state.mutate { - copy( - isLoading = false, - show = response.requireData().toTvShow(), - ) - } - - is StoreReadResponse.Error.Exception -> - state.mutate { - copy( - isLoading = false, - errorMessage = response.errorMessageOrNull(), - ) - } - - is StoreReadResponse.Error.Message -> state.mutate { - copy( - isLoading = false, - errorMessage = response.message, - ) - } + untilIdentityChanges({ state -> state.show.traktId }) { + collectWhileInState(discoverRepository.observeShow(traktShowId)) { result, state -> + updateShowDetails(result, state) } } + collectWhileInState(discoverRepository.observeShow(traktShowId)) { response, state -> + updateShowDetails(response, state) + } + collectWhileInState(seasonsRepository.observeSeasonsStoreResponse(traktShowId)) { result, state -> updateSeasonDetailsState(result, state) } @@ -119,136 +100,90 @@ class ShowDetailsStateMachine constructor( } } - private fun updateSimilarShowsState( - response: StoreReadResponse>, + private fun updateShowDetails( + response: Either, state: State, ) = when (response) { - is StoreReadResponse.NoNewData -> state.noChange() - is StoreReadResponse.Loading -> { - state.mutate { - copy( - similarShowsContent = similarShowsContent - .copy(isLoading = true), - ) - } - } - - is StoreReadResponse.Data -> { - state.mutate { - copy( - similarShowsContent = similarShowsContent.copy( - isLoading = false, - similarShows = response.requireData().toSimilarShowList(), - ), - ) - } - } - - is StoreReadResponse.Error.Exception -> { - state.mutate { - copy( - similarShowsContent = similarShowsContent.copy( - errorMessage = response.error.message, - ), - ) - } + is Either.Left -> state.mutate { + copy( + isLoading = false, + errorMessage = response.error.errorMessage, + ) } - is StoreReadResponse.Error.Message -> { - state.mutate { - copy( - similarShowsContent = similarShowsContent.copy( - errorMessage = response.message, - ), - ) - } + is Either.Right -> state.mutate { + copy( + isLoading = false, + show = response.data.toTvShow(), + ) } } - private fun updateTrailerState( - response: StoreReadResponse>, + private fun updateSimilarShowsState( + response: Either>, state: State, ) = when (response) { - is StoreReadResponse.NoNewData -> state.noChange() - is StoreReadResponse.Loading -> state.mutate { + is Either.Left -> state.mutate { copy( - trailersContent = trailersContent.copy( - isLoading = true, + similarShowsContent = similarShowsContent.copy( + errorMessage = response.error.errorMessage, ), ) } - is StoreReadResponse.Data -> { - state.mutate { - copy( - trailersContent = trailersContent.copy( - isLoading = false, - trailersList = response.requireData().toTrailerList(), - ), - ) - } - } - - is StoreReadResponse.Error.Exception -> { - state.mutate { - copy( - trailersContent = trailersContent.copy( - errorMessage = response.error.message, - ), - ) - } - } - - is StoreReadResponse.Error.Message -> { - state.mutate { - copy(trailersContent = trailersContent.copy(errorMessage = response.message)) - } + is Either.Right -> state.mutate { + copy( + similarShowsContent = similarShowsContent.copy( + isLoading = false, + similarShows = response.data.toSimilarShowList(), + ), + ) } } - private fun updateSeasonDetailsState( - response: StoreReadResponse>, + private fun updateTrailerState( + response: Either>, state: State, ) = when (response) { - is StoreReadResponse.NoNewData -> state.noChange() - is StoreReadResponse.Loading -> { + is Either.Left -> { state.mutate { - copy( - seasonsContent = seasonsContent.copy( - isLoading = true, - ), - ) + copy(trailersContent = trailersContent.copy(errorMessage = response.error.errorMessage)) } } - is StoreReadResponse.Data -> { + is Either.Right -> { state.mutate { copy( - seasonsContent = seasonsContent.copy( + trailersContent = trailersContent.copy( isLoading = false, - seasonsList = response.requireData().toSeasonsList(), + trailersList = response.data.toTrailerList(), ), ) } } + } - is StoreReadResponse.Error.Exception -> { + private fun updateSeasonDetailsState( + response: Either>, + state: State, + ) = when (response) { + is Either.Left -> { state.mutate { copy( seasonsContent = seasonsContent.copy( isLoading = true, - errorMessage = response.error.message, + errorMessage = response.error.errorMessage, ), ) } } - is StoreReadResponse.Error.Message -> { + is Either.Right -> { state.mutate { copy( seasonsContent = seasonsContent.copy( - isLoading = true, - errorMessage = response.message, + isLoading = false, + seasonsList = response.data.toSeasonsList(), ), ) } diff --git a/presentation/show-details/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachineTest.kt b/presentation/show-details/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachineTest.kt index 1a819bc67..35d9ad36b 100644 --- a/presentation/show-details/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachineTest.kt +++ b/presentation/show-details/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachineTest.kt @@ -1,19 +1,21 @@ package com.thomaskioko.tvmaniac.presentation.showdetails import app.cash.turbine.test +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.ServerError +import com.thomaskioko.tvmaniac.presentation.showdetails.ShowDetailsLoaded.Companion.EMPTY_DETAIL_STATE import com.thomaskioko.tvmaniac.presentation.showdetails.ShowDetailsLoaded.SeasonsContent.Companion.EMPTY_SEASONS import com.thomaskioko.tvmaniac.presentation.showdetails.ShowDetailsLoaded.SimilarShowsContent.Companion.EMPTY_SIMILAR_SHOWS import com.thomaskioko.tvmaniac.presentation.showdetails.ShowDetailsLoaded.TrailersContent.Companion.EMPTY_TRAILERS import com.thomaskioko.tvmaniac.seasons.testing.FakeSeasonsRepository import com.thomaskioko.tvmaniac.shows.testing.FakeDiscoverRepository +import com.thomaskioko.tvmaniac.shows.testing.selectedShow import com.thomaskioko.tvmaniac.similar.testing.FakeSimilarShowsRepository import com.thomaskioko.tvmaniac.trailers.testing.FakeTrailerRepository import com.thomaskioko.tvmaniac.trailers.testing.trailers import com.thomaskioko.tvmaniac.watchlist.testing.FakeWatchlistRepository import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest -import org.mobilenativefoundation.store.store5.StoreReadResponse -import org.mobilenativefoundation.store.store5.StoreReadResponseOrigin import kotlin.test.Ignore import kotlin.test.Test @@ -22,13 +24,13 @@ internal class ShowDetailsStateMachineTest { private val seasonsRepository = FakeSeasonsRepository() private val trailerRepository = FakeTrailerRepository() - private val traktRepository = FakeDiscoverRepository() + private val discoverRepository = FakeDiscoverRepository() private val similarShowsRepository = FakeSimilarShowsRepository() private val watchlistRepository = FakeWatchlistRepository() private val stateMachine = ShowDetailsStateMachine( traktShowId = 84958, - discoverRepository = traktRepository, + discoverRepository = discoverRepository, trailerRepository = trailerRepository, seasonsRepository = seasonsRepository, similarShowsRepository = similarShowsRepository, @@ -38,43 +40,25 @@ internal class ShowDetailsStateMachineTest { @Test fun initial_state_emits_expected_result() = runTest { stateMachine.state.test { - stateMachine.dispatch(LoadShowDetails(84958)) + discoverRepository.setShowById(selectedShow) - awaitItem() shouldBe ShowDetailsLoaded.EMPTY_DETAIL_STATE + awaitItem() shouldBe EMPTY_DETAIL_STATE.copy( + show = show, + ) } } @Test fun loadingData_state_emits_expected_result() = runTest { stateMachine.state.test { - traktRepository.setShowResult( - StoreReadResponse.Data( - value = selectedShow, - origin = StoreReadResponseOrigin.Cache, - ), - ) - seasonsRepository.setSeasonsResult( - StoreReadResponse.Data( - value = seasons, - origin = StoreReadResponseOrigin.Cache, - ), - ) - similarShowsRepository.setSimilarShowsResult( - StoreReadResponse.Data( - value = similarShowResult, - origin = StoreReadResponseOrigin.Cache, - ), - ) - trailerRepository.setTrailerResult( - StoreReadResponse.Data( - value = trailers, - origin = StoreReadResponseOrigin.Cache, - ), - ) + discoverRepository.setShowResult(Either.Right(selectedShow)) + seasonsRepository.setSeasonsResult(Either.Right(seasons)) + similarShowsRepository.setSimilarShowsResult(Either.Right(similarShowResult)) + trailerRepository.setTrailerResult(Either.Right(trailers)) stateMachine.dispatch(LoadShowDetails(84958)) - awaitItem() shouldBe ShowDetailsLoaded.EMPTY_DETAIL_STATE + awaitItem() shouldBe EMPTY_DETAIL_STATE awaitItem() shouldBe showDetailsLoaded awaitItem() shouldBe showDetailsLoaded.copy( seasonsContent = seasonsShowDetailsLoaded, @@ -95,34 +79,14 @@ internal class ShowDetailsStateMachineTest { fun error_loading_similarShows_emits_expected_result() = runTest { stateMachine.state.test { val errorMessage = "Something went wrong" - traktRepository.setShowResult( - StoreReadResponse.Data( - value = selectedShow, - origin = StoreReadResponseOrigin.Cache, - ), - ) - seasonsRepository.setSeasonsResult( - StoreReadResponse.Data( - value = seasons, - origin = StoreReadResponseOrigin.Cache, - ), - ) - trailerRepository.setTrailerResult( - StoreReadResponse.Data( - value = trailers, - origin = StoreReadResponseOrigin.Cache, - ), - ) - similarShowsRepository.setSimilarShowsResult( - StoreReadResponse.Error.Message( - message = errorMessage, - origin = StoreReadResponseOrigin.Cache, - ), - ) + discoverRepository.setShowResult(Either.Right(selectedShow)) + seasonsRepository.setSeasonsResult(Either.Right(seasons)) + trailerRepository.setTrailerResult(Either.Right(trailers)) + similarShowsRepository.setSimilarShowsResult(Either.Left(ServerError(errorMessage))) stateMachine.dispatch(LoadShowDetails(84958)) - awaitItem() shouldBe ShowDetailsLoaded.EMPTY_DETAIL_STATE + awaitItem() shouldBe EMPTY_DETAIL_STATE awaitItem() shouldBe showDetailsLoaded awaitItem() shouldBe showDetailsLoaded.copy( seasonsContent = seasonsShowDetailsLoaded, @@ -145,34 +109,14 @@ internal class ShowDetailsStateMachineTest { fun error_loading_trailers_emits_expected_result() = runTest { stateMachine.state.test { val errorMessage = "Something went wrong" - traktRepository.setShowResult( - StoreReadResponse.Data( - value = selectedShow, - origin = StoreReadResponseOrigin.Cache, - ), - ) - seasonsRepository.setSeasonsResult( - StoreReadResponse.Data( - value = seasons, - origin = StoreReadResponseOrigin.Cache, - ), - ) - similarShowsRepository.setSimilarShowsResult( - StoreReadResponse.Data( - value = similarShowResult, - origin = StoreReadResponseOrigin.Cache, - ), - ) - trailerRepository.setTrailerResult( - StoreReadResponse.Error.Message( - message = errorMessage, - origin = StoreReadResponseOrigin.Cache, - ), - ) + discoverRepository.setShowResult(Either.Right(selectedShow)) + seasonsRepository.setSeasonsResult(Either.Right(seasons)) + similarShowsRepository.setSimilarShowsResult(Either.Right(similarShowResult)) + trailerRepository.setTrailerResult(Either.Left(ServerError(errorMessage))) stateMachine.dispatch(LoadShowDetails(84958)) - awaitItem() shouldBe ShowDetailsLoaded.EMPTY_DETAIL_STATE + awaitItem() shouldBe EMPTY_DETAIL_STATE awaitItem() shouldBe showDetailsLoaded awaitItem() shouldBe showDetailsLoaded.copy( seasonsContent = seasonsShowDetailsLoaded, @@ -197,32 +141,12 @@ internal class ShowDetailsStateMachineTest { fun error_loading_seasons_emits_expected_result() = runTest { stateMachine.state.test { val errorMessage = "Something went wrong" - traktRepository.setShowResult( - StoreReadResponse.Data( - value = selectedShow, - origin = StoreReadResponseOrigin.Cache, - ), - ) - trailerRepository.setTrailerResult( - StoreReadResponse.Data( - value = trailers, - origin = StoreReadResponseOrigin.Cache, - ), - ) - similarShowsRepository.setSimilarShowsResult( - StoreReadResponse.Data( - value = similarShowResult, - origin = StoreReadResponseOrigin.Cache, - ), - ) - seasonsRepository.setSeasonsResult( - StoreReadResponse.Error.Message( - message = errorMessage, - origin = StoreReadResponseOrigin.Cache, - ), - ) + discoverRepository.setShowResult(Either.Right(selectedShow)) + similarShowsRepository.setSimilarShowsResult(Either.Right(similarShowResult)) + trailerRepository.setTrailerResult(Either.Right(trailers)) + seasonsRepository.setSeasonWithEpisodes(Either.Left(ServerError(errorMessage))) - awaitItem() shouldBe ShowDetailsLoaded.EMPTY_DETAIL_STATE + awaitItem() shouldBe EMPTY_DETAIL_STATE awaitItem() shouldBe showDetailsLoaded awaitItem() shouldBe showDetailsLoaded.copy( seasonsContent = EMPTY_SEASONS.copy( @@ -249,35 +173,14 @@ internal class ShowDetailsStateMachineTest { fun error_state_emits_expected_result() = runTest { stateMachine.state.test { val errorMessage = "Something went wrong" - traktRepository.setShowResult( - StoreReadResponse.Error.Message( - message = errorMessage, - origin = StoreReadResponseOrigin.Cache, - ), - ) - seasonsRepository.setSeasonsResult( - StoreReadResponse.Error.Message( - message = errorMessage, - origin = StoreReadResponseOrigin.Cache, - ), - ) - similarShowsRepository.setSimilarShowsResult( - StoreReadResponse.Data( - value = similarShowResult, - origin = StoreReadResponseOrigin.Cache, - ), - ) - trailerRepository.setTrailerResult( - StoreReadResponse.Data( - value = trailers, - origin = StoreReadResponseOrigin.Cache, - ), - ) - + discoverRepository.setShowResult(Either.Left(ServerError(errorMessage))) + similarShowsRepository.setSimilarShowsResult(Either.Right(similarShowResult)) + trailerRepository.setTrailerResult(Either.Right(trailers)) + seasonsRepository.setSeasonsResult(Either.Right(seasons)) stateMachine.dispatch(LoadShowDetails(84958)) - awaitItem() shouldBe ShowDetailsLoaded.EMPTY_DETAIL_STATE - awaitItem() shouldBe ShowDetailsLoaded.EMPTY_DETAIL_STATE.copy( + awaitItem() shouldBe EMPTY_DETAIL_STATE + awaitItem() shouldBe EMPTY_DETAIL_STATE.copy( errorMessage = errorMessage, ) } diff --git a/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/Mapper.kt b/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/Mapper.kt index 945541190..c9dd76c40 100644 --- a/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/Mapper.kt +++ b/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/Mapper.kt @@ -3,13 +3,13 @@ package com.thomaskioko.tvmaniac.presentation.trailers import com.thomaskioko.tvmaniac.core.db.Trailers import com.thomaskioko.tvmaniac.presentation.trailers.model.Trailer -internal fun List?.toTrailerList(): List { - return this?.map { +internal fun List.toTrailerList(): List { + return map { Trailer( showId = it.trakt_id, key = it.key, name = it.name, youtubeThumbnailUrl = "https://i.ytimg.com/vi/${it.key}/hqdefault.jpg", ) - } ?: emptyList() + } } diff --git a/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailersState.kt b/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailersState.kt index 8d6e13144..fdbf64a68 100644 --- a/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailersState.kt +++ b/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailersState.kt @@ -11,4 +11,4 @@ data class TrailersContent( val trailersList: List = emptyList(), ) : TrailersState -data class TrailerError(val errorMessage: String) : TrailersState +data class TrailerError(val errorMessage: String?) : TrailersState diff --git a/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailersStateMachine.kt b/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailersStateMachine.kt index 70f741191..fa79d4b74 100644 --- a/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailersStateMachine.kt +++ b/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailersStateMachine.kt @@ -1,16 +1,13 @@ package com.thomaskioko.tvmaniac.presentation.trailers -import com.freeletics.flowredux.dsl.ChangedState import com.freeletics.flowredux.dsl.FlowReduxStateMachine -import com.freeletics.flowredux.dsl.State +import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.data.trailers.implementation.TrailerRepository import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.FlowPreview import me.tatarka.inject.annotations.Assisted import me.tatarka.inject.annotations.Inject -import org.mobilenativefoundation.store.store5.StoreReadResponse -@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class) +@OptIn(ExperimentalCoroutinesApi::class) @Inject class TrailersStateMachine( @Assisted private val traktShowId: Long, @@ -31,6 +28,25 @@ class TrailersStateMachine( } } + untilIdentityChanges({ state -> state }) { + collectWhileInState(repository.observeTrailersStoreResponse(traktShowId)) { response, state -> + when (response) { + is Either.Left -> { + state.override { TrailerError(response.error.errorMessage) } + } + + is Either.Right -> { + state.override { + TrailersContent( + selectedVideoKey = response.data.toTrailerList() + .firstOrNull()?.key, + trailersList = response.data.toTrailerList(), + ) + } + } + } + } + } on { action, state -> state.override { TrailerError(action.errorMessage) } } @@ -45,64 +61,33 @@ class TrailersStateMachine( collectWhileInState(repository.observeTrailersStoreResponse(traktShowId)) { response, state -> when (response) { - is StoreReadResponse.Loading -> state.override { LoadingTrailers } - is StoreReadResponse.NoNewData -> state.noChange() - is StoreReadResponse.Data -> { + is Either.Left -> { + state.override { TrailerError(response.error.errorMessage) } + } + + is Either.Right -> { state.mutate { copy( - selectedVideoKey = response.requireData().toTrailerList() + selectedVideoKey = response.data.toTrailerList() .firstOrNull()?.key, - trailersList = response.requireData().toTrailerList(), + trailersList = response.data.toTrailerList(), ) } } - - is StoreReadResponse.Error.Exception -> { - state.override { TrailerError("") } - } - - is StoreReadResponse.Error.Message -> { - state.override { TrailerError(response.message) } - } } } - } - - inState { on { _, state -> - reloadTrailers(state) + state.override { LoadingTrailers } } } - } - } - - private suspend fun reloadTrailers(state: State): ChangedState { - var trailerState: ChangedState = state.override { LoadingTrailers } - repository.observeTrailersStoreResponse(traktShowId) - .collect { response -> - trailerState = when (response) { - is StoreReadResponse.Loading -> state.override { LoadingTrailers } - is StoreReadResponse.NoNewData -> state.noChange() - is StoreReadResponse.Data -> { - state.override { - TrailersContent( - selectedVideoKey = response.requireData().toTrailerList() - .firstOrNull()?.key, - trailersList = response.requireData().toTrailerList(), - ) - } - } - is StoreReadResponse.Error.Exception -> { - state.override { TrailerError("") } - } + inState { - is StoreReadResponse.Error.Message -> { - state.override { TrailerError(response.message) } - } + on { _, state -> + state.override { LoadingTrailers } } } - return trailerState + } } } diff --git a/presentation/trailers/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailerStateMachineTest.kt b/presentation/trailers/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailerStateMachineTest.kt index d3d478abe..29ba90ac5 100644 --- a/presentation/trailers/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailerStateMachineTest.kt +++ b/presentation/trailers/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailerStateMachineTest.kt @@ -1,17 +1,15 @@ package com.thomaskioko.tvmaniac.presentation.trailers import app.cash.turbine.test +import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.networkutil.ServerError import com.thomaskioko.tvmaniac.presentation.trailers.model.Trailer import com.thomaskioko.tvmaniac.trailers.testing.FakeTrailerRepository import com.thomaskioko.tvmaniac.trailers.testing.trailers import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest -import org.mobilenativefoundation.store.store5.StoreReadResponse -import org.mobilenativefoundation.store.store5.StoreReadResponseOrigin -import kotlin.test.Ignore import kotlin.test.Test -@Ignore internal class TrailerStateMachineTest { private val repository = FakeTrailerRepository() @@ -21,22 +19,51 @@ internal class TrailerStateMachineTest { ) @Test - fun reloadTrailers_emits_expected_result() = runTest { + fun `given result is success correct state is emitted`() = runTest { stateMachine.state.test { repository.setTrailerList(trailers) - repository.setTrailerResult( - StoreReadResponse.Error.Message( - message = "Something went wrong.", - origin = StoreReadResponseOrigin.Cache, + awaitItem() shouldBe LoadingTrailers + awaitItem() shouldBe TrailersContent( + selectedVideoKey = "Fd43V", + trailersList = listOf( + Trailer( + showId = 84958, + key = "Fd43V", + name = "Some title", + youtubeThumbnailUrl = "https://i.ytimg.com/vi/Fd43V/hqdefault.jpg", + ), ), ) + } + } + + @Test + fun `given reload is clicked then correct state is emitted`() = runTest { + stateMachine.state.test { + repository.setTrailerList(trailers) + + repository.setTrailerResult(Either.Left(ServerError("Something went wrong."))) awaitItem() shouldBe LoadingTrailers + awaitItem() shouldBe TrailersContent( + selectedVideoKey = "Fd43V", + trailersList = listOf( + Trailer( + showId = 84958, + key = "Fd43V", + name = "Some title", + youtubeThumbnailUrl = "https://i.ytimg.com/vi/Fd43V/hqdefault.jpg", + ), + ), + ) + awaitItem() shouldBe TrailerError("Something went wrong.") stateMachine.dispatch(ReloadTrailers) + repository.setTrailerResult(Either.Right(trailers)) + awaitItem() shouldBe LoadingTrailers awaitItem() shouldBe TrailersContent( selectedVideoKey = "Fd43V", From 3ce9d86cec284b21ac9dbc56991f2c79263c67b3 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sat, 18 Nov 2023 15:11:59 +0100 Subject: [PATCH 05/38] add store dependencies. --- data/profile/implementation/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/profile/implementation/build.gradle.kts b/data/profile/implementation/build.gradle.kts index bb0cf83f7..3993d1ef3 100644 --- a/data/profile/implementation/build.gradle.kts +++ b/data/profile/implementation/build.gradle.kts @@ -14,6 +14,8 @@ kotlin { implementation(libs.kotlinInject.runtime) implementation(libs.sqldelight.extensions) + implementation(libs.kotlinx.atomicfu) + implementation(libs.store5) } } } From 91aba88bc132e0982d45ae4d047a11bb907b68a7 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sat, 18 Nov 2023 15:12:22 +0100 Subject: [PATCH 06/38] minor cleanup. --- app/build.gradle.kts | 1 + tooling/plugins/build.gradle.kts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 55798b445..4c784a71e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -23,6 +23,7 @@ android { packaging { resources { excludes.add("/META-INF/{AL2.0,LGPL2.1}") + excludes.add("/META-INF/versions/9/previous-compilation-data.bin") } } } diff --git a/tooling/plugins/build.gradle.kts b/tooling/plugins/build.gradle.kts index 83b1c14a7..2e6888ce5 100644 --- a/tooling/plugins/build.gradle.kts +++ b/tooling/plugins/build.gradle.kts @@ -14,8 +14,8 @@ java { } dependencies { - compileOnly(libs.android.gradle.tools) - compileOnly(libs.kotlin.gradle) + compileOnly(libs.android.gradlePlugin) + compileOnly(libs.kotlin.gradlePlugin) } gradlePlugin { From 7a934343b76b7ff953a455cb162315aeef8b4505 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sat, 18 Nov 2023 15:21:09 +0100 Subject: [PATCH 07/38] update ui states. --- .../DiscoverPreviewParameterProvider.kt | 3 +- .../tvmaniac/discover/DiscoverScreen.kt | 72 ++++++++----------- 2 files changed, 30 insertions(+), 45 deletions(-) diff --git a/android-features/discover/src/main/java/com/thomaskioko/tvmaniac/discover/DiscoverPreviewParameterProvider.kt b/android-features/discover/src/main/java/com/thomaskioko/tvmaniac/discover/DiscoverPreviewParameterProvider.kt index b0d86f32d..19b4f1c14 100644 --- a/android-features/discover/src/main/java/com/thomaskioko/tvmaniac/discover/DiscoverPreviewParameterProvider.kt +++ b/android-features/discover/src/main/java/com/thomaskioko/tvmaniac/discover/DiscoverPreviewParameterProvider.kt @@ -3,6 +3,7 @@ package com.thomaskioko.tvmaniac.discover import androidx.compose.ui.tooling.preview.PreviewParameterProvider import com.thomaskioko.tvmaniac.presentation.discover.DataLoaded import com.thomaskioko.tvmaniac.presentation.discover.DiscoverState +import com.thomaskioko.tvmaniac.presentation.discover.ErrorState import com.thomaskioko.tvmaniac.presentation.discover.model.TvShow import kotlinx.collections.immutable.toImmutableList @@ -39,7 +40,7 @@ class DiscoverPreviewParameterProvider : PreviewParameterProvider get() { return sequenceOf( discoverContentSuccess, - DataLoaded(errorMessage = "Opps! Something went wrong"), + ErrorState(errorMessage = "Opps! Something went wrong"), ) } } diff --git a/android-features/discover/src/main/java/com/thomaskioko/tvmaniac/discover/DiscoverScreen.kt b/android-features/discover/src/main/java/com/thomaskioko/tvmaniac/discover/DiscoverScreen.kt index 464ab936b..10f919358 100644 --- a/android-features/discover/src/main/java/com/thomaskioko/tvmaniac/discover/DiscoverScreen.kt +++ b/android-features/discover/src/main/java/com/thomaskioko/tvmaniac/discover/DiscoverScreen.kt @@ -57,7 +57,6 @@ import androidx.compose.ui.util.lerp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.thomaskioko.tvmaniac.category.api.model.Category import com.thomaskioko.tvmaniac.compose.components.BoxTextItems -import com.thomaskioko.tvmaniac.compose.components.EmptyUi import com.thomaskioko.tvmaniac.compose.components.ErrorUi import com.thomaskioko.tvmaniac.compose.components.LoadingIndicator import com.thomaskioko.tvmaniac.compose.components.ThemePreviews @@ -72,6 +71,7 @@ import com.thomaskioko.tvmaniac.compose.util.rememberDominantColorState import com.thomaskioko.tvmaniac.navigation.extensions.viewModel import com.thomaskioko.tvmaniac.presentation.discover.DataLoaded import com.thomaskioko.tvmaniac.presentation.discover.DiscoverState +import com.thomaskioko.tvmaniac.presentation.discover.ErrorState import com.thomaskioko.tvmaniac.presentation.discover.Loading import com.thomaskioko.tvmaniac.presentation.discover.RetryLoading import com.thomaskioko.tvmaniac.presentation.discover.SnackBarDismissed @@ -140,49 +140,33 @@ private fun DiscoverScreen( onMoreClicked: (showType: Long) -> Unit, ) { when (state) { - Loading -> - LoadingIndicator( - modifier = Modifier - .fillMaxSize() - .wrapContentSize(Alignment.Center), - ) - - is DataLoaded -> - when { - state.isContentEmpty && state.errorMessage != null -> { - ErrorUi( - errorMessage = state.errorMessage, - onRetry = onRetry, - modifier = Modifier - .fillMaxSize() - .wrapContentSize(Alignment.Center), - ) - } - - state.isContentEmpty -> { - EmptyUi( - modifier = Modifier - .fillMaxSize() - .wrapContentSize(Alignment.Center), - ) - } - - else -> { - DiscoverScrollContent( - modifier = modifier, - pagerState = pagerState, - snackBarHostState = snackBarHostState, - onShowClicked = onShowClicked, - onMoreClicked = onMoreClicked, - onSnackBarErrorDismissed = onErrorDismissed, - trendingShows = state.trendingShows, - popularShows = state.popularShows, - anticipatedShows = state.anticipatedShows, - recommendedShows = state.recommendedShows, - errorMessage = state.errorMessage, - ) - } - } + Loading -> LoadingIndicator( + modifier = Modifier + .fillMaxSize() + .wrapContentSize(Alignment.Center), + ) + + is DataLoaded -> DiscoverScrollContent( + modifier = modifier, + pagerState = pagerState, + snackBarHostState = snackBarHostState, + onShowClicked = onShowClicked, + onMoreClicked = onMoreClicked, + onSnackBarErrorDismissed = onErrorDismissed, + trendingShows = state.trendingShows, + popularShows = state.popularShows, + anticipatedShows = state.anticipatedShows, + recommendedShows = state.recommendedShows, + errorMessage = state.errorMessage, + ) + + is ErrorState -> ErrorUi( + errorMessage = state.errorMessage, + onRetry = onRetry, + modifier = Modifier + .fillMaxSize() + .wrapContentSize(Alignment.Center), + ) } } From eb1087a958ffb380c3c46409ab880345184da95a Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sat, 18 Nov 2023 15:21:56 +0100 Subject: [PATCH 08/38] update result mapping. --- .../tvmaniac/showsgrid/GridStateMachine.kt | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/android-features/shows-grid/src/main/kotlin/com/thomaskioko/tvmaniac/showsgrid/GridStateMachine.kt b/android-features/shows-grid/src/main/kotlin/com/thomaskioko/tvmaniac/showsgrid/GridStateMachine.kt index 2a42501ed..57d3a120e 100644 --- a/android-features/shows-grid/src/main/kotlin/com/thomaskioko/tvmaniac/showsgrid/GridStateMachine.kt +++ b/android-features/shows-grid/src/main/kotlin/com/thomaskioko/tvmaniac/showsgrid/GridStateMachine.kt @@ -3,13 +3,13 @@ package com.thomaskioko.tvmaniac.showsgrid import com.freeletics.flowredux.dsl.ChangedState import com.freeletics.flowredux.dsl.FlowReduxStateMachine import com.freeletics.flowredux.dsl.State +import com.thomaskioko.tvmaniac.category.api.model.getCategory +import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.shows.api.DiscoverRepository import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.FlowPreview import me.tatarka.inject.annotations.Inject -import org.mobilenativefoundation.store.store5.StoreReadResponse -@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class) +@OptIn(ExperimentalCoroutinesApi::class) @Inject class GridStateMachine( private val repository: DiscoverRepository, @@ -39,22 +39,18 @@ class GridStateMachine( action: LoadShows, ): ChangedState { var nextState: ChangedState = state.noChange() - repository.observeShowsByCategory(action.category) + repository.observeShowCategory(category = action.category.getCategory()) .collect { result -> nextState = when (result) { - is StoreReadResponse.NoNewData -> state.noChange() - is StoreReadResponse.Loading -> state.override { LoadingContent } - is StoreReadResponse.Data -> state.override { + is Either.Left -> state.override { + LoadingContentError(result.error.errorMessage) + } + + is Either.Right -> state.override { ShowsLoaded( - list = result.requireData().toTvShowList(), + list = result.data.map { it.toTvShow() }, ) } - is StoreReadResponse.Error.Exception -> state.override { - LoadingContentError(result.error.message) - } - is StoreReadResponse.Error.Message -> state.override { - LoadingContentError(result.message) - } } } From f9adf25fa3ccc1c298419cb23a30b30a22741959 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sat, 18 Nov 2023 15:22:18 +0100 Subject: [PATCH 09/38] add helper classes and server error class --- .../com/thomaskioko/tvmaniac/core/networkutil/Either.kt | 5 ++++- .../com/thomaskioko/tvmaniac/core/networkutil/Failure.kt | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Either.kt b/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Either.kt index d03480de2..4f32c86a2 100644 --- a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Either.kt +++ b/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Either.kt @@ -4,10 +4,13 @@ sealed class Either { data class Left(val error: L) : Either() - data class Right(val data: R?) : Either() + data class Right(val data: R) : Either() fun fold(lfn: (L) -> T, rfn: (R?) -> T): T = when (this) { is Left -> lfn(error) is Right -> rfn(data) } + + fun getOrNull(): R? = (this as? Right)?.data + fun getErrorOrNull(): L? = (this as? Left)?.error } diff --git a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Failure.kt b/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Failure.kt index 443bb8f4e..6e8ca5a2b 100644 --- a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Failure.kt +++ b/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Failure.kt @@ -9,3 +9,8 @@ class DefaultError(val message: String?) : Failure( throwable = Throwable(message), errorMessage = message, ) + +data class ServerError(val message: String?) : Failure( + throwable = Throwable(message), + errorMessage = message, +) From 64d998cf0194dc9c454f010eab9dfe3bba7aa47f Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sat, 18 Nov 2023 15:22:31 +0100 Subject: [PATCH 10/38] add jvm test job --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 96fccbcfc..6c4c8a177 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -102,6 +102,9 @@ jobs: - name: unitTest run: ./gradlew testDemoDebug + - name: Jvm Test + run: ./gradlew jvmTest + - uses: actions/upload-artifact@v3 with: name: unit-test-report From 2ca4cf64d2e4432000b51ed3b3721018eddfff84 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 01:58:33 +0100 Subject: [PATCH 11/38] implement type-safe IDs --- .../tvmaniac/db/DatabaseComponent.kt | 38 ++++++ .../DatabaseIdsExt.kt | 24 ++++ .../com.thomaskioko.tvmaniac.db/IdAdapter.kt | 8 ++ .../tvmaniac/core/db/SeasonEpisodes.sq | 30 ----- .../tvmaniac/core/db/episode_image.sq | 45 ++++--- .../thomaskioko/tvmaniac/core/db/episodes.sq | 64 +++++---- .../thomaskioko/tvmaniac/core/db/season.sq | 88 +++++++++--- .../com/thomaskioko/tvmaniac/core/db/show.sq | 126 ++++++++++-------- .../tvmaniac/core/db/show_category.sq | 45 ++++++- .../tvmaniac/core/db/show_image.sq | 46 +++---- .../tvmaniac/core/db/similar_shows.sq | 46 +++++-- .../com/thomaskioko/tvmaniac/core/db/stats.sq | 24 ++-- .../thomaskioko/tvmaniac/core/db/trailers.sq | 37 ++--- .../tvmaniac/core/db/trakt_shows_list.sq | 12 +- .../com/thomaskioko/tvmaniac/core/db/user.sq | 42 +++--- .../thomaskioko/tvmaniac/core/db/watchlist.sq | 79 +++++++---- .../tvmaniac/core/db/BaseDatabaseTest.kt | 31 +++++ .../tvmaniac/core/db/EpisodesCacheTest.kt | 11 +- .../thomaskioko/tvmaniac/core/db/MockData.kt | 21 +-- .../tvmaniac/core/db/TvShowCacheTest.kt | 10 +- .../tvmaniac/db/DatabaseComponent.kt | 38 ++++++ 21 files changed, 577 insertions(+), 288 deletions(-) create mode 100644 core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabaseIdsExt.kt create mode 100644 core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/IdAdapter.kt delete mode 100644 core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/SeasonEpisodes.sq diff --git a/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt b/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt index 0115d508c..598891fd7 100644 --- a/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt +++ b/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt @@ -3,9 +3,17 @@ package com.thomaskioko.tvmaniac.db import android.app.Application import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.android.AndroidSqliteDriver +import com.thomaskioko.tvmaniac.core.db.Episode +import com.thomaskioko.tvmaniac.core.db.Episode_image import com.thomaskioko.tvmaniac.core.db.Last_requests +import com.thomaskioko.tvmaniac.core.db.Season import com.thomaskioko.tvmaniac.core.db.Show +import com.thomaskioko.tvmaniac.core.db.Show_category +import com.thomaskioko.tvmaniac.core.db.Show_image +import com.thomaskioko.tvmaniac.core.db.Similar_shows +import com.thomaskioko.tvmaniac.core.db.Trailers import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import com.thomaskioko.tvmaniac.core.db.Watchlist import com.thomaskioko.tvmaniac.util.scope.ApplicationScope import me.tatarka.inject.annotations.Provides @@ -29,9 +37,39 @@ actual interface DatabaseComponent { driver = sqlDriver, showAdapter = Show.Adapter( genresAdapter = stringColumnAdapter, + idAdapter = IdAdapter(), ), last_requestsAdapter = Last_requests.Adapter( timestampAdapter = InstantColumnAdapter, ), + episode_imageAdapter = Episode_image.Adapter( + idAdapter = IdAdapter(), + tmdb_idAdapter = IdAdapter(), + ), + episodeAdapter = Episode.Adapter( + idAdapter = IdAdapter(), + season_idAdapter = IdAdapter(), + ), + seasonAdapter = Season.Adapter( + idAdapter = IdAdapter(), + show_idAdapter = IdAdapter(), + ), + show_imageAdapter = Show_image.Adapter( + idAdapter = IdAdapter(), + ), + similar_showsAdapter = Similar_shows.Adapter( + idAdapter = IdAdapter(), + similar_show_idAdapter = IdAdapter(), + ), + watchlistAdapter = Watchlist.Adapter( + idAdapter = IdAdapter(), + ), + show_categoryAdapter = Show_category.Adapter( + idAdapter = IdAdapter(), + category_idAdapter = IdAdapter(), + ), + trailersAdapter = Trailers.Adapter( + show_idAdapter = IdAdapter(), + ), ) } diff --git a/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabaseIdsExt.kt b/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabaseIdsExt.kt new file mode 100644 index 000000000..55561c0be --- /dev/null +++ b/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabaseIdsExt.kt @@ -0,0 +1,24 @@ +package com.thomaskioko.tvmaniac.db + +import kotlin.jvm.JvmInline + +@JvmInline +value class CategoryId(val id: Long) + +@JvmInline +value class EpisodeId(val traktId: Long) + +@JvmInline +value class EpisodeImageId(val traktId: Long) + +@JvmInline +value class SeasonId(val id: Long) + +@JvmInline +value class ShowId(val traktId: Long) + +@JvmInline +value class SimilarShowId(val id: Long) + +@JvmInline +value class Id(val id: Long) diff --git a/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/IdAdapter.kt b/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/IdAdapter.kt new file mode 100644 index 000000000..957180058 --- /dev/null +++ b/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/IdAdapter.kt @@ -0,0 +1,8 @@ +package com.thomaskioko.tvmaniac.db + +import app.cash.sqldelight.ColumnAdapter + +internal class IdAdapter : ColumnAdapter, Long> { + override fun decode(databaseValue: Long): Id = Id(id = databaseValue) + override fun encode(value: Id): Long = value.id +} diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/SeasonEpisodes.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/SeasonEpisodes.sq deleted file mode 100644 index 58284cffd..000000000 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/SeasonEpisodes.sq +++ /dev/null @@ -1,30 +0,0 @@ -CREATE TABLE season_episodes ( -show_id INTEGER DEFAULT NULL PRIMARY KEY, -season_id INTEGER DEFAULT NULL, -season_number INTEGER DEFAULT NULL, -FOREIGN KEY (season_id) REFERENCES seasons(id), -FOREIGN KEY (show_id) REFERENCES show(trakt_id) -); - -insertOrReplace: -INSERT OR REPLACE INTO season_episodes( -show_id, -season_id, -season_number -)VALUES(?,?,?); - -seasonWithEpisodes: -SELECT show.trakt_id, show.tmdb_id ,show.title, seasons.id , seasons.name, seasons.season_number, seasons.episode_count, -episodes.trakt_id, episodes.season_id, episodes.title , episodes.episode_number, episodes.overview, episodes.runtime, -episodes.ratings, episodes.votes, episode_image.image_url -FROM show -INNER JOIN seasons ON seasons.show_trakt_id = show.trakt_id -INNER JOIN episodes ON episodes.season_id = seasons.id -LEFT OUTER JOIN episode_image ON episode_image.trakt_id = episodes.trakt_id -WHERE show.trakt_id = ? AND season_number != 0 ORDER BY seasons.season_number, episode_number ASC; - -delete: -DELETE FROM season_episodes WHERE season_id = ?; - -deleteAll: -DELETE FROM season_episodes; \ No newline at end of file diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/episode_image.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/episode_image.sq index 8df845156..bfc4f7bc3 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/episode_image.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/episode_image.sq @@ -1,28 +1,35 @@ +import com.thomaskioko.tvmaniac.db.EpisodeId; +import com.thomaskioko.tvmaniac.db.EpisodeImageId; +import com.thomaskioko.tvmaniac.db.Id; + CREATE TABLE episode_image ( -trakt_id INTEGER NOT NULL PRIMARY KEY, -tmdb_id INTEGER NOT NULL, -image_url TEXT DEFAULT NULL, -FOREIGN KEY (trakt_id) REFERENCES episodes(trakt_id) ON DELETE CASCADE + id INTEGER AS Id NOT NULL PRIMARY KEY, + tmdb_id INTEGER AS Id, + image_url TEXT DEFAULT NULL, + FOREIGN KEY(id) REFERENCES episode(id) ON DELETE CASCADE, + UNIQUE(id) ); insertOrReplace: INSERT OR REPLACE INTO episode_image( -trakt_id, -tmdb_id, -image_url + id, + tmdb_id, + image_url ) VALUES(?,?,?); episodeImage: -SELECT show.tmdb_id, seasons.season_number, episodes.trakt_id, episodes.episode_number -FROM episodes -LEFT JOIN seasons ON seasons.id = episodes.season_id -LEFT JOIN show ON show.trakt_id = seasons.show_trakt_id -LEFT OUTER JOIN episode_image ON episode_image.trakt_id = episodes.trakt_id -WHERE episode_image.image_url IS NULL; - -delete: -DELETE FROM episode_image WHERE trakt_id = ?; - -deleteAll: -DELETE FROM episode_image; \ No newline at end of file +SELECT + show.tmdb_id, + season.season_number, + episode.episode_number +FROM + episode +LEFT JOIN + season ON season.id = episode.season_id +LEFT JOIN + show ON show.id = season.show_id +LEFT OUTER JOIN + episode_image ON episode_image.id = episode.id +WHERE + episode_image.image_url IS NULL; \ No newline at end of file diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/episodes.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/episodes.sq index 205600cd7..de0ceb564 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/episodes.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/episodes.sq @@ -1,40 +1,48 @@ -CREATE TABLE episodes ( -trakt_id INTEGER NOT NULL PRIMARY KEY, -season_id INTEGER NOT NULL, -tmdb_id INTEGER, -title TEXT NOT NULL, -overview TEXT NOT NULL, -ratings REAL NOT NULL, -runtime INTEGER NOT NULL, -votes INTEGER NOT NULL, -episode_number TEXT NOT NULL, -FOREIGN KEY (season_id) REFERENCES seasons(id) +import com.thomaskioko.tvmaniac.db.EpisodeId; +import com.thomaskioko.tvmaniac.db.Id; +import com.thomaskioko.tvmaniac.db.SeasonId; + +CREATE TABLE episode ( + id INTEGER AS Id NOT NULL PRIMARY KEY, + season_id INTEGER AS Id NOT NULL, + tmdb_id INTEGER, + title TEXT NOT NULL, + overview TEXT NOT NULL, + ratings REAL NOT NULL, + runtime INTEGER NOT NULL, + votes INTEGER NOT NULL, + episode_number TEXT NOT NULL, + FOREIGN KEY(season_id) REFERENCES season(id) ); insertOrReplace: -INSERT OR REPLACE INTO episodes( -trakt_id, -season_id, -tmdb_id, -title, -overview, -ratings, -runtime, -votes, -episode_number +INSERT OR REPLACE INTO episode( + id, + season_id, + tmdb_id, + title, + overview, + ratings, + runtime, + votes, + episode_number ) VALUES(?,?,?,?,?,?,?,?,?); -episodeById: +episodesById: SELECT * -FROM episodes -LEFT OUTER JOIN episode_image ON episode_image.trakt_id = episodes.trakt_id -WHERE episodes.trakt_id = ? -ORDER BY episode_number ASC ; +FROM + episode +LEFT OUTER JOIN + episode_image ON episode_image.id = episode.id +WHERE + episode.id = ? +ORDER BY + episode_number ASC; delete: -DELETE FROM episodes WHERE trakt_id = ?; +DELETE FROM episode WHERE id = ?; deleteAll: -DELETE FROM episodes; +DELETE FROM episode; diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/season.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/season.sq index 3c136c079..b1cc881b0 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/season.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/season.sq @@ -1,32 +1,76 @@ -CREATE TABLE seasons ( -id INTEGER NOT NULL PRIMARY KEY, -show_trakt_id INTEGER NOT NULL, -season_number INTEGER NOT NULL, -episode_count INTEGER NOT NULL, -name TEXT NOT NULL, -overview TEXT, -FOREIGN KEY (show_trakt_id) REFERENCES show(trakt_id) +import com.thomaskioko.tvmaniac.db.Id; +import com.thomaskioko.tvmaniac.db.SeasonId; +import com.thomaskioko.tvmaniac.db.ShowId; + +CREATE TABLE season ( + id INTEGER AS Id NOT NULL PRIMARY KEY, + show_id INTEGER AS Id NOT NULL, + season_number INTEGER NOT NULL, + title TEXT NOT NULL, + episode_count INTEGER NOT NULL, + overview TEXT, + FOREIGN KEY(show_id) REFERENCES show(id) ); insertOrReplace: -INSERT OR REPLACE INTO seasons( -id, -show_trakt_id, -season_number, -episode_count, -name, -overview +INSERT OR REPLACE INTO season( + id, + show_id, + season_number, + episode_count, + title, + overview ) VALUES(?,?,?,?,?,?); -seasonById: -SELECT * -FROM seasons -WHERE seasons.show_trakt_id = ? AND season_number != 0 -ORDER BY season_number ASC; +seasonsByShowId: +SELECT + show.id AS show_id, + season.id AS season_id, + season.title AS season_title, + season.season_number +FROM + show +JOIN + season ON show.id = season.show_id +WHERE + show.id = ?; + +seasonEpisodeDetailsById: +SELECT + show.id AS show_id, + show.title AS show_title, + season.id AS season_id, + season.title AS season_title, + season.overview AS season_overview, + season.season_number, + season.episode_count, + episode.id AS episode_id, + episode.season_id AS episode_season_id, + episode.title AS episode_title, + episode.episode_number, + episode.overview, + episode.runtime, + episode.ratings, + episode.votes, + episode_image.image_url AS episode_image_url +FROM + show +INNER JOIN + season ON season.show_id = show.id +INNER JOIN + episode ON episode.season_id = season.id +LEFT OUTER JOIN + episode_image ON episode_image.id = episode.id +WHERE + show.id = ? +AND + season_number != 0 +ORDER BY + season.season_number, episode_number ASC; delete: -DELETE FROM seasons WHERE show_trakt_id = ?; +DELETE FROM season WHERE show_id = ?; deleteAll: -DELETE FROM seasons; +DELETE FROM season; diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show.sq index 6d59b4b4d..36c234fce 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show.sq @@ -1,68 +1,90 @@ -import kotlin.collections.List; +import com.thomaskioko.tvmaniac.db.Id; +import com.thomaskioko.tvmaniac.db.ShowId; import kotlin.String; +import kotlin.collections.List; CREATE TABLE show( -trakt_id INTEGER NOT NULL PRIMARY KEY, -tmdb_id INTEGER, -title TEXT NOT NULL, -overview TEXT NOT NULL, -language TEXT, -year TEXT NOT NULL, -rating REAL NOT NULL, -status TEXT NOT NULL, -runtime INTEGER NOT NULL, -votes INTEGER NOT NULL, -aired_episodes INTEGER DEFAULT NULL, -genres TEXT AS List NOT NULL + id INTEGER AS Id NOT NULL PRIMARY KEY, + tmdb_id INTEGER, + title TEXT NOT NULL, + overview TEXT NOT NULL, + language TEXT, + year TEXT NOT NULL, + rating REAL NOT NULL, + status TEXT NOT NULL, + runtime INTEGER NOT NULL, + votes INTEGER NOT NULL, + aired_episodes INTEGER DEFAULT NULL, + genres TEXT AS List NOT NULL ); insertOrReplace: INSERT OR REPLACE INTO show( -trakt_id, -tmdb_id, -title, -overview, -language, -year, -votes, -runtime, -rating, -genres, -status + id, + tmdb_id, + title, + overview, + language, + year, + votes, + runtime, + rating, + genres, + status ) VALUES(?,?,?,?,?,?,?,?,?,?,?); showById: -SELECT * FROM show -LEFT OUTER JOIN show_image ON show_image.trakt_id = show.trakt_id -LEFT OUTER JOIN watchlist ON show.trakt_id = watchlist.id -WHERE show.trakt_id = ?; - -selectShowByTmdbId: -SELECT * FROM show -WHERE tmdb_id = ?; +SELECT + show.id, + show.tmdb_id , + show.title, + show.overview, + show.language, + show.year, + show.rating, + show.votes, + show.status, + show.runtime, + show.genres, + show.aired_episodes, + show_image.poster_url, + show_image.backdrop_url, + CASE WHEN watchlist.id IS NOT NULL THEN 1 ELSE 0 END AS in_watchlist +FROM + show +LEFT OUTER JOIN + show_image ON show_image.id = show.id +LEFT OUTER JOIN + watchlist ON show.id = watchlist.id +WHERE + show.id = ?; shows: -SELECT show.trakt_id, show.tmdb_id ,show.title, show.overview, show.language, show.year, show.rating, -show.votes, show.status, show.runtime, show.genres, show.aired_episodes, show_image.poster_url, show_image.backdrop_url, -show_category.category_id -FROM show -INNER JOIN show_category ON show_category.trakt_id = show.trakt_id -LEFT OUTER JOIN show_image ON show_image.trakt_id = show.trakt_id -ORDER BY show.rating, show.year DESC; - -showsByCategory: -SELECT show.trakt_id, show.tmdb_id ,show.title, show.overview, show.language, show.year, show.rating, -show.votes, show.status, show.runtime, show.genres, show.aired_episodes, show_image.poster_url, show_image.backdrop_url, -show_category.category_id -FROM show -INNER JOIN show_category ON show_category.trakt_id = show.trakt_id -LEFT OUTER JOIN show_image ON show_image.trakt_id = show.trakt_id -WHERE show_category.category_id = ? -ORDER BY show.rating, show.year DESC; - -delete: -DELETE FROM show WHERE trakt_id = ?; +SELECT + show.id, + show.tmdb_id , + show.title, + show.overview, + show.language, + show.year, + show.rating, + show.votes, + show.status, + show.runtime, + show.genres, + show.aired_episodes, + show_image.poster_url, + show_image.backdrop_url, + show_category.category_id +FROM + show +JOIN + show_category ON show_category.id = show.id +LEFT OUTER JOIN + show_image ON show_image.id = show.id +ORDER BY + show.rating, show.year DESC; deleteAll: DELETE FROM show; \ No newline at end of file diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show_category.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show_category.sq index 5bd008c92..1f01b9862 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show_category.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show_category.sq @@ -1,12 +1,45 @@ +import com.thomaskioko.tvmaniac.db.CategoryId; +import com.thomaskioko.tvmaniac.db.Id; +import com.thomaskioko.tvmaniac.db.ShowId; + CREATE TABLE show_category ( -trakt_id INTEGER DEFAULT NULL PRIMARY KEY, -category_id INTEGER DEFAULT NULL, -FOREIGN KEY (trakt_id) REFERENCES show(trakt_id) + id INTEGER AS Id DEFAULT NULL, + category_id INTEGER AS Id DEFAULT NULL, + FOREIGN KEY(id) REFERENCES show(id), + PRIMARY KEY(id, category_id) ); insertOrReplace: INSERT OR REPLACE INTO show_category( -trakt_id, -category_id + id, + category_id ) -VALUES(?,?); \ No newline at end of file +VALUES(?,?); + +showsByCategory: +SELECT + show.id, + show.tmdb_id , + show.title, + show.overview, + show.language, + show.year, + show.rating, + show.votes, + show.status, + show.runtime, + show.genres, + show.aired_episodes, + show_image.poster_url, + show_image.backdrop_url, + show_category.category_id +FROM + show +INNER JOIN + show_category ON show_category.id = show.id +LEFT OUTER JOIN + show_image ON show_image.id = show.id +WHERE + show_category.category_id = ? +ORDER BY + show.rating, show.year DESC; \ No newline at end of file diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show_image.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show_image.sq index 54a9c127f..7718f3ee4 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show_image.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show_image.sq @@ -1,31 +1,31 @@ +import com.thomaskioko.tvmaniac.db.Id; +import com.thomaskioko.tvmaniac.db.ShowId; + CREATE TABLE show_image ( -trakt_id INTEGER NOT NULL PRIMARY KEY, -tmdb_id INTEGER DEFAULT NULL, -poster_url TEXT DEFAULT NULL, -backdrop_url TEXT DEFAULT NULL, -FOREIGN KEY (trakt_id) REFERENCES show(trakt_id) ON DELETE CASCADE + id INTEGER AS Id NOT NULL PRIMARY KEY, + tmdb_id INTEGER DEFAULT NULL, + poster_url TEXT DEFAULT NULL, + backdrop_url TEXT DEFAULT NULL, + FOREIGN KEY(id) REFERENCES show(id) ON DELETE CASCADE, + UNIQUE(id) ); insertOrReplace: INSERT OR REPLACE INTO show_image( -trakt_id, -tmdb_id, -poster_url, -backdrop_url + id, + tmdb_id, + poster_url, + backdrop_url ) VALUES(?,?,?,?); -selectImages: -SELECT * FROM show_image -WHERE poster_url IS NULL; - -selectShowImages: -SELECT show.trakt_id, show.tmdb_id FROM show -LEFT OUTER JOIN show_image ON show_image.trakt_id = show.trakt_id -WHERE poster_url IS NULL AND backdrop_url IS NULL; - -delete: -DELETE FROM show_image WHERE trakt_id = ?; - -deleteAll: -DELETE FROM show_image; \ No newline at end of file +emptyShowImage: +SELECT + show.id, + show.tmdb_id +FROM + show +LEFT OUTER JOIN + show_image ON show_image.id = show.id +WHERE + poster_url IS NULL AND backdrop_url IS NULL; \ No newline at end of file diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/similar_shows.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/similar_shows.sq index fa61f1337..ed4637853 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/similar_shows.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/similar_shows.sq @@ -1,26 +1,48 @@ +import com.thomaskioko.tvmaniac.db.Id; +import com.thomaskioko.tvmaniac.db.ShowId; +import com.thomaskioko.tvmaniac.db.SimilarShowId; + CREATE TABLE similar_shows ( -id INTEGER DEFAULT NULL PRIMARY KEY, -trakt_id INTEGER NOT NULL, -FOREIGN KEY (trakt_id) REFERENCES show(trakt_id) + id INTEGER AS Id, + similar_show_id INTEGER AS Id NOT NULL, + PRIMARY KEY (similar_show_id, id), + FOREIGN KEY(similar_show_id) REFERENCES show(id), + FOREIGN KEY(id) REFERENCES show(id) ); insertOrReplace: INSERT OR REPLACE INTO similar_shows( -id, -trakt_id + id, + similar_show_id ) VALUES(?,?); similarShows: -SELECT show.trakt_id, show.tmdb_id ,show.title, show.overview, show.language, show.year, show.rating, show.votes, show.status, -show.runtime, show.genres, show_image.poster_url, show_image.backdrop_url -FROM show -JOIN similar_shows ON show.trakt_id = similar_shows.id -INNER JOIN show_image ON show_image.trakt_id = similar_shows.id -WHERE similar_shows.trakt_id = ?; +SELECT + show.id, + show.tmdb_id , + show.title, + show.overview, + show.language, + show.year, + show.rating, + show.votes, + show.status, + show.runtime, + show.genres, + show_image.poster_url, + show_image.backdrop_url +FROM + show +JOIN + similar_shows ON show.id = similar_shows.id +INNER JOIN + show_image ON show_image.id = similar_shows.id +WHERE + similar_shows.similar_show_id = ?; delete: -DELETE FROM similar_shows WHERE trakt_id = ?; +DELETE FROM similar_shows WHERE similar_show_id = ?; deleteAll: DELETE FROM similar_shows; \ No newline at end of file diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/stats.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/stats.sq index e51acf2f8..28b9ff4bc 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/stats.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/stats.sq @@ -1,20 +1,20 @@ CREATE TABLE stats( -slug TEXT NOT NULL PRIMARY KEY, -months Text NOT NULL, -days Text NOT NULL, -hours Text NOT NULL, -collected_shows Text NOT NULL, -episodes_watched Text NOT NULL + slug TEXT NOT NULL PRIMARY KEY, + months Text NOT NULL, + days Text NOT NULL, + hours Text NOT NULL, + collected_shows Text NOT NULL, + episodes_watched Text NOT NULL ); insertOrReplace: INSERT OR REPLACE INTO stats( -slug, -months, -days, -hours, -collected_shows, -episodes_watched + slug, + months, + days, + hours, + collected_shows, + episodes_watched ) VALUES(?,?,?,?,?,?); diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/trailers.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/trailers.sq index e94540844..171f4ebcf 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/trailers.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/trailers.sq @@ -1,33 +1,36 @@ +import com.thomaskioko.tvmaniac.db.Id; +import com.thomaskioko.tvmaniac.db.ShowId; + CREATE TABLE trailers ( -id TEXT NOT NULL PRIMARY KEY, -trakt_id INTEGER NOT NULL, -key TEXT NOT NULL, -name TEXT NOT NULL, -site TEXT NOT NULL, -size INTEGER NOT NULL, -type TEXT NOT NULL, -FOREIGN KEY (trakt_id) REFERENCES show(trakt_id) + id TEXT NOT NULL PRIMARY KEY, + show_id INTEGER AS Id NOT NULL, + key TEXT NOT NULL, + name TEXT NOT NULL, + site TEXT NOT NULL, + size INTEGER NOT NULL, + type TEXT NOT NULL, + FOREIGN KEY(show_id)REFERENCES show(id) ); insertOrReplace: INSERT OR REPLACE INTO trailers( -id, -trakt_id, -key, -name, -site, -size, -type + id, + show_id, + key, + name, + site, + size, + type ) VALUES(?,?,?,?,?,?,?); selectByShowId: SELECT * FROM trailers -WHERE trakt_id = ?; +WHERE show_id = ?; delete: -DELETE FROM trailers WHERE trakt_id = ?; +DELETE FROM trailers WHERE show_id = ?; deleteAll: DELETE FROM trailers; \ No newline at end of file diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/trakt_shows_list.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/trakt_shows_list.sq index 292d0a3fe..eb3f25b61 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/trakt_shows_list.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/trakt_shows_list.sq @@ -1,14 +1,14 @@ CREATE TABLE trakt_shows_list ( -id INTEGER NOT NULL PRIMARY KEY, -slug TEXT NOT NULL, -description TEXT NOT NULL + id INTEGER NOT NULL PRIMARY KEY, + slug TEXT NOT NULL, + description TEXT NOT NULL ); insertOrReplace: INSERT OR REPLACE INTO trakt_shows_list( -id, -slug, -description + id, + slug, + description ) VALUES(?,?,?); diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/user.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/user.sq index 08aebafd3..a55bbb7c0 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/user.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/user.sq @@ -1,35 +1,43 @@ import kotlin.Boolean; CREATE TABLE user ( -slug TEXT NOT NULL PRIMARY KEY, -user_name Text NOT NULL, -full_name TEXT, -profile_picture TEXT, -is_me INTEGER AS Boolean NOT NULL DEFAULT 0 + slug TEXT NOT NULL PRIMARY KEY, + user_name Text NOT NULL, + full_name TEXT, + profile_picture TEXT, + is_me INTEGER AS Boolean NOT NULL DEFAULT 0 ); insertOrReplace: INSERT OR REPLACE INTO user( -slug, -user_name, -full_name, -profile_picture, -is_me + slug, + user_name, + full_name, + profile_picture, + is_me ) VALUES(?,?,?,?,? ); userBySlug: -SELECT * -FROM user -WHERE slug = ?; +SELECT + * +FROM + user +WHERE + slug = ?; getCurrentUser: -SELECT * -FROM user -WHERE is_me != 0; +SELECT + * +FROM + user +WHERE + is_me != 0; delete: -DELETE FROM user WHERE slug = ?; +DELETE FROM + user +WHERE slug = ?; deleteAll: DELETE FROM user; \ No newline at end of file diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/watchlist.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/watchlist.sq index d2e89de4c..ccb4cc502 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/watchlist.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/watchlist.sq @@ -1,36 +1,67 @@ +import com.thomaskioko.tvmaniac.db.Id; +import com.thomaskioko.tvmaniac.db.ShowId; import kotlin.Boolean; CREATE TABLE watchlist ( -id INTEGER PRIMARY KEY, -synced INTEGER AS Boolean NOT NULL DEFAULT 0, -created_at INTEGER NOT NULL, -FOREIGN KEY (id) REFERENCES show(trakt_id) ON DELETE CASCADE + id INTEGER AS Id PRIMARY KEY, + synced INTEGER AS Boolean NOT NULL DEFAULT 0, + created_at INTEGER NOT NULL, + FOREIGN KEY(id) REFERENCES show(id) ON DELETE CASCADE, + UNIQUE(id) ); insertOrReplace: INSERT OR REPLACE INTO watchlist( -id, -synced, -created_at + id, + synced, + created_at ) -VALUES(?, ?, ?); +VALUES( ?, ?, ?); -selectUnsyncedShows: -SELECT * FROM watchlist -WHERE synced != 1; +unsyncedShows: +SELECT + * +FROM + watchlist +WHERE + synced != 1; -selectWatchlist: -SELECT * -FROM watchlist -INNER JOIN show ON show.trakt_id = watchlist.id -INNER JOIN show_image ON show_image.trakt_id = watchlist.id -ORDER BY created_at DESC; - -removeShow: -DELETE FROM watchlist -WHERE id = ?; +watchedShow: +SELECT + show.id AS show_id, + show.tmdb_id, + show.title, + show.overview, + show.language, + show.year, + show.rating, + show.votes, + show.status, + show.runtime, + show.genres, + show.aired_episodes, + show_image.poster_url, + show_image.backdrop_url, + watchlist.created_at +FROM + show +JOIN + watchlist ON show.id = watchlist.id +INNER JOIN + show_image ON show_image.id = watchlist.id +ORDER BY + watchlist.created_at DESC; updateFollowedState: -UPDATE watchlist -SET synced = ? -WHERE id = ?; \ No newline at end of file +UPDATE + watchlist +SET + synced = ? +WHERE + id = ?; + +removeShowFromWatchlist: +DELETE FROM + watchlist +WHERE + id = ?; \ No newline at end of file diff --git a/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/BaseDatabaseTest.kt b/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/BaseDatabaseTest.kt index 55b8c55ea..d009bd850 100644 --- a/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/BaseDatabaseTest.kt +++ b/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/BaseDatabaseTest.kt @@ -1,6 +1,7 @@ package com.thomaskioko.tvmaniac.core.db import app.cash.sqldelight.db.SqlDriver +import com.thomaskioko.tvmaniac.db.IdAdapter import com.thomaskioko.tvmaniac.db.InstantColumnAdapter import com.thomaskioko.tvmaniac.db.stringColumnAdapter import kotlin.test.AfterTest @@ -18,10 +19,40 @@ abstract class BaseDatabaseTest { driver = sqlDriver, showAdapter = Show.Adapter( genresAdapter = stringColumnAdapter, + idAdapter = IdAdapter(), ), last_requestsAdapter = Last_requests.Adapter( timestampAdapter = InstantColumnAdapter, ), + episode_imageAdapter = Episode_image.Adapter( + idAdapter = IdAdapter(), + tmdb_idAdapter = IdAdapter(), + ), + episodeAdapter = Episode.Adapter( + idAdapter = IdAdapter(), + season_idAdapter = IdAdapter(), + ), + seasonAdapter = Season.Adapter( + idAdapter = IdAdapter(), + show_idAdapter = IdAdapter(), + ), + show_imageAdapter = Show_image.Adapter( + idAdapter = IdAdapter(), + ), + similar_showsAdapter = Similar_shows.Adapter( + idAdapter = IdAdapter(), + similar_show_idAdapter = IdAdapter(), + ), + watchlistAdapter = Watchlist.Adapter( + idAdapter = IdAdapter(), + ), + show_categoryAdapter = Show_category.Adapter( + idAdapter = IdAdapter(), + category_idAdapter = IdAdapter(), + ), + trailersAdapter = Trailers.Adapter( + show_idAdapter = IdAdapter(), + ), ) @AfterTest diff --git a/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/EpisodesCacheTest.kt b/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/EpisodesCacheTest.kt index e31efd02d..602b0ad12 100644 --- a/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/EpisodesCacheTest.kt +++ b/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/EpisodesCacheTest.kt @@ -1,6 +1,7 @@ package com.thomaskioko.tvmaniac.core.db import com.thomaskioko.tvmaniac.core.db.MockData.getEpisodeCacheList +import com.thomaskioko.tvmaniac.db.Id import io.kotest.matchers.shouldBe import kotlin.test.Test @@ -13,9 +14,9 @@ internal class EpisodesCacheTest : BaseDatabaseTest() { getEpisodeCacheList().insertEpisodeEntityQuery() val entity = getEpisodeCacheList().first() - val queryResult = episodeQueries.episodeById(2534997).executeAsOne() + val queryResult = episodeQueries.episodesById(Id(2534997)).executeAsOne() - queryResult.trakt_id shouldBe entity.trakt_id + queryResult.id.id shouldBe entity.id.id queryResult.season_id shouldBe entity.season_id queryResult.title shouldBe entity.title queryResult.overview shouldBe entity.overview @@ -23,13 +24,13 @@ internal class EpisodesCacheTest : BaseDatabaseTest() { queryResult.votes shouldBe entity.votes } - private fun List.insertEpisodeEntityQuery() { + private fun List.insertEpisodeEntityQuery() { map { it.insertEpisodeEntityQuery() } } - private fun Episodes.insertEpisodeEntityQuery() { + private fun Episode.insertEpisodeEntityQuery() { episodeQueries.insertOrReplace( - trakt_id = trakt_id, + id = id, season_id = season_id, title = title, overview = overview, diff --git a/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/MockData.kt b/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/MockData.kt index 110e51607..89fbcbd40 100644 --- a/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/MockData.kt +++ b/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/MockData.kt @@ -1,13 +1,14 @@ package com.thomaskioko.tvmaniac.core.db -import com.thomaskioko.tvmaniac.core.db.Episodes as EpisodeCache +import com.thomaskioko.tvmaniac.db.Id +import com.thomaskioko.tvmaniac.core.db.Episode as EpisodeCache object MockData { fun getEpisodeCacheList() = listOf( EpisodeCache( - trakt_id = 2534997, - season_id = 114355, + id = Id(2534997), + season_id = Id(114355), title = "Glorious Purpose", overview = "After stealing the Tesseract in Avengers: Endgame, Loki lands before the Time Variance Authority.", votes = 42, @@ -17,8 +18,8 @@ object MockData { tmdb_id = 1, ), EpisodeCache( - trakt_id = 2927202, - season_id = 114355, + id = Id(2927202), + season_id = Id(114355), title = "The Variant", overview = "Mobius puts Loki to work, but not everyone at TVA is thrilled about the God of Mischief's presence.", votes = 23, @@ -30,7 +31,7 @@ object MockData { ) fun getShow() = Show( - trakt_id = 84958, + id = Id(84958), title = "Loki", overview = "After stealing the Tesseract during the events of “Avengers: Endgame,” " + "an alternate version of Loki is brought to the mysterious Time Variance " + @@ -51,7 +52,7 @@ object MockData { fun showList() = listOf( Show( - trakt_id = 84958, + id = Id(84958), title = "Loki", overview = "After stealing the Tesseract during the events of “Avengers: Endgame,” " + "an alternate version of Loki is brought to the mysterious Time Variance " + @@ -70,7 +71,7 @@ object MockData { aired_episodes = 12, ), Show( - trakt_id = 126280, + id = Id(126280), title = "Sex/Life", overview = "A woman's daring sexual past collides with her married-with-kids " + "present when the bad-boy ex she can't stop fantasizing about crashes " + @@ -88,7 +89,7 @@ object MockData { ) fun showCategory(traktId: Long, categoryId: Long) = Show_category( - trakt_id = traktId, - category_id = categoryId, + id = Id(traktId), + category_id = Id(categoryId), ) } diff --git a/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/TvShowCacheTest.kt b/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/TvShowCacheTest.kt index 425b5beec..95ab895d1 100644 --- a/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/TvShowCacheTest.kt +++ b/core/database/src/commonTest/kotlin/com/thomaskioko/tvmaniac/core/db/TvShowCacheTest.kt @@ -19,7 +19,7 @@ internal class TvShowCacheTest : BaseDatabaseTest() { shows.insertTvShowsEntityList() for (show in shows) { - showCategory(show.trakt_id, 1).insertCategory() + showCategory(show.id.id, 1).insertCategory() } val entities = tvShowQueries.shows().executeAsList() @@ -31,7 +31,7 @@ internal class TvShowCacheTest : BaseDatabaseTest() { fun verify_selectByShowId_returnTvShowEntity_afterInsertHasBeenDone() { getShow().insertTvShowQuery() - val entity = tvShowQueries.showById(getShow().trakt_id) + val entity = tvShowQueries.showById(getShow().id) .executeAsOne() entity shouldNotBe null @@ -48,7 +48,7 @@ internal class TvShowCacheTest : BaseDatabaseTest() { tvShowQueries.deleteAll() - val entity = tvShowQueries.showById(getShow().trakt_id) + val entity = tvShowQueries.showById(getShow().id) .executeAsOneOrNull() entity shouldBe null @@ -60,7 +60,7 @@ internal class TvShowCacheTest : BaseDatabaseTest() { private fun Show.insertTvShowQuery() { tvShowQueries.insertOrReplace( - trakt_id = trakt_id, + id = id, title = title, overview = overview, language = language, @@ -76,7 +76,7 @@ internal class TvShowCacheTest : BaseDatabaseTest() { private fun Show_category.insertCategory() { showCategoryQueries.insertOrReplace( - trakt_id = trakt_id, + id = id, category_id = category_id, ) } diff --git a/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt b/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt index 2c2d1e0b3..ff47263d0 100644 --- a/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt +++ b/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt @@ -2,9 +2,17 @@ package com.thomaskioko.tvmaniac.db import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.native.NativeSqliteDriver +import com.thomaskioko.tvmaniac.core.db.Episode +import com.thomaskioko.tvmaniac.core.db.Episode_image import com.thomaskioko.tvmaniac.core.db.Last_requests +import com.thomaskioko.tvmaniac.core.db.Season import com.thomaskioko.tvmaniac.core.db.Show +import com.thomaskioko.tvmaniac.core.db.Show_category +import com.thomaskioko.tvmaniac.core.db.Show_image +import com.thomaskioko.tvmaniac.core.db.Similar_shows +import com.thomaskioko.tvmaniac.core.db.Trailers import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import com.thomaskioko.tvmaniac.core.db.Watchlist import com.thomaskioko.tvmaniac.util.scope.ApplicationScope import me.tatarka.inject.annotations.Provides @@ -22,9 +30,39 @@ actual interface DatabaseComponent { driver = sqlDriver, showAdapter = Show.Adapter( genresAdapter = stringColumnAdapter, + idAdapter = IdAdapter(), ), last_requestsAdapter = Last_requests.Adapter( timestampAdapter = InstantColumnAdapter, ), + episode_imageAdapter = Episode_image.Adapter( + idAdapter = IdAdapter(), + tmdb_idAdapter = IdAdapter(), + ), + episodeAdapter = Episode.Adapter( + idAdapter = IdAdapter(), + season_idAdapter = IdAdapter(), + ), + seasonAdapter = Season.Adapter( + idAdapter = IdAdapter(), + show_idAdapter = IdAdapter(), + ), + show_imageAdapter = Show_image.Adapter( + idAdapter = IdAdapter(), + ), + similar_showsAdapter = Similar_shows.Adapter( + idAdapter = IdAdapter(), + similar_show_idAdapter = IdAdapter(), + ), + watchlistAdapter = Watchlist.Adapter( + idAdapter = IdAdapter(), + ), + show_categoryAdapter = Show_category.Adapter( + idAdapter = IdAdapter(), + category_idAdapter = IdAdapter(), + ), + trailersAdapter = Trailers.Adapter( + show_idAdapter = IdAdapter(), + ), ) } From 374c4d4321aaa2f6c2d029b1800b3df9f5ac783a Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 02:15:19 +0100 Subject: [PATCH 12/38] Delete unused classes --- .../seasondetails/api/SeasonDetailsDao.kt | 16 ------- .../implementation/SeasonDetailsDaoImpl.kt | 43 ------------------- .../tvmaniac/seasons/testing/MockData.kt | 24 ----------- .../tvmaniac/shows/testing/MockData.kt | 32 -------------- 4 files changed, 115 deletions(-) delete mode 100644 data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsDao.kt delete mode 100644 data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsDaoImpl.kt delete mode 100644 data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/MockData.kt delete mode 100644 data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/MockData.kt diff --git a/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsDao.kt b/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsDao.kt deleted file mode 100644 index 886107d9d..000000000 --- a/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsDao.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.thomaskioko.tvmaniac.seasondetails.api - -import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes -import com.thomaskioko.tvmaniac.core.db.Season_episodes -import kotlinx.coroutines.flow.Flow - -interface SeasonDetailsDao { - - fun insert(entity: Season_episodes) - - fun observeShowEpisodes(showId: Long): Flow> - - fun delete(id: Long) - - fun deleteAll() -} diff --git a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsDaoImpl.kt b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsDaoImpl.kt deleted file mode 100644 index ea10d5227..000000000 --- a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsDaoImpl.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.thomaskioko.tvmaniac.seasondetails.implementation - -import app.cash.sqldelight.coroutines.asFlow -import app.cash.sqldelight.coroutines.mapToList -import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes -import com.thomaskioko.tvmaniac.core.db.Season_episodes -import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase -import com.thomaskioko.tvmaniac.seasondetails.api.SeasonDetailsDao -import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers -import kotlinx.coroutines.flow.Flow -import me.tatarka.inject.annotations.Inject - -@Inject -class SeasonDetailsDaoImpl( - private val database: TvManiacDatabase, - private val dispatcher: AppCoroutineDispatchers, -) : SeasonDetailsDao { - - override fun insert(entity: Season_episodes) { - database.transaction { - database.seasonEpisodesQueries.insertOrReplace( - show_id = entity.show_id, - season_id = entity.season_id, - season_number = entity.season_number, - ) - } - } - - override fun observeShowEpisodes(showId: Long): Flow> = - database.seasonEpisodesQueries.seasonWithEpisodes(showId) - .asFlow() - .mapToList(dispatcher.io) - - override fun delete(id: Long) { - database.seasonEpisodesQueries.delete(id) - } - - override fun deleteAll() { - database.transaction { - database.seasonEpisodesQueries.deleteAll() - } - } -} diff --git a/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/MockData.kt b/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/MockData.kt deleted file mode 100644 index cdf6a1b02..000000000 --- a/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/MockData.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.thomaskioko.tvmaniac.seasons.testing - -import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes - -val seasonDetails = listOf( - SeasonWithEpisodes( - trakt_id = 84958, - tmdb_id = 849583, - title = "Loki", - overview = "After stealing the Tesseract in Avengers: Endgame, Loki lands before the Time Variance Authority.", - runtime = 45, - id = 12345, - season_id = 12343, - season_number = 0, - episode_count = 15, - name = "Season 01", - trakt_id_ = 12345, - title_ = "Some title", - ratings = 4.5, - episode_number = "01", - votes = 4958, - image_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", - ), -) diff --git a/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/MockData.kt b/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/MockData.kt deleted file mode 100644 index 93227f89a..000000000 --- a/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/MockData.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.thomaskioko.tvmaniac.shows.testing - -import com.thomaskioko.tvmaniac.core.db.SelectWatchlist - -val selectWatchList = listOf( - SelectWatchlist( - trakt_id = 84958, - tmdb_id = 849583, - title = "Loki", - overview = "After stealing the Tesseract during the events of “Avengers: Endgame,” " + - "an alternate version of Loki is brought to the mysterious Time Variance " + - "Authority, a bureaucratic organization that exists outside of time and " + - "space and monitors the timeline. They give Loki a choice: face being " + - "erased from existence due to being a “time variant”or help fix " + - "the timeline and stop a greater threat.", - language = "en", - votes = 4958, - rating = 8.1, - genres = listOf("Horror", "Action"), - status = "Returning Series", - year = "2024", - runtime = 45, - poster_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", - backdrop_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", - aired_episodes = 12, - id = 84958, - synced = true, - created_at = 12345645, - trakt_id_ = 1232, - tmdb_id_ = 849583, - ), -) From 050ac0d61ae1390f807efcafd5316462a3aec804 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 02:26:17 +0100 Subject: [PATCH 13/38] Cleanup: Update function signatures, mapping implementation after table changes. --- .../thomaskioko/tvmaniac/showsgrid/Mapper.kt | 4 +- .../category/api/cache/CategoryCache.kt | 4 +- .../implementation/CategoryCacheImpl.kt | 8 ++-- .../episodeimages/api/EpisodeImageDao.kt | 4 +- .../implementation/EpisodeImageDaoImpl.kt | 8 ++-- .../EpisodeImageRepositoryImpl.kt | 7 +-- .../tvmaniac/episodes/api/EpisodesDao.kt | 2 +- .../implementation/EpisodesDaoImpl.kt | 7 +-- .../profilestats/implementation/StatsStore.kt | 2 +- .../api/SeasonDetailsRepository.kt | 6 +-- .../seasondetails/implementation/Mapper.kt | 48 +++++++++---------- .../implementation/SeasonDetailsComponent.kt | 5 -- .../SeasonDetailsRepositoryImpl.kt | 33 +++++++------ .../implementation/SeasonDetailsStore.kt | 43 +++++++---------- .../testing/FakeSeasonDetailsRepository.kt | 16 +++---- .../seasondetails/testing/MockData.kt | 25 +++++----- .../tvmaniac/seasons/api/SeasonsDao.kt | 14 ++++-- .../tvmaniac/seasons/api/SeasonsRepository.kt | 6 +-- .../tvmaniac/seasons/implementation/Mapper.kt | 13 ++--- .../seasons/implementation/SeasonsDaoImpl.kt | 30 ++++++++---- .../implementation/SeasonsRepositoryImpl.kt | 6 +-- .../seasons/implementation/SeasonsStore.kt | 10 ++-- .../seasons/testing/FakeSeasonsRepository.kt | 21 ++++---- .../tvmaniac/showimages/api/ShowImagesDao.kt | 6 +-- .../implementation/ShowImagesDaoImpl.kt | 10 ++-- .../ShowImagesRepositoryImpl.kt | 7 +-- .../tvmaniac/shows/api/ShowsDao.kt | 6 +-- .../implementation/DiscoverResponseMapper.kt | 23 ++++----- .../implementation/DiscoverShowsStore.kt | 6 +-- .../shows/implementation/ShowDaoImpl.kt | 21 ++++---- .../shows/implementation/ShowStore.kt | 4 +- .../shows/testing/FakeDiscoverRepository.kt | 15 +++--- .../tvmaniac/similar/api/SimilarShowsDao.kt | 2 +- .../similar/implementation/ResponseMapper.kt | 5 +- .../implementation/SimilarShowStore.kt | 10 ++-- .../implementation/SimilarShowsDaoImpl.kt | 11 +++-- .../TrailerDao.kt | 4 +- .../trailers/implementation/TrailerDaoImpl.kt | 13 ++--- .../trailers/implementation/TrailerMapper.kt | 3 +- .../trailers/implementation/TrailerStore.kt | 6 +-- .../tvmaniac/trailers/testing/MockData.kt | 3 +- .../tvmaniac/shows/api/WatchlistDao.kt | 10 ++-- .../tvmaniac/shows/api/WatchlistRepository.kt | 6 +-- .../implementation/WatchlistDaoImpl.kt | 35 +++++++------- .../implementation/WatchlistRepositoryImpl.kt | 19 ++++---- .../testing/FakeWatchlistRepository.kt | 20 ++++---- .../tvmaniac/watchlist/testing/MockData.kt | 11 ++--- .../discover/DiscoverShowsMapper.kt | 2 +- .../presentation/discover/MockData.kt | 9 ++-- .../presentation/seasondetails/Mapper.kt | 48 +++++++------------ .../SeasonDetailsStateMachine.kt | 42 ++-------------- .../SeasonDetailsStateMachineTest.kt | 4 +- .../showdetails/ShowDetailMapper.kt | 17 ++++--- .../showdetails/ShowDetailsStateMachine.kt | 8 ++-- .../presentation/showdetails/MockData.kt | 28 ++++------- .../tvmaniac/presentation/trailers/Mapper.kt | 2 +- .../tvmaniac/presentation/watchlist/Mapper.kt | 6 +-- .../watchlist/WatchlistStateMachineTest.kt | 3 +- 58 files changed, 348 insertions(+), 399 deletions(-) diff --git a/android-features/shows-grid/src/main/kotlin/com/thomaskioko/tvmaniac/showsgrid/Mapper.kt b/android-features/shows-grid/src/main/kotlin/com/thomaskioko/tvmaniac/showsgrid/Mapper.kt index f16897513..8133b8d22 100644 --- a/android-features/shows-grid/src/main/kotlin/com/thomaskioko/tvmaniac/showsgrid/Mapper.kt +++ b/android-features/shows-grid/src/main/kotlin/com/thomaskioko/tvmaniac/showsgrid/Mapper.kt @@ -3,10 +3,8 @@ package com.thomaskioko.tvmaniac.showsgrid import com.thomaskioko.tvmaniac.core.db.ShowsByCategory import com.thomaskioko.tvmaniac.showsgrid.model.TvShow -fun List.toTvShowList(): List = map { it.toTvShow() } - fun ShowsByCategory.toTvShow(): TvShow = TvShow( - traktId = trakt_id, + traktId = id.id, tmdbId = tmdb_id, title = title, posterImageUrl = poster_url, diff --git a/data/category/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/category/api/cache/CategoryCache.kt b/data/category/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/category/api/cache/CategoryCache.kt index d4a34253d..845e783ee 100644 --- a/data/category/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/category/api/cache/CategoryCache.kt +++ b/data/category/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/category/api/cache/CategoryCache.kt @@ -3,6 +3,6 @@ package com.thomaskioko.tvmaniac.category.api.cache import com.thomaskioko.tvmaniac.core.db.Show_category interface CategoryCache { - fun insert(category: Show_category) - fun insert(category: List) + fun upsert(category: Show_category) + fun upsert(category: List) } diff --git a/data/category/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/category/implementation/CategoryCacheImpl.kt b/data/category/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/category/implementation/CategoryCacheImpl.kt index f7efa87b8..aea103b44 100644 --- a/data/category/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/category/implementation/CategoryCacheImpl.kt +++ b/data/category/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/category/implementation/CategoryCacheImpl.kt @@ -12,16 +12,16 @@ class CategoryCacheImpl( private val showCategoryQuery get() = database.show_categoryQueries - override fun insert(category: Show_category) { + override fun upsert(category: Show_category) { database.transaction { showCategoryQuery.insertOrReplace( - trakt_id = category.trakt_id, + id = category.id, category_id = category.category_id, ) } } - override fun insert(category: List) { - category.forEach { insert(it) } + override fun upsert(category: List) { + category.forEach { upsert(it) } } } diff --git a/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageDao.kt b/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageDao.kt index c74f48296..4b8e5889c 100644 --- a/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageDao.kt +++ b/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageDao.kt @@ -6,9 +6,9 @@ import kotlinx.coroutines.flow.Flow interface EpisodeImageDao { - fun insert(entity: Episode_image) + fun upsert(entity: Episode_image) - fun insert(list: List) + fun upsert(list: List) fun observeEpisodeImage(): Flow> } diff --git a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageDaoImpl.kt b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageDaoImpl.kt index ab8fbd80e..16de93cd2 100644 --- a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageDaoImpl.kt +++ b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageDaoImpl.kt @@ -18,17 +18,17 @@ class EpisodeImageDaoImpl( private val episodeQueries get() = database.episode_imageQueries - override fun insert(entity: Episode_image) { + override fun upsert(entity: Episode_image) { episodeQueries.insertOrReplace( - trakt_id = entity.trakt_id, + id = entity.id, tmdb_id = entity.tmdb_id, image_url = entity.image_url, ) } - override fun insert(list: List) { + override fun upsert(list: List) { database.transaction { - list.map { insert(it) } + list.map { upsert(it) } } } diff --git a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt index 94ee1a533..1980d15b2 100644 --- a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt +++ b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt @@ -6,6 +6,7 @@ import com.thomaskioko.tvmaniac.core.networkutil.DefaultError import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.core.networkutil.NetworkExceptionHandler +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageDao import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageRepository import com.thomaskioko.tvmaniac.tmdb.api.TmdbNetworkDataSource @@ -38,10 +39,10 @@ class EpisodeImageRepositoryImpl( when (response) { is ApiResponse.Success -> { - episodeImageDao.insert( + episodeImageDao.upsert( Episode_image( - trakt_id = episodeArt.trakt_id, - tmdb_id = response.body.id.toLong(), + id = Id(id = response.body.id.toLong()), + tmdb_id = Id(id = tmdbId), image_url = response.body.imageUrl?.let { formatterUtil.formatTmdbPosterPath(it) }, diff --git a/data/episodes/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/api/EpisodesDao.kt b/data/episodes/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/api/EpisodesDao.kt index ab85ff44c..56f0aac79 100644 --- a/data/episodes/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/api/EpisodesDao.kt +++ b/data/episodes/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/api/EpisodesDao.kt @@ -1,6 +1,6 @@ package com.thomaskioko.tvmaniac.episodes.api -import com.thomaskioko.tvmaniac.core.db.Episodes as EpisodeCache +import com.thomaskioko.tvmaniac.core.db.Episode as EpisodeCache interface EpisodesDao { diff --git a/data/episodes/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/implementation/EpisodesDaoImpl.kt b/data/episodes/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/implementation/EpisodesDaoImpl.kt index e8e5e3f66..19848fdf0 100644 --- a/data/episodes/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/implementation/EpisodesDaoImpl.kt +++ b/data/episodes/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/implementation/EpisodesDaoImpl.kt @@ -1,9 +1,10 @@ package com.thomaskioko.tvmaniac.episodes.implementation import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.episodes.api.EpisodesDao import me.tatarka.inject.annotations.Inject -import com.thomaskioko.tvmaniac.core.db.Episodes as EpisodeCache +import com.thomaskioko.tvmaniac.core.db.Episode as EpisodeCache @Inject class EpisodesDaoImpl( @@ -15,7 +16,7 @@ class EpisodesDaoImpl( override fun insert(entity: EpisodeCache) { database.transaction { episodeQueries.insertOrReplace( - trakt_id = entity.trakt_id, + id = entity.id, season_id = entity.season_id, tmdb_id = entity.tmdb_id, title = entity.title, @@ -33,7 +34,7 @@ class EpisodesDaoImpl( } override fun delete(id: Long) { - episodeQueries.delete(id) + episodeQueries.delete(Id(id)) } override fun deleteAll() { diff --git a/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsStore.kt b/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsStore.kt index 59aeb69ae..19e09011c 100644 --- a/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsStore.kt +++ b/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsStore.kt @@ -22,7 +22,7 @@ class StatsStore( private val mapper: StatsMapper, private val logger: KermitLogger, private val scope: AppCoroutineScope, -) : Store by storeBuilderFromFetcherAndSourceOfTruth( +) : Store by storeBuilderFromFetcherAndSourceOfTruth( fetcher = Fetcher.of { slug -> when (val response = remoteDataSource.getStats(slug)) { diff --git a/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsRepository.kt b/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsRepository.kt index 3ddaa2701..bc824bc11 100644 --- a/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsRepository.kt +++ b/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsRepository.kt @@ -1,13 +1,13 @@ package com.thomaskioko.tvmaniac.seasondetails.api -import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes +import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import kotlinx.coroutines.flow.Flow interface SeasonDetailsRepository { - fun observeSeasonDetailsStream(traktId: Long): Flow>> + suspend fun fetchSeasonDetails(traktId: Long): List - fun observeCachedSeasonDetails(traktId: Long): Flow>> + fun observeSeasonDetailsStream(traktId: Long): Flow>> } diff --git a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/Mapper.kt b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/Mapper.kt index 33d7aa01f..9595a6c9b 100644 --- a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/Mapper.kt +++ b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/Mapper.kt @@ -1,31 +1,27 @@ package com.thomaskioko.tvmaniac.seasondetails.implementation -import com.thomaskioko.tvmaniac.core.db.Episodes -import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes -import com.thomaskioko.tvmaniac.trakt.api.model.TraktEpisodesResponse +import com.thomaskioko.tvmaniac.core.db.Episode +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.trakt.api.model.TraktSeasonEpisodesResponse -fun TraktSeasonEpisodesResponse.toEpisodeCacheList(): List { - return episodes.map { episodeResponse -> - Episodes( - season_id = ids.trakt.toLong(), - trakt_id = episodeResponse.ids.trakt.toLong(), - tmdb_id = episodeResponse.ids.tmdb?.toLong(), - title = episodeResponse.title, - overview = episodeResponse.overview ?: "TBA", - ratings = episodeResponse.ratings, - runtime = episodeResponse.runtime.toLong(), - votes = episodeResponse.votes.toLong(), - episode_number = episodeResponse.episodeNumber.toString().padStart(2, '0'), +internal fun List.toSeasonWithEpisodes(): List { + return map { season -> + SeasonData( + seasonId = season.ids.trakt.toLong(), + title = season.title, + overview = season.overview ?: "TBA", + episodeCount = season.episodeCount.toLong(), + seasonNumber = season.number.toLong(), + episodes = season.toEpisodeCacheList(), ) } } -fun List.toEpisodeCache(seasonId: Long): List { - return map { episodeResponse -> - Episodes( - season_id = seasonId, - trakt_id = episodeResponse.ids.trakt.toLong(), +fun TraktSeasonEpisodesResponse.toEpisodeCacheList(): List { + return episodes.map { episodeResponse -> + Episode( + id = Id(episodeResponse.ids.trakt.toLong()), + season_id = Id(ids.trakt.toLong()), tmdb_id = episodeResponse.ids.tmdb?.toLong(), title = episodeResponse.title, overview = episodeResponse.overview ?: "TBA", @@ -37,7 +33,11 @@ fun List.toEpisodeCache(seasonId: Long): List { } } -fun List.toSeasonWithEpisodes(): List { - // TODO:: Add mapping #59 - return emptyList() -} +internal data class SeasonData( + val seasonId: Long, + val title: String, + val overview: String, + val seasonNumber: Long, + val episodeCount: Long, + val episodes: List, +) diff --git a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsComponent.kt b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsComponent.kt index 491235e1b..d5568bbbf 100644 --- a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsComponent.kt +++ b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsComponent.kt @@ -1,6 +1,5 @@ package com.thomaskioko.tvmaniac.seasondetails.implementation -import com.thomaskioko.tvmaniac.seasondetails.api.SeasonDetailsDao import com.thomaskioko.tvmaniac.seasondetails.api.SeasonDetailsRepository import com.thomaskioko.tvmaniac.util.scope.ApplicationScope import me.tatarka.inject.annotations.Provides @@ -12,8 +11,4 @@ interface SeasonDetailsComponent { fun provideSeasonDetailsRepository( bind: SeasonDetailsRepositoryImpl, ): SeasonDetailsRepository = bind - - @ApplicationScope - @Provides - fun provideSeasonsDetailsDao(bind: SeasonDetailsDaoImpl): SeasonDetailsDao = bind } diff --git a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsRepositoryImpl.kt b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsRepositoryImpl.kt index c9a0cb781..63a59a3cf 100644 --- a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsRepositoryImpl.kt +++ b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsRepositoryImpl.kt @@ -1,39 +1,37 @@ package com.thomaskioko.tvmaniac.seasondetails.implementation -import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes -import com.thomaskioko.tvmaniac.core.db.Season_episodes +import com.thomaskioko.tvmaniac.core.db.Season +import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse -import com.thomaskioko.tvmaniac.core.networkutil.DefaultError import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.core.networkutil.NetworkExceptionHandler import com.thomaskioko.tvmaniac.core.networkutil.networkBoundResult +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.episodes.api.EpisodesDao -import com.thomaskioko.tvmaniac.seasondetails.api.SeasonDetailsDao import com.thomaskioko.tvmaniac.seasondetails.api.SeasonDetailsRepository +import com.thomaskioko.tvmaniac.seasons.api.SeasonsDao import com.thomaskioko.tvmaniac.trakt.api.TraktShowsRemoteDataSource import com.thomaskioko.tvmaniac.trakt.api.model.ErrorResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktSeasonEpisodesResponse import com.thomaskioko.tvmaniac.util.KermitLogger import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.map import me.tatarka.inject.annotations.Inject @Inject class SeasonDetailsRepositoryImpl( private val remoteDataSource: TraktShowsRemoteDataSource, - private val seasonCache: SeasonDetailsDao, + private val seasonCache: SeasonsDao, private val episodesDao: EpisodesDao, private val exceptionHandler: NetworkExceptionHandler, private val dispatcher: AppCoroutineDispatchers, private val logger: KermitLogger, ) : SeasonDetailsRepository { - override fun observeSeasonDetailsStream(traktId: Long): Flow>> = + override fun observeSeasonDetailsStream(traktId: Long): Flow>> = networkBoundResult( - query = { seasonCache.observeShowEpisodes(traktId) }, + query = { seasonCache.observeSeasonEpisodeDetailsById(traktId) }, shouldFetch = { it.isNullOrEmpty() }, fetch = { remoteDataSource.getSeasonEpisodes(traktId) }, saveFetchResult = { mapResponse(traktId, it) }, @@ -41,10 +39,8 @@ class SeasonDetailsRepositoryImpl( coroutineDispatcher = dispatcher.io, ) - override fun observeCachedSeasonDetails(traktId: Long): Flow>> = - seasonCache.observeShowEpisodes(traktId) - .catch { Either.Left(DefaultError(exceptionHandler.resolveError(it))) } - .map { Either.Right(it) } + override suspend fun fetchSeasonDetails(traktId: Long): List = + seasonCache.fetchSeasonDetails(traktId) private fun mapResponse( showId: Long, @@ -55,11 +51,14 @@ class SeasonDetailsRepositoryImpl( response.body.forEach { season -> episodesDao.insert(season.toEpisodeCacheList()) - seasonCache.insert( - Season_episodes( - show_id = showId, - season_id = season.ids.trakt.toLong(), + seasonCache.upsert( + Season( + id = Id(season.ids.trakt.toLong()), + show_id = Id(showId), season_number = season.number.toLong(), + title = season.title, + episode_count = season.episodeCount.toLong(), + overview = season.overview, ), ) } diff --git a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsStore.kt b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsStore.kt index cfdff1f1e..16dc03eda 100644 --- a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsStore.kt +++ b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsStore.kt @@ -1,11 +1,11 @@ package com.thomaskioko.tvmaniac.seasondetails.implementation -import com.thomaskioko.tvmaniac.core.db.Episodes -import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes -import com.thomaskioko.tvmaniac.core.db.Season_episodes +import com.thomaskioko.tvmaniac.core.db.Season +import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.episodes.api.EpisodesDao -import com.thomaskioko.tvmaniac.seasondetails.api.SeasonDetailsDao +import com.thomaskioko.tvmaniac.seasons.api.SeasonsDao import com.thomaskioko.tvmaniac.trakt.api.TraktShowsRemoteDataSource import com.thomaskioko.tvmaniac.util.KermitLogger import com.thomaskioko.tvmaniac.util.model.AppCoroutineScope @@ -18,12 +18,12 @@ import org.mobilenativefoundation.store.store5.StoreBuilder @Inject class SeasonDetailsStore( private val remoteDataSource: TraktShowsRemoteDataSource, - private val seasonDetailsDao: SeasonDetailsDao, + private val seasonCache: SeasonsDao, private val episodesDao: EpisodesDao, private val scope: AppCoroutineScope, private val logger: KermitLogger, -) : Store> by StoreBuilder - .from, List>( +) : Store> by StoreBuilder + .from( fetcher = Fetcher.of { id: Long -> when (val response = remoteDataSource.getSeasonEpisodes(id)) { is ApiResponse.Success -> response.body.toSeasonWithEpisodes() @@ -44,34 +44,25 @@ class SeasonDetailsStore( } }, sourceOfTruth = SourceOfTruth.of( - reader = seasonDetailsDao::observeShowEpisodes, + reader = seasonCache::observeSeasonEpisodeDetailsById, writer = { id, list -> list.forEach { season -> - episodesDao.insert( - Episodes( - trakt_id = season.trakt_id, - season_id = season.season_id, + seasonCache.upsert( + Season( + id = Id(season.seasonId), + show_id = Id(id), + season_number = season.seasonNumber, title = season.title, - tmdb_id = season.tmdb_id, + episode_count = season.episodeCount, overview = season.overview, - ratings = season.ratings, - runtime = season.runtime, - votes = season.votes, - episode_number = season.episode_number, ), ) - seasonDetailsDao.insert( - Season_episodes( - show_id = id, - season_id = season.trakt_id, - season_number = season.season_number, - ), - ) + episodesDao.insert(season.episodes) } }, - delete = seasonDetailsDao::delete, - deleteAll = seasonDetailsDao::deleteAll, + delete = seasonCache::delete, + deleteAll = seasonCache::deleteAll, ), ) .scope(scope.io) diff --git a/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/FakeSeasonDetailsRepository.kt b/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/FakeSeasonDetailsRepository.kt index d25663e67..7e0a13c8a 100644 --- a/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/FakeSeasonDetailsRepository.kt +++ b/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/FakeSeasonDetailsRepository.kt @@ -1,6 +1,6 @@ package com.thomaskioko.tvmaniac.seasondetails.testing -import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes +import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.seasondetails.api.SeasonDetailsRepository @@ -10,22 +10,22 @@ import kotlinx.coroutines.flow.receiveAsFlow class FakeSeasonDetailsRepository : SeasonDetailsRepository { - private val seasonsResult: Channel>> = Channel(Channel.UNLIMITED) - private val cachedResult: Channel>> = Channel(Channel.UNLIMITED) + private val seasonsResult: Channel>> = Channel(Channel.UNLIMITED) + private val cachedResult: Channel> = Channel(Channel.UNLIMITED) - suspend fun setSeasonsResult(result: Either>) { + suspend fun setSeasonsResult(result: Either>) { seasonsResult.send(result) } - suspend fun setCachedResults(result: Either>) { + suspend fun setCachedResults(result: List) { cachedResult.send(result) } - override fun observeCachedSeasonDetails( + override suspend fun fetchSeasonDetails( traktId: Long, - ): Flow>> = cachedResult.receiveAsFlow() + ): List = cachedResult.receive() override fun observeSeasonDetailsStream( traktId: Long, - ): Flow>> = seasonsResult.receiveAsFlow() + ): Flow>> = seasonsResult.receiveAsFlow() } diff --git a/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/MockData.kt b/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/MockData.kt index 0b80394d6..a4b5c86a7 100644 --- a/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/MockData.kt +++ b/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/MockData.kt @@ -1,24 +1,25 @@ package com.thomaskioko.tvmaniac.seasondetails.testing -import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes +import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById +import com.thomaskioko.tvmaniac.db.Id val SeasonWithEpisodeList = listOf( - SeasonWithEpisodes( - trakt_id = 84958, - tmdb_id = 849583, - title = "Loki", + SeasonEpisodeDetailsById( + show_id = Id(84958), + season_id = Id(12343), + show_title = "Loki", overview = "After stealing the Tesseract in Avengers: Endgame, Loki lands before the Time Variance Authority.", runtime = 45, - id = 12345, - season_id = 12343, season_number = 0, - episode_count = 15, - name = "Season 01", - trakt_id_ = 12345, - title_ = "Some title", + episode_count = 1, + season_title = "Season 01", + season_overview = "The journey to reunite the Ingham family continues as they travel to the USA.", ratings = 4.5, episode_number = "01", votes = 4958, - image_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", + episode_image_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", + episode_title = "Some title", + episode_season_id = Id(12345), + episode_id = Id(12345), ), ) diff --git a/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsDao.kt b/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsDao.kt index b66e72782..58d129411 100644 --- a/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsDao.kt +++ b/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsDao.kt @@ -1,15 +1,21 @@ package com.thomaskioko.tvmaniac.seasons.api -import com.thomaskioko.tvmaniac.core.db.Seasons +import com.thomaskioko.tvmaniac.core.db.Season +import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById +import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId import kotlinx.coroutines.flow.Flow interface SeasonsDao { - fun insertSeason(season: Seasons) + fun upsert(season: Season) - fun insertSeasons(entityList: List) + fun upsert(entityList: List) - fun observeSeasons(traktId: Long): Flow> + fun fetchSeasonDetails(traktId: Long): List + + fun observeSeasonsByShowId(traktId: Long): Flow> + + fun observeSeasonEpisodeDetailsById(showId: Long): Flow> fun delete(id: Long) diff --git a/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsRepository.kt b/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsRepository.kt index edfdf7abf..9d6a9ddaa 100644 --- a/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsRepository.kt +++ b/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsRepository.kt @@ -1,12 +1,12 @@ package com.thomaskioko.tvmaniac.seasons.api -import com.thomaskioko.tvmaniac.core.db.Seasons +import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import kotlinx.coroutines.flow.Flow interface SeasonsRepository { - suspend fun getSeasons(traktId: Long): List - fun observeSeasonsStoreResponse(traktId: Long): Flow>> + suspend fun fetchSeasonsByShowId(traktId: Long): List + fun observeSeasonsByShowId(traktId: Long): Flow>> } diff --git a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/Mapper.kt b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/Mapper.kt index 533d6d27d..21500488a 100644 --- a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/Mapper.kt +++ b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/Mapper.kt @@ -1,15 +1,16 @@ package com.thomaskioko.tvmaniac.seasons.implementation -import com.thomaskioko.tvmaniac.core.db.Seasons +import com.thomaskioko.tvmaniac.core.db.Season +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.trakt.api.model.TraktSeasonsResponse -fun List.toSeasonCacheList(traktId: Long): List = +fun List.toSeasonCacheList(traktId: Long): List = map { seasonResponse -> - Seasons( - show_trakt_id = traktId, - id = seasonResponse.ids.trakt.toLong(), + Season( + show_id = Id(traktId), + id = Id(id = seasonResponse.ids.trakt.toLong()), season_number = seasonResponse.number.toLong(), - name = seasonResponse.title, + title = seasonResponse.title, overview = seasonResponse.overview, episode_count = seasonResponse.episodeCount.toLong(), ) diff --git a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsDaoImpl.kt b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsDaoImpl.kt index 1e596acd3..0b344db0b 100644 --- a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsDaoImpl.kt +++ b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsDaoImpl.kt @@ -2,8 +2,11 @@ package com.thomaskioko.tvmaniac.seasons.implementation import app.cash.sqldelight.coroutines.asFlow import app.cash.sqldelight.coroutines.mapToList -import com.thomaskioko.tvmaniac.core.db.Seasons +import com.thomaskioko.tvmaniac.core.db.Season +import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById +import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.seasons.api.SeasonsDao import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers import kotlinx.coroutines.flow.Flow @@ -17,31 +20,40 @@ class SeasonsDaoImpl( private val seasonQueries get() = database.seasonQueries - override fun insertSeason(season: Seasons) { + override fun upsert(season: Season) { database.transaction { seasonQueries.insertOrReplace( id = season.id, - show_trakt_id = season.show_trakt_id, + show_id = season.show_id, season_number = season.season_number, episode_count = season.episode_count, - name = season.name, + title = season.title, overview = season.overview, ) } } - override fun insertSeasons(entityList: List) { - entityList.forEach { insertSeason(it) } + override fun upsert(entityList: List) { + entityList.forEach { upsert(it) } } - override fun observeSeasons(traktId: Long): Flow> { - return seasonQueries.seasonById(traktId) + override fun observeSeasonsByShowId(traktId: Long): Flow> { + return database.seasonQueries.seasonsByShowId(Id(traktId)) .asFlow() .mapToList(dispatcher.io) } + override fun fetchSeasonDetails(traktId: Long): List = + database.seasonQueries.seasonEpisodeDetailsById(id = Id(traktId)) + .executeAsList() + + override fun observeSeasonEpisodeDetailsById(showId: Long): Flow> = + database.seasonQueries.seasonEpisodeDetailsById(id = Id(showId)) + .asFlow() + .mapToList(dispatcher.io) + override fun delete(id: Long) { - seasonQueries.delete(id) + seasonQueries.delete(Id(id)) } override fun deleteAll() { diff --git a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsRepositoryImpl.kt b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsRepositoryImpl.kt index 3367dcb2b..a4cc0cb2c 100644 --- a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsRepositoryImpl.kt +++ b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsRepositoryImpl.kt @@ -1,6 +1,6 @@ package com.thomaskioko.tvmaniac.seasons.implementation -import com.thomaskioko.tvmaniac.core.db.Seasons +import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository @@ -26,10 +26,10 @@ class SeasonsRepositoryImpl( private val dispatcher: AppCoroutineDispatchers, ) : SeasonsRepository { - override suspend fun getSeasons(traktId: Long): List = + override suspend fun fetchSeasonsByShowId(traktId: Long): List = seasonsStore.get(traktId) - override fun observeSeasonsStoreResponse(traktId: Long): Flow>> = + override fun observeSeasonsByShowId(traktId: Long): Flow>> = seasonsStore.stream( StoreReadRequest.cached( key = traktId, diff --git a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsStore.kt b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsStore.kt index 54f07ca2e..b993f8695 100644 --- a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsStore.kt +++ b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsStore.kt @@ -1,6 +1,6 @@ package com.thomaskioko.tvmaniac.seasons.implementation -import com.thomaskioko.tvmaniac.core.db.Seasons +import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.resourcemanager.api.LastRequest import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository @@ -22,7 +22,7 @@ class SeasonsStore( private val seasonsDao: SeasonsDao, private val scope: AppCoroutineScope, private val logger: KermitLogger, -) : Store> by StoreBuilder.from, List>( +) : Store> by StoreBuilder.from( fetcher = Fetcher.of { id -> when (val response = remoteDataSource.getShowSeasons(id)) { is ApiResponse.Success -> response.body.toSeasonCacheList(id) @@ -43,14 +43,14 @@ class SeasonsStore( } }, sourceOfTruth = SourceOfTruth.of( - reader = seasonsDao::observeSeasons, + reader = seasonsDao::observeSeasonsByShowId, writer = { id, list -> - seasonsDao.insertSeasons(list) + seasonsDao.upsert(list) requestManagerRepository.insert( LastRequest( - id = list.first().id, + id = list.first().id.id, entityId = id, requestType = "SEASON", timestamp = Clock.System.now(), diff --git a/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/FakeSeasonsRepository.kt b/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/FakeSeasonsRepository.kt index 7eb3f74be..b07ff1914 100644 --- a/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/FakeSeasonsRepository.kt +++ b/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/FakeSeasonsRepository.kt @@ -1,7 +1,6 @@ package com.thomaskioko.tvmaniac.seasons.testing -import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes -import com.thomaskioko.tvmaniac.core.db.Seasons +import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.seasons.api.SeasonsRepository @@ -11,27 +10,27 @@ import kotlinx.coroutines.flow.receiveAsFlow class FakeSeasonsRepository : SeasonsRepository { - private var seasonsList: Channel> = Channel(Channel.UNLIMITED) - private var seasonsResult: Channel>> = Channel(Channel.UNLIMITED) + private var seasonsList: Channel> = Channel(Channel.UNLIMITED) + private var seasonsResult: Channel>> = Channel(Channel.UNLIMITED) - private var seasonEpisodesResult: Channel>> = + private var seasonEpisodesResult: Channel>> = Channel(Channel.UNLIMITED) - suspend fun setSeasonWithEpisodes(result: Either>) { + suspend fun setSeasonWithEpisodes(result: Either>) { seasonEpisodesResult.send(result) } - suspend fun setSeasons(result: List) { + suspend fun setSeasons(result: List) { seasonsList.send(result) } - suspend fun setSeasonsResult(result: Either>) { + suspend fun setSeasonsResult(result: Either>) { seasonsResult.send(result) } - override suspend fun getSeasons(traktId: Long): List = seasonsList.receive() + override suspend fun fetchSeasonsByShowId(traktId: Long): List = seasonsList.receive() - override fun observeSeasonsStoreResponse( + override fun observeSeasonsByShowId( traktId: Long, - ): Flow>> = seasonsResult.receiveAsFlow() + ): Flow>> = seasonsResult.receiveAsFlow() } diff --git a/data/showimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/api/ShowImagesDao.kt b/data/showimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/api/ShowImagesDao.kt index 1adf44f43..26d59e7b4 100644 --- a/data/showimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/api/ShowImagesDao.kt +++ b/data/showimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/api/ShowImagesDao.kt @@ -1,12 +1,12 @@ package com.thomaskioko.tvmaniac.showimages.api -import com.thomaskioko.tvmaniac.core.db.SelectShowImages +import com.thomaskioko.tvmaniac.core.db.EmptyShowImage import com.thomaskioko.tvmaniac.core.db.Show_image import kotlinx.coroutines.flow.Flow interface ShowImagesDao { - fun insert(image: Show_image) + fun upsert(image: Show_image) - fun observeShowImages(): Flow> + fun observeShowImages(): Flow> } diff --git a/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesDaoImpl.kt b/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesDaoImpl.kt index 4317e5410..ad1b7955d 100644 --- a/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesDaoImpl.kt +++ b/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesDaoImpl.kt @@ -2,7 +2,7 @@ package com.thomaskioko.tvmaniac.showimages.implementation import app.cash.sqldelight.coroutines.asFlow import app.cash.sqldelight.coroutines.mapToList -import com.thomaskioko.tvmaniac.core.db.SelectShowImages +import com.thomaskioko.tvmaniac.core.db.EmptyShowImage import com.thomaskioko.tvmaniac.core.db.Show_image import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase import com.thomaskioko.tvmaniac.showimages.api.ShowImagesDao @@ -16,10 +16,10 @@ class ShowImagesDaoImpl( private val dispatchers: AppCoroutineDispatchers, ) : ShowImagesDao { - override fun insert(image: Show_image) { + override fun upsert(image: Show_image) { database.transaction { database.show_imageQueries.insertOrReplace( - trakt_id = image.trakt_id, + id = image.id, tmdb_id = image.tmdb_id, poster_url = image.poster_url, backdrop_url = image.backdrop_url, @@ -27,8 +27,8 @@ class ShowImagesDaoImpl( } } - override fun observeShowImages(): Flow> { - return database.show_imageQueries.selectShowImages() + override fun observeShowImages(): Flow> { + return database.show_imageQueries.emptyShowImage() .asFlow() .mapToList(dispatchers.io) } diff --git a/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesRepositoryImpl.kt b/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesRepositoryImpl.kt index 8ffa4af07..50c5c5352 100644 --- a/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesRepositoryImpl.kt +++ b/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesRepositoryImpl.kt @@ -6,6 +6,7 @@ import com.thomaskioko.tvmaniac.core.networkutil.DefaultError import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.core.networkutil.NetworkExceptionHandler +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.resourcemanager.api.LastRequest import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.showimages.api.ShowImagesDao @@ -42,9 +43,9 @@ class ShowImagesRepositoryImpl( } is ApiResponse.Success -> { - imageCache.insert( + imageCache.upsert( Show_image( - trakt_id = show.trakt_id, + id = Id(id = show.id.id), tmdb_id = tmdbId, poster_url = response.body.posterPath?.let { formatterUtil.formatTmdbPosterPath(it) @@ -58,7 +59,7 @@ class ShowImagesRepositoryImpl( requestManagerRepository.insert( LastRequest( id = tmdbId, - entityId = show.trakt_id, + entityId = show.id.id, requestType = "SHOW_ARTWORK", ), ) diff --git a/data/shows/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/ShowsDao.kt b/data/shows/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/ShowsDao.kt index 4393a466b..c2720edf6 100644 --- a/data/shows/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/ShowsDao.kt +++ b/data/shows/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/ShowsDao.kt @@ -8,9 +8,9 @@ import kotlinx.coroutines.flow.Flow interface ShowsDao { - fun insert(show: Show) + fun upsert(show: Show) - fun insert(list: List) + fun upsert(list: List) fun observeTvShow(showId: Long): Flow @@ -21,6 +21,4 @@ interface ShowsDao { fun getTvShow(traktId: Long): ShowById fun deleteTvShows() - - fun getShowsByCategoryID(categoryId: Long): List } diff --git a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverResponseMapper.kt b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverResponseMapper.kt index 43aa2a87e..0d0e029df 100644 --- a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverResponseMapper.kt +++ b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverResponseMapper.kt @@ -6,6 +6,7 @@ import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.Show_category import com.thomaskioko.tvmaniac.core.db.ShowsByCategory import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.resourcemanager.api.LastRequest import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.trakt.api.model.ErrorResponse @@ -35,10 +36,12 @@ class DiscoverResponseMapper( logger.error("ShowStore GenericError", "${response.errorBody}") throw Throwable("${response.errorMessage}") } + is ApiResponse.Error.GenericError -> { logger.error("ShowStore GenericError", "${response.errorMessage}") throw Throwable("${response.errorMessage}") } + is ApiResponse.Error.SerializationError -> { logger.error("ShowStore GenericError", "${response.errorMessage}") throw Throwable("${response.errorMessage}") @@ -58,10 +61,12 @@ class DiscoverResponseMapper( logger.error("ShowStore GenericError", "${response.errorBody}") throw Throwable("${response.errorMessage}") } + is ApiResponse.Error.SerializationError -> { logger.error("ShowStore GenericError", "${response.errorMessage}") throw Throwable("${response.errorMessage}") } + is ApiResponse.Error.GenericError -> { logger.error("ShowStore GenericError", "${response.errorMessage}") throw Throwable("${response.errorMessage}") @@ -69,7 +74,7 @@ class DiscoverResponseMapper( } private fun responseToEntity(response: TraktShowResponse) = ShowsByCategory( - trakt_id = response.ids.trakt.toLong(), + id = Id(id = response.ids.trakt.toLong()), tmdb_id = response.ids.tmdb?.toLong(), title = response.title, overview = response.overview ?: "", @@ -87,7 +92,7 @@ class DiscoverResponseMapper( ) fun responseToShow(response: TraktShowResponse) = ShowById( - trakt_id = response.ids.trakt.toLong(), + id = Id(id = response.ids.trakt.toLong()), tmdb_id = response.ids.tmdb?.toLong(), title = response.title, overview = response.overview ?: "", @@ -99,18 +104,14 @@ class DiscoverResponseMapper( rating = formatterUtil.formatDouble(response.rating, 1), genres = response.genres.map { it.replaceFirstChar { it.uppercase() } }, status = response.status.replaceFirstChar { it.uppercase() }, - trakt_id_ = null, - tmdb_id_ = null, poster_url = null, backdrop_url = null, - id = null, - created_at = null, - synced = false, + in_watchlist = 0L, ) fun toShow(showById: ShowById) = Show( - trakt_id = showById.trakt_id, + id = showById.id, tmdb_id = showById.tmdb_id, title = showById.title, overview = showById.overview, @@ -126,7 +127,7 @@ class DiscoverResponseMapper( private fun showResponseToCacheList(response: TraktShowsResponse): ShowsByCategory = ShowsByCategory( - trakt_id = response.show.ids.trakt.toLong(), + id = Id(id = response.show.ids.trakt.toLong()), tmdb_id = response.show.ids.tmdb?.toLong(), title = response.show.title, overview = response.show.overview ?: "", @@ -145,8 +146,8 @@ class DiscoverResponseMapper( fun toCategoryCache(shows: List, categoryId: Long) = shows.map { Show_category( - trakt_id = it.trakt_id, - category_id = categoryId, + id = Id(id = it.id.id), + category_id = Id(categoryId), ) } } diff --git a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverShowsStore.kt b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverShowsStore.kt index 4a95c4894..582847bb3 100644 --- a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverShowsStore.kt +++ b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverShowsStore.kt @@ -47,7 +47,7 @@ class DiscoverShowsStore( val shows = list.map { Show( - trakt_id = it.trakt_id, + id = it.id, tmdb_id = it.tmdb_id, title = it.title, overview = it.overview, @@ -61,8 +61,8 @@ class DiscoverShowsStore( genres = it.genres, ) } - showsDao.insert(shows) - categoryCache.insert(mapper.toCategoryCache(shows, category.id)) + showsDao.upsert(shows) + categoryCache.upsert(mapper.toCategoryCache(shows, category.id)) }, ), ) diff --git a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/ShowDaoImpl.kt b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/ShowDaoImpl.kt index ce12d3ea4..5107b4362 100644 --- a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/ShowDaoImpl.kt +++ b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/ShowDaoImpl.kt @@ -8,21 +8,22 @@ import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.Shows import com.thomaskioko.tvmaniac.core.db.ShowsByCategory import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.shows.api.ShowsDao import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers import kotlinx.coroutines.flow.Flow import me.tatarka.inject.annotations.Inject @Inject -class ShowDaoImpl constructor( +class ShowDaoImpl( private val database: TvManiacDatabase, private val dispatchers: AppCoroutineDispatchers, ) : ShowsDao { - override fun insert(show: Show) { + override fun upsert(show: Show) { database.showQueries.transaction { database.showQueries.insertOrReplace( - trakt_id = show.trakt_id, + id = show.id, tmdb_id = show.tmdb_id, title = show.title, overview = show.overview, @@ -37,18 +38,18 @@ class ShowDaoImpl constructor( } } - override fun insert(list: List) { - list.forEach { insert(it) } + override fun upsert(list: List) { + list.forEach { upsert(it) } } override fun observeTvShow(showId: Long): Flow { - return database.showQueries.showById(showId) + return database.showQueries.showById(Id(showId)) .asFlow() .mapToOne(dispatchers.io) } override fun observeCachedShows(categoryId: Long): Flow> { - return database.showQueries.showsByCategory(categoryId) + return database.show_categoryQueries.showsByCategory(Id(categoryId)) .asFlow() .mapToList(dispatchers.io) } @@ -60,14 +61,10 @@ class ShowDaoImpl constructor( } override fun getTvShow(traktId: Long): ShowById = - database.showQueries.showById(traktId) + database.showQueries.showById(Id(traktId)) .executeAsOne() override fun deleteTvShows() { database.showQueries.deleteAll() } - - override fun getShowsByCategoryID(categoryId: Long): List = - database.showQueries.showsByCategory(categoryId) - .executeAsList() } diff --git a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/ShowStore.kt b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/ShowStore.kt index 5e8e16573..3c5751ab6 100644 --- a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/ShowStore.kt +++ b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/ShowStore.kt @@ -49,11 +49,11 @@ class ShowStore( reader = { traktId -> showsDao.observeTvShow(traktId) }, writer = { id, show -> - showsDao.insert(mapper.toShow(show)) + showsDao.upsert(mapper.toShow(show)) requestManagerRepository.insert( LastRequest( - id = id + show.trakt_id, + id = id + show.id.id, entityId = id, requestType = "SHOW_DETAILS", ), diff --git a/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/FakeDiscoverRepository.kt b/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/FakeDiscoverRepository.kt index ef6382f32..00df46a1f 100644 --- a/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/FakeDiscoverRepository.kt +++ b/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/FakeDiscoverRepository.kt @@ -5,6 +5,7 @@ import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.ShowsByCategory import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.shows.api.DiscoverRepository import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow @@ -38,7 +39,8 @@ class FakeDiscoverRepository : DiscoverRepository { showByIdResult.send(result) } - override fun observeShow(traktId: Long): Flow> = showByIdResult.receiveAsFlow() + override fun observeShow(traktId: Long): Flow> = + showByIdResult.receiveAsFlow() override fun observeShowCategory( category: Category, @@ -47,13 +49,14 @@ class FakeDiscoverRepository : DiscoverRepository { override suspend fun fetchDiscoverShows() {} - override suspend fun fetchShows(category: Category): List = showCategoryResult.receive() + override suspend fun fetchShows(category: Category): List = + showCategoryResult.receive() override suspend fun getShowById(traktId: Long): ShowById = showById.receive() } val selectedShow = ShowById( - trakt_id = 84958, + id = Id(84958), tmdb_id = 849583, title = "Loki", overview = "After stealing the Tesseract during the events of “Avengers: Endgame,” " + @@ -72,9 +75,5 @@ val selectedShow = ShowById( poster_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", backdrop_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", aired_episodes = 12, - trakt_id_ = 1234, - id = 12345, - created_at = null, - synced = false, - tmdb_id_ = 1232, + in_watchlist = 0, ) diff --git a/data/similar/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/api/SimilarShowsDao.kt b/data/similar/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/api/SimilarShowsDao.kt index e5a288a6b..fb0c8acf0 100644 --- a/data/similar/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/api/SimilarShowsDao.kt +++ b/data/similar/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/api/SimilarShowsDao.kt @@ -5,7 +5,7 @@ import kotlinx.coroutines.flow.Flow interface SimilarShowsDao { - fun insert(traktId: Long, similarShowId: Long) + fun upsert(showId: Long, similarShowId: Long) fun observeSimilarShows(traktId: Long): Flow> diff --git a/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/ResponseMapper.kt b/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/ResponseMapper.kt index 37ad2b2b7..e1928c406 100644 --- a/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/ResponseMapper.kt +++ b/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/ResponseMapper.kt @@ -2,12 +2,13 @@ package com.thomaskioko.tvmaniac.similar.implementation import com.thomaskioko.tvmaniac.core.db.Show import com.thomaskioko.tvmaniac.core.db.SimilarShows +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.trakt.api.model.TraktShowResponse fun List.responseToShow(): List { return map { SimilarShows( - trakt_id = it.ids.trakt.toLong(), + id = Id(it.ids.trakt.toLong()), tmdb_id = it.ids.tmdb?.toLong(), title = it.title, overview = it.overview ?: "", @@ -26,7 +27,7 @@ fun List.responseToShow(): List { fun SimilarShows.toShow(): Show { return Show( - trakt_id = trakt_id, + id = id, tmdb_id = tmdb_id, title = title, overview = overview, diff --git a/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowStore.kt b/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowStore.kt index b3acf71e2..990a18d0d 100644 --- a/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowStore.kt +++ b/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowStore.kt @@ -23,7 +23,7 @@ class SimilarShowStore( private val requestManagerRepository: RequestManagerRepository, private val scope: AppCoroutineScope, private val logger: KermitLogger, -) : Store> by StoreBuilder.from, List>( +) : Store> by StoreBuilder.from( fetcher = Fetcher.of { id -> when (val apiResult = remoteDataSource.getSimilarShows(id)) { @@ -50,11 +50,11 @@ class SimilarShowStore( writer = { id, list -> list.forEach { - showsDao.insert(it.toShow()) + showsDao.upsert(it.toShow()) - similarShowsDao.insert( - traktId = id, - similarShowId = it.trakt_id, + similarShowsDao.upsert( + similarShowId = it.id.id, + showId = id, ) } diff --git a/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowsDaoImpl.kt b/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowsDaoImpl.kt index 196e255a5..5d7bad51a 100644 --- a/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowsDaoImpl.kt +++ b/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowsDaoImpl.kt @@ -4,6 +4,7 @@ import app.cash.sqldelight.coroutines.asFlow import app.cash.sqldelight.coroutines.mapToList import com.thomaskioko.tvmaniac.core.db.SimilarShows import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.similar.api.SimilarShowsDao import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers import kotlinx.coroutines.flow.Flow @@ -15,23 +16,23 @@ class SimilarShowsDaoImpl( private val dispatchers: AppCoroutineDispatchers, ) : SimilarShowsDao { - override fun insert(traktId: Long, similarShowId: Long) { + override fun upsert(showId: Long, similarShowId: Long) { database.similar_showsQueries.transaction { database.similar_showsQueries.insertOrReplace( - id = similarShowId, - trakt_id = traktId, + id = Id(similarShowId), + similar_show_id = Id(showId), ) } } override fun observeSimilarShows(traktId: Long): Flow> { - return database.similar_showsQueries.similarShows(trakt_id = traktId) + return database.similar_showsQueries.similarShows(Id(traktId)) .asFlow() .mapToList(dispatchers.io) } override fun delete(id: Long) { - database.similar_showsQueries.delete(id) + database.similar_showsQueries.delete(Id(id)) } override fun deleteAll() { diff --git a/data/trailers/api/src/commonMain/kotlin/com.thomaskioko.tvmaniac.data.trailers.implementation/TrailerDao.kt b/data/trailers/api/src/commonMain/kotlin/com.thomaskioko.tvmaniac.data.trailers.implementation/TrailerDao.kt index 66abbf9f7..d2e174df3 100644 --- a/data/trailers/api/src/commonMain/kotlin/com.thomaskioko.tvmaniac.data.trailers.implementation/TrailerDao.kt +++ b/data/trailers/api/src/commonMain/kotlin/com.thomaskioko.tvmaniac.data.trailers.implementation/TrailerDao.kt @@ -5,9 +5,9 @@ import kotlinx.coroutines.flow.Flow interface TrailerDao { - fun insert(trailer: Trailers) + fun upsert(trailer: Trailers) - fun insert(trailerList: List) + fun upsert(trailerList: List) fun observeTrailersById(showId: Long): Flow> diff --git a/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerDaoImpl.kt b/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerDaoImpl.kt index 2fd127a33..c9b4fdde8 100644 --- a/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerDaoImpl.kt +++ b/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerDaoImpl.kt @@ -4,6 +4,7 @@ import app.cash.sqldelight.coroutines.asFlow import app.cash.sqldelight.coroutines.mapToList import com.thomaskioko.tvmaniac.core.db.Trailers import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers import kotlinx.coroutines.flow.Flow import me.tatarka.inject.annotations.Inject @@ -14,10 +15,10 @@ class TrailerDaoImpl( private val dispatchers: AppCoroutineDispatchers, ) : TrailerDao { - override fun insert(trailer: Trailers) { + override fun upsert(trailer: Trailers) { database.trailersQueries.insertOrReplace( id = trailer.id, - trakt_id = trailer.trakt_id, + show_id = trailer.show_id, key = trailer.key, name = trailer.name, site = trailer.site, @@ -26,19 +27,19 @@ class TrailerDaoImpl( ) } - override fun insert(trailerList: List) { - trailerList.forEach { insert(it) } + override fun upsert(trailerList: List) { + trailerList.forEach { upsert(it) } } override fun observeTrailersById(showId: Long): Flow> { - return database.trailersQueries.selectByShowId(showId) + return database.trailersQueries.selectByShowId(Id(showId)) .asFlow() .mapToList(dispatchers.io) } override fun delete(id: Long) { database.transaction { - database.trailersQueries.delete(id) + database.trailersQueries.delete(Id(id)) } } diff --git a/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerMapper.kt b/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerMapper.kt index ad1b7c77c..f7d2de761 100644 --- a/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerMapper.kt +++ b/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerMapper.kt @@ -1,12 +1,13 @@ package com.thomaskioko.tvmaniac.data.trailers.implementation import com.thomaskioko.tvmaniac.core.db.Trailers +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.tmdb.api.model.TrailerResponse fun List.toEntity(id: Long) = map { trailer -> Trailers( id = trailer.id, - trakt_id = id, + show_id = Id(id), key = trailer.key, name = trailer.name, site = trailer.site, diff --git a/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerStore.kt b/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerStore.kt index 8be7294ae..e94b68d50 100644 --- a/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerStore.kt +++ b/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerStore.kt @@ -22,7 +22,7 @@ class TrailerStore( private val requestManagerRepository: RequestManagerRepository, private val logger: KermitLogger, private val scope: AppCoroutineScope, -) : Store> by StoreBuilder.from, List>( +) : Store> by StoreBuilder.from( fetcher = Fetcher.of { id -> val show = showsDao.getTvShow(id) @@ -49,10 +49,10 @@ class TrailerStore( sourceOfTruth = SourceOfTruth.of( reader = { id -> trailerDao.observeTrailersById(id) }, writer = { id, list -> - trailerDao.insert(list) + trailerDao.upsert(list) requestManagerRepository.insert( LastRequest( - id = list.first().trakt_id, + id = list.first().show_id.id, entityId = id, requestType = "TRAILERS", ), diff --git a/data/trailers/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trailers/testing/MockData.kt b/data/trailers/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trailers/testing/MockData.kt index daf967642..4c6e9601e 100644 --- a/data/trailers/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trailers/testing/MockData.kt +++ b/data/trailers/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trailers/testing/MockData.kt @@ -1,11 +1,12 @@ package com.thomaskioko.tvmaniac.trailers.testing import com.thomaskioko.tvmaniac.core.db.Trailers +import com.thomaskioko.tvmaniac.db.Id val trailers = listOf( Trailers( id = "1231", - trakt_id = 84958, + show_id = Id(84958), key = "Fd43V", name = "Some title", site = "Youtube", diff --git a/data/watchlist/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/WatchlistDao.kt b/data/watchlist/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/WatchlistDao.kt index 1367b6fe3..84425e9f4 100644 --- a/data/watchlist/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/WatchlistDao.kt +++ b/data/watchlist/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/WatchlistDao.kt @@ -1,20 +1,20 @@ package com.thomaskioko.tvmaniac.shows.api -import com.thomaskioko.tvmaniac.core.db.SelectWatchlist +import com.thomaskioko.tvmaniac.core.db.WatchedShow import com.thomaskioko.tvmaniac.core.db.Watchlist import kotlinx.coroutines.flow.Flow interface WatchlistDao { - fun insert(followedShow: Watchlist) + fun upsert(watchlist: Watchlist) - fun insert(followedShows: List) + fun upsert(watchedShowList: List) - fun getWatchlist(): List + fun getWatchedShows(): List fun getUnSyncedShows(): List - fun observeWatchlist(): Flow> + fun observeWatchedShows(): Flow> fun updateShowSyncState(traktId: Long) diff --git a/data/watchlist/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/WatchlistRepository.kt b/data/watchlist/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/WatchlistRepository.kt index b51adbc93..e4b038aa1 100644 --- a/data/watchlist/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/WatchlistRepository.kt +++ b/data/watchlist/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/WatchlistRepository.kt @@ -1,15 +1,15 @@ package com.thomaskioko.tvmaniac.shows.api -import com.thomaskioko.tvmaniac.core.db.SelectWatchlist +import com.thomaskioko.tvmaniac.core.db.WatchedShow import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import kotlinx.coroutines.flow.Flow interface WatchlistRepository { - fun observeWatchList(): Flow>> + fun observeWatchList(): Flow>> - fun getWatchlist(): List + suspend fun getWatchlist(): List suspend fun updateWatchlist(traktId: Long, addToWatchList: Boolean) diff --git a/data/watchlist/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/implementation/WatchlistDaoImpl.kt b/data/watchlist/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/implementation/WatchlistDaoImpl.kt index 8bee0ddc9..e3036a7c8 100644 --- a/data/watchlist/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/implementation/WatchlistDaoImpl.kt +++ b/data/watchlist/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/implementation/WatchlistDaoImpl.kt @@ -2,9 +2,10 @@ package com.thomaskioko.tvmaniac.watchlist.implementation import app.cash.sqldelight.coroutines.asFlow import app.cash.sqldelight.coroutines.mapToList -import com.thomaskioko.tvmaniac.core.db.SelectWatchlist import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import com.thomaskioko.tvmaniac.core.db.WatchedShow import com.thomaskioko.tvmaniac.core.db.Watchlist +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.shows.api.WatchlistDao import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers import kotlinx.coroutines.flow.Flow @@ -16,41 +17,41 @@ class WatchlistDaoImpl( private val dispatchers: AppCoroutineDispatchers, ) : WatchlistDao { - override fun insert(followedShow: Watchlist) { + override fun upsert(watchlist: Watchlist) { database.transaction { database.watchlistQueries.insertOrReplace( - id = followedShow.id, - synced = followedShow.synced, - created_at = followedShow.created_at, + id = watchlist.id, + synced = watchlist.synced, + created_at = watchlist.created_at, ) } } - override fun insert(followedShows: List) { - followedShows.forEach { insert(it) } + override fun upsert(watchedShowList: List) { + watchedShowList.forEach { upsert(it) } } - override fun getWatchlist(): List = - database.watchlistQueries.selectWatchlist() + override fun getWatchedShows(): List = + database.watchlistQueries.watchedShow() .executeAsList() - override fun getUnSyncedShows(): List = - database.watchlistQueries.selectUnsyncedShows() - .executeAsList() - - override fun observeWatchlist(): Flow> = - database.watchlistQueries.selectWatchlist() + override fun observeWatchedShows(): Flow> = + database.watchlistQueries.watchedShow() .asFlow() .mapToList(dispatchers.io) + override fun getUnSyncedShows(): List = + database.watchlistQueries.unsyncedShows() + .executeAsList() + override fun updateShowSyncState(traktId: Long) { database.watchlistQueries.updateFollowedState( - id = traktId, + id = Id(traktId), synced = true, ) } override fun removeShow(traktId: Long) { - database.watchlistQueries.removeShow(traktId) + database.watchlistQueries.removeShowFromWatchlist(Id(traktId)) } } diff --git a/data/watchlist/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/implementation/WatchlistRepositoryImpl.kt b/data/watchlist/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/implementation/WatchlistRepositoryImpl.kt index 4563d8175..39b223222 100644 --- a/data/watchlist/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/implementation/WatchlistRepositoryImpl.kt +++ b/data/watchlist/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/implementation/WatchlistRepositoryImpl.kt @@ -1,11 +1,12 @@ package com.thomaskioko.tvmaniac.watchlist.implementation -import com.thomaskioko.tvmaniac.core.db.SelectWatchlist +import com.thomaskioko.tvmaniac.core.db.WatchedShow import com.thomaskioko.tvmaniac.core.db.Watchlist import com.thomaskioko.tvmaniac.core.networkutil.DefaultError import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.core.networkutil.NetworkExceptionHandler +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.profile.api.ProfileDao import com.thomaskioko.tvmaniac.shows.api.WatchlistDao import com.thomaskioko.tvmaniac.shows.api.WatchlistRepository @@ -20,7 +21,7 @@ import kotlinx.coroutines.flow.map import me.tatarka.inject.annotations.Inject @Inject -class WatchlistRepositoryImpl constructor( +class WatchlistRepositoryImpl( private val remoteDataSource: TraktListRemoteDataSource, private val watchlistDao: WatchlistDao, private val profileDao: ProfileDao, @@ -36,9 +37,9 @@ class WatchlistRepositoryImpl constructor( if (user.slug.isNotBlank()) { watchlistDao.getUnSyncedShows() .map { - remoteDataSource.addShowToWatchList(it.id) + remoteDataSource.addShowToWatchList(it.id.id) - watchlistDao.insert( + watchlistDao.upsert( Watchlist( id = it.id, synced = true, @@ -53,9 +54,9 @@ class WatchlistRepositoryImpl constructor( override suspend fun updateWatchlist(traktId: Long, addToWatchList: Boolean) { // TODO:: Check if user is signed into trakt and sync followed shows. when { - addToWatchList -> watchlistDao.insert( + addToWatchList -> watchlistDao.upsert( Watchlist( - id = traktId, + id = Id(traktId), synced = false, created_at = dateFormatter.getTimestampMilliseconds(), ), @@ -65,11 +66,11 @@ class WatchlistRepositoryImpl constructor( } } - override fun observeWatchList(): Flow>> = - watchlistDao.observeWatchlist() + override fun observeWatchList(): Flow>> = + watchlistDao.observeWatchedShows() .distinctUntilChanged() .map { Either.Right(it) } .catch { Either.Left(DefaultError(exceptionHandler.resolveError(it))) } - override fun getWatchlist(): List = watchlistDao.getWatchlist() + override suspend fun getWatchlist(): List = watchlistDao.getWatchedShows() } diff --git a/data/watchlist/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/testing/FakeWatchlistRepository.kt b/data/watchlist/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/testing/FakeWatchlistRepository.kt index b39f612a5..de6771737 100644 --- a/data/watchlist/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/testing/FakeWatchlistRepository.kt +++ b/data/watchlist/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/testing/FakeWatchlistRepository.kt @@ -1,25 +1,27 @@ package com.thomaskioko.tvmaniac.watchlist.testing -import com.thomaskioko.tvmaniac.core.db.SelectWatchlist +import com.thomaskioko.tvmaniac.core.db.WatchedShow import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.shows.api.WatchlistRepository +import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.receiveAsFlow class FakeWatchlistRepository : WatchlistRepository { - private var watchlistResult = flowOf>>() + private var watchlist: Channel> = Channel(Channel.UNLIMITED) + private var watchlistResult: Channel>> = + Channel(Channel.UNLIMITED) - suspend fun setFollowedResult(result: Either>) { - watchlistResult = flow { emit(result) } + suspend fun setFollowedResult(result: List) { + watchlist.send(result) } - override fun observeWatchList(): Flow>> = - watchlistResult + override fun observeWatchList(): Flow>> = + watchlistResult.receiveAsFlow() - override fun getWatchlist(): List = com.thomaskioko.tvmaniac.watchlist.testing.watchlistResult + override suspend fun getWatchlist(): List = watchlist.receive() override suspend fun updateWatchlist(traktId: Long, addToWatchList: Boolean) { } diff --git a/data/watchlist/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/testing/MockData.kt b/data/watchlist/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/testing/MockData.kt index 913e0dd7f..8216a1b7a 100644 --- a/data/watchlist/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/testing/MockData.kt +++ b/data/watchlist/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/testing/MockData.kt @@ -1,10 +1,11 @@ package com.thomaskioko.tvmaniac.watchlist.testing -import com.thomaskioko.tvmaniac.core.db.SelectWatchlist +import com.thomaskioko.tvmaniac.core.db.WatchedShow +import com.thomaskioko.tvmaniac.db.Id val watchlistResult = listOf( - SelectWatchlist( - trakt_id = 84958, + WatchedShow( + show_id = Id(84958), tmdb_id = 849583, title = "Loki", overview = "After stealing the Tesseract during the events of “Avengers: Endgame,” " + @@ -23,10 +24,6 @@ val watchlistResult = listOf( poster_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", backdrop_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", aired_episodes = 12, - id = 84958, - synced = true, created_at = 12345645, - trakt_id_ = 1232, - tmdb_id_ = 849583, ), ) diff --git a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsMapper.kt b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsMapper.kt index 7a80a1ddd..466ab72e7 100644 --- a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsMapper.kt +++ b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsMapper.kt @@ -12,7 +12,7 @@ fun List?.toTvShowList(): ImmutableList = this?.map { it.toTvShow() }?.toImmutableList() ?: persistentListOf() fun ShowsByCategory.toTvShow(): TvShow = TvShow( - traktId = trakt_id, + traktId = id.id, tmdbId = tmdb_id, title = title, overview = overview, diff --git a/presentation/discover/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/discover/MockData.kt b/presentation/discover/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/discover/MockData.kt index c62d54b90..910e5ecda 100644 --- a/presentation/discover/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/discover/MockData.kt +++ b/presentation/discover/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/discover/MockData.kt @@ -1,6 +1,7 @@ package com.thomaskioko.tvmaniac.presentation.discover import com.thomaskioko.tvmaniac.core.db.ShowsByCategory +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.presentation.discover.model.TvShow import kotlinx.collections.immutable.toImmutableList @@ -33,7 +34,7 @@ val discoverContent = DataLoaded( fun categoryResult(categoryId: Long) = listOf( ShowsByCategory( - trakt_id = 84958, + id = Id(84958), tmdb_id = 849583, title = "Loki", overview = "After stealing the Tesseract during the events of “Avengers: Endgame,” " + @@ -51,14 +52,14 @@ fun categoryResult(categoryId: Long) = listOf( runtime = 45, poster_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", backdrop_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", - category_id = categoryId, + category_id = Id(categoryId), aired_episodes = null, ), ) fun updateCategoryResult(categoryId: Long, size: Int = 1) = List(size) { ShowsByCategory( - trakt_id = 84958, + id = Id(84958), tmdb_id = 849583, title = "Loki", overview = "After stealing the Tesseract during the events of “Avengers: Endgame,” " + @@ -76,7 +77,7 @@ fun updateCategoryResult(categoryId: Long, size: Int = 1) = List(size) { runtime = 45, poster_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", backdrop_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", - category_id = categoryId, + category_id = Id(categoryId), aired_episodes = null, ) } diff --git a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/Mapper.kt b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/Mapper.kt index bfff1f713..e04b38087 100644 --- a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/Mapper.kt +++ b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/Mapper.kt @@ -1,42 +1,30 @@ package com.thomaskioko.tvmaniac.presentation.seasondetails -import com.thomaskioko.tvmaniac.core.db.SeasonWithEpisodes -import com.thomaskioko.tvmaniac.core.networkutil.Either +import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById import com.thomaskioko.tvmaniac.presentation.seasondetails.model.Episode import com.thomaskioko.tvmaniac.presentation.seasondetails.model.SeasonDetails -fun Either.Right>.toSeasonWithEpisodes(): List { - return data?.groupBy { it.name }?.map { groupMap -> +fun List?.toSeasonWithEpisodes(): List { + return this?.groupBy { it.season_id }?.map { (_, groupMap) -> + val seasonRow = groupMap.first() SeasonDetails( - seasonId = groupMap.value.first().season_id, - seasonName = groupMap.key, - episodes = groupMap.value.map { it.toEpisode() }, - episodeCount = groupMap.value.size.toLong(), - watchProgress = 0f, // TODO:: Fetch watch progress + seasonId = seasonRow.season_id.id, + seasonName = seasonRow.season_title, + episodes = groupMap.map { it.toEpisode() }, + episodeCount = seasonRow.episode_count, + watchProgress = 0f, ) } ?: emptyList() } -fun List?.toSeasonWithEpisodes(): List { - return this?.groupBy { it.name }?.map { groupMap -> - SeasonDetails( - seasonId = groupMap.value.first().season_id, - seasonName = groupMap.key, - episodes = groupMap.value.map { it.toEpisode() }, - episodeCount = groupMap.value.size.toLong(), - watchProgress = 0f, // TODO:: Fetch watch progress - ) - } ?: emptyList() -} - -fun SeasonWithEpisodes.toEpisode(): Episode { +fun SeasonEpisodeDetailsById.toEpisode(): Episode { return Episode( - id = id, - seasonId = season_id, - episodeTitle = title_, - episodeNumberTitle = "E$episode_number • $title_", + id = episode_id.id, + seasonId = season_id.id, + episodeTitle = episode_title, + episodeNumberTitle = "E$episode_number • $episode_title", overview = overview, - imageUrl = image_url, + imageUrl = episode_image_url, runtime = runtime, voteCount = votes, episodeNumber = episode_number, @@ -48,8 +36,4 @@ fun SeasonWithEpisodes.toEpisode(): Episode { ) } -fun Either.Right>.getTitle(): String = - data?.firstOrNull()?.title ?: "" - -fun List?.getTitle(): String = - this?.firstOrNull()?.title ?: "" +fun List?.getTitle(): String = this?.firstOrNull()?.show_title ?: "" diff --git a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsStateMachine.kt b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsStateMachine.kt index f4c1e9dca..834b8db18 100644 --- a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsStateMachine.kt +++ b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsStateMachine.kt @@ -1,8 +1,6 @@ package com.thomaskioko.tvmaniac.presentation.seasondetails -import com.freeletics.flowredux.dsl.ChangedState import com.freeletics.flowredux.dsl.FlowReduxStateMachine -import com.freeletics.flowredux.dsl.State import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageRepository import com.thomaskioko.tvmaniac.seasondetails.api.SeasonDetailsRepository import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -21,23 +19,12 @@ class SeasonDetailsStateMachine( spec { inState { onEnter { state -> - fetchSeasonDetails(state) - } + val seasonList = seasonDetailsRepository.fetchSeasonDetails(traktId) - untilIdentityChanges({ state -> state }) { - collectWhileInState(seasonDetailsRepository.observeSeasonDetailsStream(traktId)) { result, state -> - result.fold( - { - state.override { LoadingError(it.errorMessage) } - }, - { - state.override { - SeasonDetailsLoaded( - showTitle = it.getTitle(), - seasonDetailsList = it.toSeasonWithEpisodes(), - ) - } - }, + state.override { + SeasonDetailsLoaded( + showTitle = seasonList.getTitle(), + seasonDetailsList = seasonList.toSeasonWithEpisodes(), ) } } @@ -70,23 +57,4 @@ class SeasonDetailsStateMachine( } } } - - private suspend fun fetchSeasonDetails(state: State): ChangedState { - var nextState: SeasonDetailsState = Loading - - seasonDetailsRepository.observeCachedSeasonDetails(traktId) - .collect { result -> - nextState = result.fold( - { LoadingError(it.errorMessage) }, - { - SeasonDetailsLoaded( - showTitle = it.getTitle(), - seasonDetailsList = it.toSeasonWithEpisodes(), - ) - }, - ) - } - - return state.override { nextState } - } } diff --git a/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt b/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt index 40da3c454..5d19f535b 100644 --- a/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt +++ b/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt @@ -26,7 +26,7 @@ class SeasonDetailsStateMachineTest { @Test fun onLoadSeasonDetails_correct_state_is_emitted() = runTest { stateMachine.state.test { - seasonDetailsRepository.setSeasonsResult(Either.Right(SeasonWithEpisodeList)) + seasonDetailsRepository.setCachedResults(SeasonWithEpisodeList) awaitItem() shouldBe Loading awaitItem() shouldBe seasonDetailsLoaded @@ -37,9 +37,11 @@ class SeasonDetailsStateMachineTest { fun onLoadSeasonDetails_andErrorOccurs_correctStateIsEmitted() = runTest { stateMachine.state.test { val errorMessage = "Something went wrong" + seasonDetailsRepository.setCachedResults(SeasonWithEpisodeList) seasonDetailsRepository.setSeasonsResult(Either.Left(DefaultError(errorMessage))) awaitItem() shouldBe Loading + awaitItem() shouldBe seasonDetailsLoaded awaitItem() shouldBe LoadingError(errorMessage) } } diff --git a/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailMapper.kt b/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailMapper.kt index 2f0ca1653..050249d4d 100644 --- a/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailMapper.kt +++ b/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailMapper.kt @@ -6,11 +6,11 @@ import com.thomaskioko.tvmaniac.core.db.Trailers import com.thomaskioko.tvmaniac.presentation.showdetails.model.Season import com.thomaskioko.tvmaniac.presentation.showdetails.model.Show import com.thomaskioko.tvmaniac.presentation.showdetails.model.Trailer -import com.thomaskioko.tvmaniac.core.db.Seasons as SeasonCache +import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId as SeasonCache fun List?.toSimilarShowList(): List = this?.map { Show( - traktId = it.trakt_id, + traktId = it.id.id, tmdbId = it.tmdb_id, title = it.title, overview = it.overview, @@ -27,7 +27,7 @@ fun List?.toSimilarShowList(): List = this?.map { fun ShowById?.toTvShow(): Show = this?.let { Show( - traktId = it.trakt_id, + traktId = it.id.id, tmdbId = it.tmdb_id, title = it.title, overview = it.overview, @@ -39,22 +39,21 @@ fun ShowById?.toTvShow(): Show = this?.let { genres = it.genres, year = it.year, status = it.status, - isFollowed = it.id != null && it.id == it.trakt_id, - // TODO:: Get season count + isFollowed = it.in_watchlist == 1L, ) } ?: Show.EMPTY_SHOW fun List?.toSeasonsList(): List = this?.map { Season( - seasonId = it.id, - tvShowId = it.show_trakt_id, - name = it.name, + seasonId = it.season_id.id, + tvShowId = it.show_id.id, + name = it.season_title, ) } ?: emptyList() fun List?.toTrailerList(): List = this?.map { Trailer( - showId = it.trakt_id, + showId = it.show_id.id, key = it.key, name = it.name, youtubeThumbnailUrl = "https://i.ytimg.com/vi/${it.key}/hqdefault.jpg", diff --git a/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachine.kt b/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachine.kt index f1d1152b1..9a198ce4b 100644 --- a/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachine.kt +++ b/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachine.kt @@ -3,7 +3,7 @@ package com.thomaskioko.tvmaniac.presentation.showdetails import com.freeletics.flowredux.dsl.ChangedState import com.freeletics.flowredux.dsl.FlowReduxStateMachine import com.freeletics.flowredux.dsl.State -import com.thomaskioko.tvmaniac.core.db.Seasons +import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.SimilarShows import com.thomaskioko.tvmaniac.core.db.Trailers @@ -51,7 +51,7 @@ class ShowDetailsStateMachine( updateShowDetails(response, state) } - collectWhileInState(seasonsRepository.observeSeasonsStoreResponse(traktShowId)) { result, state -> + collectWhileInState(seasonsRepository.observeSeasonsByShowId(traktShowId)) { result, state -> updateSeasonDetailsState(result, state) } @@ -164,7 +164,7 @@ class ShowDetailsStateMachine( } private fun updateSeasonDetailsState( - response: Either>, + response: Either>, state: State, ) = when (response) { is Either.Left -> { @@ -193,7 +193,7 @@ class ShowDetailsStateMachine( private suspend fun fetchShowDetails(state: State): ChangedState { val show = discoverRepository.getShowById(traktShowId) val similar = similarShowsRepository.fetchSimilarShows(traktShowId) - val season = seasonsRepository.getSeasons(traktShowId) + val season = seasonsRepository.fetchSeasonsByShowId(traktShowId) val trailers = trailerRepository.fetchTrailersByShowId(traktShowId) return state.mutate { diff --git a/presentation/show-details/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/MockData.kt b/presentation/show-details/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/MockData.kt index 3bfc907d3..45434eabd 100644 --- a/presentation/show-details/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/MockData.kt +++ b/presentation/show-details/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/MockData.kt @@ -1,11 +1,12 @@ package com.thomaskioko.tvmaniac.presentation.showdetails +import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.SimilarShows +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.presentation.showdetails.model.Season import com.thomaskioko.tvmaniac.presentation.showdetails.model.Show import com.thomaskioko.tvmaniac.presentation.showdetails.model.Trailer -import com.thomaskioko.tvmaniac.core.db.Seasons as SeasonCache val show = Show( traktId = 84958, @@ -98,7 +99,7 @@ val similarShowLoaded = ShowDetailsLoaded.SimilarShowsContent( ) val selectedShow = ShowById( - trakt_id = 84958, + id = Id(84958), tmdb_id = 849583, title = "Loki", overview = "After stealing the Tesseract during the events of “Avengers: Endgame,” " + @@ -117,15 +118,11 @@ val selectedShow = ShowById( poster_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", backdrop_url = "/kEl2t3OhXc3Zb9FBh1AuYzRTgZp.jpg", aired_episodes = 12, - trakt_id_ = 1234, - id = 12345, - created_at = null, - synced = false, - tmdb_id_ = 1232, + in_watchlist = 0, ) val similarShowResult = listOf( SimilarShows( - trakt_id = 184958, + id = Id(184958), tmdb_id = 284958, title = "Loki", overview = "After stealing the Tesseract during the events of “Avengers: Endgame,” " + @@ -147,17 +144,10 @@ val similarShowResult = listOf( ) val seasons = listOf( - SeasonCache( - id = 84958, - show_trakt_id = 114355, - name = "Season 1", - episode_count = 10, + SeasonsByShowId( + season_id = Id(84958), + show_id = Id(114355), + season_title = "Season 1", season_number = 1, - overview = "After stealing the Tesseract during the events of “Avengers: Endgame,” " + - "an alternate version of Loki is brought to the mysterious Time Variance " + - "Authority, a bureaucratic organization that exists outside of time and " + - "space and monitors the timeline. They give Loki a choice: face being " + - "erased from existence due to being a “time variant”or help fix " + - "the timeline and stop a greater threat.", ), ) diff --git a/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/Mapper.kt b/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/Mapper.kt index c9dd76c40..8caf14feb 100644 --- a/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/Mapper.kt +++ b/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/Mapper.kt @@ -6,7 +6,7 @@ import com.thomaskioko.tvmaniac.presentation.trailers.model.Trailer internal fun List.toTrailerList(): List { return map { Trailer( - showId = it.trakt_id, + showId = it.show_id.id, key = it.key, name = it.name, youtubeThumbnailUrl = "https://i.ytimg.com/vi/${it.key}/hqdefault.jpg", diff --git a/presentation/watchlist/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/watchlist/Mapper.kt b/presentation/watchlist/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/watchlist/Mapper.kt index ac40e560b..82334b07f 100644 --- a/presentation/watchlist/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/watchlist/Mapper.kt +++ b/presentation/watchlist/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/watchlist/Mapper.kt @@ -1,11 +1,11 @@ package com.thomaskioko.tvmaniac.presentation.watchlist -import com.thomaskioko.tvmaniac.core.db.SelectWatchlist +import com.thomaskioko.tvmaniac.core.db.WatchedShow -fun List?.entityToWatchlist(): List { +fun List?.entityToWatchlist(): List { return this?.map { WatchlistItem( - traktId = it.id, + traktId = it.show_id.id, tmdbId = it.tmdb_id, title = it.title, posterImageUrl = it.poster_url, diff --git a/presentation/watchlist/src/commonTest/kotlin/com/thomaskioko/tvmaniac/domain/watchlist/WatchlistStateMachineTest.kt b/presentation/watchlist/src/commonTest/kotlin/com/thomaskioko/tvmaniac/domain/watchlist/WatchlistStateMachineTest.kt index 8d12a4f30..9ed148f15 100644 --- a/presentation/watchlist/src/commonTest/kotlin/com/thomaskioko/tvmaniac/domain/watchlist/WatchlistStateMachineTest.kt +++ b/presentation/watchlist/src/commonTest/kotlin/com/thomaskioko/tvmaniac/domain/watchlist/WatchlistStateMachineTest.kt @@ -1,7 +1,6 @@ package com.thomaskioko.tvmaniac.domain.watchlist import app.cash.turbine.test -import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.presentation.watchlist.LoadingShows import com.thomaskioko.tvmaniac.presentation.watchlist.WatchlistContent import com.thomaskioko.tvmaniac.presentation.watchlist.WatchlistStateMachine @@ -18,7 +17,7 @@ class WatchlistStateMachineTest { @Test fun initial_state_emits_expected_result() = runTest { - repository.setFollowedResult(Either.Right(data = watchlistResult)) + repository.setFollowedResult(watchlistResult) stateMachine.state.test { awaitItem() shouldBe LoadingShows From 1dc2dbb8bb2197a9dc472262b0ad9fdb4c8e923d Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 03:34:42 +0100 Subject: [PATCH 14/38] Delete networkUtil module --- app/build.gradle.kts | 1 - .../inject/NetworkPlatformComponent.kt | 15 --------- .../core/networkutil/NetworkBoundResource.kt | 32 ------------------- .../inject/NetworkPlatformComponent.kt | 3 -- .../inject/NetworkPlatformComponent.kt | 12 ------- .../inject/NetworkPlatformComponent.kt | 3 -- settings.gradle.kts | 1 - 7 files changed, 67 deletions(-) delete mode 100644 core/networkutil/src/androidMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt delete mode 100644 core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/NetworkBoundResource.kt delete mode 100644 core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt delete mode 100644 core/networkutil/src/iosMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt delete mode 100644 core/networkutil/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4c784a71e..f3b931cbc 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -45,7 +45,6 @@ dependencies { implementation(projects.androidFeatures.watchlist) implementation(projects.core.database) - implementation(projects.core.networkutil) implementation(projects.core.util) implementation(projects.core.datastore.api) implementation(projects.core.datastore.implementation) diff --git a/core/networkutil/src/androidMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt b/core/networkutil/src/androidMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt deleted file mode 100644 index 6c16a51cb..000000000 --- a/core/networkutil/src/androidMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.thomaskioko.tvmaniac.core.networkutil.inject - -import com.thomaskioko.tvmaniac.core.networkutil.AndroidNetworkExceptionHandlerUtil -import com.thomaskioko.tvmaniac.core.networkutil.NetworkExceptionHandler -import com.thomaskioko.tvmaniac.util.scope.ApplicationScope -import me.tatarka.inject.annotations.Provides - -actual interface NetworkPlatformComponent { - - @ApplicationScope - @Provides - fun provideNetworkExceptionHandler( - bind: AndroidNetworkExceptionHandlerUtil, - ): NetworkExceptionHandler = bind -} diff --git a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/NetworkBoundResource.kt b/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/NetworkBoundResource.kt deleted file mode 100644 index e0290f6fb..000000000 --- a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/NetworkBoundResource.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.thomaskioko.tvmaniac.core.networkutil - -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.flowOn - -inline fun networkBoundResult( - crossinline query: () -> Flow, - crossinline fetch: suspend () -> RequestType, - crossinline saveFetchResult: suspend (RequestType) -> Unit, - crossinline shouldFetch: (ResultType?) -> Boolean = { true }, - exceptionHandler: NetworkExceptionHandler, - coroutineDispatcher: CoroutineDispatcher, -) = flow> { - val data = query().first() - - if (shouldFetch(data)) { - try { - saveFetchResult(fetch()) - emit(Either.Right(query().first())) - } catch (e: Exception) { - emit(Either.Left(DefaultError(exceptionHandler.resolveError(e)))) - } - } else { - emit(Either.Right(query().first())) - } -}.catch { - emit(Either.Left(DefaultError(exceptionHandler.resolveError(it)))) -}.flowOn(coroutineDispatcher) diff --git a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt b/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt deleted file mode 100644 index 75bef7e04..000000000 --- a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.thomaskioko.tvmaniac.core.networkutil.inject - -expect interface NetworkPlatformComponent diff --git a/core/networkutil/src/iosMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt b/core/networkutil/src/iosMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt deleted file mode 100644 index 0f8f5b4eb..000000000 --- a/core/networkutil/src/iosMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.thomaskioko.tvmaniac.core.networkutil.inject - -import com.thomaskioko.tvmaniac.core.networkutil.IosExceptionHandler -import com.thomaskioko.tvmaniac.core.networkutil.NetworkExceptionHandler -import com.thomaskioko.tvmaniac.util.scope.ApplicationScope -import me.tatarka.inject.annotations.Provides - -actual interface NetworkPlatformComponent { - @ApplicationScope - @Provides - fun provideExceptionHandler(bind: IosExceptionHandler): NetworkExceptionHandler = bind -} diff --git a/core/networkutil/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt b/core/networkutil/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt deleted file mode 100644 index 5bea96170..000000000 --- a/core/networkutil/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/inject/NetworkPlatformComponent.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.thomaskioko.tvmaniac.core.networkutil.inject - -actual interface NetworkPlatformComponent diff --git a/settings.gradle.kts b/settings.gradle.kts index cd9654362..dc403e59f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -38,7 +38,6 @@ include( ":android-features:watchlist", ":shared", ":core:util", - ":core:networkutil", ":core:database", ":core:datastore:api", ":core:datastore:implementation", From 76bbee5829ce8595d646cad166583e821e1e16e3 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 03:35:41 +0100 Subject: [PATCH 15/38] Delete networkComponent class. --- .../com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt | 2 -- .../base/ApplicationComponent.kt | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/src/main/kotlin/com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt b/app/src/main/kotlin/com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt index b4dd2eb2f..10e2a2990 100644 --- a/app/src/main/kotlin/com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt +++ b/app/src/main/kotlin/com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt @@ -5,7 +5,6 @@ import android.content.Context import com.thomaskioko.trakt.service.implementation.inject.TraktComponent import com.thomaskioko.trakt.service.implementation.inject.TraktPlatformComponent import com.thomaskioko.tvmaniac.TvManicApplication -import com.thomaskioko.tvmaniac.core.networkutil.inject.NetworkPlatformComponent import com.thomaskioko.tvmaniac.data.category.implementation.CategoryComponent import com.thomaskioko.tvmaniac.data.trailers.implementation.TrailerComponent import com.thomaskioko.tvmaniac.datastore.implementation.DataStorePlatformComponent @@ -37,7 +36,6 @@ import me.tatarka.inject.annotations.Provides abstract class ApplicationComponent( @get:Provides val application: Application, ) : UtilPlatformComponent, - NetworkPlatformComponent, CategoryComponent, DatabaseComponent, DataStorePlatformComponent, diff --git a/shared/src/iosMain/kotlin/com.thomaskioko.tvmaniac.shared/base/ApplicationComponent.kt b/shared/src/iosMain/kotlin/com.thomaskioko.tvmaniac.shared/base/ApplicationComponent.kt index 9caa3c40f..7f846c74f 100644 --- a/shared/src/iosMain/kotlin/com.thomaskioko.tvmaniac.shared/base/ApplicationComponent.kt +++ b/shared/src/iosMain/kotlin/com.thomaskioko.tvmaniac.shared/base/ApplicationComponent.kt @@ -2,7 +2,6 @@ package com.thomaskioko.tvmaniac.shared.base import com.thomaskioko.trakt.service.implementation.inject.TraktComponent import com.thomaskioko.trakt.service.implementation.inject.TraktPlatformComponent -import com.thomaskioko.tvmaniac.core.networkutil.inject.NetworkPlatformComponent import com.thomaskioko.tvmaniac.data.category.implementation.CategoryComponent import com.thomaskioko.tvmaniac.data.trailers.implementation.TrailerComponent import com.thomaskioko.tvmaniac.datastore.implementation.DataStorePlatformComponent @@ -53,8 +52,7 @@ abstract class ApplicationComponent : TraktAuthenticationComponent, TrailerComponent, UtilPlatformComponent, - WatchlistComponent, - NetworkPlatformComponent { + WatchlistComponent { abstract val discoverStateMachine: DiscoverStateMachineWrapper abstract val seasonDetailsStateMachineWrapper: SeasonDetailsStateMachineWrapper From 4ea9840be88ca6c1f6b76e72573413253964d2e6 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 03:38:43 +0100 Subject: [PATCH 16/38] Remove networkUtil dependency --- data/episodes/api/build.gradle.kts | 1 - data/profile/api/build.gradle.kts | 1 - data/profilestats/api/build.gradle.kts | 1 - data/shows/api/build.gradle.kts | 1 - data/similar/api/build.gradle.kts | 1 - 5 files changed, 5 deletions(-) diff --git a/data/episodes/api/build.gradle.kts b/data/episodes/api/build.gradle.kts index 5dd2099de..862106859 100644 --- a/data/episodes/api/build.gradle.kts +++ b/data/episodes/api/build.gradle.kts @@ -7,7 +7,6 @@ kotlin { commonMain { dependencies { api(projects.core.util) - api(projects.core.networkutil) api(projects.core.database) api(libs.coroutines.core) diff --git a/data/profile/api/build.gradle.kts b/data/profile/api/build.gradle.kts index f24a4da61..30e94f05c 100644 --- a/data/profile/api/build.gradle.kts +++ b/data/profile/api/build.gradle.kts @@ -7,7 +7,6 @@ kotlin { commonMain { dependencies { api(projects.core.database) - api(projects.core.networkutil) api(projects.core.util) api(libs.coroutines.core) diff --git a/data/profilestats/api/build.gradle.kts b/data/profilestats/api/build.gradle.kts index f24a4da61..30e94f05c 100644 --- a/data/profilestats/api/build.gradle.kts +++ b/data/profilestats/api/build.gradle.kts @@ -7,7 +7,6 @@ kotlin { commonMain { dependencies { api(projects.core.database) - api(projects.core.networkutil) api(projects.core.util) api(libs.coroutines.core) diff --git a/data/shows/api/build.gradle.kts b/data/shows/api/build.gradle.kts index bb8a6543a..ad9438ae9 100644 --- a/data/shows/api/build.gradle.kts +++ b/data/shows/api/build.gradle.kts @@ -7,7 +7,6 @@ kotlin { commonMain { dependencies { api(projects.core.database) - api(projects.core.networkutil) api(projects.data.category.api) api(libs.coroutines.core) diff --git a/data/similar/api/build.gradle.kts b/data/similar/api/build.gradle.kts index c02395d78..28aa509b8 100644 --- a/data/similar/api/build.gradle.kts +++ b/data/similar/api/build.gradle.kts @@ -8,7 +8,6 @@ kotlin { commonMain { dependencies { - api(projects.core.networkutil) api(projects.core.database) implementation(projects.data.shows.api) From 1231b79b2c6e52983b23011467b7787fb215fa2c Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 03:40:39 +0100 Subject: [PATCH 17/38] ADd util dependency --- core/tmdb-api/api/build.gradle.kts | 2 +- core/trakt-api/api/build.gradle.kts | 2 +- data/category/api/build.gradle.kts | 2 +- data/episodeimages/api/build.gradle.kts | 2 +- data/seasondetails/api/build.gradle.kts | 2 +- data/seasondetails/implementation/build.gradle.kts | 5 +++-- data/seasons/api/build.gradle.kts | 2 +- data/showimages/api/build.gradle.kts | 2 +- data/trailers/api/build.gradle.kts | 2 +- data/watchlist/api/build.gradle.kts | 2 +- shared/build.gradle.kts | 2 +- 11 files changed, 13 insertions(+), 12 deletions(-) diff --git a/core/tmdb-api/api/build.gradle.kts b/core/tmdb-api/api/build.gradle.kts index 9d4ac4c41..cf71540da 100644 --- a/core/tmdb-api/api/build.gradle.kts +++ b/core/tmdb-api/api/build.gradle.kts @@ -8,7 +8,7 @@ kotlin { commonMain { dependencies { api(projects.core.database) - api(projects.core.networkutil) + api(projects.core.util) implementation(libs.ktor.serialization) } diff --git a/core/trakt-api/api/build.gradle.kts b/core/trakt-api/api/build.gradle.kts index 60fcd9da5..90d336850 100644 --- a/core/trakt-api/api/build.gradle.kts +++ b/core/trakt-api/api/build.gradle.kts @@ -7,7 +7,7 @@ kotlin { sourceSets { commonMain { dependencies { - api(projects.core.networkutil) + api(projects.core.util) implementation(libs.ktor.serialization) } } diff --git a/data/category/api/build.gradle.kts b/data/category/api/build.gradle.kts index 2425bebf1..52cbdb79f 100644 --- a/data/category/api/build.gradle.kts +++ b/data/category/api/build.gradle.kts @@ -9,7 +9,7 @@ kotlin { commonMain { dependencies { api(projects.core.database) - api(projects.core.networkutil) + api(projects.core.util) implementation(projects.core.tmdbApi.api) api(libs.coroutines.core) diff --git a/data/episodeimages/api/build.gradle.kts b/data/episodeimages/api/build.gradle.kts index 5dd2099de..adc8836f5 100644 --- a/data/episodeimages/api/build.gradle.kts +++ b/data/episodeimages/api/build.gradle.kts @@ -7,7 +7,7 @@ kotlin { commonMain { dependencies { api(projects.core.util) - api(projects.core.networkutil) + api(projects.core.util) api(projects.core.database) api(libs.coroutines.core) diff --git a/data/seasondetails/api/build.gradle.kts b/data/seasondetails/api/build.gradle.kts index 59e60b379..30e94f05c 100644 --- a/data/seasondetails/api/build.gradle.kts +++ b/data/seasondetails/api/build.gradle.kts @@ -7,7 +7,7 @@ kotlin { commonMain { dependencies { api(projects.core.database) - api(projects.core.networkutil) + api(projects.core.util) api(libs.coroutines.core) } diff --git a/data/seasondetails/implementation/build.gradle.kts b/data/seasondetails/implementation/build.gradle.kts index 8987cc386..af1dc42e1 100644 --- a/data/seasondetails/implementation/build.gradle.kts +++ b/data/seasondetails/implementation/build.gradle.kts @@ -13,12 +13,13 @@ kotlin { implementation(projects.core.traktApi.api) implementation(projects.core.util) implementation(projects.data.episodes.api) - implementation(projects.data.seasons.api) + implementation(projects.data.requestManager.api) implementation(projects.data.seasondetails.api) + implementation(projects.data.seasons.api) implementation(libs.kotlinInject.runtime) - implementation(libs.sqldelight.extensions) implementation(libs.kotlinx.atomicfu) + implementation(libs.sqldelight.extensions) implementation(libs.store5) } } diff --git a/data/seasons/api/build.gradle.kts b/data/seasons/api/build.gradle.kts index 59e60b379..30e94f05c 100644 --- a/data/seasons/api/build.gradle.kts +++ b/data/seasons/api/build.gradle.kts @@ -7,7 +7,7 @@ kotlin { commonMain { dependencies { api(projects.core.database) - api(projects.core.networkutil) + api(projects.core.util) api(libs.coroutines.core) } diff --git a/data/showimages/api/build.gradle.kts b/data/showimages/api/build.gradle.kts index 59e60b379..30e94f05c 100644 --- a/data/showimages/api/build.gradle.kts +++ b/data/showimages/api/build.gradle.kts @@ -7,7 +7,7 @@ kotlin { commonMain { dependencies { api(projects.core.database) - api(projects.core.networkutil) + api(projects.core.util) api(libs.coroutines.core) } diff --git a/data/trailers/api/build.gradle.kts b/data/trailers/api/build.gradle.kts index ea55b9cd9..417d75bab 100644 --- a/data/trailers/api/build.gradle.kts +++ b/data/trailers/api/build.gradle.kts @@ -7,7 +7,7 @@ kotlin { commonMain { dependencies { api(projects.core.database) - api(projects.core.networkutil) + api(projects.core.util) api(libs.coroutines.core) } diff --git a/data/watchlist/api/build.gradle.kts b/data/watchlist/api/build.gradle.kts index ea55b9cd9..417d75bab 100644 --- a/data/watchlist/api/build.gradle.kts +++ b/data/watchlist/api/build.gradle.kts @@ -7,7 +7,7 @@ kotlin { commonMain { dependencies { api(projects.core.database) - api(projects.core.networkutil) + api(projects.core.util) api(libs.coroutines.core) } diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 9a5ae459d..53fb65463 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -55,7 +55,7 @@ kotlin { implementation(projects.core.datastore.implementation) implementation(projects.data.episodeimages.api) implementation(projects.data.watchlist.api) - implementation(projects.core.networkutil) + implementation(projects.core.util) implementation(projects.data.showimages.api) implementation(projects.core.traktApi.api) implementation(projects.core.traktApi.implementation) From 5f48f59d9c11459a8bccfcc27534dba727b8a59b Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 03:42:15 +0100 Subject: [PATCH 18/38] Move classes to util module. --- .../com/thomaskioko/tvmaniac/util}/NetworkExceptionHandler.kt | 2 +- .../kotlin/com/thomaskioko/tvmaniac/util/model}/ApiResponse.kt | 2 +- .../kotlin/com/thomaskioko/tvmaniac/util/model}/Either.kt | 2 +- .../kotlin/com/thomaskioko/tvmaniac/util/model}/Failure.kt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename core/{networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil => util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util}/NetworkExceptionHandler.kt (64%) rename core/{networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil => util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/model}/ApiResponse.kt (98%) rename core/{networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil => util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/model}/Either.kt (89%) rename core/{networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil => util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/model}/Failure.kt (86%) diff --git a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/NetworkExceptionHandler.kt b/core/util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/NetworkExceptionHandler.kt similarity index 64% rename from core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/NetworkExceptionHandler.kt rename to core/util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/NetworkExceptionHandler.kt index 759880a89..f587c0e83 100644 --- a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/NetworkExceptionHandler.kt +++ b/core/util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/NetworkExceptionHandler.kt @@ -1,4 +1,4 @@ -package com.thomaskioko.tvmaniac.core.networkutil +package com.thomaskioko.tvmaniac.util interface NetworkExceptionHandler { diff --git a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/ApiResponse.kt b/core/util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/model/ApiResponse.kt similarity index 98% rename from core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/ApiResponse.kt rename to core/util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/model/ApiResponse.kt index 1491d65bb..b547ecb9f 100644 --- a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/ApiResponse.kt +++ b/core/util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/model/ApiResponse.kt @@ -1,4 +1,4 @@ -package com.thomaskioko.tvmaniac.core.networkutil +package com.thomaskioko.tvmaniac.util.model import io.ktor.client.HttpClient import io.ktor.client.call.body diff --git a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Either.kt b/core/util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/model/Either.kt similarity index 89% rename from core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Either.kt rename to core/util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/model/Either.kt index 4f32c86a2..9f89dc382 100644 --- a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Either.kt +++ b/core/util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/model/Either.kt @@ -1,4 +1,4 @@ -package com.thomaskioko.tvmaniac.core.networkutil +package com.thomaskioko.tvmaniac.util.model sealed class Either { diff --git a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Failure.kt b/core/util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/model/Failure.kt similarity index 86% rename from core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Failure.kt rename to core/util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/model/Failure.kt index 6e8ca5a2b..417ece0c4 100644 --- a/core/networkutil/src/commonMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/Failure.kt +++ b/core/util/src/commonMain/kotlin/com/thomaskioko/tvmaniac/util/model/Failure.kt @@ -1,4 +1,4 @@ -package com.thomaskioko.tvmaniac.core.networkutil +package com.thomaskioko.tvmaniac.util.model sealed class Failure( val throwable: Throwable, From 84a9274b1a2eed99a8f012e34fe61bce6a5c804c Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 03:44:12 +0100 Subject: [PATCH 19/38] Update imports. --- .../tvmaniac/showsgrid/GridStateMachine.kt | 2 +- .../tvmaniac/tmdb/api/TmdbNetworkDataSource.kt | 2 +- .../tmdb/implementation/TmdbNetworkDataSourceImpl.kt | 4 ++-- .../tvmaniac/trakt/api/TraktListRemoteDataSource.kt | 2 +- .../tvmaniac/trakt/api/TraktShowsRemoteDataSource.kt | 2 +- .../tvmaniac/trakt/api/TraktStatsRemoteDataSource.kt | 2 +- .../tvmaniac/trakt/api/TraktUserRemoteDataSource.kt | 2 +- .../trakt/service/implementation/TraktHttpClient.kt | 2 +- .../implementation/TraktListRemoteDataSourceImpl.kt | 4 ++-- .../TraktShowsShowsRemoteDataSourceImpl.kt | 4 ++-- .../implementation/TraktStatsRemoteDataSourceImpl.kt | 4 ++-- .../implementation/TraktUserRemoteDataSourceImpl.kt | 4 ++-- .../util}/AndroidNetworkExceptionHandlerUtil.kt | 2 +- .../tvmaniac/util/inject/UtilPlatformComponent.kt | 8 ++++++++ .../tvmaniac/util}/IosExceptionHandler.kt | 2 +- .../tvmaniac/util/inject/UtilPlatformComponent.kt | 6 ++++++ .../episodeimages/api/EpisodeImageRepository.kt | 4 ++-- .../implementation/EpisodeImageRepositoryImpl.kt | 10 +++++----- .../episodes/testing/FakeEpisodeImageRepository.kt | 4 ++-- .../tvmaniac/profile/api/ProfileRepository.kt | 4 ++-- .../profile/implementation/ProfileRepositoryImpl.kt | 6 +++--- .../tvmaniac/profile/implementation/ProfileStore.kt | 2 +- .../trakt/profile/testing/FakeProfileRepository.kt | 4 ++-- .../tvmaniac/profilestats/api/StatsRepository.kt | 4 ++-- .../implementation/StatsRepositoryImpl.kt | 4 ++-- .../profilestats/implementation/StatsStore.kt | 2 +- .../trakt/profile/testing/FakeStatsRepository.kt | 4 ++-- .../seasondetails/api/SeasonDetailsRepository.kt | 4 ++-- .../implementation/SeasonDetailsStore.kt | 2 +- .../testing/FakeSeasonDetailsRepository.kt | 4 ++-- .../tvmaniac/seasons/api/SeasonsRepository.kt | 4 ++-- .../seasons/implementation/SeasonsRepositoryImpl.kt | 4 ++-- .../tvmaniac/seasons/implementation/SeasonsStore.kt | 2 +- .../seasons/testing/FakeSeasonsRepository.kt | 4 ++-- .../tvmaniac/showimages/api/ShowImagesRepository.kt | 4 ++-- .../implementation/ShowImagesRepositoryImpl.kt | 10 +++++----- .../tmdb/testing/FakeShowImagesRepository.kt | 4 ++-- .../tvmaniac/shows/api/DiscoverRepository.kt | 4 ++-- .../shows/implementation/DiscoverRepositoryImpl.kt | 4 ++-- .../shows/implementation/DiscoverResponseMapper.kt | 2 +- .../tvmaniac/shows/implementation/ShowStore.kt | 2 +- .../tvmaniac/shows/testing/FakeDiscoverRepository.kt | 4 ++-- .../tvmaniac/similar/api/SimilarShowsRepository.kt | 4 ++-- .../similar/implementation/SimilarShowStore.kt | 2 +- .../implementation/SimilarShowsRepositoryImpl.kt | 4 ++-- .../similar/testing/FakeSimilarShowsRepository.kt | 4 ++-- .../TrailerRepository.kt | 4 ++-- .../trailers/implementation/TrailerRepositoryImpl.kt | 4 ++-- .../data/trailers/implementation/TrailerStore.kt | 2 +- .../trailers/testing/FakeTrailerRepository.kt | 4 ++-- .../tvmaniac/shows/api/WatchlistRepository.kt | 4 ++-- .../implementation/WatchlistRepositoryImpl.kt | 8 ++++---- .../watchlist/testing/FakeWatchlistRepository.kt | 4 ++-- .../presentation/discover/DiscoverShowsMapper.kt | 12 ++---------- .../presentation/profile/ProfileStateMachine.kt | 2 +- .../presentation/profile/ProfileStateMachineTest.kt | 4 ++-- .../seasondetails/SeasonDetailsStateMachineTest.kt | 4 ++-- .../presentation/settings/SettingsStateMachine.kt | 2 +- .../settings/SettingsStateMachineTest.kt | 4 ++-- .../showdetails/ShowDetailsStateMachine.kt | 4 ++-- .../showdetails/ShowDetailsStateMachineTest.kt | 4 ++-- .../presentation/trailers/TrailersStateMachine.kt | 2 +- .../presentation/trailers/TrailerStateMachineTest.kt | 4 ++-- 63 files changed, 125 insertions(+), 119 deletions(-) rename core/{networkutil/src/androidMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil => util/src/androidMain/kotlin/com/thomaskioko/tvmaniac/util}/AndroidNetworkExceptionHandlerUtil.kt (95%) rename core/{networkutil/src/iosMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil => util/src/iosMain/kotlin/com/thomaskioko/tvmaniac/util}/IosExceptionHandler.kt (95%) diff --git a/android-features/shows-grid/src/main/kotlin/com/thomaskioko/tvmaniac/showsgrid/GridStateMachine.kt b/android-features/shows-grid/src/main/kotlin/com/thomaskioko/tvmaniac/showsgrid/GridStateMachine.kt index 57d3a120e..52008a7f7 100644 --- a/android-features/shows-grid/src/main/kotlin/com/thomaskioko/tvmaniac/showsgrid/GridStateMachine.kt +++ b/android-features/shows-grid/src/main/kotlin/com/thomaskioko/tvmaniac/showsgrid/GridStateMachine.kt @@ -4,8 +4,8 @@ import com.freeletics.flowredux.dsl.ChangedState import com.freeletics.flowredux.dsl.FlowReduxStateMachine import com.freeletics.flowredux.dsl.State import com.thomaskioko.tvmaniac.category.api.model.getCategory -import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.shows.api.DiscoverRepository +import com.thomaskioko.tvmaniac.util.model.Either import kotlinx.coroutines.ExperimentalCoroutinesApi import me.tatarka.inject.annotations.Inject diff --git a/core/tmdb-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/api/TmdbNetworkDataSource.kt b/core/tmdb-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/api/TmdbNetworkDataSource.kt index fc55d52c4..41e1a03d5 100644 --- a/core/tmdb-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/api/TmdbNetworkDataSource.kt +++ b/core/tmdb-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/api/TmdbNetworkDataSource.kt @@ -1,10 +1,10 @@ package com.thomaskioko.tvmaniac.tmdb.api -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.tmdb.api.model.EpisodesResponse import com.thomaskioko.tvmaniac.tmdb.api.model.ErrorResponse import com.thomaskioko.tvmaniac.tmdb.api.model.ShowDetailResponse import com.thomaskioko.tvmaniac.tmdb.api.model.TrailersResponse +import com.thomaskioko.tvmaniac.util.model.ApiResponse interface TmdbNetworkDataSource { diff --git a/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbNetworkDataSourceImpl.kt b/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbNetworkDataSourceImpl.kt index cc8129c84..dc99aa1a3 100644 --- a/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbNetworkDataSourceImpl.kt +++ b/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbNetworkDataSourceImpl.kt @@ -1,12 +1,12 @@ package com.thomaskioko.tvmaniac.tmdb.implementation -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse -import com.thomaskioko.tvmaniac.core.networkutil.safeRequest import com.thomaskioko.tvmaniac.tmdb.api.TmdbNetworkDataSource import com.thomaskioko.tvmaniac.tmdb.api.model.EpisodesResponse import com.thomaskioko.tvmaniac.tmdb.api.model.ErrorResponse import com.thomaskioko.tvmaniac.tmdb.api.model.ShowDetailResponse import com.thomaskioko.tvmaniac.tmdb.api.model.TrailersResponse +import com.thomaskioko.tvmaniac.util.model.ApiResponse +import com.thomaskioko.tvmaniac.util.model.safeRequest import io.ktor.http.HttpMethod import io.ktor.http.path import me.tatarka.inject.annotations.Inject diff --git a/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktListRemoteDataSource.kt b/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktListRemoteDataSource.kt index 417b15265..b431f73b3 100644 --- a/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktListRemoteDataSource.kt +++ b/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktListRemoteDataSource.kt @@ -1,6 +1,5 @@ package com.thomaskioko.tvmaniac.trakt.api -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.trakt.api.model.ErrorResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktAddRemoveShowFromListResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktAddShowToListResponse @@ -8,6 +7,7 @@ import com.thomaskioko.tvmaniac.trakt.api.model.TraktCreateListResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktFollowedShowResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktPersonalListsResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktUserResponse +import com.thomaskioko.tvmaniac.util.model.ApiResponse interface TraktListRemoteDataSource { diff --git a/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktShowsRemoteDataSource.kt b/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktShowsRemoteDataSource.kt index 07a9350da..b74d073a4 100644 --- a/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktShowsRemoteDataSource.kt +++ b/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktShowsRemoteDataSource.kt @@ -1,11 +1,11 @@ package com.thomaskioko.tvmaniac.trakt.api -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.trakt.api.model.ErrorResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktSeasonEpisodesResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktSeasonsResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktShowResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktShowsResponse +import com.thomaskioko.tvmaniac.util.model.ApiResponse private const val DEFAULT_API_PAGE: Long = 1 private const val FETCH_PERIOD: String = "daily" diff --git a/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktStatsRemoteDataSource.kt b/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktStatsRemoteDataSource.kt index b58628730..3287ac69d 100644 --- a/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktStatsRemoteDataSource.kt +++ b/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktStatsRemoteDataSource.kt @@ -1,8 +1,8 @@ package com.thomaskioko.tvmaniac.trakt.api -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.trakt.api.model.ErrorResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktUserStatsResponse +import com.thomaskioko.tvmaniac.util.model.ApiResponse interface TraktStatsRemoteDataSource { diff --git a/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktUserRemoteDataSource.kt b/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktUserRemoteDataSource.kt index 60702f1c6..bab0c6b76 100644 --- a/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktUserRemoteDataSource.kt +++ b/core/trakt-api/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/api/TraktUserRemoteDataSource.kt @@ -1,9 +1,9 @@ package com.thomaskioko.tvmaniac.trakt.api -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.trakt.api.model.ErrorResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktPersonalListsResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktUserResponse +import com.thomaskioko.tvmaniac.util.model.ApiResponse interface TraktUserRemoteDataSource { diff --git a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktHttpClient.kt b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktHttpClient.kt index 6a96376fa..0eb1ca0c3 100644 --- a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktHttpClient.kt +++ b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktHttpClient.kt @@ -2,8 +2,8 @@ package com.thomaskioko.trakt.service.implementation import com.thomaskioko.trakt.service.implementation.inject.TraktHttpClientEngine import com.thomaskioko.trakt.service.implementation.inject.TraktJson -import com.thomaskioko.tvmaniac.core.networkutil.HttpExceptions import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.model.HttpExceptions import io.ktor.client.HttpClient import io.ktor.client.plugins.DefaultRequest import io.ktor.client.plugins.HttpResponseValidator diff --git a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktListRemoteDataSourceImpl.kt b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktListRemoteDataSourceImpl.kt index d9db22d63..28294203f 100644 --- a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktListRemoteDataSourceImpl.kt +++ b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktListRemoteDataSourceImpl.kt @@ -1,8 +1,6 @@ package com.thomaskioko.trakt.service.implementation import com.thomaskioko.trakt.service.implementation.inject.TraktHttpClient -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse -import com.thomaskioko.tvmaniac.core.networkutil.safeRequest import com.thomaskioko.tvmaniac.trakt.api.TraktListRemoteDataSource import com.thomaskioko.tvmaniac.trakt.api.model.ErrorResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktAddRemoveShowFromListResponse @@ -15,6 +13,8 @@ import com.thomaskioko.tvmaniac.trakt.api.model.TraktPersonalListsResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktShow import com.thomaskioko.tvmaniac.trakt.api.model.TraktShowIds import com.thomaskioko.tvmaniac.trakt.api.model.TraktUserResponse +import com.thomaskioko.tvmaniac.util.model.ApiResponse +import com.thomaskioko.tvmaniac.util.model.safeRequest import io.ktor.client.call.body import io.ktor.client.request.get import io.ktor.client.request.parameter diff --git a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktShowsShowsRemoteDataSourceImpl.kt b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktShowsShowsRemoteDataSourceImpl.kt index 9399a7e93..02ea930c9 100644 --- a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktShowsShowsRemoteDataSourceImpl.kt +++ b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktShowsShowsRemoteDataSourceImpl.kt @@ -1,14 +1,14 @@ package com.thomaskioko.trakt.service.implementation import com.thomaskioko.trakt.service.implementation.inject.TraktHttpClient -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse -import com.thomaskioko.tvmaniac.core.networkutil.safeRequest import com.thomaskioko.tvmaniac.trakt.api.TraktShowsRemoteDataSource import com.thomaskioko.tvmaniac.trakt.api.model.ErrorResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktSeasonEpisodesResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktSeasonsResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktShowResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktShowsResponse +import com.thomaskioko.tvmaniac.util.model.ApiResponse +import com.thomaskioko.tvmaniac.util.model.safeRequest import io.ktor.client.request.parameter import io.ktor.http.HttpMethod import io.ktor.http.path diff --git a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktStatsRemoteDataSourceImpl.kt b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktStatsRemoteDataSourceImpl.kt index c4c2572ac..e648e5777 100644 --- a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktStatsRemoteDataSourceImpl.kt +++ b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktStatsRemoteDataSourceImpl.kt @@ -1,11 +1,11 @@ package com.thomaskioko.trakt.service.implementation import com.thomaskioko.trakt.service.implementation.inject.TraktHttpClient -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse -import com.thomaskioko.tvmaniac.core.networkutil.safeRequest import com.thomaskioko.tvmaniac.trakt.api.TraktStatsRemoteDataSource import com.thomaskioko.tvmaniac.trakt.api.model.ErrorResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktUserStatsResponse +import com.thomaskioko.tvmaniac.util.model.ApiResponse +import com.thomaskioko.tvmaniac.util.model.safeRequest import io.ktor.http.HttpMethod import io.ktor.http.path import me.tatarka.inject.annotations.Inject diff --git a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktUserRemoteDataSourceImpl.kt b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktUserRemoteDataSourceImpl.kt index 6b33c77f9..7e04c468e 100644 --- a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktUserRemoteDataSourceImpl.kt +++ b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktUserRemoteDataSourceImpl.kt @@ -1,12 +1,12 @@ package com.thomaskioko.trakt.service.implementation import com.thomaskioko.trakt.service.implementation.inject.TraktHttpClient -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse -import com.thomaskioko.tvmaniac.core.networkutil.safeRequest import com.thomaskioko.tvmaniac.trakt.api.TraktUserRemoteDataSource import com.thomaskioko.tvmaniac.trakt.api.model.ErrorResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktPersonalListsResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktUserResponse +import com.thomaskioko.tvmaniac.util.model.ApiResponse +import com.thomaskioko.tvmaniac.util.model.safeRequest import io.ktor.client.call.body import io.ktor.client.request.get import io.ktor.client.request.parameter diff --git a/core/networkutil/src/androidMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/AndroidNetworkExceptionHandlerUtil.kt b/core/util/src/androidMain/kotlin/com/thomaskioko/tvmaniac/util/AndroidNetworkExceptionHandlerUtil.kt similarity index 95% rename from core/networkutil/src/androidMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/AndroidNetworkExceptionHandlerUtil.kt rename to core/util/src/androidMain/kotlin/com/thomaskioko/tvmaniac/util/AndroidNetworkExceptionHandlerUtil.kt index 728098381..f99b2d385 100644 --- a/core/networkutil/src/androidMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/AndroidNetworkExceptionHandlerUtil.kt +++ b/core/util/src/androidMain/kotlin/com/thomaskioko/tvmaniac/util/AndroidNetworkExceptionHandlerUtil.kt @@ -1,4 +1,4 @@ -package com.thomaskioko.tvmaniac.core.networkutil +package com.thomaskioko.tvmaniac.util import com.thomaskioko.tvmaniac.util.model.Configs import io.ktor.client.call.NoTransformationFoundException diff --git a/core/util/src/androidMain/kotlin/com/thomaskioko/tvmaniac/util/inject/UtilPlatformComponent.kt b/core/util/src/androidMain/kotlin/com/thomaskioko/tvmaniac/util/inject/UtilPlatformComponent.kt index 9d16508c7..64a944220 100644 --- a/core/util/src/androidMain/kotlin/com/thomaskioko/tvmaniac/util/inject/UtilPlatformComponent.kt +++ b/core/util/src/androidMain/kotlin/com/thomaskioko/tvmaniac/util/inject/UtilPlatformComponent.kt @@ -3,10 +3,12 @@ package com.thomaskioko.tvmaniac.util.inject import com.thomaskioko.tvmaniac.util.AndroidAppUtils import com.thomaskioko.tvmaniac.util.AndroidDateUtil import com.thomaskioko.tvmaniac.util.AndroidFormatterUtil +import com.thomaskioko.tvmaniac.util.AndroidNetworkExceptionHandlerUtil import com.thomaskioko.tvmaniac.util.AppUtils import com.thomaskioko.tvmaniac.util.ClasspathResourceReader import com.thomaskioko.tvmaniac.util.DateFormatter import com.thomaskioko.tvmaniac.util.FormatterUtil +import com.thomaskioko.tvmaniac.util.NetworkExceptionHandler import com.thomaskioko.tvmaniac.util.ResourceReader import com.thomaskioko.tvmaniac.util.YamlResourceReader import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers @@ -59,4 +61,10 @@ actual interface UtilPlatformComponent { @ApplicationScope @Provides fun provideResourceReader(bind: ClasspathResourceReader): ResourceReader = bind + + @ApplicationScope + @Provides + fun provideNetworkExceptionHandler( + bind: AndroidNetworkExceptionHandlerUtil, + ): NetworkExceptionHandler = bind } diff --git a/core/networkutil/src/iosMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/IosExceptionHandler.kt b/core/util/src/iosMain/kotlin/com/thomaskioko/tvmaniac/util/IosExceptionHandler.kt similarity index 95% rename from core/networkutil/src/iosMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/IosExceptionHandler.kt rename to core/util/src/iosMain/kotlin/com/thomaskioko/tvmaniac/util/IosExceptionHandler.kt index 647edda45..425a07614 100644 --- a/core/networkutil/src/iosMain/kotlin/com/thomaskioko/tvmaniac/core/networkutil/IosExceptionHandler.kt +++ b/core/util/src/iosMain/kotlin/com/thomaskioko/tvmaniac/util/IosExceptionHandler.kt @@ -1,4 +1,4 @@ -package com.thomaskioko.tvmaniac.core.networkutil +package com.thomaskioko.tvmaniac.util import com.thomaskioko.tvmaniac.util.model.Configs import io.ktor.client.call.NoTransformationFoundException diff --git a/core/util/src/iosMain/kotlin/com/thomaskioko/tvmaniac/util/inject/UtilPlatformComponent.kt b/core/util/src/iosMain/kotlin/com/thomaskioko/tvmaniac/util/inject/UtilPlatformComponent.kt index 9e04184c4..31f02ef7c 100644 --- a/core/util/src/iosMain/kotlin/com/thomaskioko/tvmaniac/util/inject/UtilPlatformComponent.kt +++ b/core/util/src/iosMain/kotlin/com/thomaskioko/tvmaniac/util/inject/UtilPlatformComponent.kt @@ -7,7 +7,9 @@ import com.thomaskioko.tvmaniac.util.DateFormatter import com.thomaskioko.tvmaniac.util.FormatterUtil import com.thomaskioko.tvmaniac.util.IosAppUtils import com.thomaskioko.tvmaniac.util.IosDateFormatter +import com.thomaskioko.tvmaniac.util.IosExceptionHandler import com.thomaskioko.tvmaniac.util.IosFormatterUtil +import com.thomaskioko.tvmaniac.util.NetworkExceptionHandler import com.thomaskioko.tvmaniac.util.ResourceReader import com.thomaskioko.tvmaniac.util.YamlResourceReader import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers @@ -66,4 +68,8 @@ actual interface UtilPlatformComponent { @ApplicationScope @Provides fun provideResourceReader(bind: BundleResourceReader): ResourceReader = bind + + @ApplicationScope + @Provides + fun provideExceptionHandler(bind: IosExceptionHandler): NetworkExceptionHandler = bind } diff --git a/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageRepository.kt b/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageRepository.kt index 8d0ec4222..c84c1e3c9 100644 --- a/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageRepository.kt +++ b/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageRepository.kt @@ -1,7 +1,7 @@ package com.thomaskioko.tvmaniac.episodeimages.api -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow interface EpisodeImageRepository { diff --git a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt index 1980d15b2..06fcb9ad0 100644 --- a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt +++ b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt @@ -1,17 +1,17 @@ package com.thomaskioko.tvmaniac.episodeimages.implementation import com.thomaskioko.tvmaniac.core.db.Episode_image -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse -import com.thomaskioko.tvmaniac.core.networkutil.DefaultError -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure -import com.thomaskioko.tvmaniac.core.networkutil.NetworkExceptionHandler import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageDao import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageRepository import com.thomaskioko.tvmaniac.tmdb.api.TmdbNetworkDataSource import com.thomaskioko.tvmaniac.util.FormatterUtil import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.NetworkExceptionHandler +import com.thomaskioko.tvmaniac.util.model.ApiResponse +import com.thomaskioko.tvmaniac.util.model.DefaultError +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.map diff --git a/data/episodeimages/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/testing/FakeEpisodeImageRepository.kt b/data/episodeimages/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/testing/FakeEpisodeImageRepository.kt index b80927a73..cd04adb9a 100644 --- a/data/episodeimages/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/testing/FakeEpisodeImageRepository.kt +++ b/data/episodeimages/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/testing/FakeEpisodeImageRepository.kt @@ -1,8 +1,8 @@ package com.thomaskioko.tvmaniac.episodes.testing -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf diff --git a/data/profile/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/api/ProfileRepository.kt b/data/profile/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/api/ProfileRepository.kt index ce6396347..fe67ad32a 100644 --- a/data/profile/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/api/ProfileRepository.kt +++ b/data/profile/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/api/ProfileRepository.kt @@ -1,8 +1,8 @@ package com.thomaskioko.tvmaniac.profile.api import com.thomaskioko.tvmaniac.core.db.User -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow interface ProfileRepository { diff --git a/data/profile/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/implementation/ProfileRepositoryImpl.kt b/data/profile/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/implementation/ProfileRepositoryImpl.kt index 166c5645b..9c61f157b 100644 --- a/data/profile/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/implementation/ProfileRepositoryImpl.kt +++ b/data/profile/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/implementation/ProfileRepositoryImpl.kt @@ -1,11 +1,11 @@ package com.thomaskioko.tvmaniac.profile.implementation import com.thomaskioko.tvmaniac.core.db.User -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.profile.api.ProfileRepository import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged @@ -21,7 +21,7 @@ import kotlin.time.Duration.Companion.days @OptIn(ExperimentalStoreApi::class, ExperimentalCoroutinesApi::class) @Inject -class ProfileRepositoryImpl constructor( +class ProfileRepositoryImpl( private val store: ProfileStore, private val requestManagerRepository: RequestManagerRepository, private val dispatchers: AppCoroutineDispatchers, diff --git a/data/profile/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/implementation/ProfileStore.kt b/data/profile/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/implementation/ProfileStore.kt index 7e5948027..268965474 100644 --- a/data/profile/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/implementation/ProfileStore.kt +++ b/data/profile/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profile/implementation/ProfileStore.kt @@ -1,12 +1,12 @@ package com.thomaskioko.tvmaniac.profile.implementation import com.thomaskioko.tvmaniac.core.db.User -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.profile.api.ProfileDao import com.thomaskioko.tvmaniac.resourcemanager.api.LastRequest import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.trakt.api.TraktUserRemoteDataSource import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.model.ApiResponse import com.thomaskioko.tvmaniac.util.model.AppCoroutineScope import me.tatarka.inject.annotations.Inject import org.mobilenativefoundation.store.store5.Fetcher diff --git a/data/profile/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeProfileRepository.kt b/data/profile/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeProfileRepository.kt index 577b28d27..b98a6e139 100644 --- a/data/profile/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeProfileRepository.kt +++ b/data/profile/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeProfileRepository.kt @@ -1,9 +1,9 @@ package com.thomaskioko.tvmaniac.trakt.profile.testing import com.thomaskioko.tvmaniac.core.db.User -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.profile.api.ProfileRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.receiveAsFlow diff --git a/data/profilestats/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/api/StatsRepository.kt b/data/profilestats/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/api/StatsRepository.kt index c1c9c340d..f351705e7 100644 --- a/data/profilestats/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/api/StatsRepository.kt +++ b/data/profilestats/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/api/StatsRepository.kt @@ -1,8 +1,8 @@ package com.thomaskioko.tvmaniac.profilestats.api import com.thomaskioko.tvmaniac.core.db.Stats -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow interface StatsRepository { diff --git a/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsRepositoryImpl.kt b/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsRepositoryImpl.kt index 3ea597767..c802465c2 100644 --- a/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsRepositoryImpl.kt +++ b/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsRepositoryImpl.kt @@ -1,11 +1,11 @@ package com.thomaskioko.tvmaniac.profilestats.implementation import com.thomaskioko.tvmaniac.core.db.Stats -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.profilestats.api.StatsRepository import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged diff --git a/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsStore.kt b/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsStore.kt index 19e09011c..4df803e1f 100644 --- a/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsStore.kt +++ b/data/profilestats/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/profilestats/implementation/StatsStore.kt @@ -1,12 +1,12 @@ package com.thomaskioko.tvmaniac.profilestats.implementation import com.thomaskioko.tvmaniac.core.db.Stats -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.profilestats.api.StatsDao import com.thomaskioko.tvmaniac.resourcemanager.api.LastRequest import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.trakt.api.TraktStatsRemoteDataSource import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.model.ApiResponse import com.thomaskioko.tvmaniac.util.model.AppCoroutineScope import me.tatarka.inject.annotations.Inject import org.mobilenativefoundation.store.store5.Fetcher diff --git a/data/profilestats/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeStatsRepository.kt b/data/profilestats/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeStatsRepository.kt index da4409af3..c1e9404f3 100644 --- a/data/profilestats/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeStatsRepository.kt +++ b/data/profilestats/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trakt/profile/testing/FakeStatsRepository.kt @@ -1,9 +1,9 @@ package com.thomaskioko.tvmaniac.trakt.profile.testing import com.thomaskioko.tvmaniac.core.db.Stats -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.profilestats.api.StatsRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf diff --git a/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsRepository.kt b/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsRepository.kt index bc824bc11..be291958e 100644 --- a/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsRepository.kt +++ b/data/seasondetails/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/api/SeasonDetailsRepository.kt @@ -1,8 +1,8 @@ package com.thomaskioko.tvmaniac.seasondetails.api import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow interface SeasonDetailsRepository { diff --git a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsStore.kt b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsStore.kt index 16dc03eda..ff39ad426 100644 --- a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsStore.kt +++ b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsStore.kt @@ -2,12 +2,12 @@ package com.thomaskioko.tvmaniac.seasondetails.implementation import com.thomaskioko.tvmaniac.core.db.Season import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.episodes.api.EpisodesDao import com.thomaskioko.tvmaniac.seasons.api.SeasonsDao import com.thomaskioko.tvmaniac.trakt.api.TraktShowsRemoteDataSource import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.model.ApiResponse import com.thomaskioko.tvmaniac.util.model.AppCoroutineScope import me.tatarka.inject.annotations.Inject import org.mobilenativefoundation.store.store5.Fetcher diff --git a/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/FakeSeasonDetailsRepository.kt b/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/FakeSeasonDetailsRepository.kt index 7e0a13c8a..eba976381 100644 --- a/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/FakeSeasonDetailsRepository.kt +++ b/data/seasondetails/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/testing/FakeSeasonDetailsRepository.kt @@ -1,9 +1,9 @@ package com.thomaskioko.tvmaniac.seasondetails.testing import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.seasondetails.api.SeasonDetailsRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.receiveAsFlow diff --git a/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsRepository.kt b/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsRepository.kt index 9d6a9ddaa..4224e76b1 100644 --- a/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsRepository.kt +++ b/data/seasons/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/api/SeasonsRepository.kt @@ -1,8 +1,8 @@ package com.thomaskioko.tvmaniac.seasons.api import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow interface SeasonsRepository { diff --git a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsRepositoryImpl.kt b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsRepositoryImpl.kt index a4cc0cb2c..3c28dcf5c 100644 --- a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsRepositoryImpl.kt +++ b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsRepositoryImpl.kt @@ -1,11 +1,11 @@ package com.thomaskioko.tvmaniac.seasons.implementation import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.seasons.api.SeasonsRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged diff --git a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsStore.kt b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsStore.kt index b993f8695..afe4299a5 100644 --- a/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsStore.kt +++ b/data/seasons/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/implementation/SeasonsStore.kt @@ -1,12 +1,12 @@ package com.thomaskioko.tvmaniac.seasons.implementation import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.resourcemanager.api.LastRequest import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.seasons.api.SeasonsDao import com.thomaskioko.tvmaniac.trakt.api.TraktShowsRemoteDataSource import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.model.ApiResponse import com.thomaskioko.tvmaniac.util.model.AppCoroutineScope import kotlinx.datetime.Clock import me.tatarka.inject.annotations.Inject diff --git a/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/FakeSeasonsRepository.kt b/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/FakeSeasonsRepository.kt index b07ff1914..eceb5705f 100644 --- a/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/FakeSeasonsRepository.kt +++ b/data/seasons/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasons/testing/FakeSeasonsRepository.kt @@ -1,9 +1,9 @@ package com.thomaskioko.tvmaniac.seasons.testing import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.seasons.api.SeasonsRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.receiveAsFlow diff --git a/data/showimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/api/ShowImagesRepository.kt b/data/showimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/api/ShowImagesRepository.kt index 49ea9df12..5cb3717c8 100644 --- a/data/showimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/api/ShowImagesRepository.kt +++ b/data/showimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/api/ShowImagesRepository.kt @@ -1,7 +1,7 @@ package com.thomaskioko.tvmaniac.showimages.api -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow interface ShowImagesRepository { diff --git a/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesRepositoryImpl.kt b/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesRepositoryImpl.kt index 50c5c5352..52dc3432b 100644 --- a/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesRepositoryImpl.kt +++ b/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesRepositoryImpl.kt @@ -1,11 +1,6 @@ package com.thomaskioko.tvmaniac.showimages.implementation import com.thomaskioko.tvmaniac.core.db.Show_image -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse -import com.thomaskioko.tvmaniac.core.networkutil.DefaultError -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure -import com.thomaskioko.tvmaniac.core.networkutil.NetworkExceptionHandler import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.resourcemanager.api.LastRequest import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository @@ -14,7 +9,12 @@ import com.thomaskioko.tvmaniac.showimages.api.ShowImagesRepository import com.thomaskioko.tvmaniac.tmdb.api.TmdbNetworkDataSource import com.thomaskioko.tvmaniac.util.FormatterUtil import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.NetworkExceptionHandler +import com.thomaskioko.tvmaniac.util.model.ApiResponse import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import com.thomaskioko.tvmaniac.util.model.DefaultError +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flowOn diff --git a/data/showimages/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/testing/FakeShowImagesRepository.kt b/data/showimages/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/testing/FakeShowImagesRepository.kt index 10dde84fa..cb2746a1f 100644 --- a/data/showimages/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/testing/FakeShowImagesRepository.kt +++ b/data/showimages/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/testing/FakeShowImagesRepository.kt @@ -1,8 +1,8 @@ package com.thomaskioko.tvmaniac.tmdb.testing -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.showimages.api.ShowImagesRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf diff --git a/data/shows/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/DiscoverRepository.kt b/data/shows/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/DiscoverRepository.kt index 2c569e28c..ae538c16d 100644 --- a/data/shows/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/DiscoverRepository.kt +++ b/data/shows/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/DiscoverRepository.kt @@ -3,8 +3,8 @@ package com.thomaskioko.tvmaniac.shows.api import com.thomaskioko.tvmaniac.category.api.model.Category import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.ShowsByCategory -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow import kotlin.time.Duration import kotlin.time.Duration.Companion.days diff --git a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverRepositoryImpl.kt b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverRepositoryImpl.kt index 1f661fde2..21e36e4e0 100644 --- a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverRepositoryImpl.kt +++ b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverRepositoryImpl.kt @@ -7,11 +7,11 @@ import com.thomaskioko.tvmaniac.category.api.model.Category.RECOMMENDED import com.thomaskioko.tvmaniac.category.api.model.Category.TRENDING import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.ShowsByCategory -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.shows.api.DiscoverRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged diff --git a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverResponseMapper.kt b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverResponseMapper.kt index 0d0e029df..8db1bdaa5 100644 --- a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverResponseMapper.kt +++ b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/DiscoverResponseMapper.kt @@ -5,7 +5,6 @@ import com.thomaskioko.tvmaniac.core.db.Show import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.Show_category import com.thomaskioko.tvmaniac.core.db.ShowsByCategory -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.resourcemanager.api.LastRequest import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository @@ -14,6 +13,7 @@ import com.thomaskioko.tvmaniac.trakt.api.model.TraktShowResponse import com.thomaskioko.tvmaniac.trakt.api.model.TraktShowsResponse import com.thomaskioko.tvmaniac.util.FormatterUtil import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.model.ApiResponse import me.tatarka.inject.annotations.Inject @Inject diff --git a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/ShowStore.kt b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/ShowStore.kt index 3c5751ab6..710ce4799 100644 --- a/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/ShowStore.kt +++ b/data/shows/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/implementation/ShowStore.kt @@ -1,12 +1,12 @@ package com.thomaskioko.tvmaniac.shows.implementation import com.thomaskioko.tvmaniac.core.db.ShowById -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.resourcemanager.api.LastRequest import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.shows.api.ShowsDao import com.thomaskioko.tvmaniac.trakt.api.TraktShowsRemoteDataSource import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.model.ApiResponse import com.thomaskioko.tvmaniac.util.model.AppCoroutineScope import me.tatarka.inject.annotations.Inject import org.mobilenativefoundation.store.store5.Fetcher diff --git a/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/FakeDiscoverRepository.kt b/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/FakeDiscoverRepository.kt index 00df46a1f..64e4d25f4 100644 --- a/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/FakeDiscoverRepository.kt +++ b/data/shows/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/testing/FakeDiscoverRepository.kt @@ -3,10 +3,10 @@ package com.thomaskioko.tvmaniac.shows.testing import com.thomaskioko.tvmaniac.category.api.model.Category import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.ShowsByCategory -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.shows.api.DiscoverRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.receiveAsFlow diff --git a/data/similar/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/api/SimilarShowsRepository.kt b/data/similar/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/api/SimilarShowsRepository.kt index 3ac79d614..f5f373fcf 100644 --- a/data/similar/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/api/SimilarShowsRepository.kt +++ b/data/similar/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/api/SimilarShowsRepository.kt @@ -1,8 +1,8 @@ package com.thomaskioko.tvmaniac.similar.api import com.thomaskioko.tvmaniac.core.db.SimilarShows -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow interface SimilarShowsRepository { diff --git a/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowStore.kt b/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowStore.kt index 990a18d0d..d44314b13 100644 --- a/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowStore.kt +++ b/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowStore.kt @@ -1,13 +1,13 @@ package com.thomaskioko.tvmaniac.similar.implementation import com.thomaskioko.tvmaniac.core.db.SimilarShows -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.resourcemanager.api.LastRequest import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.shows.api.ShowsDao import com.thomaskioko.tvmaniac.similar.api.SimilarShowsDao import com.thomaskioko.tvmaniac.trakt.api.TraktShowsRemoteDataSource import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.model.ApiResponse import com.thomaskioko.tvmaniac.util.model.AppCoroutineScope import me.tatarka.inject.annotations.Inject import org.mobilenativefoundation.store.store5.Fetcher diff --git a/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowsRepositoryImpl.kt b/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowsRepositoryImpl.kt index d37dd5681..abe793ec4 100644 --- a/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowsRepositoryImpl.kt +++ b/data/similar/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/implementation/SimilarShowsRepositoryImpl.kt @@ -1,11 +1,11 @@ package com.thomaskioko.tvmaniac.similar.implementation import com.thomaskioko.tvmaniac.core.db.SimilarShows -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.similar.api.SimilarShowsRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged diff --git a/data/similar/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/testing/FakeSimilarShowsRepository.kt b/data/similar/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/testing/FakeSimilarShowsRepository.kt index 3036aa5f8..81343e06f 100644 --- a/data/similar/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/testing/FakeSimilarShowsRepository.kt +++ b/data/similar/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/similar/testing/FakeSimilarShowsRepository.kt @@ -1,9 +1,9 @@ package com.thomaskioko.tvmaniac.similar.testing import com.thomaskioko.tvmaniac.core.db.SimilarShows -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.similar.api.SimilarShowsRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf diff --git a/data/trailers/api/src/commonMain/kotlin/com.thomaskioko.tvmaniac.data.trailers.implementation/TrailerRepository.kt b/data/trailers/api/src/commonMain/kotlin/com.thomaskioko.tvmaniac.data.trailers.implementation/TrailerRepository.kt index 2e83a7f45..1cb15fa65 100644 --- a/data/trailers/api/src/commonMain/kotlin/com.thomaskioko.tvmaniac.data.trailers.implementation/TrailerRepository.kt +++ b/data/trailers/api/src/commonMain/kotlin/com.thomaskioko.tvmaniac.data.trailers.implementation/TrailerRepository.kt @@ -1,8 +1,8 @@ package com.thomaskioko.tvmaniac.data.trailers.implementation import com.thomaskioko.tvmaniac.core.db.Trailers -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow interface TrailerRepository { diff --git a/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerRepositoryImpl.kt b/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerRepositoryImpl.kt index 3a6b20fe3..035aa9a07 100644 --- a/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerRepositoryImpl.kt +++ b/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerRepositoryImpl.kt @@ -1,11 +1,11 @@ package com.thomaskioko.tvmaniac.data.trailers.implementation import com.thomaskioko.tvmaniac.core.db.Trailers -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.util.AppUtils import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged diff --git a/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerStore.kt b/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerStore.kt index e94b68d50..856524041 100644 --- a/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerStore.kt +++ b/data/trailers/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/data/trailers/implementation/TrailerStore.kt @@ -1,12 +1,12 @@ package com.thomaskioko.tvmaniac.data.trailers.implementation import com.thomaskioko.tvmaniac.core.db.Trailers -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse import com.thomaskioko.tvmaniac.resourcemanager.api.LastRequest import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.shows.api.ShowsDao import com.thomaskioko.tvmaniac.tmdb.api.TmdbNetworkDataSource import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.model.ApiResponse import com.thomaskioko.tvmaniac.util.model.AppCoroutineScope import me.tatarka.inject.annotations.Inject import org.mobilenativefoundation.store.store5.Fetcher diff --git a/data/trailers/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trailers/testing/FakeTrailerRepository.kt b/data/trailers/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trailers/testing/FakeTrailerRepository.kt index 5530995c0..412f30428 100644 --- a/data/trailers/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trailers/testing/FakeTrailerRepository.kt +++ b/data/trailers/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/trailers/testing/FakeTrailerRepository.kt @@ -1,9 +1,9 @@ package com.thomaskioko.tvmaniac.trailers.testing import com.thomaskioko.tvmaniac.core.db.Trailers -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.data.trailers.implementation.TrailerRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf diff --git a/data/watchlist/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/WatchlistRepository.kt b/data/watchlist/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/WatchlistRepository.kt index e4b038aa1..802fbffd4 100644 --- a/data/watchlist/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/WatchlistRepository.kt +++ b/data/watchlist/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/shows/api/WatchlistRepository.kt @@ -1,8 +1,8 @@ package com.thomaskioko.tvmaniac.shows.api import com.thomaskioko.tvmaniac.core.db.WatchedShow -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow interface WatchlistRepository { diff --git a/data/watchlist/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/implementation/WatchlistRepositoryImpl.kt b/data/watchlist/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/implementation/WatchlistRepositoryImpl.kt index 39b223222..b12486c5b 100644 --- a/data/watchlist/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/implementation/WatchlistRepositoryImpl.kt +++ b/data/watchlist/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/implementation/WatchlistRepositoryImpl.kt @@ -2,17 +2,17 @@ package com.thomaskioko.tvmaniac.watchlist.implementation import com.thomaskioko.tvmaniac.core.db.WatchedShow import com.thomaskioko.tvmaniac.core.db.Watchlist -import com.thomaskioko.tvmaniac.core.networkutil.DefaultError -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure -import com.thomaskioko.tvmaniac.core.networkutil.NetworkExceptionHandler import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.profile.api.ProfileDao import com.thomaskioko.tvmaniac.shows.api.WatchlistDao import com.thomaskioko.tvmaniac.shows.api.WatchlistRepository import com.thomaskioko.tvmaniac.trakt.api.TraktListRemoteDataSource import com.thomaskioko.tvmaniac.util.DateFormatter +import com.thomaskioko.tvmaniac.util.NetworkExceptionHandler import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import com.thomaskioko.tvmaniac.util.model.DefaultError +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.distinctUntilChanged diff --git a/data/watchlist/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/testing/FakeWatchlistRepository.kt b/data/watchlist/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/testing/FakeWatchlistRepository.kt index de6771737..c8ff4d5da 100644 --- a/data/watchlist/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/testing/FakeWatchlistRepository.kt +++ b/data/watchlist/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/watchlist/testing/FakeWatchlistRepository.kt @@ -1,9 +1,9 @@ package com.thomaskioko.tvmaniac.watchlist.testing import com.thomaskioko.tvmaniac.core.db.WatchedShow -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.shows.api.WatchlistRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.receiveAsFlow diff --git a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsMapper.kt b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsMapper.kt index 466ab72e7..915879701 100644 --- a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsMapper.kt +++ b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverShowsMapper.kt @@ -1,9 +1,9 @@ package com.thomaskioko.tvmaniac.presentation.discover import com.thomaskioko.tvmaniac.core.db.ShowsByCategory -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.presentation.discover.model.TvShow +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @@ -33,11 +33,3 @@ fun getErrorMessage( recommended: Either>, ) = trending.getErrorOrNull()?.errorMessage ?: popular.getErrorOrNull()?.errorMessage ?: anticipated.getErrorOrNull()?.errorMessage ?: recommended.getErrorOrNull()?.errorMessage - -fun getIsContentEmpty( - trending: Either>, - popular: Either>, - anticipated: Either>, - recommended: Either>, -) = trending.getOrNull().isNullOrEmpty() && popular.getOrNull().isNullOrEmpty() && - anticipated.getOrNull().isNullOrEmpty() && recommended.getOrNull().isNullOrEmpty() diff --git a/presentation/profile/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachine.kt b/presentation/profile/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachine.kt index 940efd877..ac240eee9 100644 --- a/presentation/profile/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachine.kt +++ b/presentation/profile/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachine.kt @@ -1,11 +1,11 @@ package com.thomaskioko.tvmaniac.presentation.profile import com.freeletics.flowredux.dsl.FlowReduxStateMachine -import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.datastore.api.DatastoreRepository import com.thomaskioko.tvmaniac.profile.api.ProfileRepository import com.thomaskioko.tvmaniac.traktauth.api.TraktAuthRepository import com.thomaskioko.tvmaniac.traktauth.api.TraktAuthState +import com.thomaskioko.tvmaniac.util.model.Either import kotlinx.coroutines.ExperimentalCoroutinesApi import me.tatarka.inject.annotations.Inject diff --git a/presentation/profile/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachineTest.kt b/presentation/profile/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachineTest.kt index 920803907..caae38e4f 100644 --- a/presentation/profile/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachineTest.kt +++ b/presentation/profile/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/profile/ProfileStateMachineTest.kt @@ -1,14 +1,14 @@ package com.thomaskioko.tvmaniac.presentation.profile import app.cash.turbine.test -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.ServerError import com.thomaskioko.tvmaniac.datastore.testing.FakeDatastoreRepository import com.thomaskioko.tvmaniac.datastore.testing.authenticatedAuthState import com.thomaskioko.tvmaniac.trakt.profile.testing.FakeProfileRepository import com.thomaskioko.tvmaniac.trakt.profile.testing.user import com.thomaskioko.tvmaniac.traktauth.api.TraktAuthState import com.thomaskioko.tvmaniac.traktauth.testing.FakeTraktAuthRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.ServerError import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest import kotlin.test.Test diff --git a/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt b/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt index 5d19f535b..38b87549a 100644 --- a/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt +++ b/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt @@ -1,14 +1,14 @@ package com.thomaskioko.tvmaniac.data.seasondetails import app.cash.turbine.test -import com.thomaskioko.tvmaniac.core.networkutil.DefaultError -import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.episodes.testing.FakeEpisodeImageRepository import com.thomaskioko.tvmaniac.presentation.seasondetails.Loading import com.thomaskioko.tvmaniac.presentation.seasondetails.LoadingError import com.thomaskioko.tvmaniac.presentation.seasondetails.SeasonDetailsStateMachine import com.thomaskioko.tvmaniac.seasondetails.testing.FakeSeasonDetailsRepository import com.thomaskioko.tvmaniac.seasondetails.testing.SeasonWithEpisodeList +import com.thomaskioko.tvmaniac.util.model.DefaultError +import com.thomaskioko.tvmaniac.util.model.Either import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest import kotlin.test.Test diff --git a/presentation/settings/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachine.kt b/presentation/settings/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachine.kt index 5bc119ecd..834774869 100644 --- a/presentation/settings/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachine.kt +++ b/presentation/settings/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachine.kt @@ -1,11 +1,11 @@ package com.thomaskioko.tvmaniac.presentation.settings import com.freeletics.flowredux.dsl.FlowReduxStateMachine -import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.datastore.api.DatastoreRepository import com.thomaskioko.tvmaniac.profile.api.ProfileRepository import com.thomaskioko.tvmaniac.traktauth.api.TraktAuthRepository import com.thomaskioko.tvmaniac.traktauth.api.TraktAuthState +import com.thomaskioko.tvmaniac.util.model.Either import kotlinx.coroutines.ExperimentalCoroutinesApi import me.tatarka.inject.annotations.Inject diff --git a/presentation/settings/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachineTest.kt b/presentation/settings/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachineTest.kt index 418584b18..61f7f230e 100644 --- a/presentation/settings/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachineTest.kt +++ b/presentation/settings/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/settings/SettingsStateMachineTest.kt @@ -1,8 +1,6 @@ package com.thomaskioko.tvmaniac.presentation.settings import app.cash.turbine.test -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.ServerError import com.thomaskioko.tvmaniac.datastore.api.Theme import com.thomaskioko.tvmaniac.datastore.testing.FakeDatastoreRepository import com.thomaskioko.tvmaniac.datastore.testing.authenticatedAuthState @@ -10,6 +8,8 @@ import com.thomaskioko.tvmaniac.trakt.profile.testing.FakeProfileRepository import com.thomaskioko.tvmaniac.trakt.profile.testing.user import com.thomaskioko.tvmaniac.traktauth.api.TraktAuthState import com.thomaskioko.tvmaniac.traktauth.testing.FakeTraktAuthRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.ServerError import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest import kotlin.test.Test diff --git a/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachine.kt b/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachine.kt index 9a198ce4b..71efb4e35 100644 --- a/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachine.kt +++ b/presentation/show-details/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachine.kt @@ -7,14 +7,14 @@ import com.thomaskioko.tvmaniac.core.db.SeasonsByShowId import com.thomaskioko.tvmaniac.core.db.ShowById import com.thomaskioko.tvmaniac.core.db.SimilarShows import com.thomaskioko.tvmaniac.core.db.Trailers -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure import com.thomaskioko.tvmaniac.data.trailers.implementation.TrailerRepository import com.thomaskioko.tvmaniac.presentation.showdetails.ShowDetailsLoaded.TrailersContent.Companion.playerErrorMessage import com.thomaskioko.tvmaniac.seasons.api.SeasonsRepository import com.thomaskioko.tvmaniac.shows.api.DiscoverRepository import com.thomaskioko.tvmaniac.shows.api.WatchlistRepository import com.thomaskioko.tvmaniac.similar.api.SimilarShowsRepository +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure import kotlinx.coroutines.ExperimentalCoroutinesApi import me.tatarka.inject.annotations.Assisted import me.tatarka.inject.annotations.Inject diff --git a/presentation/show-details/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachineTest.kt b/presentation/show-details/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachineTest.kt index 35d9ad36b..57034196e 100644 --- a/presentation/show-details/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachineTest.kt +++ b/presentation/show-details/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/showdetails/ShowDetailsStateMachineTest.kt @@ -1,8 +1,6 @@ package com.thomaskioko.tvmaniac.presentation.showdetails import app.cash.turbine.test -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.ServerError import com.thomaskioko.tvmaniac.presentation.showdetails.ShowDetailsLoaded.Companion.EMPTY_DETAIL_STATE import com.thomaskioko.tvmaniac.presentation.showdetails.ShowDetailsLoaded.SeasonsContent.Companion.EMPTY_SEASONS import com.thomaskioko.tvmaniac.presentation.showdetails.ShowDetailsLoaded.SimilarShowsContent.Companion.EMPTY_SIMILAR_SHOWS @@ -13,6 +11,8 @@ import com.thomaskioko.tvmaniac.shows.testing.selectedShow import com.thomaskioko.tvmaniac.similar.testing.FakeSimilarShowsRepository import com.thomaskioko.tvmaniac.trailers.testing.FakeTrailerRepository import com.thomaskioko.tvmaniac.trailers.testing.trailers +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.ServerError import com.thomaskioko.tvmaniac.watchlist.testing.FakeWatchlistRepository import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest diff --git a/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailersStateMachine.kt b/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailersStateMachine.kt index fa79d4b74..4d8250496 100644 --- a/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailersStateMachine.kt +++ b/presentation/trailers/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailersStateMachine.kt @@ -1,8 +1,8 @@ package com.thomaskioko.tvmaniac.presentation.trailers import com.freeletics.flowredux.dsl.FlowReduxStateMachine -import com.thomaskioko.tvmaniac.core.networkutil.Either import com.thomaskioko.tvmaniac.data.trailers.implementation.TrailerRepository +import com.thomaskioko.tvmaniac.util.model.Either import kotlinx.coroutines.ExperimentalCoroutinesApi import me.tatarka.inject.annotations.Assisted import me.tatarka.inject.annotations.Inject diff --git a/presentation/trailers/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailerStateMachineTest.kt b/presentation/trailers/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailerStateMachineTest.kt index 29ba90ac5..c92141439 100644 --- a/presentation/trailers/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailerStateMachineTest.kt +++ b/presentation/trailers/src/commonTest/kotlin/com/thomaskioko/tvmaniac/presentation/trailers/TrailerStateMachineTest.kt @@ -1,11 +1,11 @@ package com.thomaskioko.tvmaniac.presentation.trailers import app.cash.turbine.test -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.ServerError import com.thomaskioko.tvmaniac.presentation.trailers.model.Trailer import com.thomaskioko.tvmaniac.trailers.testing.FakeTrailerRepository import com.thomaskioko.tvmaniac.trailers.testing.trailers +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.ServerError import io.kotest.matchers.shouldBe import kotlinx.coroutines.test.runTest import kotlin.test.Test From ca4d5fb0b53968deb2e9a5fd4c2ce6aec31e987d Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 19:53:52 +0100 Subject: [PATCH 20/38] Change log level to info --- .../thomaskioko/trakt/service/implementation/TraktHttpClient.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktHttpClient.kt b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktHttpClient.kt index 0eb1ca0c3..7cd4e27c3 100644 --- a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktHttpClient.kt +++ b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktHttpClient.kt @@ -83,7 +83,7 @@ fun traktHttpClient( } install(Logging) { - level = LogLevel.BODY + level = LogLevel.INFO logger = if (isDebug) { object : Logger { override fun log(message: String) { From 2a164c97857f71fafc8e342bda2fa8d6d7776568 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 19:54:52 +0100 Subject: [PATCH 21/38] Cleanup TMDB DI component. --- .../tvmaniac/inject/ApplicationComponent.kt | 2 + .../implementation/TmdbPlatformComponent.kt | 28 +---------- .../tmdb/implementation/TmdbClient.kt | 20 ++++++++ .../tmdb/implementation/TmdbComponent.kt | 46 +++++++++++++++++++ .../implementation/TmdbPlatformComponent.kt | 11 ----- .../implementation/TmdbPlatformComponent.kt | 31 +------------ .../implementation/TmdbPlatformComponent.kt | 2 +- .../base/ApplicationComponent.kt | 2 + 8 files changed, 73 insertions(+), 69 deletions(-) create mode 100644 core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbComponent.kt delete mode 100644 core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt diff --git a/app/src/main/kotlin/com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt b/app/src/main/kotlin/com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt index 10e2a2990..e18516b79 100644 --- a/app/src/main/kotlin/com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt +++ b/app/src/main/kotlin/com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt @@ -20,6 +20,7 @@ import com.thomaskioko.tvmaniac.seasons.implementation.SeasonsComponent import com.thomaskioko.tvmaniac.showimages.implementation.ShowImagesComponent import com.thomaskioko.tvmaniac.shows.implementation.DiscoverComponent import com.thomaskioko.tvmaniac.similar.implementation.SimilarShowsComponent +import com.thomaskioko.tvmaniac.tmdb.implementation.TmdbComponent import com.thomaskioko.tvmaniac.tmdb.implementation.TmdbPlatformComponent import com.thomaskioko.tvmaniac.traktauth.implementation.TraktAuthComponent import com.thomaskioko.tvmaniac.traktauth.implementation.TraktAuthenticationComponent @@ -52,6 +53,7 @@ abstract class ApplicationComponent( SimilarShowsComponent, StatsComponent, TasksComponent, + TmdbComponent, TmdbPlatformComponent, TraktComponent, TraktPlatformComponent, diff --git a/core/tmdb-api/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt b/core/tmdb-api/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt index a7feec22b..22e3c071d 100644 --- a/core/tmdb-api/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt +++ b/core/tmdb-api/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt @@ -1,38 +1,12 @@ package com.thomaskioko.tvmaniac.tmdb.implementation -import com.thomaskioko.tvmaniac.tmdb.api.TmdbNetworkDataSource -import com.thomaskioko.tvmaniac.util.model.Configs import com.thomaskioko.tvmaniac.util.scope.ApplicationScope import io.ktor.client.engine.okhttp.OkHttp -import kotlinx.serialization.json.Json import me.tatarka.inject.annotations.Provides -actual interface TmdbPlatformComponent { - - @ApplicationScope - @Provides - fun provideTmdbJson(): TmdbJson = Json { - ignoreUnknownKeys = true - prettyPrint = true - encodeDefaults = true - } +interface TmdbPlatformComponent { @ApplicationScope @Provides fun provideTmdbHttpClientEngine(): TmdbHttpClientEngine = OkHttp.create() - - @ApplicationScope - @Provides - fun provideTmdbHttpClient( - configs: Configs, - json: TmdbJson, - httpClientEngine: TmdbHttpClientEngine, - ): TmdbHttpClient = tmdbHttpClient( - tmdbApiKey = configs.tmdbApiKey, - json = json, - httpClientEngine = httpClientEngine, - ) - - @Provides - fun provideTmdbService(bind: TmdbNetworkDataSourceImpl): TmdbNetworkDataSource = bind } diff --git a/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbClient.kt b/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbClient.kt index 30e8fba69..168135818 100644 --- a/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbClient.kt +++ b/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbClient.kt @@ -1,10 +1,15 @@ package com.thomaskioko.tvmaniac.tmdb.implementation +import com.thomaskioko.tvmaniac.util.KermitLogger import io.ktor.client.HttpClient import io.ktor.client.engine.HttpClientEngine import io.ktor.client.plugins.DefaultRequest import io.ktor.client.plugins.HttpTimeout import io.ktor.client.plugins.contentnegotiation.ContentNegotiation +import io.ktor.client.plugins.logging.EMPTY +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.request.headers import io.ktor.http.HttpHeaders import io.ktor.http.URLProtocol @@ -14,9 +19,11 @@ import kotlinx.serialization.json.Json const val TIMEOUT_DURATION: Long = 60_000 fun tmdbHttpClient( + isDebug: Boolean = false, tmdbApiKey: String, json: Json, httpClientEngine: HttpClientEngine, + kermitLogger: KermitLogger, ) = HttpClient(httpClientEngine) { install(ContentNegotiation) { json(json = json) @@ -43,4 +50,17 @@ fun tmdbHttpClient( connectTimeoutMillis = TIMEOUT_DURATION socketTimeoutMillis = TIMEOUT_DURATION } + + install(Logging) { + level = LogLevel.BODY + logger = if (isDebug) { + object : Logger { + override fun log(message: String) { + kermitLogger.debug(message) + } + } + } else { + Logger.EMPTY + } + } } diff --git a/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbComponent.kt b/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbComponent.kt new file mode 100644 index 000000000..732c2fdfd --- /dev/null +++ b/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbComponent.kt @@ -0,0 +1,46 @@ +package com.thomaskioko.tvmaniac.tmdb.implementation + +import com.thomaskioko.tvmaniac.tmdb.api.TmdbNetworkDataSource +import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.model.Configs +import com.thomaskioko.tvmaniac.util.scope.ApplicationScope +import io.ktor.client.HttpClient +import io.ktor.client.engine.HttpClientEngine +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json +import me.tatarka.inject.annotations.Provides + +typealias TmdbHttpClient = HttpClient +typealias TmdbHttpClientEngine = HttpClientEngine +typealias TmdbJson = Json + +interface TmdbComponent { + + @OptIn(ExperimentalSerializationApi::class) + @ApplicationScope + @Provides + fun provideTmdbJson(): TmdbJson = Json { + isLenient = true + ignoreUnknownKeys = true + useAlternativeNames = false + explicitNulls = false + } + + @ApplicationScope + @Provides + fun provideTmdbHttpClient( + configs: Configs, + json: TmdbJson, + httpClientEngine: TmdbHttpClientEngine, + logger: KermitLogger, + ): TmdbHttpClient = tmdbHttpClient( + tmdbApiKey = configs.tmdbApiKey, + json = json, + httpClientEngine = httpClientEngine, + kermitLogger = logger, + isDebug = configs.isDebug, + ) + + @Provides + fun provideTmdbService(bind: TmdbNetworkDataSourceImpl): TmdbNetworkDataSource = bind +} diff --git a/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt b/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt deleted file mode 100644 index a4fc2c2bc..000000000 --- a/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.thomaskioko.tvmaniac.tmdb.implementation - -import io.ktor.client.HttpClient -import io.ktor.client.engine.HttpClientEngine -import kotlinx.serialization.json.Json - -typealias TmdbHttpClient = HttpClient -typealias TmdbHttpClientEngine = HttpClientEngine -typealias TmdbJson = Json - -expect interface TmdbPlatformComponent diff --git a/core/tmdb-api/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt b/core/tmdb-api/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt index 9159ffdd6..fc7eb13eb 100644 --- a/core/tmdb-api/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt +++ b/core/tmdb-api/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt @@ -1,41 +1,12 @@ package com.thomaskioko.tvmaniac.tmdb.implementation -import com.thomaskioko.tvmaniac.tmdb.api.TmdbNetworkDataSource -import com.thomaskioko.tvmaniac.util.model.Configs import com.thomaskioko.tvmaniac.util.scope.ApplicationScope import io.ktor.client.engine.darwin.Darwin -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.json.Json import me.tatarka.inject.annotations.Provides -actual interface TmdbPlatformComponent { - - @OptIn(ExperimentalSerializationApi::class) - @ApplicationScope - @Provides - fun provideTmdbJson(): TmdbJson = Json { - isLenient = true - ignoreUnknownKeys = true - useAlternativeNames = false - explicitNulls = false - } +interface TmdbPlatformComponent { @ApplicationScope @Provides fun provideTmdbHttpClientEngine(): TmdbHttpClientEngine = Darwin.create() - - @ApplicationScope - @Provides - fun provideTmdbHttpClient( - configs: Configs, - json: TmdbJson, - httpClientEngine: TmdbHttpClientEngine, - ): TmdbHttpClient = tmdbHttpClient( - json = json, - httpClientEngine = httpClientEngine, - tmdbApiKey = configs.tmdbApiKey, - ) - - @Provides - fun provideTmdbService(bind: TmdbNetworkDataSourceImpl): TmdbNetworkDataSource = bind } diff --git a/core/tmdb-api/implementation/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt b/core/tmdb-api/implementation/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt index fbd673b97..0706afc5c 100644 --- a/core/tmdb-api/implementation/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt +++ b/core/tmdb-api/implementation/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt @@ -1,3 +1,3 @@ package com.thomaskioko.tvmaniac.tmdb.implementation -actual interface TmdbPlatformComponent +interface TmdbPlatformComponent diff --git a/shared/src/iosMain/kotlin/com.thomaskioko.tvmaniac.shared/base/ApplicationComponent.kt b/shared/src/iosMain/kotlin/com.thomaskioko.tvmaniac.shared/base/ApplicationComponent.kt index 7f846c74f..36e7baf91 100644 --- a/shared/src/iosMain/kotlin/com.thomaskioko.tvmaniac.shared/base/ApplicationComponent.kt +++ b/shared/src/iosMain/kotlin/com.thomaskioko.tvmaniac.shared/base/ApplicationComponent.kt @@ -23,6 +23,7 @@ import com.thomaskioko.tvmaniac.shared.base.wrappers.WatchlistStateMachineWrappe import com.thomaskioko.tvmaniac.showimages.implementation.ShowImagesComponent import com.thomaskioko.tvmaniac.shows.implementation.DiscoverComponent import com.thomaskioko.tvmaniac.similar.implementation.SimilarShowsComponent +import com.thomaskioko.tvmaniac.tmdb.implementation.TmdbComponent import com.thomaskioko.tvmaniac.tmdb.implementation.TmdbPlatformComponent import com.thomaskioko.tvmaniac.traktauth.implementation.TraktAuthenticationComponent import com.thomaskioko.tvmaniac.util.inject.UtilPlatformComponent @@ -46,6 +47,7 @@ abstract class ApplicationComponent : ShowImagesComponent, SimilarShowsComponent, StatsComponent, + TmdbComponent, TmdbPlatformComponent, TraktComponent, TraktPlatformComponent, From c44aa2fec21328f397984c50d26a601c411ea70c Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 19:56:14 +0100 Subject: [PATCH 22/38] Create transaction runner object. --- .../tvmaniac/db/DatabaseComponent.kt | 6 ++++++ .../DbTransactionRunner.kt | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DbTransactionRunner.kt diff --git a/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt b/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt index 598891fd7..174189203 100644 --- a/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt +++ b/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt @@ -72,4 +72,10 @@ actual interface DatabaseComponent { show_idAdapter = IdAdapter(), ), ) + + @ApplicationScope + @Provides + fun provideDbTransactionRunner( + bind: DbTransactionRunner, + ): DatabaseTransactionRunner = bind } diff --git a/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DbTransactionRunner.kt b/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DbTransactionRunner.kt new file mode 100644 index 000000000..08febe361 --- /dev/null +++ b/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DbTransactionRunner.kt @@ -0,0 +1,17 @@ +package com.thomaskioko.tvmaniac.db + +import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import me.tatarka.inject.annotations.Inject + +interface DatabaseTransactionRunner { + operator fun invoke(block: () -> T): T +} + +@Inject +class DbTransactionRunner(private val db: TvManiacDatabase) : DatabaseTransactionRunner { + override fun invoke(block: () -> T): T { + return db.transactionWithResult { + block() + } + } +} From bb16c5f41fed453f864b34573fa42852cd44eed1 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 19:58:13 +0100 Subject: [PATCH 23/38] Add delete functions and update dao implementation. --- .../tvmaniac/core/db/episode_image.sq | 12 +++++-- .../tvmaniac/core/db/show_image.sq | 12 +++++-- .../episodeimages/api/EpisodeImageDao.kt | 8 ++++- .../api/EpisodeImageRepository.kt | 2 +- .../implementation/EpisodeImageDaoImpl.kt | 29 ++++++++++++----- .../testing/FakeEpisodeImageRepository.kt | 4 ++- .../tvmaniac/showimages/api/ShowImagesDao.kt | 8 +++++ .../implementation/ShowImagesDaoImpl.kt | 32 +++++++++++++++---- 8 files changed, 85 insertions(+), 22 deletions(-) diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/episode_image.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/episode_image.sq index bfc4f7bc3..f8b3111fa 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/episode_image.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/episode_image.sq @@ -22,7 +22,9 @@ episodeImage: SELECT show.tmdb_id, season.season_number, - episode.episode_number + episode.id, + episode.episode_number, + episode_image.image_url FROM episode LEFT JOIN @@ -32,4 +34,10 @@ LEFT JOIN LEFT OUTER JOIN episode_image ON episode_image.id = episode.id WHERE - episode_image.image_url IS NULL; \ No newline at end of file + show.id = :showId AND episode_image.image_url IS NULL; + +delete: +DELETE FROM episode_image WHERE id = ?; + +deleteAll: +DELETE FROM episode_image; \ No newline at end of file diff --git a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show_image.sq b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show_image.sq index 7718f3ee4..fe7c3b00e 100644 --- a/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show_image.sq +++ b/core/database/src/commonMain/sqldelight/com/thomaskioko/tvmaniac/core/db/show_image.sq @@ -22,10 +22,18 @@ VALUES(?,?,?,?); emptyShowImage: SELECT show.id, - show.tmdb_id + show.tmdb_id, + show_image.poster_url, + show_image.backdrop_url FROM show LEFT OUTER JOIN show_image ON show_image.id = show.id WHERE - poster_url IS NULL AND backdrop_url IS NULL; \ No newline at end of file + poster_url IS NULL AND backdrop_url IS NULL; + +delete: +DELETE FROM show_image WHERE id = ?; + +deleteAll: +DELETE FROM show_image; \ No newline at end of file diff --git a/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageDao.kt b/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageDao.kt index 4b8e5889c..89cae219b 100644 --- a/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageDao.kt +++ b/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageDao.kt @@ -10,5 +10,11 @@ interface EpisodeImageDao { fun upsert(list: List) - fun observeEpisodeImage(): Flow> + fun observeEpisodeImage(showId: Long): Flow> + + fun getEpisodeImage(showId: Long): List + + fun delete(id: Long) + + fun deleteAll() } diff --git a/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageRepository.kt b/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageRepository.kt index c84c1e3c9..886c3e657 100644 --- a/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageRepository.kt +++ b/data/episodeimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/api/EpisodeImageRepository.kt @@ -6,5 +6,5 @@ import kotlinx.coroutines.flow.Flow interface EpisodeImageRepository { - fun updateEpisodeImage(): Flow> + fun updateEpisodeImage(traktId: Long): Flow> } diff --git a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageDaoImpl.kt b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageDaoImpl.kt index 16de93cd2..13b3dd320 100644 --- a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageDaoImpl.kt +++ b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageDaoImpl.kt @@ -5,6 +5,7 @@ import app.cash.sqldelight.coroutines.mapToList import com.thomaskioko.tvmaniac.core.db.EpisodeImage import com.thomaskioko.tvmaniac.core.db.Episode_image import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageDao import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers import kotlinx.coroutines.flow.Flow @@ -18,6 +19,12 @@ class EpisodeImageDaoImpl( private val episodeQueries get() = database.episode_imageQueries + override fun upsert(list: List) { + database.transaction { + list.forEach { upsert(it) } + } + } + override fun upsert(entity: Episode_image) { episodeQueries.insertOrReplace( id = entity.id, @@ -26,14 +33,20 @@ class EpisodeImageDaoImpl( ) } - override fun upsert(list: List) { - database.transaction { - list.map { upsert(it) } - } - } - - override fun observeEpisodeImage(): Flow> = - episodeQueries.episodeImage() + override fun observeEpisodeImage(showId: Long): Flow> = + episodeQueries.episodeImage(Id(showId)) .asFlow() .mapToList(dispatchers.io) + + override fun getEpisodeImage(showId: Long): List = + episodeQueries.episodeImage(Id(showId)) + .executeAsList() + + override fun delete(id: Long) { + episodeQueries.delete(Id(id)) + } + + override fun deleteAll() { + episodeQueries.deleteAll() + } } diff --git a/data/episodeimages/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/testing/FakeEpisodeImageRepository.kt b/data/episodeimages/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/testing/FakeEpisodeImageRepository.kt index cd04adb9a..84cbebc38 100644 --- a/data/episodeimages/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/testing/FakeEpisodeImageRepository.kt +++ b/data/episodeimages/testing/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodes/testing/FakeEpisodeImageRepository.kt @@ -8,5 +8,7 @@ import kotlinx.coroutines.flow.flowOf class FakeEpisodeImageRepository : EpisodeImageRepository { - override fun updateEpisodeImage(): Flow> = flowOf(Either.Right(Unit)) + override fun updateEpisodeImage( + traktId: Long, + ): Flow> = flowOf(Either.Right(Unit)) } diff --git a/data/showimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/api/ShowImagesDao.kt b/data/showimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/api/ShowImagesDao.kt index 26d59e7b4..164483c7e 100644 --- a/data/showimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/api/ShowImagesDao.kt +++ b/data/showimages/api/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/api/ShowImagesDao.kt @@ -6,7 +6,15 @@ import kotlinx.coroutines.flow.Flow interface ShowImagesDao { + fun upsert(images: List) + fun upsert(image: Show_image) fun observeShowImages(): Flow> + + fun fetchShowImages(): List + + fun delete(id: Long) + + fun deleteAll() } diff --git a/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesDaoImpl.kt b/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesDaoImpl.kt index ad1b7955d..2fa8a2759 100644 --- a/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesDaoImpl.kt +++ b/data/showimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/showimages/implementation/ShowImagesDaoImpl.kt @@ -5,6 +5,7 @@ import app.cash.sqldelight.coroutines.mapToList import com.thomaskioko.tvmaniac.core.db.EmptyShowImage import com.thomaskioko.tvmaniac.core.db.Show_image import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.showimages.api.ShowImagesDao import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers import kotlinx.coroutines.flow.Flow @@ -16,20 +17,37 @@ class ShowImagesDaoImpl( private val dispatchers: AppCoroutineDispatchers, ) : ShowImagesDao { - override fun upsert(image: Show_image) { + override fun upsert(images: List) { database.transaction { - database.show_imageQueries.insertOrReplace( - id = image.id, - tmdb_id = image.tmdb_id, - poster_url = image.poster_url, - backdrop_url = image.backdrop_url, - ) + images.forEach { upsert(it) } } } + override fun upsert(image: Show_image) { + database.show_imageQueries.insertOrReplace( + id = image.id, + tmdb_id = image.tmdb_id, + poster_url = image.poster_url, + backdrop_url = image.backdrop_url, + ) + } + override fun observeShowImages(): Flow> { return database.show_imageQueries.emptyShowImage() .asFlow() .mapToList(dispatchers.io) } + + override fun fetchShowImages(): List { + return database.show_imageQueries.emptyShowImage() + .executeAsList() + } + + override fun delete(id: Long) { + database.show_imageQueries.delete(Id(id)) + } + + override fun deleteAll() { + database.show_imageQueries.deleteAll() + } } From 829b49096efe9d248e35f4f670bf649743f235f2 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 19:58:35 +0100 Subject: [PATCH 24/38] Add season detail error state. --- .../presentation/seasondetails/SeasonDetailsState.kt | 1 + .../presentation/seasondetails/SeasonDetailsStateMachine.kt | 6 ++++-- .../data/seasondetails/SeasonDetailsStateMachineTest.kt | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsState.kt b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsState.kt index bd25a053e..184c48226 100644 --- a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsState.kt +++ b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsState.kt @@ -9,6 +9,7 @@ object Loading : SeasonDetailsState data class SeasonDetailsLoaded( val showTitle: String = "", val seasonDetailsList: List = emptyList(), + val errorMessage: String? = null, ) : SeasonDetailsState data class LoadingError(val message: String? = null) : SeasonDetailsState diff --git a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsStateMachine.kt b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsStateMachine.kt index 834b8db18..3d5c3caff 100644 --- a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsStateMachine.kt +++ b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsStateMachine.kt @@ -34,7 +34,9 @@ class SeasonDetailsStateMachine( collectWhileInState(seasonDetailsRepository.observeSeasonDetailsStream(traktId)) { result, state -> result.fold( { - state.override { LoadingError(it.errorMessage) } + state.mutate { + copy(errorMessage = it.errorMessage) + } }, { state.mutate { @@ -44,7 +46,7 @@ class SeasonDetailsStateMachine( ) } - collectWhileInStateEffect(episodeImageRepository.updateEpisodeImage()) { _, _ -> + collectWhileInStateEffect(episodeImageRepository.updateEpisodeImage(traktId)) { _, _ -> /** No need to do anything. Just trigger artwork download. **/ } } diff --git a/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt b/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt index 38b87549a..01f98cc37 100644 --- a/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt +++ b/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/SeasonDetailsStateMachineTest.kt @@ -3,7 +3,6 @@ package com.thomaskioko.tvmaniac.data.seasondetails import app.cash.turbine.test import com.thomaskioko.tvmaniac.episodes.testing.FakeEpisodeImageRepository import com.thomaskioko.tvmaniac.presentation.seasondetails.Loading -import com.thomaskioko.tvmaniac.presentation.seasondetails.LoadingError import com.thomaskioko.tvmaniac.presentation.seasondetails.SeasonDetailsStateMachine import com.thomaskioko.tvmaniac.seasondetails.testing.FakeSeasonDetailsRepository import com.thomaskioko.tvmaniac.seasondetails.testing.SeasonWithEpisodeList @@ -42,7 +41,8 @@ class SeasonDetailsStateMachineTest { awaitItem() shouldBe Loading awaitItem() shouldBe seasonDetailsLoaded - awaitItem() shouldBe LoadingError(errorMessage) + awaitItem() shouldBe seasonDetailsLoaded + .copy(errorMessage = errorMessage) } } } From c0d5e39f6b6d8b562482a6b3bb2dc5d48b1a6a20 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 20:05:31 +0100 Subject: [PATCH 25/38] Update dependencies. --- core/tmdb-api/implementation/build.gradle.kts | 1 + data/episodeimages/implementation/build.gradle.kts | 3 +++ data/showimages/implementation/build.gradle.kts | 2 ++ 3 files changed, 6 insertions(+) diff --git a/core/tmdb-api/implementation/build.gradle.kts b/core/tmdb-api/implementation/build.gradle.kts index 2244ed949..a3f1192a9 100644 --- a/core/tmdb-api/implementation/build.gradle.kts +++ b/core/tmdb-api/implementation/build.gradle.kts @@ -20,6 +20,7 @@ kotlin { implementation(libs.kotlinInject.runtime) implementation(libs.ktor.core) + implementation(libs.ktor.logging) implementation(libs.ktor.negotiation) implementation(libs.ktor.serialization.json) implementation(libs.sqldelight.extensions) diff --git a/data/episodeimages/implementation/build.gradle.kts b/data/episodeimages/implementation/build.gradle.kts index ddb8a4baf..7dac36ace 100644 --- a/data/episodeimages/implementation/build.gradle.kts +++ b/data/episodeimages/implementation/build.gradle.kts @@ -10,9 +10,12 @@ kotlin { dependencies { implementation(projects.core.tmdbApi.api) implementation(projects.data.episodeimages.api) + implementation(projects.data.requestManager.api) implementation(libs.kotlinInject.runtime) + implementation(libs.kotlinx.atomicfu) implementation(libs.sqldelight.extensions) + implementation(libs.store5) } } diff --git a/data/showimages/implementation/build.gradle.kts b/data/showimages/implementation/build.gradle.kts index 11b76c2e6..1285c1f04 100644 --- a/data/showimages/implementation/build.gradle.kts +++ b/data/showimages/implementation/build.gradle.kts @@ -14,7 +14,9 @@ kotlin { implementation(projects.core.tmdbApi.api) implementation(libs.kotlinInject.runtime) + implementation(libs.kotlinx.atomicfu) implementation(libs.sqldelight.extensions) + implementation(libs.store5) } } From 3f6967b99719b770f1c7d5c50f25e38e3b9142c3 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 20:16:09 +0100 Subject: [PATCH 26/38] Migrate season details and episodeImage to use Store5 --- .../EpisodeImageRepositoryImpl.kt | 75 +++++-------- .../implementation/EpisodeImageStore.kt | 94 ++++++++++++++++ .../SeasonDetailsRepositoryImpl.kt | 102 +++++++----------- 3 files changed, 156 insertions(+), 115 deletions(-) create mode 100644 data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageStore.kt diff --git a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt index 06fcb9ad0..fcbf7d916 100644 --- a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt +++ b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt @@ -1,63 +1,38 @@ package com.thomaskioko.tvmaniac.episodeimages.implementation -import com.thomaskioko.tvmaniac.core.db.Episode_image -import com.thomaskioko.tvmaniac.db.Id -import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageDao import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageRepository -import com.thomaskioko.tvmaniac.tmdb.api.TmdbNetworkDataSource -import com.thomaskioko.tvmaniac.util.FormatterUtil -import com.thomaskioko.tvmaniac.util.KermitLogger -import com.thomaskioko.tvmaniac.util.NetworkExceptionHandler -import com.thomaskioko.tvmaniac.util.model.ApiResponse -import com.thomaskioko.tvmaniac.util.model.DefaultError +import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository +import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers import com.thomaskioko.tvmaniac.util.model.Either import com.thomaskioko.tvmaniac.util.model.Failure +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.flowOn import me.tatarka.inject.annotations.Inject +import org.mobilenativefoundation.store.store5.StoreReadRequest +import kotlin.time.Duration.Companion.hours +@OptIn(ExperimentalCoroutinesApi::class) @Inject class EpisodeImageRepositoryImpl( - private val tmdbNetworkDataSource: TmdbNetworkDataSource, - private val episodeImageDao: EpisodeImageDao, - private val formatterUtil: FormatterUtil, - private val logger: KermitLogger, - private val exceptionHandler: NetworkExceptionHandler, + private val dispatchers: AppCoroutineDispatchers, + private val requestManagerRepository: RequestManagerRepository, + private val store: EpisodeImageStore, ) : EpisodeImageRepository { - override fun updateEpisodeImage(): Flow> = - episodeImageDao.observeEpisodeImage() - .map { episode -> - episode.forEach { episodeArt -> - episodeArt.tmdb_id?.let { tmdbId -> - val response = tmdbNetworkDataSource.getEpisodeDetails( - tmdbShow = tmdbId, - ssnNumber = episodeArt.season_number!!, - epNumber = episodeArt.episode_number.toLong(), - ) - - when (response) { - is ApiResponse.Success -> { - episodeImageDao.upsert( - Episode_image( - id = Id(id = response.body.id.toLong()), - tmdb_id = Id(id = tmdbId), - image_url = response.body.imageUrl?.let { - formatterUtil.formatTmdbPosterPath(it) - }, - ), - ) - } - - is ApiResponse.Error -> { - logger.error("updateEpisodeArtWork", "$response") - } - } - } - } - - Either.Right(Unit) - } - .catch { Either.Left(DefaultError(exceptionHandler.resolveError(it))) } + override fun updateEpisodeImage(traktId: Long): Flow> = + store.stream( + StoreReadRequest.cached( + key = traktId, + refresh = requestManagerRepository.isRequestExpired( + entityId = traktId, + requestType = "EPISODE_IMAGE", + threshold = 1.hours, + ), + ), + ) + .flatMapLatest { flowOf(Either.Right(Unit)) } + .flowOn(dispatchers.io) } diff --git a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageStore.kt b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageStore.kt new file mode 100644 index 000000000..05b40b00e --- /dev/null +++ b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageStore.kt @@ -0,0 +1,94 @@ +package com.thomaskioko.tvmaniac.episodeimages.implementation + +import com.thomaskioko.tvmaniac.core.db.EpisodeImage +import com.thomaskioko.tvmaniac.core.db.Episode_image +import com.thomaskioko.tvmaniac.db.DatabaseTransactionRunner +import com.thomaskioko.tvmaniac.db.Id +import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageDao +import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository +import com.thomaskioko.tvmaniac.tmdb.api.TmdbNetworkDataSource +import com.thomaskioko.tvmaniac.util.FormatterUtil +import com.thomaskioko.tvmaniac.util.KermitLogger +import com.thomaskioko.tvmaniac.util.model.ApiResponse +import com.thomaskioko.tvmaniac.util.model.AppCoroutineScope +import me.tatarka.inject.annotations.Inject +import org.mobilenativefoundation.store.store5.Fetcher +import org.mobilenativefoundation.store.store5.SourceOfTruth +import org.mobilenativefoundation.store.store5.Store +import org.mobilenativefoundation.store.store5.StoreBuilder +import org.mobilenativefoundation.store.store5.Validator +import kotlin.time.Duration.Companion.days +import kotlin.time.Duration.Companion.hours + +@Inject +class EpisodeImageStore( + private val tmdbNetworkDataSource: TmdbNetworkDataSource, + private val episodeImageDao: EpisodeImageDao, + private val requestManagerRepository: RequestManagerRepository, + private val dbTransactionRunner: DatabaseTransactionRunner, + private val formatterUtil: FormatterUtil, + private val logger: KermitLogger, + private val scope: AppCoroutineScope, +) : Store> by StoreBuilder.from( + fetcher = Fetcher.of { id -> + + episodeImageDao.getEpisodeImage(id) + .filter { it.tmdb_id != null && it.image_url == null } + .map { episodeArt -> + val apiResponse = tmdbNetworkDataSource.getEpisodeDetails( + tmdbShow = episodeArt.tmdb_id!!, + ssnNumber = episodeArt.season_number!!, + epNumber = episodeArt.episode_number.toLong(), + ) + + when (apiResponse) { + is ApiResponse.Success -> { + Episode_image( + id = Id(id = episodeArt.id.id), + tmdb_id = Id(id = episodeArt.tmdb_id!!), + image_url = apiResponse.body.imageUrl?.let { + formatterUtil.formatTmdbPosterPath(it) + }, + ) + } + + is ApiResponse.Error -> { + logger.error("EpisodeImageStore", "$apiResponse") + throw Throwable("$apiResponse") + } + } + } + }, + sourceOfTruth = SourceOfTruth.of( + reader = { id -> episodeImageDao.observeEpisodeImage(id) }, + writer = { _, imageList -> + dbTransactionRunner { + episodeImageDao.upsert(imageList) + } + }, + delete = episodeImageDao::delete, + deleteAll = { dbTransactionRunner(episodeImageDao::deleteAll) }, + ), +).validator( + Validator.by { result -> + if (result.isNotEmpty()) { + requestManagerRepository.isRequestExpired( + entityId = result.first().tmdb_id!!, + requestType = "EPISODE_IMAGE", + threshold = 180.days, + ) + } else { + result.firstOrNull()?.tmdb_id?.let { + requestManagerRepository.isRequestExpired( + entityId = it, + requestType = "EPISODE_IMAGE", + threshold = 1.hours, + ) + } ?: run { + true + } + } + }, +) + .scope(scope.io) + .build() diff --git a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsRepositoryImpl.kt b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsRepositoryImpl.kt index 63a59a3cf..ff4590c11 100644 --- a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsRepositoryImpl.kt +++ b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsRepositoryImpl.kt @@ -1,83 +1,55 @@ package com.thomaskioko.tvmaniac.seasondetails.implementation -import com.thomaskioko.tvmaniac.core.db.Season import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById -import com.thomaskioko.tvmaniac.core.networkutil.ApiResponse -import com.thomaskioko.tvmaniac.core.networkutil.Either -import com.thomaskioko.tvmaniac.core.networkutil.Failure -import com.thomaskioko.tvmaniac.core.networkutil.NetworkExceptionHandler -import com.thomaskioko.tvmaniac.core.networkutil.networkBoundResult -import com.thomaskioko.tvmaniac.db.Id -import com.thomaskioko.tvmaniac.episodes.api.EpisodesDao +import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.seasondetails.api.SeasonDetailsRepository -import com.thomaskioko.tvmaniac.seasons.api.SeasonsDao -import com.thomaskioko.tvmaniac.trakt.api.TraktShowsRemoteDataSource -import com.thomaskioko.tvmaniac.trakt.api.model.ErrorResponse -import com.thomaskioko.tvmaniac.trakt.api.model.TraktSeasonEpisodesResponse -import com.thomaskioko.tvmaniac.util.KermitLogger import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers +import com.thomaskioko.tvmaniac.util.model.Either +import com.thomaskioko.tvmaniac.util.model.Failure +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.flowOn import me.tatarka.inject.annotations.Inject +import org.mobilenativefoundation.store.store5.StoreReadRequest +import org.mobilenativefoundation.store.store5.impl.extensions.get +import kotlin.time.Duration.Companion.days +@OptIn(ExperimentalCoroutinesApi::class) @Inject class SeasonDetailsRepositoryImpl( - private val remoteDataSource: TraktShowsRemoteDataSource, - private val seasonCache: SeasonsDao, - private val episodesDao: EpisodesDao, - private val exceptionHandler: NetworkExceptionHandler, + private val seasonDetailsStore: SeasonDetailsStore, + private val requestManagerRepository: RequestManagerRepository, private val dispatcher: AppCoroutineDispatchers, - private val logger: KermitLogger, ) : SeasonDetailsRepository { - override fun observeSeasonDetailsStream(traktId: Long): Flow>> = - networkBoundResult( - query = { seasonCache.observeSeasonEpisodeDetailsById(traktId) }, - shouldFetch = { it.isNullOrEmpty() }, - fetch = { remoteDataSource.getSeasonEpisodes(traktId) }, - saveFetchResult = { mapResponse(traktId, it) }, - exceptionHandler = exceptionHandler, - coroutineDispatcher = dispatcher.io, + override fun observeSeasonDetailsStream( + traktId: Long, + ): Flow>> = + seasonDetailsStore.stream( + StoreReadRequest.cached( + key = traktId, + refresh = requestManagerRepository.isRequestExpired( + entityId = traktId, + requestType = "SEASON_DETAILS", + threshold = 3.days, + ), + ), ) - - override suspend fun fetchSeasonDetails(traktId: Long): List = - seasonCache.fetchSeasonDetails(traktId) - - private fun mapResponse( - showId: Long, - response: ApiResponse, ErrorResponse>, - ) { - when (response) { - is ApiResponse.Success -> { - response.body.forEach { season -> - episodesDao.insert(season.toEpisodeCacheList()) - - seasonCache.upsert( - Season( - id = Id(season.ids.trakt.toLong()), - show_id = Id(showId), - season_number = season.number.toLong(), - title = season.title, - episode_count = season.episodeCount.toLong(), - overview = season.overview, - ), - ) + .distinctUntilChanged() + .flatMapLatest { + val data = it.dataOrNull() + if (data != null) { + flowOf(Either.Right(data)) + } else { + emptyFlow() } } + .flowOn(dispatcher.io) - is ApiResponse.Error.GenericError -> { - logger.error("observeSeasonDetails", "$response") - throw Throwable("${response.errorMessage}") - } - - is ApiResponse.Error.HttpError -> { - logger.error("observeSeasonDetails", "$response") - throw Throwable("${response.code} - ${response.errorMessage}") - } - - is ApiResponse.Error.SerializationError -> { - logger.error("observeSeasonDetails", "${response.errorMessage}") - throw Throwable("${response.errorMessage}") - } - } - } + override suspend fun fetchSeasonDetails(traktId: Long): List = + seasonDetailsStore.get(traktId) } From 200ad301ee40327c55046070fa687bc4bcfb302c Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 20:23:17 +0100 Subject: [PATCH 27/38] Move image call to combine block --- .../tvmaniac/presentation/discover/DiscoverStateMachine.kt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachine.kt b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachine.kt index 7d5a8bd02..8628a9d4a 100644 --- a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachine.kt +++ b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachine.kt @@ -40,10 +40,6 @@ class DiscoverStateMachine( } } - collectWhileInStateEffect(showImagesRepository.updateShowArtWork()) { _, _ -> - /** No need to do anything. Just trigger artwork download. **/ - } - on { _, state -> // TODO:: Implement reloading category data state.noChange() @@ -86,7 +82,8 @@ class DiscoverStateMachine( discoverRepository.observeShowCategory(Category.POPULAR), discoverRepository.observeShowCategory(Category.ANTICIPATED), discoverRepository.observeShowCategory(Category.RECOMMENDED), - ) { trending, popular, anticipated, recommended -> + showImagesRepository.updateShowArtWork(), + ) { trending, popular, anticipated, recommended, _-> DataLoaded( trendingShows = trending.getOrNull().toTvShowList(), popularShows = popular.getOrNull().toTvShowList(), From b45595c99367fa4043a781d74717b976cf66f25c Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Sun, 19 Nov 2023 20:36:41 +0100 Subject: [PATCH 28/38] Male spotless happy --- .../tvmaniac/presentation/discover/DiscoverStateMachine.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachine.kt b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachine.kt index 8628a9d4a..e9eb1fac5 100644 --- a/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachine.kt +++ b/presentation/discover/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/discover/DiscoverStateMachine.kt @@ -83,7 +83,7 @@ class DiscoverStateMachine( discoverRepository.observeShowCategory(Category.ANTICIPATED), discoverRepository.observeShowCategory(Category.RECOMMENDED), showImagesRepository.updateShowArtWork(), - ) { trending, popular, anticipated, recommended, _-> + ) { trending, popular, anticipated, recommended, _ -> DataLoaded( trendingShows = trending.getOrNull().toTvShowList(), popularShows = popular.getOrNull().toTvShowList(), From 5d15fa04f00ccf753bd7d175eebc605976ff41c1 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Tue, 21 Nov 2023 19:03:34 +0100 Subject: [PATCH 29/38] Update logger to info. --- .../thomaskioko/tvmaniac/tmdb/implementation/TmdbClient.kt | 4 ++-- .../trakt/service/implementation/TraktHttpClient.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbClient.kt b/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbClient.kt index 168135818..b8ac6d96e 100644 --- a/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbClient.kt +++ b/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbClient.kt @@ -52,11 +52,11 @@ fun tmdbHttpClient( } install(Logging) { - level = LogLevel.BODY + level = LogLevel.INFO logger = if (isDebug) { object : Logger { override fun log(message: String) { - kermitLogger.debug(message) + kermitLogger.info("TmbdHttp", message) } } } else { diff --git a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktHttpClient.kt b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktHttpClient.kt index 7cd4e27c3..056487169 100644 --- a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktHttpClient.kt +++ b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/TraktHttpClient.kt @@ -87,7 +87,7 @@ fun traktHttpClient( logger = if (isDebug) { object : Logger { override fun log(message: String) { - kermitLogger.debug(message) + kermitLogger.info("TraktHttp", message) } } } else { From 1cb61cc91fb7454c3d5c1dd66c6acc9200a3bebb Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Tue, 21 Nov 2023 19:08:27 +0100 Subject: [PATCH 30/38] Wrap write function in db transaction. --- .../implementation/SeasonDetailsStore.kt | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsStore.kt b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsStore.kt index ff39ad426..d8f961290 100644 --- a/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsStore.kt +++ b/data/seasondetails/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/seasondetails/implementation/SeasonDetailsStore.kt @@ -2,6 +2,7 @@ package com.thomaskioko.tvmaniac.seasondetails.implementation import com.thomaskioko.tvmaniac.core.db.Season import com.thomaskioko.tvmaniac.core.db.SeasonEpisodeDetailsById +import com.thomaskioko.tvmaniac.db.DbTransactionRunner import com.thomaskioko.tvmaniac.db.Id import com.thomaskioko.tvmaniac.episodes.api.EpisodesDao import com.thomaskioko.tvmaniac.seasons.api.SeasonsDao @@ -21,6 +22,7 @@ class SeasonDetailsStore( private val seasonCache: SeasonsDao, private val episodesDao: EpisodesDao, private val scope: AppCoroutineScope, + private val dbTransactionRunner: DbTransactionRunner, private val logger: KermitLogger, ) : Store> by StoreBuilder .from( @@ -46,19 +48,21 @@ class SeasonDetailsStore( sourceOfTruth = SourceOfTruth.of( reader = seasonCache::observeSeasonEpisodeDetailsById, writer = { id, list -> - list.forEach { season -> - seasonCache.upsert( - Season( - id = Id(season.seasonId), - show_id = Id(id), - season_number = season.seasonNumber, - title = season.title, - episode_count = season.episodeCount, - overview = season.overview, - ), - ) + dbTransactionRunner { + list.forEach { season -> + seasonCache.upsert( + Season( + id = Id(season.seasonId), + show_id = Id(id), + season_number = season.seasonNumber, + title = season.title, + episode_count = season.episodeCount, + overview = season.overview, + ), + ) - episodesDao.insert(season.episodes) + episodesDao.insert(season.episodes) + } } }, delete = seasonCache::delete, From 8a97d454d33fcc8023aea510fb79571305ea8bfe Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Tue, 21 Nov 2023 19:09:42 +0100 Subject: [PATCH 31/38] Fix images not loading on the first call. --- .../EpisodeImageRepositoryImpl.kt | 25 +++++++++++-------- .../implementation/EpisodeImageStore.kt | 1 - 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt index fcbf7d916..441bd3eda 100644 --- a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt +++ b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageRepositoryImpl.kt @@ -1,5 +1,6 @@ package com.thomaskioko.tvmaniac.episodeimages.implementation +import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageDao import com.thomaskioko.tvmaniac.episodeimages.api.EpisodeImageRepository import com.thomaskioko.tvmaniac.resourcemanager.api.RequestManagerRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineDispatchers @@ -20,19 +21,23 @@ class EpisodeImageRepositoryImpl( private val dispatchers: AppCoroutineDispatchers, private val requestManagerRepository: RequestManagerRepository, private val store: EpisodeImageStore, + private val episodeImageDao: EpisodeImageDao, ) : EpisodeImageRepository { override fun updateEpisodeImage(traktId: Long): Flow> = - store.stream( - StoreReadRequest.cached( - key = traktId, - refresh = requestManagerRepository.isRequestExpired( - entityId = traktId, - requestType = "EPISODE_IMAGE", - threshold = 1.hours, - ), - ), - ) + episodeImageDao.observeEpisodeImage(traktId) + .flatMapLatest { + store.stream( + StoreReadRequest.cached( + key = traktId, + refresh = requestManagerRepository.isRequestExpired( + entityId = traktId, + requestType = "EPISODE_IMAGE", + threshold = 1.hours, + ), + ), + ) + } .flatMapLatest { flowOf(Either.Right(Unit)) } .flowOn(dispatchers.io) } diff --git a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageStore.kt b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageStore.kt index 05b40b00e..27c9fd74a 100644 --- a/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageStore.kt +++ b/data/episodeimages/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/episodeimages/implementation/EpisodeImageStore.kt @@ -31,7 +31,6 @@ class EpisodeImageStore( private val scope: AppCoroutineScope, ) : Store> by StoreBuilder.from( fetcher = Fetcher.of { id -> - episodeImageDao.getEpisodeImage(id) .filter { it.tmdb_id != null && it.image_url == null } .map { episodeArt -> From 07ecfa2ef0fb47f850df13ad40aecc66e66fcca0 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Wed, 22 Nov 2023 13:20:31 +0100 Subject: [PATCH 32/38] Add material shapes --- .../com/thomaskioko/tvmaniac/compose/theme/Shape.kt | 11 +++++++++++ .../com/thomaskioko/tvmaniac/compose/theme/Theme.kt | 1 + 2 files changed, 12 insertions(+) create mode 100644 android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/theme/Shape.kt diff --git a/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/theme/Shape.kt b/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/theme/Shape.kt new file mode 100644 index 000000000..f8bd01058 --- /dev/null +++ b/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/theme/Shape.kt @@ -0,0 +1,11 @@ +package com.thomaskioko.tvmaniac.compose.theme + +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Shapes +import androidx.compose.ui.unit.dp + +val tvManiacShapes = Shapes( + small = RoundedCornerShape(4.dp), + medium = RoundedCornerShape(8.dp), + large = RoundedCornerShape(16.dp) +) diff --git a/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/theme/Theme.kt b/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/theme/Theme.kt index a949932c5..398d8ae47 100644 --- a/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/theme/Theme.kt +++ b/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/theme/Theme.kt @@ -54,6 +54,7 @@ fun TvManiacTheme( MaterialTheme( colorScheme = colorScheme, typography = tvManiacTypography, + shapes = tvManiacShapes, content = content, ) } From 6026d7bb78a130cc0eed06bad9b012eb1ff28c64 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Wed, 22 Nov 2023 13:31:39 +0100 Subject: [PATCH 33/38] Minor cleanup: Implement material shapes and animate content --- .../com/thomaskioko/tvmaniac/compose/components/Buttons.kt | 3 +-- .../com/thomaskioko/tvmaniac/compose/components/Card.kt | 5 +++-- .../com/thomaskioko/tvmaniac/compose/components/Dialogs.kt | 3 +-- .../kotlin/com/thomaskioko/tvmaniac/compose/theme/Shape.kt | 2 +- .../java/com/thomaskioko/tvmaniac/discover/DiscoverScreen.kt | 4 +++- .../kotlin/com/thomaskioko/showdetails/ShowDetailScreen.kt | 5 ++++- .../com/thomaskioko/tvmaniac/watchlist/WatchlistScreen.kt | 4 ++++ 7 files changed, 17 insertions(+), 9 deletions(-) diff --git a/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/components/Buttons.kt b/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/components/Buttons.kt index f37d9c332..d881c10da 100644 --- a/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/components/Buttons.kt +++ b/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/components/Buttons.kt @@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.sizeIn -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ButtonColors import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme @@ -93,7 +92,7 @@ fun TvManiacOutlinedButton( borderColor: Color, modifier: Modifier = Modifier, enabled: Boolean = true, - shape: Shape = RoundedCornerShape(4.dp), + shape: Shape = MaterialTheme.shapes.small, contentPadding: PaddingValues = ButtonDefaults.ContentPadding, content: @Composable RowScope.() -> Unit, ) { diff --git a/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/components/Card.kt b/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/components/Card.kt index 2dd7640c4..1cd86ba95 100644 --- a/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/components/Card.kt +++ b/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/components/Card.kt @@ -14,7 +14,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.graphics.Shape import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.Dp @@ -26,6 +26,7 @@ fun TvPosterCard( posterImageUrl: String?, title: String, modifier: Modifier = Modifier, + shape: Shape = MaterialTheme.shapes.small, imageWidth: Dp = 120.dp, onClick: () -> Unit = {}, ) { @@ -33,7 +34,7 @@ fun TvPosterCard( modifier = modifier .width(imageWidth) .clickable { onClick() }, - shape = RectangleShape, + shape = shape, elevation = CardDefaults.cardElevation( defaultElevation = 4.dp, ), diff --git a/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/components/Dialogs.kt b/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/components/Dialogs.kt index c46fdf376..0564f8365 100644 --- a/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/components/Dialogs.kt +++ b/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/components/Dialogs.kt @@ -9,7 +9,6 @@ import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.Shape import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.unit.dp @@ -24,7 +23,7 @@ fun BasicDialog( enableConfirmButton: Boolean = true, enableDismissButton: Boolean = true, dismissButtonText: String? = null, - shape: Shape = RectangleShape, + shape: Shape = MaterialTheme.shapes.small, onDismissDialog: () -> Unit = {}, confirmButtonClicked: () -> Unit = {}, dismissButtonClicked: () -> Unit = {}, diff --git a/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/theme/Shape.kt b/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/theme/Shape.kt index f8bd01058..6e386334c 100644 --- a/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/theme/Shape.kt +++ b/android-core/designsystem/src/main/kotlin/com/thomaskioko/tvmaniac/compose/theme/Shape.kt @@ -7,5 +7,5 @@ import androidx.compose.ui.unit.dp val tvManiacShapes = Shapes( small = RoundedCornerShape(4.dp), medium = RoundedCornerShape(8.dp), - large = RoundedCornerShape(16.dp) + large = RoundedCornerShape(16.dp), ) diff --git a/android-features/discover/src/main/java/com/thomaskioko/tvmaniac/discover/DiscoverScreen.kt b/android-features/discover/src/main/java/com/thomaskioko/tvmaniac/discover/DiscoverScreen.kt index 10f919358..02f532554 100644 --- a/android-features/discover/src/main/java/com/thomaskioko/tvmaniac/discover/DiscoverScreen.kt +++ b/android-features/discover/src/main/java/com/thomaskioko/tvmaniac/discover/DiscoverScreen.kt @@ -417,7 +417,7 @@ fun HorizontalPagerItem( } } -@OptIn(ExperimentalSnapperApi::class) +@OptIn(ExperimentalSnapperApi::class, ExperimentalFoundationApi::class) @Composable private fun RowContent( category: Category, @@ -449,6 +449,8 @@ private fun RowContent( posterImageUrl = tvShow.posterImageUrl, title = tvShow.title, onClick = { onItemClicked(tvShow.traktId) }, + modifier = Modifier + .animateItemPlacement(), ) } } diff --git a/android-features/show-details/src/main/kotlin/com/thomaskioko/showdetails/ShowDetailScreen.kt b/android-features/show-details/src/main/kotlin/com/thomaskioko/showdetails/ShowDetailScreen.kt index 2b7f07cc2..c9ad89deb 100644 --- a/android-features/show-details/src/main/kotlin/com/thomaskioko/showdetails/ShowDetailScreen.kt +++ b/android-features/show-details/src/main/kotlin/com/thomaskioko/showdetails/ShowDetailScreen.kt @@ -1,6 +1,7 @@ package com.thomaskioko.showdetails import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -670,7 +671,7 @@ private fun TrailersContent( } } -@OptIn(ExperimentalSnapperApi::class) +@OptIn(ExperimentalSnapperApi::class, ExperimentalFoundationApi::class) @Composable fun SimilarShowsContent( isLoading: Boolean, @@ -696,6 +697,8 @@ fun SimilarShowsContent( Spacer(modifier = Modifier.width(value.dp)) TvPosterCard( + modifier = Modifier + .animateItemPlacement(), posterImageUrl = tvShow.posterImageUrl, title = tvShow.title, onClick = { onShowClicked(tvShow.traktId) }, diff --git a/android-features/watchlist/src/main/kotlin/com/thomaskioko/tvmaniac/watchlist/WatchlistScreen.kt b/android-features/watchlist/src/main/kotlin/com/thomaskioko/tvmaniac/watchlist/WatchlistScreen.kt index 448dcaba9..b4db906cb 100644 --- a/android-features/watchlist/src/main/kotlin/com/thomaskioko/tvmaniac/watchlist/WatchlistScreen.kt +++ b/android-features/watchlist/src/main/kotlin/com/thomaskioko/tvmaniac/watchlist/WatchlistScreen.kt @@ -1,5 +1,6 @@ package com.thomaskioko.tvmaniac.watchlist +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.statusBarsPadding @@ -113,6 +114,7 @@ private fun WatchlistScreen( ) } +@OptIn(ExperimentalFoundationApi::class) @Composable private fun FollowingGridContent( list: List, @@ -128,6 +130,8 @@ private fun FollowingGridContent( ) { show -> TvPosterCard( + modifier = Modifier + .animateItemPlacement(), posterImageUrl = show.posterImageUrl, title = show.title, onClick = { onItemClicked(show.traktId) }, From 2b03b5870b498b1f00c2dde0f173b24a8dc243a1 Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Wed, 22 Nov 2023 17:20:12 +0100 Subject: [PATCH 34/38] Cleanup platform component implementation. --- .../tvmaniac/inject/ApplicationComponent.kt | 8 +- .../tvmaniac/db/DatabaseComponent.kt | 81 ------------------- .../tvmaniac/db/DatabasePlatformComponent.kt | 31 +++++++ .../DatabaseComponent.kt | 3 - .../DatabasePlatformComponent.kt} | 15 ++-- .../tvmaniac/db/DatabasePlatformComponent.kt | 25 ++++++ .../tvmaniac/db/DatabaseComponent.kt | 3 - .../tvmaniac/db/DatabasePlatformComponent.kt | 3 + .../DataStorePlatformComponent.kt | 3 - .../DataStorePlatformComponent.kt | 12 +++ .../DataStorePlatformComponent.kt | 3 - .../implementation/TmdbPlatformComponent.kt | 2 +- .../tmdb/implementation/TmdbComponent.kt | 4 +- .../implementation/TmdbPlatformComponent.kt | 2 +- .../implementation/TmdbPlatformComponent.kt | 2 +- .../implementation/inject/TraktComponent.kt | 2 +- .../base/ApplicationComponent.kt | 8 +- 17 files changed, 91 insertions(+), 116 deletions(-) delete mode 100644 core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt create mode 100644 core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt delete mode 100644 core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabaseComponent.kt rename core/database/src/{iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt => commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabasePlatformComponent.kt} (91%) create mode 100644 core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt delete mode 100644 core/database/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt create mode 100644 core/database/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt diff --git a/app/src/main/kotlin/com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt b/app/src/main/kotlin/com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt index e18516b79..1c2518ed5 100644 --- a/app/src/main/kotlin/com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt +++ b/app/src/main/kotlin/com/thomaskioko/tvmaniac/inject/ApplicationComponent.kt @@ -3,11 +3,10 @@ package com.thomaskioko.tvmaniac.inject import android.app.Application import android.content.Context import com.thomaskioko.trakt.service.implementation.inject.TraktComponent -import com.thomaskioko.trakt.service.implementation.inject.TraktPlatformComponent import com.thomaskioko.tvmaniac.TvManicApplication import com.thomaskioko.tvmaniac.data.category.implementation.CategoryComponent import com.thomaskioko.tvmaniac.data.trailers.implementation.TrailerComponent -import com.thomaskioko.tvmaniac.datastore.implementation.DataStorePlatformComponent +import com.thomaskioko.tvmaniac.datastore.implementation.DataStoreComponent import com.thomaskioko.tvmaniac.db.DatabaseComponent import com.thomaskioko.tvmaniac.episodeimages.implementation.EpisodeImageComponent import com.thomaskioko.tvmaniac.episodes.implementation.EpisodeComponent @@ -21,7 +20,6 @@ import com.thomaskioko.tvmaniac.showimages.implementation.ShowImagesComponent import com.thomaskioko.tvmaniac.shows.implementation.DiscoverComponent import com.thomaskioko.tvmaniac.similar.implementation.SimilarShowsComponent import com.thomaskioko.tvmaniac.tmdb.implementation.TmdbComponent -import com.thomaskioko.tvmaniac.tmdb.implementation.TmdbPlatformComponent import com.thomaskioko.tvmaniac.traktauth.implementation.TraktAuthComponent import com.thomaskioko.tvmaniac.traktauth.implementation.TraktAuthenticationComponent import com.thomaskioko.tvmaniac.util.inject.UtilPlatformComponent @@ -39,7 +37,7 @@ abstract class ApplicationComponent( ) : UtilPlatformComponent, CategoryComponent, DatabaseComponent, - DataStorePlatformComponent, + DataStoreComponent, EpisodeComponent, EpisodeImageComponent, WatchlistComponent, @@ -54,9 +52,7 @@ abstract class ApplicationComponent( StatsComponent, TasksComponent, TmdbComponent, - TmdbPlatformComponent, TraktComponent, - TraktPlatformComponent, TrailerComponent, TraktAuthComponent, TraktAuthenticationComponent { diff --git a/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt b/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt deleted file mode 100644 index 174189203..000000000 --- a/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.thomaskioko.tvmaniac.db - -import android.app.Application -import app.cash.sqldelight.db.SqlDriver -import app.cash.sqldelight.driver.android.AndroidSqliteDriver -import com.thomaskioko.tvmaniac.core.db.Episode -import com.thomaskioko.tvmaniac.core.db.Episode_image -import com.thomaskioko.tvmaniac.core.db.Last_requests -import com.thomaskioko.tvmaniac.core.db.Season -import com.thomaskioko.tvmaniac.core.db.Show -import com.thomaskioko.tvmaniac.core.db.Show_category -import com.thomaskioko.tvmaniac.core.db.Show_image -import com.thomaskioko.tvmaniac.core.db.Similar_shows -import com.thomaskioko.tvmaniac.core.db.Trailers -import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase -import com.thomaskioko.tvmaniac.core.db.Watchlist -import com.thomaskioko.tvmaniac.util.scope.ApplicationScope -import me.tatarka.inject.annotations.Provides - -actual interface DatabaseComponent { - - @ApplicationScope - @Provides - fun provideSqlDriver( - application: Application, - ): SqlDriver = AndroidSqliteDriver( - schema = TvManiacDatabase.Schema, - context = application, - name = "tvShows.db", - ) - - @ApplicationScope - @Provides - fun provideTvManiacDatabase( - sqlDriver: SqlDriver, - ): TvManiacDatabase = TvManiacDatabase( - driver = sqlDriver, - showAdapter = Show.Adapter( - genresAdapter = stringColumnAdapter, - idAdapter = IdAdapter(), - ), - last_requestsAdapter = Last_requests.Adapter( - timestampAdapter = InstantColumnAdapter, - ), - episode_imageAdapter = Episode_image.Adapter( - idAdapter = IdAdapter(), - tmdb_idAdapter = IdAdapter(), - ), - episodeAdapter = Episode.Adapter( - idAdapter = IdAdapter(), - season_idAdapter = IdAdapter(), - ), - seasonAdapter = Season.Adapter( - idAdapter = IdAdapter(), - show_idAdapter = IdAdapter(), - ), - show_imageAdapter = Show_image.Adapter( - idAdapter = IdAdapter(), - ), - similar_showsAdapter = Similar_shows.Adapter( - idAdapter = IdAdapter(), - similar_show_idAdapter = IdAdapter(), - ), - watchlistAdapter = Watchlist.Adapter( - idAdapter = IdAdapter(), - ), - show_categoryAdapter = Show_category.Adapter( - idAdapter = IdAdapter(), - category_idAdapter = IdAdapter(), - ), - trailersAdapter = Trailers.Adapter( - show_idAdapter = IdAdapter(), - ), - ) - - @ApplicationScope - @Provides - fun provideDbTransactionRunner( - bind: DbTransactionRunner, - ): DatabaseTransactionRunner = bind -} diff --git a/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt b/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt new file mode 100644 index 000000000..fd439842e --- /dev/null +++ b/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt @@ -0,0 +1,31 @@ +package com.thomaskioko.tvmaniac.db + +import android.app.Application +import app.cash.sqldelight.db.SqlDriver +import app.cash.sqldelight.driver.android.AndroidSqliteDriver +import com.thomaskioko.tvmaniac.core.db.Episode +import com.thomaskioko.tvmaniac.core.db.Episode_image +import com.thomaskioko.tvmaniac.core.db.Last_requests +import com.thomaskioko.tvmaniac.core.db.Season +import com.thomaskioko.tvmaniac.core.db.Show +import com.thomaskioko.tvmaniac.core.db.Show_category +import com.thomaskioko.tvmaniac.core.db.Show_image +import com.thomaskioko.tvmaniac.core.db.Similar_shows +import com.thomaskioko.tvmaniac.core.db.Trailers +import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import com.thomaskioko.tvmaniac.core.db.Watchlist +import com.thomaskioko.tvmaniac.util.scope.ApplicationScope +import me.tatarka.inject.annotations.Provides + +actual interface DatabasePlatformComponent { + + @ApplicationScope + @Provides + fun provideSqlDriver( + application: Application, + ): SqlDriver = AndroidSqliteDriver( + schema = TvManiacDatabase.Schema, + context = application, + name = "tvShows.db", + ) +} diff --git a/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabaseComponent.kt b/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabaseComponent.kt deleted file mode 100644 index 10b34033d..000000000 --- a/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabaseComponent.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.thomaskioko.tvmaniac.db - -expect interface DatabaseComponent diff --git a/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt b/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabasePlatformComponent.kt similarity index 91% rename from core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt rename to core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabasePlatformComponent.kt index ff47263d0..cb326e14e 100644 --- a/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt +++ b/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabasePlatformComponent.kt @@ -1,7 +1,6 @@ package com.thomaskioko.tvmaniac.db import app.cash.sqldelight.db.SqlDriver -import app.cash.sqldelight.driver.native.NativeSqliteDriver import com.thomaskioko.tvmaniac.core.db.Episode import com.thomaskioko.tvmaniac.core.db.Episode_image import com.thomaskioko.tvmaniac.core.db.Last_requests @@ -16,12 +15,10 @@ import com.thomaskioko.tvmaniac.core.db.Watchlist import com.thomaskioko.tvmaniac.util.scope.ApplicationScope import me.tatarka.inject.annotations.Provides -actual interface DatabaseComponent { +expect interface DatabasePlatformComponent - @ApplicationScope - @Provides - fun provideSqlDriver(): SqlDriver = NativeSqliteDriver(TvManiacDatabase.Schema, "tvShows.db") +interface DatabaseComponent : DatabasePlatformComponent { @ApplicationScope @Provides fun provideTvManiacDatabase( @@ -65,4 +62,10 @@ actual interface DatabaseComponent { show_idAdapter = IdAdapter(), ), ) -} + + @ApplicationScope + @Provides + fun provideDbTransactionRunner( + bind: DbTransactionRunner, + ): DatabaseTransactionRunner = bind +} \ No newline at end of file diff --git a/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt b/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt new file mode 100644 index 000000000..f94ce7104 --- /dev/null +++ b/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt @@ -0,0 +1,25 @@ +package com.thomaskioko.tvmaniac.db + +import app.cash.sqldelight.db.SqlDriver +import app.cash.sqldelight.driver.native.NativeSqliteDriver +import com.thomaskioko.tvmaniac.core.db.Episode +import com.thomaskioko.tvmaniac.core.db.Episode_image +import com.thomaskioko.tvmaniac.core.db.Last_requests +import com.thomaskioko.tvmaniac.core.db.Season +import com.thomaskioko.tvmaniac.core.db.Show +import com.thomaskioko.tvmaniac.core.db.Show_category +import com.thomaskioko.tvmaniac.core.db.Show_image +import com.thomaskioko.tvmaniac.core.db.Similar_shows +import com.thomaskioko.tvmaniac.core.db.Trailers +import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase +import com.thomaskioko.tvmaniac.core.db.Watchlist +import com.thomaskioko.tvmaniac.util.scope.ApplicationScope +import me.tatarka.inject.annotations.Provides + +actual interface DatabasePlatformComponent { + + @ApplicationScope + @Provides + fun provideSqlDriver(): SqlDriver = NativeSqliteDriver(TvManiacDatabase.Schema, "tvShows.db") + +} diff --git a/core/database/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt b/core/database/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt deleted file mode 100644 index 312227327..000000000 --- a/core/database/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/db/DatabaseComponent.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.thomaskioko.tvmaniac.db - -actual interface DatabaseComponent diff --git a/core/database/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt b/core/database/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt new file mode 100644 index 000000000..952dcb6ec --- /dev/null +++ b/core/database/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt @@ -0,0 +1,3 @@ +package com.thomaskioko.tvmaniac.db + +actual interface DatabasePlatformComponent diff --git a/core/datastore/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt b/core/datastore/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt index dab2f748c..d46cd4846 100644 --- a/core/datastore/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt +++ b/core/datastore/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt @@ -20,7 +20,4 @@ actual interface DataStorePlatformComponent { producePath = { context.filesDir.resolve(dataStoreFileName).absolutePath }, ) - @ApplicationScope - @Provides - fun provideDatastoreRepository(bind: DatastoreRepositoryImpl): DatastoreRepository = bind } diff --git a/core/datastore/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt b/core/datastore/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt index 09e6ef4be..220c676e2 100644 --- a/core/datastore/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt +++ b/core/datastore/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt @@ -1,3 +1,15 @@ package com.thomaskioko.tvmaniac.datastore.implementation +import com.thomaskioko.tvmaniac.datastore.api.DatastoreRepository +import com.thomaskioko.tvmaniac.util.scope.ApplicationScope +import me.tatarka.inject.annotations.Provides + expect interface DataStorePlatformComponent + + +interface DataStoreComponent : DataStorePlatformComponent { + + @ApplicationScope + @Provides + fun provideDatastoreRepository(bind: DatastoreRepositoryImpl): DatastoreRepository = bind +} \ No newline at end of file diff --git a/core/datastore/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt b/core/datastore/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt index b08b6606b..5f8f4c246 100644 --- a/core/datastore/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt +++ b/core/datastore/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt @@ -33,7 +33,4 @@ actual interface DataStorePlatformComponent { }, ) - @ApplicationScope - @Provides - fun provideDatastoreRepository(bind: DatastoreRepositoryImpl): DatastoreRepository = bind } diff --git a/core/tmdb-api/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt b/core/tmdb-api/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt index 22e3c071d..455994245 100644 --- a/core/tmdb-api/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt +++ b/core/tmdb-api/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt @@ -4,7 +4,7 @@ import com.thomaskioko.tvmaniac.util.scope.ApplicationScope import io.ktor.client.engine.okhttp.OkHttp import me.tatarka.inject.annotations.Provides -interface TmdbPlatformComponent { +actual interface TmdbPlatformComponent { @ApplicationScope @Provides diff --git a/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbComponent.kt b/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbComponent.kt index 732c2fdfd..d621cc0d6 100644 --- a/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbComponent.kt +++ b/core/tmdb-api/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbComponent.kt @@ -14,7 +14,9 @@ typealias TmdbHttpClient = HttpClient typealias TmdbHttpClientEngine = HttpClientEngine typealias TmdbJson = Json -interface TmdbComponent { +expect interface TmdbPlatformComponent + +interface TmdbComponent : TmdbPlatformComponent { @OptIn(ExperimentalSerializationApi::class) @ApplicationScope diff --git a/core/tmdb-api/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt b/core/tmdb-api/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt index fc7eb13eb..930725e2d 100644 --- a/core/tmdb-api/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt +++ b/core/tmdb-api/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt @@ -4,7 +4,7 @@ import com.thomaskioko.tvmaniac.util.scope.ApplicationScope import io.ktor.client.engine.darwin.Darwin import me.tatarka.inject.annotations.Provides -interface TmdbPlatformComponent { +actual interface TmdbPlatformComponent { @ApplicationScope @Provides diff --git a/core/tmdb-api/implementation/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt b/core/tmdb-api/implementation/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt index 0706afc5c..932806517 100644 --- a/core/tmdb-api/implementation/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt +++ b/core/tmdb-api/implementation/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt @@ -1,3 +1,3 @@ package com.thomaskioko.tvmaniac.tmdb.implementation -interface TmdbPlatformComponent +actual interface TmdbPlatformComponent diff --git a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/inject/TraktComponent.kt b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/inject/TraktComponent.kt index 44e786260..6f5f234ba 100644 --- a/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/inject/TraktComponent.kt +++ b/core/trakt-api/implementation/src/commonMain/kotlin/com/thomaskioko/trakt/service/implementation/inject/TraktComponent.kt @@ -21,7 +21,7 @@ import me.tatarka.inject.annotations.Provides typealias TraktHttpClient = HttpClient typealias TraktJson = Json -interface TraktComponent { +interface TraktComponent : TraktPlatformComponent { @ApplicationScope @Provides diff --git a/shared/src/iosMain/kotlin/com.thomaskioko.tvmaniac.shared/base/ApplicationComponent.kt b/shared/src/iosMain/kotlin/com.thomaskioko.tvmaniac.shared/base/ApplicationComponent.kt index 36e7baf91..2af826c9b 100644 --- a/shared/src/iosMain/kotlin/com.thomaskioko.tvmaniac.shared/base/ApplicationComponent.kt +++ b/shared/src/iosMain/kotlin/com.thomaskioko.tvmaniac.shared/base/ApplicationComponent.kt @@ -1,10 +1,9 @@ package com.thomaskioko.tvmaniac.shared.base import com.thomaskioko.trakt.service.implementation.inject.TraktComponent -import com.thomaskioko.trakt.service.implementation.inject.TraktPlatformComponent import com.thomaskioko.tvmaniac.data.category.implementation.CategoryComponent import com.thomaskioko.tvmaniac.data.trailers.implementation.TrailerComponent -import com.thomaskioko.tvmaniac.datastore.implementation.DataStorePlatformComponent +import com.thomaskioko.tvmaniac.datastore.implementation.DataStoreComponent import com.thomaskioko.tvmaniac.db.DatabaseComponent import com.thomaskioko.tvmaniac.episodeimages.implementation.EpisodeImageComponent import com.thomaskioko.tvmaniac.episodes.implementation.EpisodeComponent @@ -24,7 +23,6 @@ import com.thomaskioko.tvmaniac.showimages.implementation.ShowImagesComponent import com.thomaskioko.tvmaniac.shows.implementation.DiscoverComponent import com.thomaskioko.tvmaniac.similar.implementation.SimilarShowsComponent import com.thomaskioko.tvmaniac.tmdb.implementation.TmdbComponent -import com.thomaskioko.tvmaniac.tmdb.implementation.TmdbPlatformComponent import com.thomaskioko.tvmaniac.traktauth.implementation.TraktAuthenticationComponent import com.thomaskioko.tvmaniac.util.inject.UtilPlatformComponent import com.thomaskioko.tvmaniac.util.scope.ApplicationScope @@ -36,7 +34,7 @@ import me.tatarka.inject.annotations.Component abstract class ApplicationComponent : CategoryComponent, DatabaseComponent, - DataStorePlatformComponent, + DataStoreComponent, EpisodeComponent, EpisodeImageComponent, ProfileComponent, @@ -48,9 +46,7 @@ abstract class ApplicationComponent : SimilarShowsComponent, StatsComponent, TmdbComponent, - TmdbPlatformComponent, TraktComponent, - TraktPlatformComponent, TraktAuthenticationComponent, TrailerComponent, UtilPlatformComponent, From 1496a099d09e7fb368a320f55890a36fe2ea420b Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Wed, 22 Nov 2023 17:27:35 +0100 Subject: [PATCH 35/38] Replace List with PersistenceList --- .../SeasonPreviewParameterProvider.kt | 6 ++-- presentation/seasondetails/build.gradle.kts | 2 ++ .../presentation/seasondetails/Mapper.kt | 28 +++++++++++-------- .../seasondetails/SeasonDetailsState.kt | 6 ++-- .../seasondetails/model/SeasonDetails.kt | 4 ++- .../tvmaniac/data/seasondetails/MockData.kt | 5 ++-- 6 files changed, 33 insertions(+), 18 deletions(-) diff --git a/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/SeasonPreviewParameterProvider.kt b/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/SeasonPreviewParameterProvider.kt index b13afa457..5f2080937 100644 --- a/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/SeasonPreviewParameterProvider.kt +++ b/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/SeasonPreviewParameterProvider.kt @@ -6,6 +6,8 @@ import com.thomaskioko.tvmaniac.presentation.seasondetails.SeasonDetailsLoaded import com.thomaskioko.tvmaniac.presentation.seasondetails.SeasonDetailsState import com.thomaskioko.tvmaniac.presentation.seasondetails.model.Episode import com.thomaskioko.tvmaniac.presentation.seasondetails.model.SeasonDetails +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList val episode = Episode( id = 2534997, @@ -27,7 +29,7 @@ val seasonDetails = SeasonDetails( watchProgress = 0.4f, episodes = List(8) { episode - }, + }.toPersistentList(), ) class SeasonPreviewParameterProvider : PreviewParameterProvider { @@ -36,7 +38,7 @@ class SeasonPreviewParameterProvider : PreviewParameterProvider?.toSeasonWithEpisodes(): List { - return this?.groupBy { it.season_id }?.map { (_, groupMap) -> - val seasonRow = groupMap.first() - SeasonDetails( - seasonId = seasonRow.season_id.id, - seasonName = seasonRow.season_title, - episodes = groupMap.map { it.toEpisode() }, - episodeCount = seasonRow.episode_count, - watchProgress = 0f, - ) - } ?: emptyList() +fun List?.toSeasonWithEpisodes(): PersistentList { + return this + ?.groupBy { it.season_id } + ?.map { (_, groupMap) -> + val seasonRow = groupMap.first() + SeasonDetails( + seasonId = seasonRow.season_id.id, + seasonName = seasonRow.season_title, + episodes = groupMap.map { it.toEpisode() }.toImmutableList(), + episodeCount = seasonRow.episode_count, + watchProgress = 0f, + ) + }?.toPersistentList() ?: persistentListOf() } fun SeasonEpisodeDetailsById.toEpisode(): Episode { diff --git a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsState.kt b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsState.kt index 184c48226..449f31bcf 100644 --- a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsState.kt +++ b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/SeasonDetailsState.kt @@ -1,14 +1,16 @@ package com.thomaskioko.tvmaniac.presentation.seasondetails import com.thomaskioko.tvmaniac.presentation.seasondetails.model.SeasonDetails +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf sealed interface SeasonDetailsState -object Loading : SeasonDetailsState +data object Loading : SeasonDetailsState data class SeasonDetailsLoaded( val showTitle: String = "", - val seasonDetailsList: List = emptyList(), + val seasonDetailsList: PersistentList = persistentListOf(), val errorMessage: String? = null, ) : SeasonDetailsState diff --git a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/model/SeasonDetails.kt b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/model/SeasonDetails.kt index b46347ed2..312eeeb06 100644 --- a/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/model/SeasonDetails.kt +++ b/presentation/seasondetails/src/commonMain/kotlin/com/thomaskioko/tvmaniac/presentation/seasondetails/model/SeasonDetails.kt @@ -1,9 +1,11 @@ package com.thomaskioko.tvmaniac.presentation.seasondetails.model +import kotlinx.collections.immutable.ImmutableList + data class SeasonDetails( val seasonId: Long, val seasonName: String, val episodeCount: Long, val watchProgress: Float, - val episodes: List, + val episodes: ImmutableList, ) diff --git a/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/MockData.kt b/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/MockData.kt index 261f3f860..73f19a495 100644 --- a/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/MockData.kt +++ b/presentation/seasondetails/src/commonTest/kotlin/com/thomaskioko/tvmaniac/data/seasondetails/MockData.kt @@ -3,8 +3,9 @@ package com.thomaskioko.tvmaniac.data.seasondetails import com.thomaskioko.tvmaniac.presentation.seasondetails.SeasonDetailsLoaded import com.thomaskioko.tvmaniac.presentation.seasondetails.model.Episode import com.thomaskioko.tvmaniac.presentation.seasondetails.model.SeasonDetails +import kotlinx.collections.immutable.persistentListOf -val episodes = listOf( +val episodes = persistentListOf( Episode( id = 12345, seasonId = 12343, @@ -19,7 +20,7 @@ val episodes = listOf( ), ) -val seasonDetailsList = listOf( +val seasonDetailsList = persistentListOf( SeasonDetails( seasonId = 12343, seasonName = "Season 01", From 329630d18e1f004e188b4c79aa22d4d5cadadf8b Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Wed, 22 Nov 2023 17:27:44 +0100 Subject: [PATCH 36/38] Minor update on Episode List UI. --- .../resources/src/main/res/values/strings.xml | 1 + .../seasondetails/SeasonDetailsScreen.kt | 89 ++++++++++--- .../components/CollapsableContent.kt | 124 ++---------------- .../{WatchNextList.kt => EpisodeItem.kt} | 113 +++++----------- 4 files changed, 109 insertions(+), 218 deletions(-) rename android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/components/{WatchNextList.kt => EpisodeItem.kt} (53%) diff --git a/android-core/resources/src/main/res/values/strings.xml b/android-core/resources/src/main/res/values/strings.xml index 3e72dc04e..6e8fd09b7 100644 --- a/android-core/resources/src/main/res/values/strings.xml +++ b/android-core/resources/src/main/res/values/strings.xml @@ -40,6 +40,7 @@ Settings All Seasons + All Episodes Watch Next Back Online! No Internet Connection! diff --git a/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/SeasonDetailsScreen.kt b/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/SeasonDetailsScreen.kt index 6d78b3315..92757d8b2 100644 --- a/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/SeasonDetailsScreen.kt +++ b/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/SeasonDetailsScreen.kt @@ -7,10 +7,13 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.ExperimentalMaterial3Api @@ -41,10 +44,14 @@ import com.thomaskioko.tvmaniac.presentation.seasondetails.Loading import com.thomaskioko.tvmaniac.presentation.seasondetails.LoadingError import com.thomaskioko.tvmaniac.presentation.seasondetails.SeasonDetailsLoaded import com.thomaskioko.tvmaniac.presentation.seasondetails.SeasonDetailsState +import com.thomaskioko.tvmaniac.presentation.seasondetails.model.Episode import com.thomaskioko.tvmaniac.presentation.seasondetails.model.SeasonDetails import com.thomaskioko.tvmaniac.resources.R import com.thomaskioko.tvmaniac.seasondetails.components.CollapsableContent -import com.thomaskioko.tvmaniac.seasondetails.components.WatchNextContent +import com.thomaskioko.tvmaniac.seasondetails.components.EpisodeItem +import dev.chrisbanes.snapper.ExperimentalSnapperApi +import dev.chrisbanes.snapper.rememberSnapperFlingBehavior +import kotlinx.collections.immutable.ImmutableList import me.tatarka.inject.annotations.Assisted import me.tatarka.inject.annotations.Inject @@ -106,8 +113,7 @@ internal fun SeasonDetailScreen( navigateUp = onBackClicked, ) }, - modifier = modifier - .statusBarsPadding(), + modifier = modifier.statusBarsPadding(), content = { contentPadding -> when (state) { Loading -> LoadingIndicator( @@ -116,14 +122,13 @@ internal fun SeasonDetailScreen( .wrapContentSize(Alignment.Center), ) - is LoadingError -> - ErrorUi( - errorMessage = state.message, - onRetry = {}, - modifier = Modifier - .fillMaxSize() - .wrapContentSize(Alignment.Center), - ) + is LoadingError -> ErrorUi( + errorMessage = state.message, + onRetry = {}, + modifier = Modifier + .fillMaxSize() + .wrapContentSize(Alignment.Center), + ) is SeasonDetailsLoaded -> { SeasonContent( @@ -155,7 +160,7 @@ private fun TopBar( @Composable private fun SeasonContent( - seasonsEpList: List?, + seasonsEpList: ImmutableList?, initialSeasonName: String?, listState: LazyListState, contentPadding: PaddingValues, @@ -179,7 +184,9 @@ private fun SeasonContent( LazyColumn( state = listState, contentPadding = contentPadding.copy(copyTop = false), - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxSize(), ) { item { Spacer(modifier = Modifier.height(64.dp)) } @@ -187,7 +194,11 @@ private fun SeasonContent( item { Spacer(modifier = Modifier.height(16.dp)) } - item { AllSeasonsTitle() } + item { + LabelTitle( + label = stringResource(id = R.string.title_all_episodes), + ) + } itemsIndexed(seasonsEpList) { index, season -> CollapsableContent( @@ -204,20 +215,57 @@ private fun SeasonContent( } } +@OptIn(ExperimentalSnapperApi::class) +@Composable +fun WatchNextContent( + episodeList: ImmutableList?, + modifier: Modifier = Modifier, + onEpisodeClicked: () -> Unit = {}, +) { + episodeList?.let { + LabelTitle( + modifier = modifier + .padding(top = 16.dp, bottom = 8.dp), + label = stringResource(id = R.string.title_watch_next), + ) + + val lazyListState = rememberLazyListState() + + LazyRow( + state = lazyListState, + flingBehavior = rememberSnapperFlingBehavior(lazyListState), + ) { + itemsIndexed(episodeList) { index, episode -> + val value = if (index == 0) 0 else 8 + Spacer(modifier = Modifier.width(value.dp)) + + EpisodeItem( + modifier = modifier.size(width = 320.dp, height = 90.dp), + imageUrl = episode.imageUrl, + title = episode.seasonEpisodeNumber, + episodeOverview = episode.overview, + onEpisodeClicked = onEpisodeClicked, + ) + } + + item { Spacer(modifier = Modifier.height(16.dp)) } + } + } +} + @Composable -private fun AllSeasonsTitle( +private fun LabelTitle( + label: String, modifier: Modifier = Modifier, ) { Box( - modifier = modifier - .fillMaxWidth() - .padding(2.dp), + modifier = modifier.fillMaxWidth(), contentAlignment = Alignment.Center, ) { Spacer(modifier = Modifier.height(8.dp)) Text( - text = stringResource(id = R.string.title_all_seasons), + text = label, style = MaterialTheme.typography.labelMedium.copy(MaterialTheme.colorScheme.secondary), ) } @@ -226,8 +274,7 @@ private fun AllSeasonsTitle( @ThemePreviews @Composable private fun SeasonDetailScreenPreview( - @PreviewParameter(SeasonPreviewParameterProvider::class) - state: SeasonDetailsState, + @PreviewParameter(SeasonPreviewParameterProvider::class) state: SeasonDetailsState, ) { TvManiacTheme { Surface { diff --git a/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/components/CollapsableContent.kt b/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/components/CollapsableContent.kt index 077e5cc6b..9aa0c5448 100644 --- a/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/components/CollapsableContent.kt +++ b/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/components/CollapsableContent.kt @@ -12,9 +12,7 @@ import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.rounded.ExpandLess @@ -31,21 +29,16 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Color.Companion.LightGray -import androidx.compose.ui.graphics.RectangleShape -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.stringResource +import androidx.compose.ui.graphics.Shape import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension -import com.thomaskioko.tvmaniac.compose.components.AsyncImageComposable import com.thomaskioko.tvmaniac.compose.components.ThemePreviews import com.thomaskioko.tvmaniac.compose.theme.TvManiacTheme import com.thomaskioko.tvmaniac.compose.theme.green import com.thomaskioko.tvmaniac.presentation.seasondetails.model.Episode -import com.thomaskioko.tvmaniac.resources.R -import com.thomaskioko.tvmaniac.seasondetails.episode import com.thomaskioko.tvmaniac.seasondetails.seasonDetails @Composable @@ -79,8 +72,13 @@ fun CollapsableContent( Spacer(modifier = Modifier.height(8.dp)) EpisodeItem( - episode = episode, - onEpisodeClicked = onEpisodeClicked, + modifier = Modifier + .fillMaxWidth() + .defaultMinSize(minHeight = 84.dp), + imageUrl = episode.imageUrl, + title = episode.episodeNumberTitle, + episodeOverview = episode.overview, + onEpisodeClicked = { onEpisodeClicked(episode.id) }, ) Spacer(modifier = Modifier.height(8.dp)) @@ -96,6 +94,7 @@ private fun SeasonTitleHeader( episodesCount: Long, watchProgress: Float, expanded: Boolean, + shape: Shape = MaterialTheme.shapes.small, onSeasonHeaderClicked: () -> Unit = {}, ) { val transitionState = remember { @@ -112,11 +111,10 @@ private fun SeasonTitleHeader( ) Card( - shape = RectangleShape, + shape = shape, modifier = Modifier .fillMaxWidth() .height(64.dp) - .padding(horizontal = 16.dp) .clickable { onSeasonHeaderClicked() }, ) { ConstraintLayout( @@ -209,108 +207,6 @@ private fun SeasonTitleHeader( } } -@Composable -fun EpisodeItem( - episode: Episode, - modifier: Modifier = Modifier, - onEpisodeClicked: (Long) -> Unit = {}, -) { - Card( - shape = RectangleShape, - modifier = modifier - .fillMaxWidth() - .defaultMinSize(minHeight = 84.dp) - .padding(horizontal = 16.dp) - .clickable { onEpisodeClicked(episode.id) }, - ) { - ConstraintLayout( - modifier = Modifier.fillMaxWidth(), - ) { - val (episodeTitle, image, overview, watchedStatusIcon) = createRefs() - - AsyncImageComposable( - model = episode.imageUrl, - contentDescription = stringResource( - R.string.cd_show_poster, - episode.episodeNumberTitle, - ), - contentScale = ContentScale.Crop, - modifier = Modifier - .width(94.dp) - .constrainAs(image) { - start.linkTo(parent.start) - top.linkTo(parent.top) - bottom.linkTo(parent.bottom) - - height = Dimension.fillToConstraints - }, - ) - - Text( - text = episode.episodeNumberTitle, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.onSurface, - modifier = Modifier - .constrainAs(episodeTitle) { - start.linkTo(image.end, 8.dp) - end.linkTo(watchedStatusIcon.start) - top.linkTo(parent.top, 8.dp) - - width = Dimension.fillToConstraints - }, - ) - - Text( - text = episode.overview, - maxLines = 3, - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.bodyMedium, - modifier = Modifier - .constrainAs(overview) { - start.linkTo(image.end, 8.dp) - top.linkTo(episodeTitle.bottom, 5.dp) - end.linkTo(watchedStatusIcon.start, 8.dp) - bottom.linkTo(parent.bottom, 8.dp) - - width = Dimension.fillToConstraints - }, - ) - - IconButton( - onClick = {}, - modifier = Modifier - .constrainAs(watchedStatusIcon) { - centerVerticallyTo(parent) - end.linkTo(parent.end, 8.dp) - }, - ) { - Icon( - imageVector = Icons.Filled.CheckCircle, - contentDescription = stringResource(R.string.cd_navigate_back), - tint = MaterialTheme.colorScheme.onSurface, - modifier = Modifier - .size(32.dp), - ) - } - } - } -} - -@ThemePreviews -@Composable -fun EpisodeItemPreview() { - TvManiacTheme { - Surface { - EpisodeItem( - episode = episode, - ) - } - } -} - @ThemePreviews @Composable fun SeasonTitleHeaderPreview() { diff --git a/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/components/WatchNextList.kt b/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/components/EpisodeItem.kt similarity index 53% rename from android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/components/WatchNextList.kt rename to android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/components/EpisodeItem.kt index 57773e9b1..047a9bb7d 100644 --- a/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/components/WatchNextList.kt +++ b/android-features/season-details/src/main/java/com/thomaskioko/tvmaniac/seasondetails/components/EpisodeItem.kt @@ -1,16 +1,9 @@ package com.thomaskioko.tvmaniac.seasondetails.components import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material3.Card @@ -20,11 +13,11 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.graphics.Shape import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.constraintlayout.compose.ConstraintLayout @@ -32,67 +25,22 @@ import androidx.constraintlayout.compose.Dimension import com.thomaskioko.tvmaniac.compose.components.AsyncImageComposable import com.thomaskioko.tvmaniac.compose.components.ThemePreviews import com.thomaskioko.tvmaniac.compose.theme.TvManiacTheme -import com.thomaskioko.tvmaniac.presentation.seasondetails.model.Episode import com.thomaskioko.tvmaniac.resources.R import com.thomaskioko.tvmaniac.seasondetails.episode -import dev.chrisbanes.snapper.ExperimentalSnapperApi -import dev.chrisbanes.snapper.rememberSnapperFlingBehavior -@OptIn(ExperimentalSnapperApi::class) @Composable -fun WatchNextContent( - episodeList: List?, +fun EpisodeItem( + imageUrl: String?, + title: String, + episodeOverview: String, modifier: Modifier = Modifier, -) { - episodeList?.let { - Box( - modifier = modifier - .fillMaxWidth() - .padding(top = 16.dp), - contentAlignment = Alignment.Center, - ) { - Spacer(modifier = Modifier.height(8.dp)) - - Text( - text = stringResource(id = R.string.title_watch_next), - style = MaterialTheme.typography.labelMedium.copy(MaterialTheme.colorScheme.secondary), - ) - } - - Spacer(modifier = Modifier.height(8.dp)) - - val lazyListState = rememberLazyListState() - - LazyRow( - state = lazyListState, - flingBehavior = rememberSnapperFlingBehavior(lazyListState), - ) { - itemsIndexed(episodeList) { index, episode -> - val value = if (index == 0) 32 else 8 - Spacer(modifier = Modifier.width(value.dp)) - - WatchNextItem( - episode = episode, - onEpisodeClicked = {}, - ) - } - - item { Spacer(modifier = Modifier.height(16.dp)) } - } - } -} - -@Composable -fun WatchNextItem( - episode: Episode, - modifier: Modifier = Modifier, - onEpisodeClicked: (Long) -> Unit = {}, + shape: Shape = MaterialTheme.shapes.small, + onEpisodeClicked: () -> Unit = {}, ) { Card( - shape = RectangleShape, + shape = shape, modifier = modifier - .size(width = 260.dp, height = 90.dp) - .clickable { onEpisodeClicked(episode.id) }, + .clickable { onEpisodeClicked() }, ) { ConstraintLayout( modifier = Modifier.fillMaxWidth(), @@ -100,54 +48,51 @@ fun WatchNextItem( val (episodeTitle, image, overview, watchedStatusIcon) = createRefs() AsyncImageComposable( - model = episode.imageUrl, + model = imageUrl, contentDescription = stringResource( R.string.cd_show_poster, - episode.episodeNumberTitle, + title, ), contentScale = ContentScale.Crop, modifier = Modifier - .width(84.dp) + .width(94.dp) .constrainAs(image) { start.linkTo(parent.start) - bottom.linkTo(parent.bottom) top.linkTo(parent.top) + bottom.linkTo(parent.bottom) height = Dimension.fillToConstraints }, ) Text( - text = episode.seasonEpisodeNumber, + text = title, maxLines = 1, overflow = TextOverflow.Ellipsis, style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.onSurface, modifier = Modifier .constrainAs(episodeTitle) { - linkTo( - start = image.end, - end = watchedStatusIcon.start, - startMargin = 8.dp, - bias = 0f, - ) - top.linkTo(parent.top, 16.dp) + start.linkTo(image.end, 8.dp) + end.linkTo(watchedStatusIcon.start) + top.linkTo(parent.top, 8.dp) - width = Dimension.preferredWrapContent + width = Dimension.fillToConstraints }, ) Text( - text = episode.episodeTitle, - maxLines = 1, + text = episodeOverview, + maxLines = 3, overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.titleMedium, + style = MaterialTheme.typography.bodyMedium, modifier = Modifier - .padding(bottom = 8.dp) .constrainAs(overview) { start.linkTo(image.end, 8.dp) top.linkTo(episodeTitle.bottom, 5.dp) end.linkTo(watchedStatusIcon.start, 8.dp) - bottom.linkTo(parent.bottom) + bottom.linkTo(parent.bottom, 8.dp) width = Dimension.fillToConstraints }, @@ -163,7 +108,7 @@ fun WatchNextItem( ) { Icon( imageVector = Icons.Filled.CheckCircle, - contentDescription = null, + contentDescription = stringResource(R.string.cd_navigate_back), tint = MaterialTheme.colorScheme.onSurface, modifier = Modifier .size(32.dp), @@ -178,8 +123,10 @@ fun WatchNextItem( fun WatchlistRowItemPreview() { TvManiacTheme { Surface { - WatchNextItem( - episode = episode, + EpisodeItem( + title = episode.episodeNumberTitle, + episodeOverview = episode.overview, + imageUrl = episode.imageUrl, ) } } From ca233444376449807c70276675b2189312bb563a Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Wed, 22 Nov 2023 17:29:24 +0100 Subject: [PATCH 37/38] Make spotless happy --- .../tvmaniac/db/DatabasePlatformComponent.kt | 10 ---------- .../DatabasePlatformComponent.kt | 3 +-- .../tvmaniac/db/DatabasePlatformComponent.kt | 11 ----------- .../implementation/DataStorePlatformComponent.kt | 2 -- .../implementation/DataStorePlatformComponent.kt | 3 +-- .../implementation/DataStorePlatformComponent.kt | 2 -- .../tmdb/implementation/TmdbPlatformComponent.kt | 2 +- 7 files changed, 3 insertions(+), 30 deletions(-) diff --git a/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt b/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt index fd439842e..f1f79a2c6 100644 --- a/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt +++ b/core/database/src/androidMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt @@ -3,17 +3,7 @@ package com.thomaskioko.tvmaniac.db import android.app.Application import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.android.AndroidSqliteDriver -import com.thomaskioko.tvmaniac.core.db.Episode -import com.thomaskioko.tvmaniac.core.db.Episode_image -import com.thomaskioko.tvmaniac.core.db.Last_requests -import com.thomaskioko.tvmaniac.core.db.Season -import com.thomaskioko.tvmaniac.core.db.Show -import com.thomaskioko.tvmaniac.core.db.Show_category -import com.thomaskioko.tvmaniac.core.db.Show_image -import com.thomaskioko.tvmaniac.core.db.Similar_shows -import com.thomaskioko.tvmaniac.core.db.Trailers import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase -import com.thomaskioko.tvmaniac.core.db.Watchlist import com.thomaskioko.tvmaniac.util.scope.ApplicationScope import me.tatarka.inject.annotations.Provides diff --git a/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabasePlatformComponent.kt b/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabasePlatformComponent.kt index cb326e14e..1c7284223 100644 --- a/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabasePlatformComponent.kt +++ b/core/database/src/commonMain/kotlin/com.thomaskioko.tvmaniac.db/DatabasePlatformComponent.kt @@ -17,7 +17,6 @@ import me.tatarka.inject.annotations.Provides expect interface DatabasePlatformComponent - interface DatabaseComponent : DatabasePlatformComponent { @ApplicationScope @Provides @@ -68,4 +67,4 @@ interface DatabaseComponent : DatabasePlatformComponent { fun provideDbTransactionRunner( bind: DbTransactionRunner, ): DatabaseTransactionRunner = bind -} \ No newline at end of file +} diff --git a/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt b/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt index f94ce7104..e1816c660 100644 --- a/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt +++ b/core/database/src/iosMain/kotlin/com/thomaskioko/tvmaniac/db/DatabasePlatformComponent.kt @@ -2,17 +2,7 @@ package com.thomaskioko.tvmaniac.db import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.native.NativeSqliteDriver -import com.thomaskioko.tvmaniac.core.db.Episode -import com.thomaskioko.tvmaniac.core.db.Episode_image -import com.thomaskioko.tvmaniac.core.db.Last_requests -import com.thomaskioko.tvmaniac.core.db.Season -import com.thomaskioko.tvmaniac.core.db.Show -import com.thomaskioko.tvmaniac.core.db.Show_category -import com.thomaskioko.tvmaniac.core.db.Show_image -import com.thomaskioko.tvmaniac.core.db.Similar_shows -import com.thomaskioko.tvmaniac.core.db.Trailers import com.thomaskioko.tvmaniac.core.db.TvManiacDatabase -import com.thomaskioko.tvmaniac.core.db.Watchlist import com.thomaskioko.tvmaniac.util.scope.ApplicationScope import me.tatarka.inject.annotations.Provides @@ -21,5 +11,4 @@ actual interface DatabasePlatformComponent { @ApplicationScope @Provides fun provideSqlDriver(): SqlDriver = NativeSqliteDriver(TvManiacDatabase.Schema, "tvShows.db") - } diff --git a/core/datastore/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt b/core/datastore/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt index d46cd4846..0e9996d76 100644 --- a/core/datastore/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt +++ b/core/datastore/implementation/src/androidMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt @@ -3,7 +3,6 @@ package com.thomaskioko.tvmaniac.datastore.implementation import android.app.Application import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences -import com.thomaskioko.tvmaniac.datastore.api.DatastoreRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineScope import com.thomaskioko.tvmaniac.util.scope.ApplicationScope import me.tatarka.inject.annotations.Provides @@ -19,5 +18,4 @@ actual interface DataStorePlatformComponent { coroutineScope = scope.io, producePath = { context.filesDir.resolve(dataStoreFileName).absolutePath }, ) - } diff --git a/core/datastore/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt b/core/datastore/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt index 220c676e2..9c911c7c5 100644 --- a/core/datastore/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt +++ b/core/datastore/implementation/src/commonMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt @@ -6,10 +6,9 @@ import me.tatarka.inject.annotations.Provides expect interface DataStorePlatformComponent - interface DataStoreComponent : DataStorePlatformComponent { @ApplicationScope @Provides fun provideDatastoreRepository(bind: DatastoreRepositoryImpl): DatastoreRepository = bind -} \ No newline at end of file +} diff --git a/core/datastore/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt b/core/datastore/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt index 5f8f4c246..3bf7f2a80 100644 --- a/core/datastore/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt +++ b/core/datastore/implementation/src/iosMain/kotlin/com/thomaskioko/tvmaniac/datastore/implementation/DataStorePlatformComponent.kt @@ -2,7 +2,6 @@ package com.thomaskioko.tvmaniac.datastore.implementation import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences -import com.thomaskioko.tvmaniac.datastore.api.DatastoreRepository import com.thomaskioko.tvmaniac.util.model.AppCoroutineScope import com.thomaskioko.tvmaniac.util.scope.ApplicationScope import kotlinx.cinterop.ExperimentalForeignApi @@ -32,5 +31,4 @@ actual interface DataStorePlatformComponent { requireNotNull(documentDirectory).path + "/$dataStoreFileName" }, ) - } diff --git a/core/tmdb-api/implementation/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt b/core/tmdb-api/implementation/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt index 932806517..fbd673b97 100644 --- a/core/tmdb-api/implementation/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt +++ b/core/tmdb-api/implementation/src/jvmMain/kotlin/com/thomaskioko/tvmaniac/tmdb/implementation/TmdbPlatformComponent.kt @@ -1,3 +1,3 @@ package com.thomaskioko.tvmaniac.tmdb.implementation -actual interface TmdbPlatformComponent +actual interface TmdbPlatformComponent From 97f6c5f4a4409b281ae1fc4a6b7d028901515b6a Mon Sep 17 00:00:00 2001 From: Thomas Kioko Date: Wed, 22 Nov 2023 17:29:30 +0100 Subject: [PATCH 38/38] Bump up dependency versions. --- gradle/libs.versions.toml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cb32e8463..9da524c3a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,8 +1,8 @@ [versions] accompanist = "0.33.2-alpha" -agp = "8.1.3" -androidx-activity = "1.8.0" -androidx-browser = "1.6.0" +agp = "8.1.4" +androidx-activity = "1.8.1" +androidx-browser = "1.7.0" androidx-core = "1.12.0" androidx-core-splashscreen = "1.0.1" androidx-datastore = "1.1.0-alpha06" @@ -13,7 +13,7 @@ androidx-palette = "1.0.0" androidx-work = "2.8.1" appauth = "0.11.1" atomicfu = "0.22.0" -coil = "2.4.0" +coil = "2.5.0" compose-bom = "2023.10.01" compose-constraintlayout = "1.0.1" compose-paging = "3.2.1" @@ -23,7 +23,7 @@ datetime = "0.4.1" dependency-analysis = "1.25.0" dependency-check = "0.49.0" desugar = "2.0.4" -detekt = "1.23.0" +detekt = "1.23.3" flowredux = "1.2.0" kenburns = "1.0.7" kermit = "1.2.3" @@ -32,8 +32,8 @@ kotest = "5.5.4" kotlin = "1.9.20" kotlininject = "0.6.3" kotlinx-collections = "0.3.6" -ksp = "1.9.20-1.0.14" -ktor = "2.3.5" +ksp = "1.9.20-1.0.13" +ktor = "2.3.6" lint = "1.2.0" moko-resources = "0.23.0" shared-module-version = "0.8.0"