mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-04-27 08:35:58 +00:00
android: Animated switch between chat and chatList
This commit is contained in:
@@ -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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user