android: Animated switch between chat and chatList

This commit is contained in:
Avently
2022-10-05 19:15:31 +03:00
parent 22edd92079
commit 6058ef33aa
4 changed files with 73 additions and 40 deletions
@@ -327,13 +327,14 @@ fun MainPage(
else {
showAdvertiseLAAlert = true
val stopped = chatModel.chatRunning.value == false
if (chatModel.chatId.value == null) {
if (chatModel.sharedContent.value == null)
ChatListView(chatModel, setPerformLA, stopped)
else
ShareListView(chatModel, stopped)
AnimateScreensNullable(chatModel.chatId) { current ->
if (current == null) {
if (chatModel.sharedContent.value == null)
ChatListView(chatModel, setPerformLA, stopped)
else
ShareListView(chatModel, stopped)
} else ChatView(chatModel)
}
else ChatView(chatModel)
}
}
}
@@ -15,7 +15,6 @@ import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.platform.LocalUriHandler
@@ -0,0 +1,65 @@
package chat.simplex.app.views.helpers
import androidx.compose.animation.*
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun <S: Comparable<S>> AnimateScreens(
targetState: MutableState<S>,
content: @Composable AnimatedVisibilityScope.(targetState: S) -> Unit
) {
AnimatedContent(
targetState = targetState.value,
transitionSpec = {
when {
targetState.value > initialState -> fromEndToStartTransition()
else -> fromStartToEndTransition()
}.using(SizeTransform(clip = false))
},
content = content
)
}
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun <S> AnimateScreensNullable(
targetState: MutableState<S>,
content: @Composable AnimatedVisibilityScope.(targetState: S) -> Unit
) {
AnimatedContent(
targetState = targetState.value,
transitionSpec = {
when {
targetState.value != null -> fromEndToStartTransition()
else -> fromStartToEndTransition()
}.using(SizeTransform(clip = false))
},
content = content
)
}
@OptIn(ExperimentalAnimationApi::class)
private fun fromStartToEndTransition() =
slideInHorizontally(
initialOffsetX = { fullWidth -> -fullWidth },
animationSpec = animationSpec()
) with slideOutHorizontally(
targetOffsetX = { fullWidth -> fullWidth },
animationSpec = animationSpec()
)
@OptIn(ExperimentalAnimationApi::class)
private fun fromEndToStartTransition() =
slideInHorizontally(
initialOffsetX = { fullWidth -> fullWidth },
animationSpec = animationSpec()
) with slideOutHorizontally(
targetOffsetX = { fullWidth -> -fullWidth },
animationSpec = animationSpec()
)
private fun <T> animationSpec() = tween<T>(durationMillis = 250, easing = FastOutSlowInEasing)
@@ -69,15 +69,7 @@ class ModalManager {
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun showInView() {
AnimatedContent(targetState = modalCount.value,
transitionSpec = {
if (targetState > initialState) {
fromEndToStartTransition()
} else {
fromStartToEndTransition()
}.using(SizeTransform(clip = false))
}
) {
AnimateScreens(modalCount) {
modalViews.getOrNull(it - 1)?.invoke(::closeModal)
// This is needed because if we delete from modalViews immediately on request, animation will be bad
if (toRemove.isNotEmpty() && it == modalCount.value && transition.currentState == EnterExitState.Visible && !transition.isRunning) {
@@ -86,30 +78,6 @@ class ModalManager {
}
}
@OptIn(ExperimentalAnimationApi::class)
private fun fromStartToEndTransition() =
slideInHorizontally(
initialOffsetX = { fullWidth -> -fullWidth },
animationSpec = animationSpec()
) with slideOutHorizontally(
targetOffsetX = { fullWidth -> fullWidth },
animationSpec = animationSpec()
)
@OptIn(ExperimentalAnimationApi::class)
private fun fromEndToStartTransition() =
slideInHorizontally(
initialOffsetX = { fullWidth -> fullWidth },
animationSpec = animationSpec()
) with slideOutHorizontally(
targetOffsetX = { fullWidth -> -fullWidth },
animationSpec = animationSpec()
)
private fun <T> animationSpec() = tween<T>(durationMillis = 250, easing = FastOutSlowInEasing)
// private fun <T> animationSpecFromStart() = tween<T>(durationMillis = 150, easing = FastOutLinearInEasing)
// private fun <T> animationSpecFromEnd() = tween<T>(durationMillis = 100, easing = FastOutSlowInEasing)
companion object {
val shared = ModalManager()
}