Merge remote-tracking branch 'refs/remotes/origin/main'

This commit is contained in:
2024-09-16 18:05:10 +08:00
4 changed files with 102 additions and 54 deletions

View File

@@ -9,6 +9,7 @@ import androidx.paging.Pager
import androidx.paging.PagingConfig import androidx.paging.PagingConfig
import androidx.paging.PagingData import androidx.paging.PagingData
import androidx.paging.cachedIn import androidx.paging.cachedIn
import androidx.paging.filter
import androidx.paging.map import androidx.paging.map
import com.aiosman.riderpro.data.CommentRemoteDataSource import com.aiosman.riderpro.data.CommentRemoteDataSource
import com.aiosman.riderpro.data.CommentService import com.aiosman.riderpro.data.CommentService
@@ -51,7 +52,7 @@ class CommentsViewModel(
fun reloadComment() { fun reloadComment() {
viewModelScope.launch { viewModelScope.launch {
try { try {
Pager(config = PagingConfig(pageSize = 5, enablePlaceholders = false), Pager(config = PagingConfig(pageSize = 20, enablePlaceholders = false),
pagingSourceFactory = { pagingSourceFactory = {
CommentPagingSource( CommentPagingSource(
CommentRemoteDataSource(commentService), CommentRemoteDataSource(commentService),
@@ -143,7 +144,8 @@ class CommentsViewModel(
replyCommentId = replyCommentId replyCommentId = replyCommentId
) )
MomentViewModel.updateCommentCount(postId.toInt()) MomentViewModel.updateCommentCount(postId.toInt())
addedCommentList = addedCommentList.plus(comment) // add to first
addedCommentList = listOf(comment) + addedCommentList
} }
fun deleteComment(commentId: Int) { fun deleteComment(commentId: Int) {
@@ -153,7 +155,9 @@ class CommentsViewModel(
if (addedCommentList.any { it.id == commentId }) { if (addedCommentList.any { it.id == commentId }) {
addedCommentList = addedCommentList.filter { it.id != commentId } addedCommentList = addedCommentList.filter { it.id != commentId }
} else { } else {
reloadComment() val currentPagingData = commentsFlow.value
val updatedPagingData = currentPagingData.filter { it.id != commentId }
_commentsFlow.value = updatedPagingData
} }
} }
} }

View File

@@ -2,8 +2,13 @@ package com.aiosman.riderpro.ui.post
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalSharedTransitionApi import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.spring
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.slideInVertically import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
@@ -46,6 +51,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.focusModifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
@@ -266,7 +272,9 @@ fun PostScreen(
StatusBarSpacer() StatusBarSpacer()
if (viewModel.isError) { if (viewModel.isError) {
Box( Box(
modifier = Modifier.fillMaxWidth().padding(16.dp) modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) { ) {
NoticeScreenHeader("Post", moreIcon = false) NoticeScreenHeader("Post", moreIcon = false)
} }
@@ -284,7 +292,7 @@ fun PostScreen(
) )
) )
} }
}else{ } else {
Header( Header(
avatar = viewModel.avatar, avatar = viewModel.avatar,
nickname = viewModel.nickname, nickname = viewModel.nickname,
@@ -309,6 +317,11 @@ fun PostScreen(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.weight(1f) .weight(1f)
.animateContentSize(
animationSpec = tween(
durationMillis = 500
)
)
) { ) {
item { item {
Box( Box(
@@ -393,10 +406,58 @@ fun CommentContent(
it.parentCommentId == null it.parentCommentId == null
} }
for (item in addedTopLevelComment) { Column(
modifier = Modifier
.padding(horizontal = 16.dp)
.animateContentSize(animationSpec = tween(durationMillis = 500))
) {
for (item in addedTopLevelComment) {
AnimatedVisibility(
visible = true,
enter = fadeIn() + slideInVertically(),
exit = fadeOut() + slideOutVertically()
) {
Box {
CommentItem(
item,
onLike = { comment ->
viewModel.viewModelScope.launch {
if (comment.liked) {
viewModel.unlikeComment(comment.id)
} else {
viewModel.likeComment(comment.id)
}
}
},
onLongClick = { comment ->
onLongClick(comment)
},
onReply = { parentComment, _, _, _ ->
onReply(
parentComment,
parentComment.author,
parentComment.name,
parentComment.avatar
)
},
onLoadMoreSubComments = {
viewModel.viewModelScope.launch {
viewModel.loadMoreSubComments(it.id)
}
},
addedCommentList = viewModel.addedCommentList
)
}
}
}
}
for (idx in 0 until commentsPagging.itemCount) {
val item = commentsPagging[idx] ?: return
AnimatedVisibility( AnimatedVisibility(
visible = true, visible = true,
enter = fadeIn() + slideInVertically() enter = slideInVertically(),
exit = slideOutVertically()
) { ) {
Box( Box(
modifier = Modifier.padding(horizontal = 16.dp) modifier = Modifier.padding(horizontal = 16.dp)
@@ -434,45 +495,12 @@ fun CommentContent(
} }
} }
for (idx in 0 until commentsPagging.itemCount) { // Handle loading and error states as before
val item = commentsPagging[idx] ?: return
Box(
modifier = Modifier.padding(horizontal = 16.dp)
) {
CommentItem(
item,
onLike = { comment ->
viewModel.viewModelScope.launch {
if (comment.liked) {
viewModel.unlikeComment(comment.id)
} else {
viewModel.likeComment(comment.id)
}
}
},
onLongClick = { comment ->
onLongClick(comment)
},
onReply = { parentComment, _, _, _ ->
onReply(
parentComment,
parentComment.author,
parentComment.name,
parentComment.avatar
)
},
onLoadMoreSubComments = {
viewModel.viewModelScope.launch {
viewModel.loadMoreSubComments(it.id)
}
},
addedCommentList = viewModel.addedCommentList
)
}
}
if (commentsPagging.loadState.refresh is LoadState.Loading) { if (commentsPagging.loadState.refresh is LoadState.Loading) {
Box( Box(
modifier = Modifier.fillMaxSize().height(120.dp), modifier = Modifier
.fillMaxSize()
.height(120.dp),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
Column( Column(
@@ -488,13 +516,14 @@ fun CommentContent(
fontSize = 14.sp fontSize = 14.sp
) )
} }
} }
return return
} }
if (commentsPagging.loadState.append is LoadState.Loading) { if (commentsPagging.loadState.append is LoadState.Loading) {
Box( Box(
modifier = Modifier.fillMaxSize().height(64.dp), modifier = Modifier
.fillMaxSize()
.height(64.dp),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
LinearProgressIndicator( LinearProgressIndicator(
@@ -505,11 +534,13 @@ fun CommentContent(
} }
if (commentsPagging.loadState.refresh is LoadState.Error) { if (commentsPagging.loadState.refresh is LoadState.Error) {
Box( Box(
modifier = Modifier.fillMaxSize().height(120.dp), modifier = Modifier
.fillMaxSize()
.height(120.dp),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
Text( Text(
text = "Failed to load comments,click to retry", text = "Failed to load comments, click to retry",
fontSize = 14.sp, fontSize = 14.sp,
modifier = Modifier.noRippleClickable { modifier = Modifier.noRippleClickable {
viewModel.reloadComment() viewModel.reloadComment()
@@ -519,11 +550,13 @@ fun CommentContent(
} }
if (commentsPagging.loadState.append is LoadState.Error) { if (commentsPagging.loadState.append is LoadState.Error) {
Box( Box(
modifier = Modifier.fillMaxSize().height(64.dp), modifier = Modifier
.fillMaxSize()
.height(64.dp),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
Text( Text(
text = "Failed to load more comments,click to retry", text = "Failed to load more comments, click to retry",
fontSize = 14.sp, fontSize = 14.sp,
modifier = Modifier.noRippleClickable { modifier = Modifier.noRippleClickable {
commentsPagging.retry() commentsPagging.retry()
@@ -531,8 +564,6 @@ fun CommentContent(
) )
} }
} }
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@@ -618,7 +649,9 @@ fun Header(
FollowButton( FollowButton(
isFollowing = isFollowing, isFollowing = isFollowing,
onFollowClick = onFollowClick, onFollowClick = onFollowClick,
imageModifier = Modifier.height(18.dp).width(80.dp), imageModifier = Modifier
.height(18.dp)
.width(80.dp),
fontSize = 12.sp fontSize = 12.sp
) )
} }
@@ -899,7 +932,11 @@ fun CommentItem(
} }
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
Column( Column(
modifier = Modifier.padding(start = 12.dp + 40.dp) modifier = Modifier.padding(start = 12.dp + 40.dp).animateContentSize(
animationSpec = tween(
durationMillis = 500
)
)
) { ) {
val addedCommentList = val addedCommentList =
addedCommentList.filter { it.parentCommentId == commentEntity.id } addedCommentList.filter { it.parentCommentId == commentEntity.id }

View File

@@ -65,6 +65,7 @@ class PostViewModel(
replyUserId = replyUserId, replyUserId = replyUserId,
replyCommentId = replyCommentId replyCommentId = replyCommentId
) )
moment = moment?.copy(commentCount = moment?.commentCount?.plus(1) ?: 0)
} }
suspend fun likeMoment() { suspend fun likeMoment() {

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path
name="cache"
path="." />
</paths>