Moment 页面优化

- Moment 页面新增图片索引指示器
- 调整 Moment 页面布局,增加间距
- 优化 Moment 页面加载逻辑
This commit is contained in:
2024-09-02 23:14:38 +08:00
parent 48b1b1fe51
commit 51c8eaa9ef
4 changed files with 147 additions and 139 deletions

View File

@@ -8,8 +8,6 @@ import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.navigationBars
@@ -36,14 +34,14 @@ import com.aiosman.riderpro.ui.gallery.OfficialGalleryScreen
import com.aiosman.riderpro.ui.gallery.OfficialPhotographerScreen import com.aiosman.riderpro.ui.gallery.OfficialPhotographerScreen
import com.aiosman.riderpro.ui.gallery.ProfileTimelineScreen import com.aiosman.riderpro.ui.gallery.ProfileTimelineScreen
import com.aiosman.riderpro.ui.index.IndexScreen import com.aiosman.riderpro.ui.index.IndexScreen
import com.aiosman.riderpro.ui.index.tabs.message.NotificationsScreen
import com.aiosman.riderpro.ui.index.tabs.search.SearchScreen
import com.aiosman.riderpro.ui.like.LikeScreen import com.aiosman.riderpro.ui.like.LikeScreen
import com.aiosman.riderpro.ui.location.LocationDetailScreen import com.aiosman.riderpro.ui.location.LocationDetailScreen
import com.aiosman.riderpro.ui.login.EmailSignupScreen import com.aiosman.riderpro.ui.login.EmailSignupScreen
import com.aiosman.riderpro.ui.login.LoginPage import com.aiosman.riderpro.ui.login.LoginPage
import com.aiosman.riderpro.ui.login.SignupScreen import com.aiosman.riderpro.ui.login.SignupScreen
import com.aiosman.riderpro.ui.login.UserAuthScreen import com.aiosman.riderpro.ui.login.UserAuthScreen
import com.aiosman.riderpro.ui.index.tabs.message.NotificationsScreen
import com.aiosman.riderpro.ui.index.tabs.search.SearchScreen
import com.aiosman.riderpro.ui.modification.EditModificationScreen import com.aiosman.riderpro.ui.modification.EditModificationScreen
import com.aiosman.riderpro.ui.post.NewPostImageGridScreen import com.aiosman.riderpro.ui.post.NewPostImageGridScreen
import com.aiosman.riderpro.ui.post.NewPostScreen import com.aiosman.riderpro.ui.post.NewPostScreen
@@ -130,10 +128,10 @@ fun NavigationController(
route = NavigationRoute.Post.route, route = NavigationRoute.Post.route,
arguments = listOf(navArgument("id") { type = NavType.StringType }), arguments = listOf(navArgument("id") { type = NavType.StringType }),
enterTransition = { enterTransition = {
fadeIn(animationSpec = tween(durationMillis = 100)) fadeIn(animationSpec = tween(durationMillis = 50))
}, },
exitTransition = { exitTransition = {
fadeOut(animationSpec = tween(durationMillis = 100)) fadeOut(animationSpec = tween(durationMillis = 50))
} }
) { backStackEntry -> ) { backStackEntry ->
CompositionLocalProvider( CompositionLocalProvider(

View File

@@ -63,9 +63,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.paging.LoadState import androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import com.aiosman.riderpro.LocalAnimatedContentScope
import com.aiosman.riderpro.LocalNavController import com.aiosman.riderpro.LocalNavController
import com.aiosman.riderpro.LocalSharedTransitionScope
import com.aiosman.riderpro.R import com.aiosman.riderpro.R
import com.aiosman.riderpro.entity.MomentEntity import com.aiosman.riderpro.entity.MomentEntity
import com.aiosman.riderpro.entity.MomentImageEntity import com.aiosman.riderpro.entity.MomentImageEntity
@@ -148,6 +146,7 @@ fun MomentsList() {
} }
} }
) )
Box(modifier = Modifier.height(16.dp).fillMaxWidth().background(Color(0xFFF0F2F5)))
} }
} }
PullRefreshIndicator(refreshing, state, Modifier.align(Alignment.TopCenter)) PullRefreshIndicator(refreshing, state, Modifier.align(Alignment.TopCenter))
@@ -163,12 +162,13 @@ fun MomentCard(
onAddComment: () -> Unit = {}, onAddComment: () -> Unit = {},
hideAction: Boolean = false hideAction: Boolean = false
) { ) {
var imageIndex by remember { mutableStateOf(0) }
val navController = LocalNavController.current val navController = LocalNavController.current
Column( Column(
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
Box( Box(
modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp) modifier = Modifier.padding(start = 24.dp, end = 24.dp, top = 16.dp, bottom = 8.dp)
) { ) {
MomentTopRowGroup(momentEntity = momentEntity) MomentTopRowGroup(momentEntity = momentEntity)
} }
@@ -180,15 +180,13 @@ fun MomentCard(
navController.navigate("Post/${momentEntity.id}") navController.navigate("Post/${momentEntity.id}")
} }
) { ) {
MomentContentGroup(momentEntity = momentEntity) MomentContentGroup(
momentEntity = momentEntity,
onPageChange = { index -> imageIndex = index }
)
} }
val momentOperateBtnBoxModifier = Modifier
.fillMaxHeight()
.weight(1f)
// ModificationListHeader()
if (!hideAction) { if (!hideAction) {
MomentBottomOperateRowGroup( MomentBottomOperateRowGroup(
momentOperateBtnBoxModifier,
momentEntity = momentEntity, momentEntity = momentEntity,
onLikeClick = onLikeClick, onLikeClick = onLikeClick,
onAddComment = onAddComment, onAddComment = onAddComment,
@@ -197,10 +195,10 @@ fun MomentCard(
NewPostViewModel.relPostId = momentEntity.id NewPostViewModel.relPostId = momentEntity.id
navController.navigate(NavigationRoute.NewPost.route) navController.navigate(NavigationRoute.NewPost.route)
}, },
onFavoriteClick = onFavoriteClick onFavoriteClick = onFavoriteClick,
imageIndex = imageIndex
) )
} }
} }
} }
@@ -294,7 +292,7 @@ fun MomentPostLocation(location: String) {
@Composable @Composable
fun MomentPostTime(time: String) { fun MomentPostTime(time: String) {
Text( Text(
modifier = Modifier.padding(start = 8.dp), modifier = Modifier,
text = time, color = Color(0f, 0f, 0f, 0.6f), text = time, color = Color(0f, 0f, 0f, 0.6f),
fontSize = 12.sp fontSize = 12.sp
) )
@@ -343,8 +341,10 @@ fun MomentTopRowGroup(momentEntity: MomentEntity) {
.height(21.dp), .height(21.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
MomentPostLocation(momentEntity.location)
MomentPostTime(momentEntity.time.timeAgo(context)) MomentPostTime(momentEntity.time.timeAgo(context))
Spacer(modifier = Modifier.width(8.dp))
MomentPostLocation(momentEntity.location)
} }
} }
} }
@@ -353,13 +353,13 @@ fun MomentTopRowGroup(momentEntity: MomentEntity) {
@OptIn(ExperimentalFoundationApi::class, ExperimentalSharedTransitionApi::class) @OptIn(ExperimentalFoundationApi::class, ExperimentalSharedTransitionApi::class)
@Composable @Composable
fun PostImageView( fun PostImageView(
postId: String,
images: List<MomentImageEntity>, images: List<MomentImageEntity>,
onPageChange: (Int) -> Unit = {}
) { ) {
val pagerState = rememberPagerState(pageCount = { images.size }) val pagerState = rememberPagerState(pageCount = { images.size })
val navController = LocalNavController.current LaunchedEffect(pagerState.currentPage) {
val sharedTransitionScope = LocalSharedTransitionScope.current onPageChange(pagerState.currentPage)
val animatedVisibilityScope = LocalAnimatedContentScope.current }
val context = LocalContext.current val context = LocalContext.current
Column( Column(
@@ -372,18 +372,6 @@ fun PostImageView(
.aspectRatio(1f), .aspectRatio(1f),
) { page -> ) { page ->
val image = images[page] val image = images[page]
// AsyncBlurImage(
// imageUrl = image.url,
// blurHash = image.blurHash ?: "",
// contentDescription = "Image",
// contentScale = ContentScale.Crop,
// modifier = Modifier
// .sharedElement(
// rememberSharedContentState(key = image),
// animatedVisibilityScope = animatedVisibilityScope
// )
// .fillMaxSize()
// )
CustomAsyncImage( CustomAsyncImage(
context, context,
image.thumbnail, image.thumbnail,
@@ -392,43 +380,34 @@ fun PostImageView(
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
// .noRippleClickable {
// ImageViewerViewModel.asNew(images, page)
// navController.navigate(
// NavigationRoute.ImageViewer.route
// )
// }
) )
} }
// Indicator container // Indicator container
if (images.size > 1) { // if (images.size > 1) {
Row( // Row(
modifier = Modifier // modifier = Modifier
.padding(8.dp) // .padding(8.dp)
.fillMaxWidth(), // .fillMaxWidth(),
horizontalArrangement = Arrangement.Center // horizontalArrangement = Arrangement.Center
) { // ) {
images.forEachIndexed { index, _ -> // images.forEachIndexed { index, _ ->
Box( // Box(
modifier = Modifier // modifier = Modifier
.size(8.dp) // .size(8.dp)
.clip(CircleShape) // .clip(CircleShape)
// .background(
.background( // if (pagerState.currentPage == index) Color.Red else Color.Gray.copy(
if (pagerState.currentPage == index) Color.Red else Color.Gray.copy( // alpha = 0.5f
alpha = 0.5f // )
) // )
) // .padding(4.dp)
.padding(4.dp) // )
// Spacer(modifier = Modifier.width(8.dp))
// }
) // }
Spacer(modifier = Modifier.width(8.dp)) // }
}
}
}
} }
@@ -437,13 +416,14 @@ fun PostImageView(
@Composable @Composable
fun MomentContentGroup( fun MomentContentGroup(
momentEntity: MomentEntity, momentEntity: MomentEntity,
onPageChange: (Int) -> Unit = {}
) { ) {
if (momentEntity.momentTextContent.isNotEmpty()) { if (momentEntity.momentTextContent.isNotEmpty()) {
Text( Text(
text = momentEntity.momentTextContent, text = momentEntity.momentTextContent,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 24.dp, vertical = 8.dp), .padding(start = 24.dp,end = 24.dp, bottom = 8.dp),
fontSize = 16.sp fontSize = 16.sp
) )
} }
@@ -457,8 +437,8 @@ fun MomentContentGroup(
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
PostImageView( PostImageView(
postId = momentEntity.id.toString(), images = momentEntity.images,
images = momentEntity.images onPageChange = onPageChange
) )
} }
} }
@@ -493,7 +473,9 @@ fun MomentOperateBtn(count: String, content: @Composable () -> Unit) {
AnimatedCounter( AnimatedCounter(
count = count.toInt(), count = count.toInt(),
fontSize = 14, fontSize = 14,
modifier = Modifier.padding(start = 7.dp) modifier = Modifier
.padding(start = 7.dp)
.width(24.dp)
) )
} }
} }
@@ -501,12 +483,12 @@ fun MomentOperateBtn(count: String, content: @Composable () -> Unit) {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun MomentBottomOperateRowGroup( fun MomentBottomOperateRowGroup(
modifier: Modifier,
onLikeClick: () -> Unit = {}, onLikeClick: () -> Unit = {},
onAddComment: () -> Unit = {}, onAddComment: () -> Unit = {},
onFavoriteClick: () -> Unit = {}, onFavoriteClick: () -> Unit = {},
onShareClick: () -> Unit = {}, onShareClick: () -> Unit = {},
momentEntity: MomentEntity momentEntity: MomentEntity,
imageIndex: Int = 0
) { ) {
var showCommentModal by remember { mutableStateOf(false) } var showCommentModal by remember { mutableStateOf(false) }
if (showCommentModal) { if (showCommentModal) {
@@ -528,24 +510,25 @@ fun MomentBottomOperateRowGroup(
} }
} }
) { ) {
// systemUiController.setNavigationBarColor(Color(0xfff7f7f7))
CommentModalContent(postId = momentEntity.id, onCommentAdded = { CommentModalContent(postId = momentEntity.id, onCommentAdded = {
showCommentModal = false showCommentModal = false
onAddComment() onAddComment()
}) { })
// systemUiController.setNavigationBarColor(Color.Black)
} }
} }
} Box(
Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(56.dp) .height(56.dp)
.padding(horizontal = 16.dp)
) {
Row(
modifier = Modifier.fillMaxSize()
) { ) {
Box( Box(
modifier = modifier, modifier = Modifier.fillMaxHeight(),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
MomentOperateBtn(count = momentEntity.likeCount.toString()) { MomentOperateBtn(count = momentEntity.likeCount.toString()) {
@@ -557,8 +540,11 @@ fun MomentBottomOperateRowGroup(
} }
} }
} }
Spacer(modifier = Modifier.width(4.dp))
Box( Box(
modifier = modifier.clickable( modifier = Modifier
.fillMaxHeight()
.clickable(
indication = null, indication = null,
interactionSource = remember { MutableInteractionSource() } interactionSource = remember { MutableInteractionSource() }
) { ) {
@@ -571,19 +557,11 @@ fun MomentBottomOperateRowGroup(
count = momentEntity.commentCount.toString() count = momentEntity.commentCount.toString()
) )
} }
// Box( Spacer(modifier = Modifier.weight(1f))
// modifier = modifier.noRippleClickable {
// onShareClick()
// },
// contentAlignment = Alignment.Center
// ) {
// MomentOperateBtn(
// icon = R.drawable.rider_pro_share,
// count = momentEntity.shareCount.toString()
// )
// }
Box( Box(
modifier = modifier.noRippleClickable { modifier = Modifier
.fillMaxHeight()
.noRippleClickable {
onFavoriteClick() onFavoriteClick()
}, },
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
@@ -598,6 +576,32 @@ fun MomentBottomOperateRowGroup(
} }
} }
} }
if (momentEntity.images.size > 1) {
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
momentEntity.images.forEachIndexed { index, _ ->
Box(
modifier = Modifier
.size(4.dp)
.clip(CircleShape)
.background(
if (imageIndex == index) Color.Red else Color.Gray.copy(
alpha = 0.5f
)
)
.padding(1.dp)
)
Spacer(modifier = Modifier.width(8.dp))
}
}
}
}
} }
@Composable @Composable

