diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/MediaItemMenu.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/MediaItemMenu.kt index 43f6a01..76da774 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/MediaItemMenu.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/components/themed/MediaItemMenu.kt @@ -3,6 +3,8 @@ package it.vfsfitvnm.vimusic.ui.components.themed import android.content.Intent import android.text.format.DateUtils import androidx.compose.animation.AnimatedContentScope +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.ExitTransition import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.with import androidx.compose.foundation.background @@ -35,7 +37,6 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.media3.common.MediaItem import it.vfsfitvnm.route.RouteHandler -import it.vfsfitvnm.route.empty import it.vfsfitvnm.vimusic.Database import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder import it.vfsfitvnm.vimusic.R @@ -282,7 +283,7 @@ fun MediaItemMenu( else -> when (initialState.route) { viewPlaylistsRoute -> slideIntoContainer(AnimatedContentScope.SlideDirection.Right) with slideOutOfContainer(AnimatedContentScope.SlideDirection.Right) - else -> empty + else -> EnterTransition.None with ExitTransition.None } } } diff --git a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/home/HomeScreen.kt b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/home/HomeScreen.kt index 6a42c07..396b00a 100644 --- a/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/home/HomeScreen.kt +++ b/app/src/main/kotlin/it/vfsfitvnm/vimusic/ui/screens/home/HomeScreen.kt @@ -5,6 +5,12 @@ import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.runtime.Composable import androidx.compose.runtime.saveable.rememberSaveableStateHolder import it.vfsfitvnm.route.RouteHandler +import it.vfsfitvnm.route.defaultStacking +import it.vfsfitvnm.route.defaultStill +import it.vfsfitvnm.route.defaultUnstacking +import it.vfsfitvnm.route.isStacking +import it.vfsfitvnm.route.isUnknown +import it.vfsfitvnm.route.isUnstacking import it.vfsfitvnm.vimusic.Database import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.models.SearchQuery @@ -33,7 +39,21 @@ import it.vfsfitvnm.vimusic.utils.rememberPreference fun HomeScreen(onPlaylistUrl: (String) -> Unit) { val saveableStateHolder = rememberSaveableStateHolder() - RouteHandler(listenToGlobalEmitter = true) { + RouteHandler( + listenToGlobalEmitter = true, + transitionSpec = { + when { + isStacking -> defaultStacking + isUnstacking -> defaultUnstacking + isUnknown -> when { + initialState.route == searchRoute && targetState.route == searchResultRoute -> defaultStacking + initialState.route == searchResultRoute && targetState.route == searchRoute -> defaultUnstacking + else -> defaultStill + } + else -> defaultStill + } + } + ) { globalRoutes() settingsRoute { @@ -65,6 +85,7 @@ fun HomeScreen(onPlaylistUrl: (String) -> Unit) { SearchScreen( initialTextInput = initialTextInput, onSearch = { query -> + pop() searchResultRoute(query) query { diff --git a/compose-routing/src/main/kotlin/it/vfsfitvnm/route/RouteHandler.kt b/compose-routing/src/main/kotlin/it/vfsfitvnm/route/RouteHandler.kt index a71b1ee..14032bc 100644 --- a/compose-routing/src/main/kotlin/it/vfsfitvnm/route/RouteHandler.kt +++ b/compose-routing/src/main/kotlin/it/vfsfitvnm/route/RouteHandler.kt @@ -21,7 +21,13 @@ fun RouteHandler( modifier: Modifier = Modifier, listenToGlobalEmitter: Boolean = false, handleBackPress: Boolean = true, - transitionSpec: AnimatedContentScope.() -> ContentTransform = { fastFade }, + transitionSpec: AnimatedContentScope.() -> ContentTransform = { + when { + isStacking -> defaultStacking + isStill -> defaultStill + else -> defaultUnstacking + } + }, content: @Composable RouteHandlerScope.() -> Unit ) { var route by rememberSaveable(stateSaver = Route.Saver) { @@ -47,7 +53,13 @@ fun RouteHandler( modifier: Modifier = Modifier, listenToGlobalEmitter: Boolean = false, handleBackPress: Boolean = true, - transitionSpec: AnimatedContentScope.() -> ContentTransform = { fastFade }, + transitionSpec: AnimatedContentScope.() -> ContentTransform = { + when { + isStacking -> defaultStacking + isStill -> defaultStill + else -> defaultUnstacking + } + }, content: @Composable RouteHandlerScope.() -> Unit ) { val backDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher diff --git a/compose-routing/src/main/kotlin/it/vfsfitvnm/route/Transitions.kt b/compose-routing/src/main/kotlin/it/vfsfitvnm/route/Transitions.kt index b87cad0..79a54a1 100644 --- a/compose-routing/src/main/kotlin/it/vfsfitvnm/route/Transitions.kt +++ b/compose-routing/src/main/kotlin/it/vfsfitvnm/route/Transitions.kt @@ -3,27 +3,44 @@ package it.vfsfitvnm.route import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.ContentTransform import androidx.compose.animation.EnterTransition -import androidx.compose.animation.ExitTransition import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut -import androidx.compose.animation.with +import androidx.compose.animation.scaleOut @ExperimentalAnimationApi -val AnimatedContentScope.leftSlide: ContentTransform - get() = slideIntoContainer(AnimatedContentScope.SlideDirection.Left) with - slideOutOfContainer(AnimatedContentScope.SlideDirection.Left) +val defaultStacking = ContentTransform( + initialContentExit = scaleOut(targetScale = 0.9f) + fadeOut(), + targetContentEnter = fadeIn(), + targetContentZIndex = 1f +) @ExperimentalAnimationApi -val AnimatedContentScope.rightSlide: ContentTransform - get() = slideIntoContainer(AnimatedContentScope.SlideDirection.Right) with - slideOutOfContainer(AnimatedContentScope.SlideDirection.Right) +val defaultUnstacking = ContentTransform( + initialContentExit = fadeOut(), + targetContentEnter = EnterTransition.None, + targetContentZIndex = 0f +) @ExperimentalAnimationApi -val AnimatedContentScope.fastFade: ContentTransform - get() = fadeIn(tween(200)) with fadeOut(tween(200)) +val defaultStill = ContentTransform( + initialContentExit = scaleOut(targetScale = 0.9f) + fadeOut(), + targetContentEnter = fadeIn(), + targetContentZIndex = 1f +) @ExperimentalAnimationApi -val AnimatedContentScope.empty: ContentTransform - get() = EnterTransition.None with ExitTransition.None +inline val AnimatedContentScope.isStacking: Boolean + get() = initialState.route == null && targetState.route != null + +@ExperimentalAnimationApi +inline val AnimatedContentScope.isUnstacking: Boolean + get() = initialState.route != null && targetState.route == null + +@ExperimentalAnimationApi +inline val AnimatedContentScope.isStill: Boolean + get() = initialState.route == null && targetState.route == null + +@ExperimentalAnimationApi +inline val AnimatedContentScope.isUnknown: Boolean + get() = initialState.route != null && targetState.route != null