diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/favorite/FavoriteScreenComponent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/favorite/FavoriteScreenComponent.kt index 215940e7..320abbe7 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/favorite/FavoriteScreenComponent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/favorite/FavoriteScreenComponent.kt @@ -38,6 +38,7 @@ class FavoriteScreenComponent( .favoriteSeries() .asFlow() .mapToList(ioDispatcher()) + .flowOn(ioDispatcher()) .stateIn(ioScope(), SharingStarted.WhileSubscribed(), emptyList()) private val searchQuery: MutableStateFlow = MutableStateFlow(String()) @@ -60,7 +61,7 @@ class FavoriteScreenComponent( }.sortedByDescending { it.second }.map { it.first }.safeSubList(0, 10) } } - }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), emptyList()) + }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), emptyList()) private val navigation = SlotNavigation() override val child: Value> = childSlot( diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeScreenComponent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeScreenComponent.kt index d5036a58..0657848a 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeScreenComponent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeScreenComponent.kt @@ -49,7 +49,7 @@ class HomeScreenComponent( } else { null } - }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), null) + }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), null) private val navigation = SlotNavigation() override val child: Value> = childSlot( diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/search/SearchScreenComponent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/search/SearchScreenComponent.kt index c8306803..540e8eba 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/search/SearchScreenComponent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/search/SearchScreenComponent.kt @@ -36,18 +36,18 @@ class SearchScreenComponent( private val searchStateMachine: SearchStateMachine by di.instance() override val searchState: StateFlow = searchStateMachine.state.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), SearchState.Loading) - private val allGenres = searchState.mapNotNull { it as SearchState.Success }.map { it.genres }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), emptyList()) - private val allItems = allGenres.map { it.flatMap { g -> g.items } } - private val maxGenres = allGenres.map { it.size } + private val allGenres = searchState.mapNotNull { it as SearchState.Success }.map { it.genres }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), emptyList()) + private val allItems = allGenres.map { it.flatMap { g -> g.items } }.flowOn(ioDispatcher()) + private val maxGenres = allGenres.map { it.size }.flowOn(ioDispatcher()) private val loadedGenres = MutableStateFlow(1) override val genres: StateFlow> = combine(allGenres, loadedGenres) { t1, t2 -> t1.safeSubList(0, t2) - }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), emptyList()) + }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), emptyList()) override val canLoadMoreGenres: StateFlow = combine(loadedGenres, maxGenres) { t1, t2 -> t1 < t2 - }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), allGenres.value.size > loadedGenres.value) + }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), allGenres.value.size > loadedGenres.value) private val searchQuery: MutableStateFlow = MutableStateFlow(String()) @@ -70,7 +70,7 @@ class SearchScreenComponent( }.sortedByDescending { it.second }.map { it.first }.safeSubList(0, 10) } } - }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), emptyList()) + }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), emptyList()) private val navigation = SlotNavigation() override val child: Value> = childSlot( diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/series/SeriesScreenComponent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/series/SeriesScreenComponent.kt index 1ec3128a..fff8023d 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/series/SeriesScreenComponent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/series/SeriesScreenComponent.kt @@ -68,17 +68,17 @@ class SeriesScreenComponent( ) override val seriesState: StateFlow = seriesStateMachine.state.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), SeriesState.Loading(initialHref)) - private val successState = seriesState.mapNotNull { it as? SeriesState.Success } - private val currentSeries = successState.map { it.series }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), null) - private val onDeviceReachable = successState.map { it.onDeviceReachable }.stateIn(ioScope(), SharingStarted.Eagerly, true) - override val title: StateFlow = currentSeries.mapNotNull { it?.bestTitle }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), initialTitle) - override val href: StateFlow = currentSeries.mapNotNull { it?.href }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), BSUtil.fixSeriesHref(initialHref)) + private val successState = seriesState.mapNotNull { it as? SeriesState.Success }.flowOn(ioDispatcher()) + private val currentSeries = successState.map { it.series }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), null) + private val onDeviceReachable = successState.map { it.onDeviceReachable }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.Eagerly, true) + override val title: StateFlow = currentSeries.mapNotNull { it?.bestTitle }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), initialTitle) + override val href: StateFlow = currentSeries.mapNotNull { it?.href }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), BSUtil.fixSeriesHref(initialHref)) override val commonHref: StateFlow = href.map { val commonized = BSUtil.commonSeriesHref(it) database.burningSeriesQueries.seriesUpdateHrefByCommonHref(it, commonized) commonized - }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), BSUtil.commonSeriesHref(initialHref)) - override val coverHref: StateFlow = currentSeries.mapNotNull { it?.coverHref }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), initialCoverHref) + }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), BSUtil.commonSeriesHref(initialHref)) + override val coverHref: StateFlow = currentSeries.mapNotNull { it?.coverHref }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), initialCoverHref) private val database: BurningSeries by di.instance() override val isFavorite: StateFlow = commonHref.transform { @@ -92,13 +92,13 @@ class SeriesScreenComponent( s != null && s.favoriteSince > 0 } ) - }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), database.burningSeriesQueries.seriesByHref(commonHref.value).executeAsOneOrNull()?.favoriteSince?.let { it > 0 } ?: false) + }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), database.burningSeriesQueries.seriesByHref(commonHref.value).executeAsOneOrNull()?.favoriteSince?.let { it > 0 } ?: false) private val episodeStateMachine by di.instance() private val episodeState: StateFlow = episodeStateMachine.state.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), EpisodeState.Waiting) override val loadingEpisodeHref: StateFlow = episodeState.map { (it as? EpisodeState.Loading)?.episode?.href ?: (it as? EpisodeState.SuccessHoster)?.episode?.href - }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), null) + }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), null) override val dbEpisodes = commonHref.transform { return@transform emitAll(database.burningSeriesQueries.selectEpisodesBySeriesHref(it).asFlow().mapToList( diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/series/activate/ActivateScreenComponent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/series/activate/ActivateScreenComponent.kt index 07122c6e..a6934cc5 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/series/activate/ActivateScreenComponent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/series/activate/ActivateScreenComponent.kt @@ -15,6 +15,7 @@ import dev.datlag.burningseries.model.state.SaveAction import dev.datlag.burningseries.model.state.SaveState import dev.datlag.burningseries.network.state.SaveStateMachine import dev.datlag.burningseries.shared.LocalDI +import dev.datlag.burningseries.shared.common.ioDispatcher import dev.datlag.burningseries.shared.common.ioScope import dev.datlag.burningseries.shared.common.launchIO import dev.datlag.burningseries.shared.common.withMainContext @@ -24,6 +25,7 @@ import dev.datlag.burningseries.shared.ui.screen.initial.series.activate.dialog. import dev.datlag.burningseries.shared.ui.screen.initial.series.activate.dialog.success.SuccessDialogComponent import dev.datlag.skeo.Stream import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.serialization.json.Json @@ -40,11 +42,11 @@ class ActivateScreenComponent( ) : ActivateComponent, ComponentContext by componentContext { private val saveStateMachine by di.instance() - private val saveState = saveStateMachine.state.stateIn(ioScope(), SharingStarted.WhileSubscribed(), SaveState.Waiting) + private val saveState = saveStateMachine.state.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), SaveState.Waiting) private val json by di.instance() private val savedData: MutableSet = mutableSetOf() - override val isSaving = saveState.map { it is SaveState.Saving }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), saveState.value is SaveState.Saving) + override val isSaving = saveState.map { it is SaveState.Saving }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), saveState.value is SaveState.Saving) private val dialogNavigation = SlotNavigation() override val dialog = childSlot( diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/video/VideoScreenComponent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/video/VideoScreenComponent.kt index d7ec3094..35638479 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/video/VideoScreenComponent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/video/VideoScreenComponent.kt @@ -12,6 +12,7 @@ import dev.datlag.burningseries.model.BSUtil import dev.datlag.burningseries.model.Series import dev.datlag.burningseries.model.state.EpisodeState import dev.datlag.burningseries.network.state.EpisodeStateMachine +import dev.datlag.burningseries.shared.common.ioDispatcher import dev.datlag.burningseries.shared.common.ioScope import dev.datlag.burningseries.shared.common.launchIO import dev.datlag.burningseries.shared.ui.navigation.DialogComponent @@ -37,20 +38,22 @@ class VideoScreenComponent( override val streams: List = initialStreams.sortedBy { it.headers.size } private val episodeStateMachine by di.instance() - override val episode: StateFlow = episodeStateMachine.state.mapNotNull { it as? EpisodeState.EpisodeHolder }.map { it.episode }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), initialEpisode) + override val episode: StateFlow = episodeStateMachine.state.mapNotNull { it as? EpisodeState.EpisodeHolder }.map { it.episode }.flowOn( + ioDispatcher() + ).stateIn(ioScope(), SharingStarted.WhileSubscribed(), initialEpisode) private val database by di.instance() private val dbEpisode = episode.transform { return@transform emitAll(database.burningSeriesQueries.selectEpisodeByHref(it.href).asFlow().mapToOneOrNull( currentCoroutineContext() )) - }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), database.burningSeriesQueries.selectEpisodeByHref(episode.value.href).executeAsOneOrNull()) + }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), database.burningSeriesQueries.selectEpisodeByHref(episode.value.href).executeAsOneOrNull()) override val selectedSubtitle = MutableStateFlow(null) override val startingPos: StateFlow = dbEpisode.transform { return@transform emit(it?.progress ?: 0L) - }.stateIn(ioScope(), SharingStarted.WhileSubscribed(), dbEpisode.value?.progress ?: 0L) + }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), dbEpisode.value?.progress ?: 0L) private val dialogNavigation = SlotNavigation() override val dialog: Value> = childSlot( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 86668491..5f046371 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,7 +28,7 @@ kmpalette = "2.2.0" kodein = "7.21.1" kolor = "1.3.0" kotlin = "1.9.21" -ksp = "1.9.21-1.0.15" +ksp = "1.9.21-1.0.16" ktor = "2.3.7" ktorfit = "1.11.0" ktsoup = "0.3.0"