From 6058ef33aa9b40aceb83b1858ea5feeaf106c5bb Mon Sep 17 00:00:00 2001 From: Avently <7953703+avently@users.noreply.github.com> Date: Wed, 5 Oct 2022 19:15:31 +0300 Subject: [PATCH] android: Animated switch between chat and chatList --- .../java/chat/simplex/app/MainActivity.kt | 13 ++-- .../app/views/chatlist/ChatListView.kt | 1 - .../app/views/helpers/AnimationUtils.kt | 65 +++++++++++++++++++ .../simplex/app/views/helpers/ModalView.kt | 34 +--------- 4 files changed, 73 insertions(+), 40 deletions(-) create mode 100644 apps/android/app/src/main/java/chat/simplex/app/views/helpers/AnimationUtils.kt diff --git a/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt b/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt index 17ab557f68..709f28c859 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt @@ -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) } } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt index bd5018546e..ba12f4d2ec 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt @@ -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 diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AnimationUtils.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AnimationUtils.kt new file mode 100644 index 0000000000..12408ccc3d --- /dev/null +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AnimationUtils.kt @@ -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 > AnimateScreens( + targetState: MutableState, + 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 AnimateScreensNullable( + targetState: MutableState, + 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 animationSpec() = tween(durationMillis = 250, easing = FastOutSlowInEasing) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt index ae184c1efe..b9dd843c51 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt @@ -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 animationSpec() = tween(durationMillis = 250, easing = FastOutSlowInEasing) -// private fun animationSpecFromStart() = tween(durationMillis = 150, easing = FastOutLinearInEasing) -// private fun animationSpecFromEnd() = tween(durationMillis = 100, easing = FastOutSlowInEasing) - companion object { val shared = ModalManager() }