diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/MediumComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/MediumComponent.kt index 537d4f7c..ca4616f5 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/MediumComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/MediumComponent.kt @@ -5,6 +5,8 @@ import androidx.compose.material.icons.rounded.Devices import androidx.compose.material.icons.rounded.Speaker import androidx.compose.material.icons.rounded.Tv import androidx.compose.material.icons.rounded.Warning +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.graphics.vector.ImageVector import com.arkivanov.decompose.router.slot.ChildSlot import com.arkivanov.decompose.value.Value @@ -50,6 +52,8 @@ interface MediumComponent : Component { val isFavorite: StateFlow + val focus: Focus + fun back() fun season(value: Series.Season) fun language(value: Series.Language) @@ -69,6 +73,25 @@ interface MediumComponent : Component { streams: ImmutableCollection ) + data class Focus( + val seasonAndLanguageButtons: FocusRequester, + val floatingActionButton: FocusRequester, + val descriptionExtender: FocusRequester + ) { + companion object { + @OptIn(ExperimentalComposeUiApi::class) + fun create(): Focus { + val (sl, fab, desc) = FocusRequester.createRefs() + + return Focus( + seasonAndLanguageButtons = sl, + floatingActionButton = fab, + descriptionExtender = desc + ) + } + } + } + sealed interface Device { val icon: ImageVector val name: String diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/MediumScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/MediumScreen.kt index 9937816c..8f8efc40 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/MediumScreen.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/MediumScreen.kt @@ -46,6 +46,7 @@ import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusProperties import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextOverflow @@ -122,14 +123,11 @@ fun MediumScreen(component: MediumComponent, updater: SchemeTheme.Updater?) { dialogState.child?.instance?.render() - val (seasonFocus, fabFocus) = FocusRequester.createRefs() Scaffold( topBar = { Toolbar( component = component, - series = (seriesState as? SeriesState.Success)?.series, - seasonFocus = seasonFocus, - fabFocus = fabFocus + series = (seriesState as? SeriesState.Success)?.series ) }, floatingActionButton = { @@ -137,7 +135,11 @@ fun MediumScreen(component: MediumComponent, updater: SchemeTheme.Updater?) { nextEpisode?.ifHasHoster()?.let { episode -> ExtendedFloatingActionButton( - modifier = Modifier.focusRequester(fabFocus), + modifier = Modifier + .focusRequester(component.focus.floatingActionButton) + .focusProperties { + start = component.focus.seasonAndLanguageButtons + }, onClick = { component.episode(episode) }, @@ -192,7 +194,11 @@ fun MediumScreen(component: MediumComponent, updater: SchemeTheme.Updater?) { .fillParentMaxWidth() .padding(horizontal = 16.dp) .padding(top = 8.dp) - .focusRequester(seasonFocus) + .focusRequester(component.focus.seasonAndLanguageButtons) + .focusProperties { + down = component.focus.descriptionExtender + next = component.focus.descriptionExtender + } ) } if (isAndroidPhone && isAnime && !isAniFlowInstalled) { diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/MediumScreenComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/MediumScreenComponent.kt index c7e4c7ef..f6e44855 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/MediumScreenComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/MediumScreenComponent.kt @@ -212,6 +212,8 @@ class MediumScreenComponent( private val userHelper by instance() + override val focus: MediumComponent.Focus = MediumComponent.Focus.create() + init { val hrefWithLanguage = if (initialLanguage != null) { seriesData.toHref(newLanguage = initialLanguage.code) diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/component/DescriptionSection.kt b/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/component/DescriptionSection.kt index c0c80e24..3dcff3a9 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/component/DescriptionSection.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/component/DescriptionSection.kt @@ -1,8 +1,11 @@ package dev.datlag.burningseries.ui.navigation.screen.medium.component +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.animateIntAsState import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -23,6 +26,8 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.focusProperties +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import dev.datlag.burningseries.composeapp.generated.resources.Res @@ -88,9 +93,19 @@ internal fun DescriptionSection( } ) } - if (descriptionExpandable) { + AnimatedVisibility( + visible = descriptionExpandable, + enter = fadeIn(), + exit = fadeOut() + ) { PlatformIconButton( - modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + .focusRequester(component.focus.descriptionExtender) + .focusProperties { + previous = component.focus.seasonAndLanguageButtons + }, onClick = { descriptionExpanded = !descriptionExpanded }, diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/component/Toolbar.kt b/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/component/Toolbar.kt index 09272754..f1df9b23 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/component/Toolbar.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/burningseries/ui/navigation/screen/medium/component/Toolbar.kt @@ -93,14 +93,15 @@ import org.jetbrains.compose.resources.stringResource @Composable internal fun Toolbar( component: MediumComponent, - series: Series?, - seasonFocus: FocusRequester, - fabFocus: FocusRequester + series: Series? ) { TopAppBar( navigationIcon = { ProvideNonTvContentColor { PlatformIconButton( + modifier = Modifier.focusProperties { + down = component.focus.seasonAndLanguageButtons + }, onClick = component::back ) { PlatformIcon( @@ -272,8 +273,8 @@ internal fun Toolbar( if (isFavorite) { PlatformIconButton( modifier = Modifier.focusProperties { - end = fabFocus - down = seasonFocus + end = component.focus.floatingActionButton + down = component.focus.seasonAndLanguageButtons }, onClick = { if (series != null) { @@ -290,8 +291,8 @@ internal fun Toolbar( } else { PlatformIconButton( modifier = Modifier.focusProperties { - end = fabFocus - down = seasonFocus + end = component.focus.floatingActionButton + down = component.focus.seasonAndLanguageButtons }, onClick = { if (series != null) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 33132911..a6b43a09 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -36,7 +36,7 @@ ksoup = "0.1.2" ksp = "2.0.0-1.0.23" ktor = "2.3.12" ktorfit = "2.0.0" -media3 = "1.4.0-rc01" +media3 = "1.4.0" moko-resources = "0.24.1" multidex = "2.0.1" nanoid = "1.0.1"