Use sliding transition for settings navigation

This commit is contained in:
Niels van Velzen authored and Niels van Velzen committed 2026-01-01 18:05:20 +01:00
1 parent 0f5f1b23fc
commit 875f094ff2
6 files changed
+73 -10

No files matched your search

@@ -6,9 +6,9 @@ import androidx.compose.ui.platform.ComposeView
import kotlinx.coroutines.flow.MutableStateFlow
import org.jellyfin.androidtv.ui.base.JellyfinTheme
import org.jellyfin.androidtv.ui.navigation.ProvideRouter
import org.jellyfin.androidtv.ui.navigation.RouterContent
import org.jellyfin.androidtv.ui.settings.Routes
import org.jellyfin.androidtv.ui.settings.composable.SettingsDialog
import org.jellyfin.androidtv.ui.settings.composable.SettingsRouterContent
import org.jellyfin.androidtv.ui.settings.routes
import java.util.UUID
@@ -32,7 +32,7 @@ fun BrowseGridFragment.addSettings(
onResume()
}
) {
RouterContent()
SettingsRouterContent()
}
}
}
@@ -17,9 +17,9 @@ import org.jellyfin.androidtv.databinding.LiveTvGuideBinding
import org.jellyfin.androidtv.ui.GuideChannelHeader
import org.jellyfin.androidtv.ui.base.JellyfinTheme
import org.jellyfin.androidtv.ui.navigation.ProvideRouter
import org.jellyfin.androidtv.ui.navigation.RouterContent
import org.jellyfin.androidtv.ui.settings.Routes
import org.jellyfin.androidtv.ui.settings.composable.SettingsDialog
import org.jellyfin.androidtv.ui.settings.composable.SettingsRouterContent
import org.jellyfin.androidtv.ui.settings.routes
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
@@ -104,7 +104,7 @@ fun LiveTvGuideFragment.addSettingsOptions(binding: LiveTvGuideBinding): Mutable
doLoad()
}
) {
RouterContent()
SettingsRouterContent()
}
}
}
@@ -132,7 +132,7 @@ fun LiveTvGuideFragment.addSettingsFilters(binding: LiveTvGuideBinding): Mutable
doLoad()
}
) {
RouterContent()
SettingsRouterContent()
}
}
}
@@ -1,5 +1,7 @@
package org.jellyfin.androidtv.ui.navigation
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.ContentTransform
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
@@ -8,7 +10,11 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.navigation3.runtime.NavEntry
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
import androidx.navigation3.scene.Scene
import androidx.navigation3.ui.NavDisplay
import androidx.navigation3.ui.defaultPopTransitionSpec
import androidx.navigation3.ui.defaultTransitionSpec
import androidx.navigationevent.NavigationEvent
typealias RouteParameters = Map<String, String>
typealias RouteComposable = @Composable ((context: RouteContext) -> Unit)
@@ -75,7 +81,10 @@ fun ProvideRouter(
@Composable
fun RouterContent(
router: Router = LocalRouter.current,
fallbackRoute: String = "/"
fallbackRoute: String = "/",
transitionSpec: AnimatedContentTransitionScope<Scene<RouteContext>>.() -> ContentTransform = defaultTransitionSpec(),
popTransitionSpec: AnimatedContentTransitionScope<Scene<RouteContext>>.() -> ContentTransform = defaultPopTransitionSpec(),
predictivePopTransitionSpec: AnimatedContentTransitionScope<Scene<RouteContext>>.(@NavigationEvent.SwipeEdge Int) -> ContentTransform = { popTransitionSpec() },
) {
NavDisplay(
backStack = router.backStack,
@@ -83,6 +92,9 @@ fun RouterContent(
entryDecorators = listOf(
rememberSaveableStateHolderNavEntryDecorator(),
),
transitionSpec = transitionSpec,
popTransitionSpec = popTransitionSpec,
predictivePopTransitionSpec = predictivePopTransitionSpec,
entryProvider = { backStackEntry ->
NavEntry(backStackEntry) {
val route = backStackEntry.route
@@ -5,9 +5,9 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import org.jellyfin.androidtv.ui.base.JellyfinTheme
import org.jellyfin.androidtv.ui.navigation.ProvideRouter
import org.jellyfin.androidtv.ui.navigation.RouterContent
import org.jellyfin.androidtv.ui.settings.Routes
import org.jellyfin.androidtv.ui.settings.composable.SettingsDialog
import org.jellyfin.androidtv.ui.settings.composable.SettingsRouterContent
import org.jellyfin.androidtv.ui.settings.routes
import org.koin.compose.viewmodel.koinActivityViewModel
@@ -22,7 +22,7 @@ fun MainActivitySettings() {
visible = visible,
onDismissRequest = { viewModel.hide() }
) {
RouterContent()
SettingsRouterContent()
}
}
}
@@ -0,0 +1,51 @@
package org.jellyfin.androidtv.ui.settings.composable
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.togetherWith
import androidx.compose.runtime.Composable
import org.jellyfin.androidtv.ui.navigation.RouterContent
/**
* Wrapper for the [RouterContent] composable that sets the settings slide in/out transitions.
*/
@Composable
fun SettingsRouterContent() {
val duration = 400 // milliseconds
val transitionIn = slideInHorizontally(
initialOffsetX = { it },
animationSpec = tween(duration, easing = FastOutSlowInEasing)
) + fadeIn(
animationSpec = tween(duration)
)
val transitionOut = slideOutHorizontally(
targetOffsetX = { -it / 3 },
animationSpec = tween(duration, easing = FastOutSlowInEasing)
) + fadeOut(
animationSpec = tween(duration)
)
val popIn = slideInHorizontally(
initialOffsetX = { -it / 3 },
animationSpec = tween(duration, easing = FastOutSlowInEasing)
) + fadeIn(
animationSpec = tween(duration)
)
val popOut = slideOutHorizontally(
targetOffsetX = { it },
animationSpec = tween(duration, easing = FastOutSlowInEasing)
) + fadeOut(
animationSpec = tween(duration)
)
RouterContent(
transitionSpec = { transitionIn togetherWith transitionOut },
popTransitionSpec = { popIn togetherWith popOut },
)
}
@@ -16,9 +16,9 @@ import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.ui.base.Icon
import org.jellyfin.androidtv.ui.base.button.IconButton
import org.jellyfin.androidtv.ui.navigation.ProvideRouter
import org.jellyfin.androidtv.ui.navigation.RouterContent
import org.jellyfin.androidtv.ui.settings.Routes
import org.jellyfin.androidtv.ui.settings.composable.SettingsDialog
import org.jellyfin.androidtv.ui.settings.composable.SettingsRouterContent
import org.jellyfin.androidtv.ui.settings.routes
@Composable
@@ -57,7 +57,7 @@ fun StartupToolbar(
visible = settingsVisible,
onDismissRequest = { settingsVisible = false }
) {
RouterContent()
SettingsRouterContent()
}
}
}