From dd9debbd3267b76e406a6ef48f18a541c25caefd Mon Sep 17 00:00:00 2001 From: DatLag Date: Wed, 1 May 2024 13:37:18 +0200 Subject: [PATCH] improve performance --- .../dev/datlag/aniflow/other/StateSaver.kt | 4 +- .../datlag/aniflow/ui/navigation/Component.kt | 1 + .../aniflow/ui/navigation/RootComponent.kt | 2 +- .../screen/initial/home/HomeScreen.kt | 10 +- .../initial/home/HomeScreenComponent.kt | 4 +- .../initial/home/component/AiringCard.kt | 4 +- .../initial/home/component/AiringOverview.kt | 6 +- .../initial/home/component/MediumCard.kt | 4 +- .../home/component/PopularSeasonOverview.kt | 6 +- .../home/component/TrendingOverview.kt | 6 +- .../settings/SettingsScreenComponent.kt | 14 +-- .../screen/medium/MediumScreenComponent.kt | 98 ++++----------- .../screen/medium/component/TrailerSection.kt | 10 +- .../dialog/character/CharacterComponent.kt | 17 +-- .../dialog/character/CharacterDialog.kt | 16 +-- .../character/CharacterDialogComponent.kt | 118 ++++-------------- .../datlag/aniflow/ui/theme/SchemeTheme.kt | 12 +- 17 files changed, 111 insertions(+), 221 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/other/StateSaver.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/other/StateSaver.kt index c247973..f8f3579 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/other/StateSaver.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/other/StateSaver.kt @@ -74,9 +74,7 @@ data object StateSaver { _popularNextState ) { t1, t2, t3, t4 -> t1.isLoadingOrWaiting && t2.isLoadingOrWaiting && t3.isLoadingOrWaiting && t4.isLoadingOrWaiting - }.flowOn( - context = ioDispatcher() - ).distinctUntilChanged() + }.distinctUntilChanged() fun updateAiring(state: AiringTodayStateMachine.State) = _airingState.updateAndGet { state diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/Component.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/Component.kt index 831401e..27b12c5 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/Component.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/Component.kt @@ -9,6 +9,7 @@ import dev.datlag.tooling.decompose.defaultScope import dev.datlag.tooling.decompose.ioScope import dev.datlag.tooling.decompose.mainScope import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.coroutineScope import org.kodein.di.DIAware interface Component : DIAware, ComponentContext { diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/RootComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/RootComponent.kt index 35c9771..a6259e7 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/RootComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/RootComponent.kt @@ -77,7 +77,7 @@ class RootComponent( } fun onLogin(accessToken: String, expiresIn: Int?) { - launchIO { + launchDefault { userHelper.saveLogin(accessToken, expiresIn) } } diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/HomeScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/HomeScreen.kt index 853ddd3..97af1fc 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/HomeScreen.kt @@ -82,6 +82,7 @@ private fun MainView(component: HomeComponent, modifier: Modifier = Modifier) { it?.let(component::trace) } val traceState by component.traceState.collectAsStateWithLifecycle(TraceStateMachine.State.Waiting) + val titleLanguage by component.titleLanguage.collectAsStateWithLifecycle(null) LaunchedEffect(listState, traceState) { FABConfig.state.value = FABConfig.Scan( @@ -105,7 +106,6 @@ private fun MainView(component: HomeComponent, modifier: Modifier = Modifier) { ) } val useCase = rememberUseCaseState(visible = results.isNotEmpty()) - val titleLanguage by component.titleLanguage.collectAsStateWithLifecycle(null) OptionDialog( state = useCase, @@ -152,7 +152,7 @@ private fun MainView(component: HomeComponent, modifier: Modifier = Modifier) { item { AiringOverview( state = component.airingState, - titleLanguage = component.titleLanguage, + titleLanguage = titleLanguage, onClick = component::details ) } @@ -167,7 +167,7 @@ private fun MainView(component: HomeComponent, modifier: Modifier = Modifier) { item { TrendingOverview( state = component.trendingState, - titleLanguage = component.titleLanguage, + titleLanguage = titleLanguage, onClick = component::details ) } @@ -183,7 +183,7 @@ private fun MainView(component: HomeComponent, modifier: Modifier = Modifier) { PopularSeasonOverview( state = component.popularSeasonState, current = true, - titleLanguage = component.titleLanguage, + titleLanguage = titleLanguage, onClick = component::details, ) } @@ -199,7 +199,7 @@ private fun MainView(component: HomeComponent, modifier: Modifier = Modifier) { PopularSeasonOverview( state = component.popularNextSeasonState, current = false, - titleLanguage = component.titleLanguage, + titleLanguage = titleLanguage, onClick = component::details ) } diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/HomeScreenComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/HomeScreenComponent.kt index b55337d..f27b913 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/HomeScreenComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/HomeScreenComponent.kt @@ -36,7 +36,7 @@ class HomeScreenComponent( ) : HomeComponent, ComponentContext by componentContext { private val appSettings by di.instance() - override val titleLanguage: Flow = appSettings.titleLanguage.flowOn(ioDispatcher()) + override val titleLanguage: Flow = appSettings.titleLanguage private val airingTodayStateMachine by di.instance() override val airingState: Flow = airingTodayStateMachine.state.map { @@ -87,7 +87,7 @@ class HomeScreenComponent( } override fun trace(channel: ByteArray) { - launchIO { + launchDefault { traceStateMachine.dispatch(TraceStateMachine.Action.Load(channel)) } } diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/AiringCard.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/AiringCard.kt index 4e1724f..47851de 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/AiringCard.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/AiringCard.kt @@ -32,7 +32,7 @@ import org.kodein.di.instanceOrNull @Composable fun AiringCard( airing: AiringQuery.AiringSchedule, - titleLanguageFlow: Flow, + titleLanguage: AppSettings.TitleLanguage?, modifier: Modifier = Modifier, onClick: (Medium) -> Unit ) { @@ -49,8 +49,6 @@ fun AiringCard( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - val titleLanguage by titleLanguageFlow.collectAsStateWithLifecycle(null) - AsyncImage( modifier = Modifier.widthIn(min = 100.dp, max = 120.dp).fillMaxHeight().clip(MaterialTheme.shapes.medium), model = media.coverImage.extraLarge, diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/AiringOverview.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/AiringOverview.kt index 3370b68..1db3714 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/AiringOverview.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/AiringOverview.kt @@ -29,7 +29,7 @@ import kotlinx.coroutines.flow.StateFlow @Composable fun AiringOverview( state: Flow, - titleLanguage: Flow, + titleLanguage: AppSettings.TitleLanguage?, onClick: (Medium) -> Unit ) { val loadingState by state.collectAsStateWithLifecycle(StateSaver.Home.airingState) @@ -67,7 +67,7 @@ private fun Loading() { @Composable private fun SuccessContent( data: List, - titleLanguage: Flow, + titleLanguage: AppSettings.TitleLanguage?, onClick: (Medium) -> Unit ) { val state = rememberLazyListState( @@ -85,7 +85,7 @@ private fun SuccessContent( items(data, key = { it.episode to it.media?.id }) { media -> AiringCard( airing = media, - titleLanguageFlow = titleLanguage, + titleLanguage = titleLanguage, modifier = Modifier .height(150.dp) .fillParentMaxWidth(fraction = 0.9F) diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/MediumCard.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/MediumCard.kt index b3f1347..69813c1 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/MediumCard.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/MediumCard.kt @@ -29,7 +29,7 @@ import kotlinx.coroutines.flow.Flow @Composable fun MediumCard( medium: Medium, - titleLanguageFlow: Flow, + titleLanguage: AppSettings.TitleLanguage?, modifier: Modifier = Modifier, onClick: (Medium) -> Unit ) { @@ -100,8 +100,6 @@ fun MediumCard( .padding(top = 16.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { - val titleLanguage by titleLanguageFlow.collectAsStateWithLifecycle(null) - Text( text = medium.preferred(titleLanguage), style = MaterialTheme.typography.titleLarge, diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/PopularSeasonOverview.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/PopularSeasonOverview.kt index f9310f5..5a8544e 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/PopularSeasonOverview.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/PopularSeasonOverview.kt @@ -30,7 +30,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged fun PopularSeasonOverview( state: Flow, current: Boolean, - titleLanguage: Flow, + titleLanguage: AppSettings.TitleLanguage?, onClick: (Medium) -> Unit, ) { val loadingState by state.collectAsStateWithLifecycle( @@ -76,7 +76,7 @@ private fun Loading() { private fun SuccessContent( data: List, current: Boolean, - titleLanguage: Flow, + titleLanguage: AppSettings.TitleLanguage?, onClick: (Medium) -> Unit ) { val listState = rememberLazyListState( @@ -101,7 +101,7 @@ private fun SuccessContent( itemsIndexed(data, key = { _, it -> it.id }) { _, medium -> MediumCard( medium = Medium(medium), - titleLanguageFlow = titleLanguage, + titleLanguage = titleLanguage, modifier = Modifier .width(200.dp) .height(280.dp) diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/TrendingOverview.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/TrendingOverview.kt index b9d2875..8d28f74 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/TrendingOverview.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/home/component/TrendingOverview.kt @@ -27,7 +27,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged @Composable fun TrendingOverview( state: Flow, - titleLanguage: Flow, + titleLanguage: AppSettings.TitleLanguage?, onClick: (Medium) -> Unit, ) { val loadingState by state.collectAsStateWithLifecycle(StateSaver.Home.trendingState) @@ -65,7 +65,7 @@ private fun Loading() { @Composable private fun SuccessContent( data: List, - titleLanguage: Flow, + titleLanguage: AppSettings.TitleLanguage?, onClick: (Medium) -> Unit ) { val listState = rememberLazyListState( @@ -82,7 +82,7 @@ private fun SuccessContent( itemsIndexed(data, key = { _, it -> it.id }) { _, medium -> MediumCard( medium = Medium(medium), - titleLanguageFlow = titleLanguage, + titleLanguage = titleLanguage, modifier = Modifier .width(200.dp) .height(280.dp) diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/settings/SettingsScreenComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/settings/SettingsScreenComponent.kt index b95d13b..382d49a 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/settings/SettingsScreenComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/initial/settings/SettingsScreenComponent.kt @@ -21,10 +21,10 @@ class SettingsScreenComponent( private val appSettings by di.instance() private val userHelper by di.instance() - override val user: Flow = userHelper.user.flowOn(ioDispatcher()) - override val adultContent: Flow = appSettings.adultContent.flowOn(ioDispatcher()) - override val selectedColor: Flow = appSettings.color.flowOn(ioDispatcher()) - override val selectedTitleLanguage: Flow = appSettings.titleLanguage.flowOn(ioDispatcher()) + override val user: Flow = userHelper.user + override val adultContent: Flow = appSettings.adultContent + override val selectedColor: Flow = appSettings.color + override val selectedTitleLanguage: Flow = appSettings.titleLanguage @Composable override fun render() { @@ -34,19 +34,19 @@ class SettingsScreenComponent( } override fun changeAdultContent(value: Boolean) { - launchIO { + launchDefault { userHelper.updateAdultSetting(value) } } override fun changeProfileColor(value: AppSettings.Color?) { - launchIO { + launchDefault { userHelper.updateProfileColorSetting(value) } } override fun changeTitleLanguage(value: AppSettings.TitleLanguage?) { - launchIO { + launchDefault { userHelper.updateTitleLanguage(value) } } diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumScreenComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumScreenComponent.kt index 4ff7a56..6e570bd 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumScreenComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumScreenComponent.kt @@ -52,7 +52,7 @@ class MediumScreenComponent( private val appSettings by di.instance() private val userHelper by di.instance() - override val titleLanguage: Flow = appSettings.titleLanguage.flowOn(ioDispatcher()) + override val titleLanguage: Flow = appSettings.titleLanguage private val mediumStateMachine = MediumStateMachine( client = aniListClient, @@ -71,115 +71,81 @@ class MediumScreenComponent( private val mediumSuccessState = mediumState.mapNotNull { it.safeCast() - }.flowOn( - context = ioDispatcher() - ) + } override val isAdult: Flow = mediumSuccessState.map { it.data.isAdult - }.flowOn( - context = ioDispatcher() - ) + } override val isAdultAllowed: Flow = appSettings.adultContent private val type: Flow = mediumSuccessState.map { it.data.type - }.flowOn( - context = ioDispatcher() - ) + } override val bannerImage: Flow = mediumSuccessState.map { it.data.bannerImage - }.flowOn( - context = ioDispatcher() - ) + } override val coverImage: Flow = mediumSuccessState.map { it.data.coverImage - }.flowOn( - context = ioDispatcher() - ) + } override val title: Flow = mediumSuccessState.map { it.data.title - }.flowOn( - context = ioDispatcher() - ) + } override val description: Flow = mediumSuccessState.map { it.data.description?.ifBlank { null } - }.flowOn( - context = ioDispatcher() - ) + } override val translatedDescription: MutableStateFlow = MutableStateFlow(null) override val genres: Flow> = mediumSuccessState.map { it.data.genres - }.flowOn( - context = ioDispatcher() - ) + } override val format: Flow = mediumSuccessState.map { it.data.format - }.flowOn( - context = ioDispatcher() - ) + } private val nextAiringEpisode: Flow = mediumSuccessState.map { it.data.nextAiringEpisode - }.flowOn( - context = ioDispatcher() - ) + } override val episodes: Flow = mediumSuccessState.map { it.data.episodes - }.flowOn( - context = ioDispatcher() - ) + } override val duration: Flow = mediumSuccessState.map { it.data.avgEpisodeDurationInMin - }.flowOn( - context = ioDispatcher() - ) + } override val status: Flow = mediumSuccessState.map { it.data.status - }.flowOn( - context = ioDispatcher() - ) + } override val rated: Flow = mediumSuccessState.map { it.data.rated() - }.flowOn( - context = ioDispatcher() - ) + } override val popular: Flow = mediumSuccessState.map { it.data.popular() - }.flowOn( - context = ioDispatcher() - ) + } override val score: Flow = mediumSuccessState.mapNotNull { it.data.averageScore.ifValue(-1) { return@mapNotNull null } - }.flowOn( - context = ioDispatcher() - ) + } override val characters: Flow> = mediumSuccessState.map { it.data.characters - }.flowOn( - context = ioDispatcher() - ) + } private val changedRating: MutableStateFlow = MutableStateFlow(initialMedium.entry?.score?.toInt() ?: -1) override val rating: Flow = combine( mediumSuccessState.map { it.data.entry?.score?.toInt() - }.flowOn(ioDispatcher()), + }, changedRating ) { t1, t2 -> if (t2 > -1) { @@ -187,39 +153,27 @@ class MediumScreenComponent( } else { t1 ?: t2 } - }.flowOn( - context = ioDispatcher() - ) + } override val trailer: Flow = mediumSuccessState.map { it.data.trailer - }.flowOn( - context = ioDispatcher() - ) + } override val alreadyAdded: Flow = mediumSuccessState.map { it.data.entry != null - }.flowOn( - context = ioDispatcher() - ) + } override val isFavorite: Flow = mediumSuccessState.map { it.data.isFavorite - }.flowOn( - context = ioDispatcher() - ) + } override val isFavoriteBlocked: Flow = mediumSuccessState.map { it.data.isFavoriteBlocked - }.flowOn( - context = ioDispatcher() - ) + } override val siteUrl: Flow = mediumSuccessState.map { it.data.siteUrl - }.flowOn( - context = ioDispatcher() - ) + } private val burningSeriesResolver by di.instance() @@ -272,7 +226,7 @@ class MediumScreenComponent( } override fun rate(onLoggedIn: () -> Unit) { - launchIO { + launchDefault { val currentRating = rating.safeFirstOrNull() ?: initialMedium.entry?.score?.toInt() ?: -1 if (currentRating <= -1) { requestMediaListEntry() diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/component/TrailerSection.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/component/TrailerSection.kt index 442cc5d..4ac6efb 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/component/TrailerSection.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/component/TrailerSection.kt @@ -9,6 +9,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalUriHandler @@ -63,7 +64,14 @@ fun TrailerSection( modifier = Modifier.size(48.dp), painter = painterResource(SharedRes.images.youtube), contentDescription = null, - colorFilter = ColorFilter.tint(LocalContentColor.current) + colorFilter = ColorFilter.tint( + Color( + alpha = 200, + red = 205, + green = 32, + blue = 31 + ) + ) ) } else { Icon( diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterComponent.kt index bb479f2..c203126 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterComponent.kt @@ -3,6 +3,7 @@ package dev.datlag.aniflow.ui.navigation.screen.medium.dialog.character import dev.datlag.aniflow.anilist.CharacterStateMachine import dev.datlag.aniflow.anilist.model.Character import dev.datlag.aniflow.ui.navigation.DialogComponent +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow interface CharacterComponent : DialogComponent { @@ -10,15 +11,15 @@ interface CharacterComponent : DialogComponent { val state: StateFlow - val image: StateFlow - val name: StateFlow - val gender: StateFlow - val bloodType: StateFlow - val birthDate: StateFlow - val description: StateFlow + val image: Flow + val name: Flow + val gender: Flow + val bloodType: Flow + val birthDate: Flow + val description: Flow val translatedDescription: StateFlow - val isFavorite: StateFlow - val isFavoriteBlocked: StateFlow + val isFavorite: Flow + val isFavoriteBlocked: Flow fun descriptionTranslation(text: String?) fun retry() diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialog.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialog.kt index 58d7653..b8c1d30 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialog.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialog.kt @@ -52,13 +52,13 @@ fun CharacterDialog(component: CharacterComponent) { windowInsets = insets, sheetState = sheetState ) { - val name by component.name.collectAsStateWithLifecycle() + val name by component.name.collectAsStateWithLifecycle(component.initialChar.name) Box( modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), contentAlignment = Alignment.Center ) { - val image by component.image.collectAsStateWithLifecycle() + val image by component.image.collectAsStateWithLifecycle(component.initialChar.image) val state by component.state.collectAsStateWithLifecycle() this@ModalBottomSheet.AnimatedVisibility( @@ -108,8 +108,8 @@ fun CharacterDialog(component: CharacterComponent) { enter = fadeIn(), exit = fadeOut() ) { - val isFavoriteBlocked by component.isFavoriteBlocked.collectAsStateWithLifecycle() - val isFavorite by component.isFavorite.collectAsStateWithLifecycle() + val isFavoriteBlocked by component.isFavoriteBlocked.collectAsStateWithLifecycle(component.initialChar.isFavoriteBlocked) + val isFavorite by component.isFavorite.collectAsStateWithLifecycle(component.initialChar.isFavorite) var favoriteChanged by remember(isFavorite) { mutableStateOf(null) } IconButton( @@ -146,7 +146,7 @@ fun CharacterDialog(component: CharacterComponent) { verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), horizontalAlignment = Alignment.CenterHorizontally ) { - val description by component.description.collectAsStateWithLifecycle() + val description by component.description.collectAsStateWithLifecycle(component.initialChar.description) val translatedDescription by component.translatedDescription.collectAsStateWithLifecycle() val textHasPadding = remember(translatedDescription, description) { !translatedDescription.isNullOrBlank() || !description.isNullOrBlank() @@ -162,9 +162,9 @@ fun CharacterDialog(component: CharacterComponent) { verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), horizontalArrangement = Arrangement.SpaceAround ) { - val gender by component.gender.collectAsStateWithLifecycle() - val bloodType by component.bloodType.collectAsStateWithLifecycle() - val birthDate by component.birthDate.collectAsStateWithLifecycle() + val gender by component.gender.collectAsStateWithLifecycle(component.initialChar.gender) + val bloodType by component.bloodType.collectAsStateWithLifecycle(component.initialChar.bloodType) + val birthDate by component.birthDate.collectAsStateWithLifecycle(component.initialChar.birthDate) bloodType?.let { Column( diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialogComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialogComponent.kt index ba2425c..5754be9 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialogComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialogComponent.kt @@ -43,105 +43,41 @@ class CharacterDialogComponent( ) private val characterSuccessState = state.mapNotNull { it.safeCast() - }.flowOn( - context = ioDispatcher() - ).stateIn( - scope = ioScope(), - started = SharingStarted.WhileSubscribed(), - initialValue = null - ) - - private val id = characterSuccessState.mapNotNull { - it?.character?.id - }.flowOn( - context = ioDispatcher() - ).stateIn( - scope = ioScope(), - started = SharingStarted.WhileSubscribed(), - initialValue = initialChar.id - ) + } - override val image: StateFlow = characterSuccessState.mapNotNull { - it?.character?.image - }.flowOn( - context = ioDispatcher() - ).stateIn( - scope = ioScope(), - started = SharingStarted.WhileSubscribed(), - initialValue = initialChar.image - ) + override val image: Flow = characterSuccessState.map { + it.character.image + } - override val name: StateFlow = characterSuccessState.mapNotNull { - it?.character?.name - }.flowOn( - context = ioDispatcher() - ).stateIn( - scope = ioScope(), - started = SharingStarted.WhileSubscribed(), - initialValue = initialChar.name - ) + override val name: Flow = characterSuccessState.map { + it.character.name + } - override val gender: StateFlow = characterSuccessState.mapNotNull { - it?.character?.gender - }.flowOn( - context = ioDispatcher() - ).stateIn( - scope = ioScope(), - started = SharingStarted.WhileSubscribed(), - initialValue = initialChar.gender - ) + override val gender: Flow = characterSuccessState.map { + it.character.gender + } - override val bloodType: StateFlow = characterSuccessState.mapNotNull { - it?.character?.bloodType - }.flowOn( - context = ioDispatcher() - ).stateIn( - scope = ioScope(), - started = SharingStarted.WhileSubscribed(), - initialValue = initialChar.bloodType - ) + override val bloodType: Flow = characterSuccessState.map { + it.character.bloodType + } - override val birthDate: StateFlow = characterSuccessState.mapNotNull { - it?.character?.birthDate - }.flowOn( - context = ioDispatcher() - ).stateIn( - scope = ioScope(), - started = SharingStarted.WhileSubscribed(), - initialValue = initialChar.birthDate - ) + override val birthDate: Flow = characterSuccessState.map { + it.character.birthDate + } - override val description: StateFlow = characterSuccessState.mapNotNull { - it?.character?.description - }.flowOn( - context = ioDispatcher() - ).stateIn( - scope = ioScope(), - started = SharingStarted.WhileSubscribed(), - initialValue = initialChar.description - ) + override val description: Flow = characterSuccessState.map { + it.character.description + } override val translatedDescription: MutableStateFlow = MutableStateFlow(null) - override val isFavorite: StateFlow = characterSuccessState.mapNotNull { - it?.character?.isFavorite - }.flowOn( - context = ioDispatcher() - ).stateIn( - scope = ioScope(), - started = SharingStarted.WhileSubscribed(), - initialValue = initialChar.isFavorite - ) + override val isFavorite: Flow = characterSuccessState.map { + it.character.isFavorite + } - override val isFavoriteBlocked: StateFlow = characterSuccessState.mapNotNull { - it?.character?.isFavoriteBlocked - }.flowOn( - context = ioDispatcher() - ).stateIn( - scope = ioScope(), - started = SharingStarted.WhileSubscribed(), - initialValue = initialChar.isFavoriteBlocked - ) + override val isFavoriteBlocked: Flow = characterSuccessState.map { + it.character.isFavoriteBlocked + } @Composable override fun render() { @@ -159,14 +95,14 @@ class CharacterDialogComponent( } override fun retry() { - launchIO { + launchDefault { characterStateMachine.dispatch(CharacterStateMachine.Action.Retry) } } override fun toggleFavorite() { launchIO { - val charId = id.safeFirstOrNull() ?: id.value + val charId = initialChar.id val mutation = FavoriteToggleMutation( characterId = Optional.present(charId) ) diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/theme/SchemeTheme.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/theme/SchemeTheme.kt index d37b560..1b15a09 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/theme/SchemeTheme.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/theme/SchemeTheme.kt @@ -18,7 +18,7 @@ import dev.datlag.aniflow.model.coroutines.Executor import dev.datlag.tooling.async.scopeCatching import dev.datlag.tooling.async.suspendCatching import dev.datlag.tooling.compose.ioDispatcher -import dev.datlag.tooling.compose.launchIO +import dev.datlag.tooling.compose.launchDefault import dev.datlag.tooling.compose.withIOContext import dev.datlag.tooling.decompose.lifecycle.collectAsStateWithLifecycle import kotlinx.coroutines.CoroutineScope @@ -73,7 +73,7 @@ data object SchemeTheme { return } - scope.launchIO { + scope.launchDefault { executor.enqueue { state.updateFrom(input) } @@ -90,7 +90,7 @@ data object SchemeTheme { return } - scope.launchIO { + scope.launchDefault { executor.enqueue { val state = get(key) ?: return@enqueue state.updateFrom(input) @@ -106,7 +106,6 @@ fun rememberSchemeThemeDominantColorState( key: Any?, defaultColor: Color = MaterialTheme.colorScheme.primary, defaultOnColor: Color = MaterialTheme.colorScheme.onPrimary, - coroutineContext: CoroutineContext = ioDispatcher(), isSwatchValid: (Palette.Swatch) -> Boolean = { true }, builder: Palette.Builder.() -> Unit = {}, ): DominantColorState? { @@ -119,7 +118,6 @@ fun rememberSchemeThemeDominantColorState( } ?: rememberPainterDominantColorState( defaultColor = defaultColor, defaultOnColor = defaultOnColor, - coroutineContext = coroutineContext, builder = builder, isSwatchValid = isSwatchValid ) @@ -139,14 +137,12 @@ fun rememberSchemeThemeDominantColorState( defaultOnColor: Color = MaterialTheme.colorScheme.onPrimary, clearFilter: Boolean = false, applyMinContrast: Boolean = false, - minContrastBackgroundColor: Color = Color.Transparent, - coroutineContext: CoroutineContext = ioDispatcher() + minContrastBackgroundColor: Color = Color.Transparent ): DominantColorState? { return rememberSchemeThemeDominantColorState( key = key, defaultColor = defaultColor, defaultOnColor = defaultOnColor, - coroutineContext = coroutineContext, builder = { if (clearFilter) { clearFilters()