From 4e1971605b2a72d5f12569736e78e21fec92e623 Mon Sep 17 00:00:00 2001 From: Dan Galpin Date: Thu, 30 May 2024 09:19:32 -0700 Subject: [PATCH 1/2] Added shared element transition between contact row and chat screen --- .../samples/socialite/BubbleActivity.kt | 2 + .../android/samples/socialite/ui/Bubble.kt | 38 +-- .../samples/socialite/ui/ContactRow.kt | 118 ++++++---- .../android/samples/socialite/ui/Main.kt | 218 ++++++++++-------- .../samples/socialite/ui/chat/ChatScreen.kt | 136 +++++++---- .../samples/socialite/ui/home/ChatList.kt | 9 +- .../android/samples/socialite/ui/home/Home.kt | 21 +- gradle/libs.versions.toml | 2 +- 8 files changed, 336 insertions(+), 208 deletions(-) diff --git a/app/src/main/java/com/google/android/samples/socialite/BubbleActivity.kt b/app/src/main/java/com/google/android/samples/socialite/BubbleActivity.kt index deb8cc47..ba1303ba 100644 --- a/app/src/main/java/com/google/android/samples/socialite/BubbleActivity.kt +++ b/app/src/main/java/com/google/android/samples/socialite/BubbleActivity.kt @@ -20,7 +20,9 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import com.google.android.samples.socialite.ui.Bubble +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class BubbleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/Bubble.kt b/app/src/main/java/com/google/android/samples/socialite/ui/Bubble.kt index 4cb2d4db..ce2e6cdb 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/Bubble.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/Bubble.kt @@ -16,25 +16,37 @@ package com.google.android.samples.socialite.ui +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.AnimatedContentScope +import androidx.compose.animation.ExperimentalSharedTransitionApi +import androidx.compose.animation.SharedTransitionLayout +import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.google.android.samples.socialite.ui.chat.ChatScreen +@OptIn(ExperimentalSharedTransitionApi::class) @Composable fun Bubble(chatId: Long) { - SocialTheme { - ChatScreen( - chatId = chatId, - foreground = false, - onBackPressed = null, - // TODO (donovanfm): Hook up camera button in the Bubble composable - onCameraClick = {}, - // TODO (jolandaverhoef): Hook up play video button in the Bubble composable - onVideoClick = {}, - // TODO (mayurikhin): Hook up camera button in the Bubble composable - onPhotoPickerClick = {}, - modifier = Modifier.fillMaxSize(), - ) + SharedTransitionLayout { + AnimatedContent(targetState = 1) { _ -> + SocialTheme { + ChatScreen( + chatId = chatId, + foreground = false, + onBackPressed = null, + // TODO (donovanfm): Hook up camera button in the Bubble composable + onCameraClick = {}, + // TODO (jolandaverhoef): Hook up play video button in the Bubble composable + onVideoClick = {}, + // TODO (mayurikhin): Hook up camera button in the Bubble composable + onPhotoPickerClick = {}, + modifier = Modifier.fillMaxSize(), + sharedTransitionScope = this@SharedTransitionLayout, + animatedContentScope = this@AnimatedContent + ) + } + } } } diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/ContactRow.kt b/app/src/main/java/com/google/android/samples/socialite/ui/ContactRow.kt index 0651a6f2..800d22a4 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/ContactRow.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/ContactRow.kt @@ -16,6 +16,11 @@ package com.google.android.samples.socialite.ui +import androidx.compose.animation.AnimatedContentScope +import androidx.compose.animation.ExperimentalSharedTransitionApi +import androidx.compose.animation.SharedTransitionScope +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -40,60 +45,81 @@ import androidx.compose.ui.unit.sp import com.google.android.samples.socialite.data.utils.toReadableString import com.google.android.samples.socialite.model.ChatDetail +@OptIn(ExperimentalSharedTransitionApi::class) @Composable fun ChatRow( chat: ChatDetail, onClick: (() -> Unit)?, modifier: Modifier = Modifier, + sharedTransitionScope: SharedTransitionScope, + animatedContentScope: AnimatedContentScope ) { - Row( - modifier = modifier - .fillMaxWidth() - .then( - if (onClick != null) Modifier.clickable(onClick = onClick) else Modifier, - ) - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp), - ) { - // This only supports DM for now. - val contact = chat.attendees.first() - Image( - painter = rememberIconPainter(contentUri = contact.iconUri), - contentDescription = null, - modifier = Modifier - .size(48.dp) - .clip(CircleShape) - .background(Color.LightGray), - ) - Column( - modifier = Modifier.weight(1f), - verticalArrangement = Arrangement.SpaceEvenly, - horizontalAlignment = Alignment.Start, - ) { - Text( - text = contact.name, - style = MaterialTheme.typography.bodyLarge, - fontSize = 16.sp, - ) - Text( - text = chat.chatWithLastMessage.text, - style = MaterialTheme.typography.bodySmall, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - modifier = Modifier.padding(top = 4.dp), - fontWeight = FontWeight.Light, - fontSize = 14.sp, - ) - } - Column( - verticalArrangement = Arrangement.SpaceEvenly, - horizontalAlignment = Alignment.CenterHorizontally, + with(sharedTransitionScope) { + Row( + modifier = modifier + .fillMaxWidth() + .then( + if (onClick != null) Modifier.clickable(onClick = onClick) else Modifier, + ) + .padding(16.dp) + .sharedBounds( + sharedTransitionScope.rememberSharedContentState(key = "Bounds${chat.chatWithLastMessage.id}"), + animatedVisibilityScope = animatedContentScope, + enter = fadeIn(), + exit = fadeOut(), + ), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(16.dp), ) { - Text( - text = chat.chatWithLastMessage.timestamp.toReadableString(), - fontSize = 14.sp, + // This only supports DM for now. + val contact = chat.attendees.first() + Image( + painter = rememberIconPainter(contentUri = contact.iconUri), + contentDescription = null, + modifier = Modifier.Companion + .sharedElement( + sharedTransitionScope.rememberSharedContentState(key = chat.chatWithLastMessage.id), + animatedVisibilityScope = animatedContentScope + ) + .size(48.dp) + .clip(CircleShape) + .background(Color.LightGray), ) + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.SpaceEvenly, + horizontalAlignment = Alignment.Start, + ) { + Text( + text = contact.name, + style = MaterialTheme.typography.bodyLarge, + fontSize = 16.sp, + modifier = Modifier.Companion.sharedBounds( + sharedTransitionScope.rememberSharedContentState(key = "Text${chat.chatWithLastMessage.id}"), + animatedVisibilityScope = animatedContentScope, + enter = fadeIn(), + exit = fadeOut(), + ) + ) + Text( + text = chat.chatWithLastMessage.text, + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.padding(top = 4.dp), + fontWeight = FontWeight.Light, + fontSize = 14.sp, + ) + } + Column( + verticalArrangement = Arrangement.SpaceEvenly, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + text = chat.chatWithLastMessage.timestamp.toReadableString(), + fontSize = 14.sp, + ) + } } } } diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/Main.kt b/app/src/main/java/com/google/android/samples/socialite/ui/Main.kt index 6f923a8c..dc211ebd 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/Main.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/Main.kt @@ -20,6 +20,8 @@ import android.app.Activity import android.content.Intent import android.content.pm.ActivityInfo import android.os.Bundle +import androidx.compose.animation.ExperimentalSharedTransitionApi +import androidx.compose.animation.SharedTransitionLayout import androidx.compose.animation.core.FastOutLinearInEasing import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.tween @@ -60,6 +62,7 @@ fun Main( } } +@OptIn(ExperimentalSharedTransitionApi::class) @Composable fun MainNavigation( modifier: Modifier, @@ -78,116 +81,129 @@ fun MainNavigation( activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED } } - - NavHost( - navController = navController, - startDestination = "home", - popEnterTransition = { - scaleIn(initialScale = 1.1F) + fadeIn() - }, - popExitTransition = { - scaleOut(targetScale = 0.9F) + fadeOut() - }, - modifier = modifier, - ) { - composable( - route = "home", + SharedTransitionLayout { + NavHost( + navController = navController, + startDestination = "home", + popEnterTransition = { + scaleIn(initialScale = 1.1F) + fadeIn() + }, + popExitTransition = { + scaleOut(targetScale = 0.9F) + fadeOut() + }, + modifier = modifier, ) { - Home( - modifier = Modifier.fillMaxSize(), - onChatClicked = { chatId -> navController.navigate("chat/$chatId") }, - ) - } - composable( - route = "chat/{chatId}?text={text}", - arguments = listOf( - navArgument("chatId") { type = NavType.LongType }, - navArgument("text") { defaultValue = "" }, - ), - deepLinks = listOf( - navDeepLink { - action = Intent.ACTION_VIEW - uriPattern = "https://socialite.google.com/chat/{chatId}" - }, - ), - ) { backStackEntry -> - val chatId = backStackEntry.arguments?.getLong("chatId") ?: 0L - val text = backStackEntry.arguments?.getString("text") - ChatScreen( - chatId = chatId, - foreground = true, - onBackPressed = { navController.popBackStack() }, - onCameraClick = { navController.navigate("chat/$chatId/camera") }, - onPhotoPickerClick = { navController.navigateToPhotoPicker(chatId) }, - onVideoClick = { uri -> navController.navigate("videoPlayer?uri=$uri") }, - prefilledText = text, - modifier = Modifier.fillMaxSize(), - ) - } - composable( - route = "chat/{chatId}/camera", - arguments = listOf( - navArgument("chatId") { type = NavType.LongType }, - ), - ) { backStackEntry -> - val chatId = backStackEntry.arguments?.getLong("chatId") ?: 0L - Camera( - onMediaCaptured = { capturedMedia: Media? -> - when (capturedMedia?.mediaType) { - MediaType.PHOTO -> { - navController.popBackStack() - } + composable( + route = "home", + ) { + Home( + modifier = Modifier.fillMaxSize(), + onChatClicked = { chatId -> navController.navigate("chat/$chatId") }, + sharedTransitionScope = this@SharedTransitionLayout, + animatedContentScope = this@composable + ) + } + composable( + route = "chat/{chatId}?text={text}", + arguments = listOf( + navArgument("chatId") { type = NavType.LongType }, + navArgument("text") { defaultValue = "" }, + ), + deepLinks = listOf( + navDeepLink { + action = Intent.ACTION_VIEW + uriPattern = "https://socialite.google.com/chat/{chatId}" + }, + ), + ) { backStackEntry -> + val chatId = backStackEntry.arguments?.getLong("chatId") ?: 0L + val text = backStackEntry.arguments?.getString("text") + ChatScreen( + chatId = chatId, + foreground = true, + onBackPressed = { navController.popBackStack() }, + onCameraClick = { navController.navigate("chat/$chatId/camera") }, + onPhotoPickerClick = { navController.navigateToPhotoPicker(chatId) }, + onVideoClick = { uri -> navController.navigate("videoPlayer?uri=$uri") }, + prefilledText = text, + modifier = Modifier + .fillMaxSize() + .sharedBounds( + this@SharedTransitionLayout.rememberSharedContentState(key = "Bounds${chatId}"), + animatedVisibilityScope = this@composable, + enter = fadeIn(), + exit = fadeOut(), + ), + sharedTransitionScope = this@SharedTransitionLayout, + animatedContentScope = this@composable, + ) + } + composable( + route = "chat/{chatId}/camera", + arguments = listOf( + navArgument("chatId") { type = NavType.LongType }, + ), + ) { backStackEntry -> + val chatId = backStackEntry.arguments?.getLong("chatId") ?: 0L + Camera( + onMediaCaptured = { capturedMedia: Media? -> + when (capturedMedia?.mediaType) { + MediaType.PHOTO -> { + navController.popBackStack() + } - MediaType.VIDEO -> { - navController.navigate("videoEdit?uri=${capturedMedia.uri}&chatId=$chatId") - } + MediaType.VIDEO -> { + navController.navigate("videoEdit?uri=${capturedMedia.uri}&chatId=$chatId") + } - else -> { - // No media to use. - navController.popBackStack() + else -> { + // No media to use. + navController.popBackStack() + } } - } - }, - chatId = chatId, - modifier = Modifier.fillMaxSize(), - ) - } + }, + chatId = chatId, + modifier = Modifier.fillMaxSize(), + ) + } - // Invoke PhotoPicker to select photo or video from device gallery - photoPickerScreen( - onPhotoPicked = navController::popBackStack, - ) - - composable( - route = "videoEdit?uri={videoUri}&chatId={chatId}", - arguments = listOf( - navArgument("videoUri") { type = NavType.StringType }, - navArgument("chatId") { type = NavType.LongType }, - ), - ) { backStackEntry -> - val chatId = backStackEntry.arguments?.getLong("chatId") ?: 0L - val videoUri = backStackEntry.arguments?.getString("videoUri") ?: "" - VideoEditScreen( - chatId = chatId, - uri = videoUri, - onCloseButtonClicked = { navController.popBackStack() }, - navController = navController, - ) - } - composable( - route = "videoPlayer?uri={videoUri}", - arguments = listOf( - navArgument("videoUri") { type = NavType.StringType }, - ), - ) { backStackEntry -> - val videoUri = backStackEntry.arguments?.getString("videoUri") ?: "" - VideoPlayerScreen( - uri = videoUri, - onCloseButtonClicked = { navController.popBackStack() }, + // Invoke PhotoPicker to select photo or video from device gallery + photoPickerScreen( + onPhotoPicked = navController::popBackStack, ) + + composable( + route = "videoEdit?uri={videoUri}&chatId={chatId}", + arguments = listOf( + navArgument("videoUri") { type = NavType.StringType }, + navArgument("chatId") { type = NavType.LongType }, + ), + ) { backStackEntry -> + val chatId = backStackEntry.arguments?.getLong("chatId") ?: 0L + val videoUri = backStackEntry.arguments?.getString("videoUri") ?: "" + VideoEditScreen( + chatId = chatId, + uri = videoUri, + onCloseButtonClicked = { navController.popBackStack() }, + navController = navController, + ) + } + composable( + route = "videoPlayer?uri={videoUri}", + arguments = listOf( + navArgument("videoUri") { type = NavType.StringType }, + ), + ) { backStackEntry -> + val videoUri = backStackEntry.arguments?.getString("videoUri") ?: "" + VideoPlayerScreen( + uri = videoUri, + onCloseButtonClicked = { navController.popBackStack() }, + ) + } } } + if (shortcutParams != null) { val chatId = extractChatId(shortcutParams.shortcutId) val text = shortcutParams.text diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/chat/ChatScreen.kt b/app/src/main/java/com/google/android/samples/socialite/ui/chat/ChatScreen.kt index cbaef7ab..f1e7afc2 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/chat/ChatScreen.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/chat/ChatScreen.kt @@ -16,10 +16,18 @@ package com.google.android.samples.socialite.ui.chat +import android.annotation.SuppressLint import android.graphics.Bitmap import android.media.MediaMetadataRetriever import android.net.Uri import android.util.Log +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.AnimatedContentScope +import androidx.compose.animation.ExperimentalSharedTransitionApi +import androidx.compose.animation.SharedTransitionLayout +import androidx.compose.animation.SharedTransitionScope +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -108,6 +116,7 @@ import kotlinx.coroutines.withContext private const val TAG = "ChatUI" +@OptIn(ExperimentalSharedTransitionApi::class) @Composable fun ChatScreen( chatId: Long, @@ -119,6 +128,8 @@ fun ChatScreen( onVideoClick: (uri: String) -> Unit, prefilledText: String? = null, viewModel: ChatViewModel = hiltViewModel(), + sharedTransitionScope: SharedTransitionScope, + animatedContentScope: AnimatedContentScope ) { LaunchedEffect(chatId) { viewModel.setChatId(chatId) @@ -144,6 +155,8 @@ fun ChatScreen( onVideoClick = onVideoClick, modifier = modifier .clip(RoundedCornerShape(5)), + sharedTransitionScope = sharedTransitionScope, + animatedContentScope = animatedContentScope ) } LifecycleEffect( @@ -175,7 +188,7 @@ private fun LifecycleEffect( } } -@OptIn(ExperimentalMaterial3Api::class) +@OptIn(ExperimentalMaterial3Api::class, ExperimentalSharedTransitionApi::class) @Composable private fun ChatContent( chat: ChatDetail, @@ -189,6 +202,8 @@ private fun ChatContent( onPhotoPickerClick: () -> Unit, onVideoClick: (uri: String) -> Unit, modifier: Modifier = Modifier, + sharedTransitionScope: SharedTransitionScope, + animatedContentScope: AnimatedContentScope ) { val topAppBarState = rememberTopAppBarState() val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(topAppBarState) @@ -200,6 +215,8 @@ private fun ChatContent( chat = chat, scrollBehavior = scrollBehavior, onBackPressed = onBackPressed, + sharedTransitionScope = sharedTransitionScope, + animatedContentScope = animatedContentScope ) }, ) { innerPadding -> @@ -242,39 +259,63 @@ private fun PaddingValues.copy( bottom = bottom ?: calculateBottomPadding(), ) -@OptIn(ExperimentalMaterial3Api::class) +@OptIn(ExperimentalMaterial3Api::class, ExperimentalSharedTransitionApi::class) @Composable private fun ChatAppBar( chat: ChatDetail, scrollBehavior: TopAppBarScrollBehavior, onBackPressed: (() -> Unit)?, modifier: Modifier = Modifier, + sharedTransitionScope: SharedTransitionScope, + animatedContentScope: AnimatedContentScope + ) { - TopAppBar( - title = { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp), - ) { - // This only supports DM for now. - val contact = chat.attendees.first() - SmallContactIcon(iconUri = contact.iconUri, size = 32.dp) - Text(text = contact.name) - } - }, - modifier = modifier, - scrollBehavior = scrollBehavior, - navigationIcon = { - if (onBackPressed != null) { - IconButton(onClick = onBackPressed) { - Icon( - imageVector = Icons.Default.ArrowBack, - contentDescription = stringResource(R.string.back), + with(sharedTransitionScope) { + TopAppBar( + title = { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + // This only supports DM for now. + val contact = chat.attendees.first() + Image( + painter = rememberIconPainter(contact.iconUri), + contentDescription = null, + modifier = Modifier.Companion + .sharedElement( + sharedTransitionScope.rememberSharedContentState(key = chat.chatWithLastMessage.id), + animatedVisibilityScope = animatedContentScope + ) + .size(32.dp) + .clip(CircleShape) + .background(Color.LightGray), + ) + Text( + text = contact.name, + modifier = Modifier.Companion.sharedBounds( + sharedTransitionScope.rememberSharedContentState(key = "Text${chat.chatWithLastMessage.id}"), + animatedVisibilityScope = animatedContentScope, + enter = fadeIn(), + exit = fadeOut(), + ) ) } - } - }, - ) + }, + modifier = modifier, + scrollBehavior = scrollBehavior, + navigationIcon = { + if (onBackPressed != null) { + IconButton(onClick = onBackPressed) { + Icon( + imageVector = Icons.Default.ArrowBack, + contentDescription = stringResource(R.string.back), + ) + } + } + }, + ) + } } @Composable @@ -500,27 +541,34 @@ private fun PreviewInputBar() { } } +@OptIn(ExperimentalSharedTransitionApi::class) @Preview @Composable private fun PreviewChatContent() { - SocialTheme { - ChatContent( - chat = ChatDetail(ChatWithLastMessage(0L), listOf(Contact.CONTACTS[0])), - messages = listOf( - ChatMessage("Hi!", null, null, 0L, false, null), - ChatMessage("Hello", null, null, 0L, true, null), - ChatMessage("world", null, null, 0L, true, null), - ChatMessage("!", null, null, 0L, true, null), - ChatMessage("Hello, world!", null, null, 0L, true, null), - ), - input = "Hello", - sendEnabled = true, - onBackPressed = {}, - onInputChanged = {}, - onSendClick = {}, - onCameraClick = {}, - onPhotoPickerClick = {}, - onVideoClick = {}, - ) + SharedTransitionScope { + AnimatedContent(targetState = 1) {_ -> + SocialTheme { + ChatContent( + chat = ChatDetail(ChatWithLastMessage(0L), listOf(Contact.CONTACTS[0])), + messages = listOf( + ChatMessage("Hi!", null, null, 0L, false, null), + ChatMessage("Hello", null, null, 0L, true, null), + ChatMessage("world", null, null, 0L, true, null), + ChatMessage("!", null, null, 0L, true, null), + ChatMessage("Hello, world!", null, null, 0L, true, null), + ), + input = "Hello", + sendEnabled = true, + onBackPressed = {}, + onInputChanged = {}, + onSendClick = {}, + onCameraClick = {}, + onPhotoPickerClick = {}, + onVideoClick = {}, + sharedTransitionScope = this@SharedTransitionScope, + animatedContentScope = this@AnimatedContent + ) + } + } } } diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/home/ChatList.kt b/app/src/main/java/com/google/android/samples/socialite/ui/home/ChatList.kt index e68a27e4..166024cc 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/home/ChatList.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/home/ChatList.kt @@ -17,6 +17,9 @@ package com.google.android.samples.socialite.ui.home import android.annotation.SuppressLint +import androidx.compose.animation.AnimatedContentScope +import androidx.compose.animation.ExperimentalSharedTransitionApi +import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth @@ -39,13 +42,15 @@ import com.google.android.samples.socialite.R import com.google.android.samples.socialite.model.ChatDetail import com.google.android.samples.socialite.ui.ChatRow -@OptIn(ExperimentalPermissionsApi::class) +@OptIn(ExperimentalPermissionsApi::class, ExperimentalSharedTransitionApi::class) @Composable internal fun ChatList( chats: List, contentPadding: PaddingValues, onChatClicked: (chatId: Long) -> Unit, modifier: Modifier = Modifier, + sharedTransitionScope: SharedTransitionScope, + animatedContentScope: AnimatedContentScope ) { @SuppressLint("InlinedApi") // Granted at install time on API <33. val notificationPermissionState = rememberPermissionState( @@ -72,6 +77,8 @@ internal fun ChatList( ChatRow( chat = chat, onClick = { onChatClicked(chat.chatWithLastMessage.id) }, + sharedTransitionScope = sharedTransitionScope, + animatedContentScope = animatedContentScope ) } } diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt b/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt index f82dde11..72c73407 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt @@ -17,6 +17,9 @@ package com.google.android.samples.socialite.ui.home import androidx.annotation.StringRes +import androidx.compose.animation.AnimatedContentScope +import androidx.compose.animation.ExperimentalSharedTransitionApi +import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.ChatBubbleOutline @@ -48,11 +51,15 @@ import com.google.android.samples.socialite.R import com.google.android.samples.socialite.ui.AnimationConstants import com.google.android.samples.socialite.ui.home.timeline.Timeline -@OptIn(ExperimentalMaterial3AdaptiveNavigationSuiteApi::class) +@OptIn(ExperimentalMaterial3AdaptiveNavigationSuiteApi::class, + ExperimentalSharedTransitionApi::class +) @Composable fun Home( onChatClicked: (chatId: Long) -> Unit, modifier: Modifier = Modifier, + sharedTransitionScope: SharedTransitionScope, + animatedContentScope: AnimatedContentScope ) { var currentDestination by rememberSaveable { mutableStateOf(Destination.Chats) } NavigationSuiteScaffold( @@ -75,14 +82,22 @@ fun Home( ) } }, - ) { HomeContent(currentDestination, modifier, onChatClicked) } + ) { HomeContent( + currentDestination, + modifier, + onChatClicked, + sharedTransitionScope, + animatedContentScope) } } +@OptIn(ExperimentalSharedTransitionApi::class) @Composable private fun HomeContent( currentDestination: Destination, modifier: Modifier, onChatClicked: (chatId: Long) -> Unit, + sharedTransitionScope: SharedTransitionScope, + animatedContentScope: AnimatedContentScope ) { Scaffold( modifier = modifier, @@ -117,6 +132,8 @@ private fun HomeContent( contentPadding = innerPadding, onChatClicked = onChatClicked, modifier = modifier, + sharedTransitionScope = sharedTransitionScope, + animatedContentScope = animatedContentScope ) } composable( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d501f88e..02443a30 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ cameraViewfinderCompose = "1.0.0-SNAPSHOT" coil = "2.4.0" compose_bom = "2024.04.00" composeCompiler = "1.5.4" # Used in app/build.gradle.kts -compose-foundation = "1.6.0-beta03" +compose-foundation = "1.7.0-beta01" concurrent = "1.1.0" core = "1.12.0" core-splashscreen = "1.0.1" From de822c1e0f01efa47cb6c235612ba472e04df55b Mon Sep 17 00:00:00 2001 From: Dan Galpin Date: Wed, 5 Jun 2024 15:25:26 -0700 Subject: [PATCH 2/2] Removed most of the shared element and shared bounds transitions --- .../android/samples/socialite/ui/Bubble.kt | 6 +- .../samples/socialite/ui/ContactRow.kt | 112 ++++----- .../android/samples/socialite/ui/Main.kt | 216 ++++++++---------- .../samples/socialite/ui/chat/ChatScreen.kt | 99 +++----- .../samples/socialite/ui/home/ChatList.kt | 8 +- .../android/samples/socialite/ui/home/Home.kt | 19 +- 6 files changed, 190 insertions(+), 270 deletions(-) diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/Bubble.kt b/app/src/main/java/com/google/android/samples/socialite/ui/Bubble.kt index ce2e6cdb..4b2af807 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/Bubble.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/Bubble.kt @@ -17,10 +17,8 @@ package com.google.android.samples.socialite.ui import androidx.compose.animation.AnimatedContent -import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.ExperimentalSharedTransitionApi import androidx.compose.animation.SharedTransitionLayout -import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -43,8 +41,8 @@ fun Bubble(chatId: Long) { // TODO (mayurikhin): Hook up camera button in the Bubble composable onPhotoPickerClick = {}, modifier = Modifier.fillMaxSize(), - sharedTransitionScope = this@SharedTransitionLayout, - animatedContentScope = this@AnimatedContent + // sharedTransitionScope = this@SharedTransitionLayout, + // animatedContentScope = this@AnimatedContent ) } } diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/ContactRow.kt b/app/src/main/java/com/google/android/samples/socialite/ui/ContactRow.kt index 800d22a4..75239d2b 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/ContactRow.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/ContactRow.kt @@ -51,75 +51,55 @@ fun ChatRow( chat: ChatDetail, onClick: (() -> Unit)?, modifier: Modifier = Modifier, - sharedTransitionScope: SharedTransitionScope, - animatedContentScope: AnimatedContentScope ) { - with(sharedTransitionScope) { - Row( - modifier = modifier - .fillMaxWidth() - .then( - if (onClick != null) Modifier.clickable(onClick = onClick) else Modifier, - ) - .padding(16.dp) - .sharedBounds( - sharedTransitionScope.rememberSharedContentState(key = "Bounds${chat.chatWithLastMessage.id}"), - animatedVisibilityScope = animatedContentScope, - enter = fadeIn(), - exit = fadeOut(), - ), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp), + Row( + modifier = modifier + .fillMaxWidth() + .then( + if (onClick != null) Modifier.clickable(onClick = onClick) else Modifier, + ) + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + // This only supports DM for now. + val contact = chat.attendees.first() + Image( + painter = rememberIconPainter(contentUri = contact.iconUri), + contentDescription = null, + modifier = Modifier.Companion + .size(48.dp) + .clip(CircleShape) + .background(Color.LightGray), + ) + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.SpaceEvenly, + horizontalAlignment = Alignment.Start, + ) { + Text( + text = contact.name, + style = MaterialTheme.typography.bodyLarge, + fontSize = 16.sp, + ) + Text( + text = chat.chatWithLastMessage.text, + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.padding(top = 4.dp), + fontWeight = FontWeight.Light, + fontSize = 14.sp, + ) + } + Column( + verticalArrangement = Arrangement.SpaceEvenly, + horizontalAlignment = Alignment.CenterHorizontally, ) { - // This only supports DM for now. - val contact = chat.attendees.first() - Image( - painter = rememberIconPainter(contentUri = contact.iconUri), - contentDescription = null, - modifier = Modifier.Companion - .sharedElement( - sharedTransitionScope.rememberSharedContentState(key = chat.chatWithLastMessage.id), - animatedVisibilityScope = animatedContentScope - ) - .size(48.dp) - .clip(CircleShape) - .background(Color.LightGray), + Text( + text = chat.chatWithLastMessage.timestamp.toReadableString(), + fontSize = 14.sp, ) - Column( - modifier = Modifier.weight(1f), - verticalArrangement = Arrangement.SpaceEvenly, - horizontalAlignment = Alignment.Start, - ) { - Text( - text = contact.name, - style = MaterialTheme.typography.bodyLarge, - fontSize = 16.sp, - modifier = Modifier.Companion.sharedBounds( - sharedTransitionScope.rememberSharedContentState(key = "Text${chat.chatWithLastMessage.id}"), - animatedVisibilityScope = animatedContentScope, - enter = fadeIn(), - exit = fadeOut(), - ) - ) - Text( - text = chat.chatWithLastMessage.text, - style = MaterialTheme.typography.bodySmall, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - modifier = Modifier.padding(top = 4.dp), - fontWeight = FontWeight.Light, - fontSize = 14.sp, - ) - } - Column( - verticalArrangement = Arrangement.SpaceEvenly, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text( - text = chat.chatWithLastMessage.timestamp.toReadableString(), - fontSize = 14.sp, - ) - } } } } diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/Main.kt b/app/src/main/java/com/google/android/samples/socialite/ui/Main.kt index dc211ebd..f5ea95b9 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/Main.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/Main.kt @@ -21,7 +21,6 @@ import android.content.Intent import android.content.pm.ActivityInfo import android.os.Bundle import androidx.compose.animation.ExperimentalSharedTransitionApi -import androidx.compose.animation.SharedTransitionLayout import androidx.compose.animation.core.FastOutLinearInEasing import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.tween @@ -81,129 +80,114 @@ fun MainNavigation( activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED } } - SharedTransitionLayout { - NavHost( - navController = navController, - startDestination = "home", - popEnterTransition = { - scaleIn(initialScale = 1.1F) + fadeIn() - }, - popExitTransition = { - scaleOut(targetScale = 0.9F) + fadeOut() - }, - modifier = modifier, + NavHost( + navController = navController, + startDestination = "home", + popEnterTransition = { + scaleIn(initialScale = 1.1F) + fadeIn() + }, + popExitTransition = { + scaleOut(targetScale = 0.9F) + fadeOut() + }, + modifier = modifier, + ) { + composable( + route = "home", ) { - composable( - route = "home", - ) { - Home( - modifier = Modifier.fillMaxSize(), - onChatClicked = { chatId -> navController.navigate("chat/$chatId") }, - sharedTransitionScope = this@SharedTransitionLayout, - animatedContentScope = this@composable - ) - } - composable( - route = "chat/{chatId}?text={text}", - arguments = listOf( - navArgument("chatId") { type = NavType.LongType }, - navArgument("text") { defaultValue = "" }, - ), - deepLinks = listOf( - navDeepLink { - action = Intent.ACTION_VIEW - uriPattern = "https://socialite.google.com/chat/{chatId}" - }, - ), - ) { backStackEntry -> - val chatId = backStackEntry.arguments?.getLong("chatId") ?: 0L - val text = backStackEntry.arguments?.getString("text") - ChatScreen( - chatId = chatId, - foreground = true, - onBackPressed = { navController.popBackStack() }, - onCameraClick = { navController.navigate("chat/$chatId/camera") }, - onPhotoPickerClick = { navController.navigateToPhotoPicker(chatId) }, - onVideoClick = { uri -> navController.navigate("videoPlayer?uri=$uri") }, - prefilledText = text, - modifier = Modifier - .fillMaxSize() - .sharedBounds( - this@SharedTransitionLayout.rememberSharedContentState(key = "Bounds${chatId}"), - animatedVisibilityScope = this@composable, - enter = fadeIn(), - exit = fadeOut(), - ), - sharedTransitionScope = this@SharedTransitionLayout, - animatedContentScope = this@composable, - ) - } - composable( - route = "chat/{chatId}/camera", - arguments = listOf( - navArgument("chatId") { type = NavType.LongType }, - ), - ) { backStackEntry -> - val chatId = backStackEntry.arguments?.getLong("chatId") ?: 0L - Camera( - onMediaCaptured = { capturedMedia: Media? -> - when (capturedMedia?.mediaType) { - MediaType.PHOTO -> { - navController.popBackStack() - } - - MediaType.VIDEO -> { - navController.navigate("videoEdit?uri=${capturedMedia.uri}&chatId=$chatId") - } + Home( + onChatClicked = { chatId -> navController.navigate("chat/$chatId") }, + modifier = Modifier.fillMaxSize() + ) + } + composable( + route = "chat/{chatId}?text={text}", + arguments = listOf( + navArgument("chatId") { type = NavType.LongType }, + navArgument("text") { defaultValue = "" }, + ), + deepLinks = listOf( + navDeepLink { + action = Intent.ACTION_VIEW + uriPattern = "https://socialite.google.com/chat/{chatId}" + }, + ), + ) { backStackEntry -> + val chatId = backStackEntry.arguments?.getLong("chatId") ?: 0L + val text = backStackEntry.arguments?.getString("text") + ChatScreen( + chatId = chatId, + foreground = true, + modifier = Modifier.fillMaxSize(), + onBackPressed = { navController.popBackStack() }, + onCameraClick = { navController.navigate("chat/$chatId/camera") }, + onPhotoPickerClick = { navController.navigateToPhotoPicker(chatId) }, + onVideoClick = { uri -> navController.navigate("videoPlayer?uri=$uri") }, + prefilledText = text, + ) + } + composable( + route = "chat/{chatId}/camera", + arguments = listOf( + navArgument("chatId") { type = NavType.LongType }, + ), + ) { backStackEntry -> + val chatId = backStackEntry.arguments?.getLong("chatId") ?: 0L + Camera( + onMediaCaptured = { capturedMedia: Media? -> + when (capturedMedia?.mediaType) { + MediaType.PHOTO -> { + navController.popBackStack() + } - else -> { - // No media to use. - navController.popBackStack() - } + MediaType.VIDEO -> { + navController.navigate("videoEdit?uri=${capturedMedia.uri}&chatId=$chatId") } - }, - chatId = chatId, - modifier = Modifier.fillMaxSize(), - ) - } - // Invoke PhotoPicker to select photo or video from device gallery - photoPickerScreen( - onPhotoPicked = navController::popBackStack, + else -> { + // No media to use. + navController.popBackStack() + } + } + }, + chatId = chatId, + modifier = Modifier.fillMaxSize(), ) - - composable( - route = "videoEdit?uri={videoUri}&chatId={chatId}", - arguments = listOf( - navArgument("videoUri") { type = NavType.StringType }, - navArgument("chatId") { type = NavType.LongType }, - ), - ) { backStackEntry -> - val chatId = backStackEntry.arguments?.getLong("chatId") ?: 0L - val videoUri = backStackEntry.arguments?.getString("videoUri") ?: "" - VideoEditScreen( - chatId = chatId, - uri = videoUri, - onCloseButtonClicked = { navController.popBackStack() }, - navController = navController, - ) - } - composable( - route = "videoPlayer?uri={videoUri}", - arguments = listOf( - navArgument("videoUri") { type = NavType.StringType }, - ), - ) { backStackEntry -> - val videoUri = backStackEntry.arguments?.getString("videoUri") ?: "" - VideoPlayerScreen( - uri = videoUri, - onCloseButtonClicked = { navController.popBackStack() }, - ) - } } - } + // Invoke PhotoPicker to select photo or video from device gallery + photoPickerScreen( + onPhotoPicked = navController::popBackStack, + ) + composable( + route = "videoEdit?uri={videoUri}&chatId={chatId}", + arguments = listOf( + navArgument("videoUri") { type = NavType.StringType }, + navArgument("chatId") { type = NavType.LongType }, + ), + ) { backStackEntry -> + val chatId = backStackEntry.arguments?.getLong("chatId") ?: 0L + val videoUri = backStackEntry.arguments?.getString("videoUri") ?: "" + VideoEditScreen( + chatId = chatId, + uri = videoUri, + onCloseButtonClicked = { navController.popBackStack() }, + navController = navController, + ) + } + composable( + route = "videoPlayer?uri={videoUri}", + arguments = listOf( + navArgument("videoUri") { type = NavType.StringType }, + ), + ) { backStackEntry -> + val videoUri = backStackEntry.arguments?.getString("videoUri") ?: "" + VideoPlayerScreen( + uri = videoUri, + onCloseButtonClicked = { navController.popBackStack() }, + ) + } + } if (shortcutParams != null) { val chatId = extractChatId(shortcutParams.shortcutId) val text = shortcutParams.text diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/chat/ChatScreen.kt b/app/src/main/java/com/google/android/samples/socialite/ui/chat/ChatScreen.kt index f1e7afc2..02da3f96 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/chat/ChatScreen.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/chat/ChatScreen.kt @@ -16,7 +16,6 @@ package com.google.android.samples.socialite.ui.chat -import android.annotation.SuppressLint import android.graphics.Bitmap import android.media.MediaMetadataRetriever import android.net.Uri @@ -24,7 +23,6 @@ import android.util.Log import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.ExperimentalSharedTransitionApi -import androidx.compose.animation.SharedTransitionLayout import androidx.compose.animation.SharedTransitionScope import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -102,7 +100,6 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.viewmodel.compose.viewModel import coil.compose.AsyncImage import coil.request.ImageRequest import com.google.android.samples.socialite.R @@ -127,9 +124,7 @@ fun ChatScreen( onPhotoPickerClick: () -> Unit, onVideoClick: (uri: String) -> Unit, prefilledText: String? = null, - viewModel: ChatViewModel = hiltViewModel(), - sharedTransitionScope: SharedTransitionScope, - animatedContentScope: AnimatedContentScope + viewModel: ChatViewModel = hiltViewModel() ) { LaunchedEffect(chatId) { viewModel.setChatId(chatId) @@ -154,9 +149,7 @@ fun ChatScreen( onPhotoPickerClick = onPhotoPickerClick, onVideoClick = onVideoClick, modifier = modifier - .clip(RoundedCornerShape(5)), - sharedTransitionScope = sharedTransitionScope, - animatedContentScope = animatedContentScope + .clip(RoundedCornerShape(5)) ) } LifecycleEffect( @@ -201,9 +194,7 @@ private fun ChatContent( onCameraClick: () -> Unit, onPhotoPickerClick: () -> Unit, onVideoClick: (uri: String) -> Unit, - modifier: Modifier = Modifier, - sharedTransitionScope: SharedTransitionScope, - animatedContentScope: AnimatedContentScope + modifier: Modifier = Modifier ) { val topAppBarState = rememberTopAppBarState() val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(topAppBarState) @@ -215,8 +206,6 @@ private fun ChatContent( chat = chat, scrollBehavior = scrollBehavior, onBackPressed = onBackPressed, - sharedTransitionScope = sharedTransitionScope, - animatedContentScope = animatedContentScope ) }, ) { innerPadding -> @@ -266,56 +255,42 @@ private fun ChatAppBar( scrollBehavior: TopAppBarScrollBehavior, onBackPressed: (() -> Unit)?, modifier: Modifier = Modifier, - sharedTransitionScope: SharedTransitionScope, - animatedContentScope: AnimatedContentScope ) { - with(sharedTransitionScope) { - TopAppBar( - title = { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp), - ) { - // This only supports DM for now. - val contact = chat.attendees.first() - Image( - painter = rememberIconPainter(contact.iconUri), - contentDescription = null, - modifier = Modifier.Companion - .sharedElement( - sharedTransitionScope.rememberSharedContentState(key = chat.chatWithLastMessage.id), - animatedVisibilityScope = animatedContentScope - ) - .size(32.dp) - .clip(CircleShape) - .background(Color.LightGray), - ) - Text( - text = contact.name, - modifier = Modifier.Companion.sharedBounds( - sharedTransitionScope.rememberSharedContentState(key = "Text${chat.chatWithLastMessage.id}"), - animatedVisibilityScope = animatedContentScope, - enter = fadeIn(), - exit = fadeOut(), - ) + TopAppBar( + title = { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + // This only supports DM for now. + val contact = chat.attendees.first() + Image( + painter = rememberIconPainter(contact.iconUri), + contentDescription = null, + modifier = Modifier.Companion + .size(32.dp) + .clip(CircleShape) + .background(Color.LightGray), + ) + Text( + text = contact.name, + ) + } + }, + modifier = modifier, + scrollBehavior = scrollBehavior, + navigationIcon = { + if (onBackPressed != null) { + IconButton(onClick = onBackPressed) { + Icon( + imageVector = Icons.Default.ArrowBack, + contentDescription = stringResource(R.string.back), ) } - }, - modifier = modifier, - scrollBehavior = scrollBehavior, - navigationIcon = { - if (onBackPressed != null) { - IconButton(onClick = onBackPressed) { - Icon( - imageVector = Icons.Default.ArrowBack, - contentDescription = stringResource(R.string.back), - ) - } - } - }, - ) - } + } + }, + ) } @Composable @@ -564,9 +539,7 @@ private fun PreviewChatContent() { onSendClick = {}, onCameraClick = {}, onPhotoPickerClick = {}, - onVideoClick = {}, - sharedTransitionScope = this@SharedTransitionScope, - animatedContentScope = this@AnimatedContent + onVideoClick = {} ) } } diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/home/ChatList.kt b/app/src/main/java/com/google/android/samples/socialite/ui/home/ChatList.kt index 166024cc..b7f7bd62 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/home/ChatList.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/home/ChatList.kt @@ -17,9 +17,7 @@ package com.google.android.samples.socialite.ui.home import android.annotation.SuppressLint -import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.ExperimentalSharedTransitionApi -import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth @@ -48,9 +46,7 @@ internal fun ChatList( chats: List, contentPadding: PaddingValues, onChatClicked: (chatId: Long) -> Unit, - modifier: Modifier = Modifier, - sharedTransitionScope: SharedTransitionScope, - animatedContentScope: AnimatedContentScope + modifier: Modifier = Modifier ) { @SuppressLint("InlinedApi") // Granted at install time on API <33. val notificationPermissionState = rememberPermissionState( @@ -77,8 +73,6 @@ internal fun ChatList( ChatRow( chat = chat, onClick = { onChatClicked(chat.chatWithLastMessage.id) }, - sharedTransitionScope = sharedTransitionScope, - animatedContentScope = animatedContentScope ) } } diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt b/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt index 72c73407..66fb9349 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt @@ -17,9 +17,7 @@ package com.google.android.samples.socialite.ui.home import androidx.annotation.StringRes -import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.ExperimentalSharedTransitionApi -import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.ChatBubbleOutline @@ -57,9 +55,7 @@ import com.google.android.samples.socialite.ui.home.timeline.Timeline @Composable fun Home( onChatClicked: (chatId: Long) -> Unit, - modifier: Modifier = Modifier, - sharedTransitionScope: SharedTransitionScope, - animatedContentScope: AnimatedContentScope + modifier: Modifier = Modifier ) { var currentDestination by rememberSaveable { mutableStateOf(Destination.Chats) } NavigationSuiteScaffold( @@ -85,9 +81,8 @@ fun Home( ) { HomeContent( currentDestination, modifier, - onChatClicked, - sharedTransitionScope, - animatedContentScope) } + onChatClicked + ) } } @OptIn(ExperimentalSharedTransitionApi::class) @@ -95,9 +90,7 @@ fun Home( private fun HomeContent( currentDestination: Destination, modifier: Modifier, - onChatClicked: (chatId: Long) -> Unit, - sharedTransitionScope: SharedTransitionScope, - animatedContentScope: AnimatedContentScope + onChatClicked: (chatId: Long) -> Unit ) { Scaffold( modifier = modifier, @@ -131,9 +124,7 @@ private fun HomeContent( chats = chats, contentPadding = innerPadding, onChatClicked = onChatClicked, - modifier = modifier, - sharedTransitionScope = sharedTransitionScope, - animatedContentScope = animatedContentScope + modifier = modifier ) } composable(