View File

@@ -143,9 +143,9 @@ object PostViewModel : ViewModel() {
suspend fun initData() { suspend fun initData() {
moment = service.getMomentById(postId.toInt()) moment = service.getMomentById(postId.toInt())
moment?.let { // moment?.let {
accountProfileEntity = userService.getUserProfile(it.authorId.toString()) // accountProfileEntity = userService.getUserProfile(it.authorId.toString())
} // }
} }
suspend fun likeComment(commentId: Int) { suspend fun likeComment(commentId: Int) {
@@ -321,7 +321,8 @@ fun PostScreen(
) )
LazyColumn( LazyColumn(
modifier = Modifier modifier = Modifier
.fillMaxWidth().weight(1f) .fillMaxWidth()
.weight(1f)
) { ) {
item { item {
Box( Box(
@@ -588,23 +589,27 @@ fun CommentItem(commentEntity: CommentEntity, onLike: () -> Unit = {}) {
val navController = LocalNavController.current val navController = LocalNavController.current
Column { Column {
Row(modifier = Modifier.padding(vertical = 8.dp)) { Row(modifier = Modifier.padding(vertical = 8.dp)) {
CustomAsyncImage( Box(
context = context,
imageUrl = commentEntity.avatar,
contentDescription = "Comment Profile Picture",
modifier = Modifier modifier = Modifier
.size(40.dp) .size(40.dp)
.clip(CircleShape) .clip(CircleShape)
.noRippleClickable { .background(Color.Gray.copy(alpha = 0.1f)).noRippleClickable {
navController.navigate( navController.navigate(
NavigationRoute.AccountProfile.route.replace( NavigationRoute.AccountProfile.route.replace(
"{id}", "{id}",
commentEntity.author.toString() commentEntity.author.toString()
) )
) )
}, }
) {
CustomAsyncImage(
context = context,
imageUrl = commentEntity.avatar,
contentDescription = "Comment Profile Picture",
modifier = Modifier.size(40.dp),
contentScale = ContentScale.Crop contentScale = ContentScale.Crop
) )
}
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
Column( Column(
modifier = Modifier.weight(1f) modifier = Modifier.weight(1f)

View File

@@ -32,6 +32,7 @@ fun AccountProfile(id: String) {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
model.loadProfile(id) model.loadProfile(id)
} }
LazyColumn( LazyColumn(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()