添加更新数据

This commit is contained in:
2024-07-29 16:50:07 +08:00
parent d23c5f5c7e
commit 53c71973ae
11 changed files with 398 additions and 189 deletions

View File

@@ -23,6 +23,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -35,30 +36,54 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.cachedIn
import androidx.paging.compose.collectAsLazyPagingItems
import com.aiosman.riderpro.ui.post.CommentsSection
import com.aiosman.riderpro.R
import com.aiosman.riderpro.data.Comment
import com.aiosman.riderpro.data.CommentPagingSource
import com.aiosman.riderpro.data.CommentRemoteDataSource
import com.aiosman.riderpro.data.CommentService
import com.aiosman.riderpro.data.TestCommentServiceImpl
import com.aiosman.riderpro.ui.modifiers.noRippleClickable
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
class CommentModalViewModel(
postId: Int?
):ViewModel(){
val commentService:CommentService = TestCommentServiceImpl()
val commentsFlow: Flow<PagingData<Comment>> = Pager(
config = PagingConfig(pageSize = 20, enablePlaceholders = false),
pagingSourceFactory = {
CommentPagingSource(
CommentRemoteDataSource(commentService),
postId
)
}
).flow.cachedIn(viewModelScope)
}
@Preview
@Composable
fun CommentModalContent(onDismiss: () -> Unit = {}) {
var commentSource = CommentPagingSource(
CommentRemoteDataSource(TestCommentServiceImpl())
fun CommentModalContent(postId: Int? = null, onDismiss: () -> Unit = {}) {
val model = viewModel<CommentModalViewModel>(
factory = object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return CommentModalViewModel(postId) as T
}
}
)
val commentsFlow: Flow<PagingData<Comment>> = Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = { commentSource }
).flow
val comments = commentsFlow.collectAsLazyPagingItems()
val scope = rememberCoroutineScope()
val comments = model.commentsFlow.collectAsLazyPagingItems()
val insets = WindowInsets
val imePadding = insets.ime.getBottom(density = LocalDensity.current)
var bottomPadding by remember { mutableStateOf(0.dp) }
@@ -70,7 +95,14 @@ fun CommentModalContent(onDismiss: () -> Unit = {}) {
onDismiss()
}
}
var commentText by remember { mutableStateOf("") }
suspend fun sendComment() {
if (commentText.isNotEmpty()) {
model.commentService.createComment(postId!!, commentText, 1)
commentText = ""
}
comments.refresh()
}
Column(
modifier = Modifier
) {
@@ -97,8 +129,13 @@ fun CommentModalContent(onDismiss: () -> Unit = {}) {
.padding(horizontal = 16.dp)
.weight(1f)
) {
CommentsSection(lazyPagingItems = comments) {
CommentsSection(lazyPagingItems = comments, onLike = {
comment: Comment ->
scope.launch {
model.commentService.likeComment(comment.id)
comments.refresh()
}
}) {
}
@@ -127,8 +164,8 @@ fun CommentModalContent(onDismiss: () -> Unit = {}) {
) {
BasicTextField(
value = "",
onValueChange = { },
value = commentText,
onValueChange = { text -> commentText = text },
modifier = Modifier
.fillMaxWidth(),
textStyle = TextStyle(
@@ -144,7 +181,11 @@ fun CommentModalContent(onDismiss: () -> Unit = {}) {
contentDescription = "Send",
modifier = Modifier
.size(32.dp)
.noRippleClickable {
scope.launch {
sendComment()
}
}
)
}

View File

@@ -72,7 +72,7 @@ fun MomentsList() {
MomentCard(momentItem = momentItem, onLikeClick = {
scope.launch {
model.likeMoment(momentItem.id)
moments.refresh()
// moments.refresh()
}
})
}
@@ -253,7 +253,7 @@ fun MomentContentGroup(
) {
val displayImageUrl = momentItem.images.firstOrNull()
Text(
text = momentItem.momentTextContent,
text = "${momentItem.id} ${momentItem.momentTextContent}",
modifier = Modifier
.fillMaxWidth()
.padding(top = 22.dp, bottom = 16.dp, start = 24.dp, end = 24.dp),
@@ -323,7 +323,7 @@ fun MomentBottomOperateRowGroup(
)
) {
systemUiController.setNavigationBarColor(Color(0xfff7f7f7))
CommentModalContent() {
CommentModalContent(postId = momentItem.id) {
systemUiController.setNavigationBarColor(Color.Black)
}
}

View File

@@ -1,39 +1,57 @@
package com.aiosman.riderpro.ui.index.tabs.moment
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.toMutableStateList
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.aiosman.riderpro.R
import androidx.paging.cachedIn
import androidx.paging.map
import com.aiosman.riderpro.data.AccountService
import com.aiosman.riderpro.data.MomentPagingSource
import com.aiosman.riderpro.data.MomentRemoteDataSource
import com.aiosman.riderpro.data.MomentService
import com.aiosman.riderpro.data.TestAccountServiceImpl
import com.aiosman.riderpro.data.TestMomentServiceImpl
import com.aiosman.riderpro.model.MomentItem
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
object MomentViewModel : ViewModel() {
val momentService: MomentService = TestMomentServiceImpl()
var momentListPagingSource = MomentPagingSource(
MomentRemoteDataSource(momentService)
)
var momentsFlow: Flow<PagingData<MomentItem>> = Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = {
MomentPagingSource(
MomentRemoteDataSource(momentService)
)
private val momentService: MomentService = TestMomentServiceImpl()
private val _momentsFlow = MutableStateFlow<PagingData<MomentItem>>(PagingData.empty())
val momentsFlow = _momentsFlow.asStateFlow()
val accountService: AccountService = TestAccountServiceImpl()
init {
viewModelScope.launch {
val profile = accountService.getMyAccountProfile()
Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = { MomentPagingSource(
MomentRemoteDataSource(momentService),
timelineId = profile.id
) }
).flow.cachedIn(viewModelScope).collectLatest {
_momentsFlow.value = it
}
}
).flow
}
suspend fun likeMoment(id: Int) {
momentService.likeMoment(id)
val currentPagingData = _momentsFlow.value
val updatedPagingData = currentPagingData.map { momentItem ->
if (momentItem.id == id) {
momentItem.copy(likeCount = momentItem.likeCount + 1)
} else {
momentItem
}
}
_momentsFlow.value = updatedPagingData
}
}

View File

@@ -18,18 +18,20 @@ import kotlinx.coroutines.flow.Flow
object MyProfileViewModel {
val service: AccountService = TestAccountServiceImpl()
var profile by mutableStateOf<AccountProfile?>(null)
var momentsFlow by mutableStateOf<Flow<PagingData<MomentItem>>?>(null)
suspend fun loadProfile() {
profile = service.getAccountProfile()
profile = service.getMyAccountProfile()
momentsFlow = Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = {
MomentPagingSource(
MomentRemoteDataSource(TestMomentServiceImpl()),
author = profile?.id ?: 0,
)
}
).flow
}
var momentListPagingSource = MomentPagingSource(
MomentRemoteDataSource(TestMomentServiceImpl())
)
val momentsFlow: Flow<PagingData<MomentItem>> = Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = { momentListPagingSource }
).flow
val followerCount get() = profile?.followerCount ?: 0
val followingCount get() = profile?.followingCount ?: 0
val bio get() = profile?.bio ?: ""

View File

@@ -19,9 +19,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -51,7 +49,7 @@ fun ProfilePage() {
LaunchedEffect(Unit) {
model.loadProfile()
}
val profile = model.momentsFlow.collectAsLazyPagingItems()
val moments = model.momentsFlow?.collectAsLazyPagingItems()
LazyColumn(
modifier = Modifier
.fillMaxSize()
@@ -67,10 +65,13 @@ fun ProfilePage() {
RidingStyle()
}
items(profile.itemCount) { idx ->
val momentItem = profile[idx] ?: return@items
MomentPostUnit(momentItem)
moments?.let {
items(it.itemCount) { idx ->
val momentItem = it[idx] ?: return@items
MomentPostUnit(momentItem)
}
}
}
}
@@ -409,7 +410,7 @@ fun MomentPostUnit(momentItem: MomentItem) {
TimeGroup(momentItem.time)
MomentCard(
momentItem.momentTextContent,
momentItem.momentPicture,
momentItem.images[0],
momentItem.likeCount.toString(),
momentItem.commentCount.toString()
)
@@ -439,7 +440,7 @@ fun TimeGroup(time: String = "2024.06.08 12:23") {
}
@Composable
fun MomentCard(content: String, @DrawableRes picture: Int, like: String, comment: String) {
fun MomentCard(content: String, imageUrl: String, like: String, comment: String) {
Column(
modifier = Modifier
.fillMaxWidth()
@@ -447,7 +448,7 @@ fun MomentCard(content: String, @DrawableRes picture: Int, like: String, comment
.border(width = 1.dp, color = Color(0f, 0f, 0f, 0.1f), shape = RoundedCornerShape(6.dp))
) {
MomentCardTopContent(content)
MomentCardPicture(picture)
MomentCardPicture(imageUrl)
MomentCardOperation(like, comment)
}
}
@@ -468,13 +469,15 @@ fun MomentCardTopContent(content: String) {
}
@Composable
fun MomentCardPicture(@DrawableRes drawable: Int) {
Image(
fun MomentCardPicture(imageUrl:String) {
AsyncImage(
imageUrl,
modifier = Modifier
.fillMaxSize()
.padding(16.dp), painter = painterResource(id = drawable), contentDescription = ""
.padding(16.dp),
contentDescription = "",
contentScale = ContentScale.FillWidth
)
}
@Composable

View File

@@ -66,11 +66,14 @@ import androidx.paging.compose.collectAsLazyPagingItems
import coil.compose.AsyncImage
import com.aiosman.riderpro.LocalNavController
import com.aiosman.riderpro.R
import com.aiosman.riderpro.data.AccountProfile
import com.aiosman.riderpro.data.AccountService
import com.aiosman.riderpro.data.Comment
import com.aiosman.riderpro.data.CommentPagingSource
import com.aiosman.riderpro.data.CommentRemoteDataSource
import com.aiosman.riderpro.data.TestCommentServiceImpl
import com.aiosman.riderpro.data.MomentService
import com.aiosman.riderpro.data.TestAccountServiceImpl
import com.aiosman.riderpro.data.TestMomentServiceImpl
import com.aiosman.riderpro.model.MomentItem
import com.aiosman.riderpro.ui.composables.StatusBarMaskLayout
@@ -101,9 +104,14 @@ fun PostScreen(
val scrollState = rememberLazyListState()
val uiController = rememberSystemUiController()
var moment by remember { mutableStateOf<MomentItem?>(null) }
var accountProfile by remember { mutableStateOf<AccountProfile?>(null) }
var accountService: AccountService = TestAccountServiceImpl()
LaunchedEffect(Unit) {
uiController.setNavigationBarColor(Color.White)
moment = service.getMomentById(id.toInt())
moment?.let {
accountProfile = accountService.getAccountProfileById(it.authorId)
}
}
StatusBarMaskLayout {
Scaffold(
@@ -115,7 +123,7 @@ fun PostScreen(
modifier = Modifier
.fillMaxSize()
) {
Header()
Header(accountProfile)
Column(modifier = Modifier.animateContentSize()) {
AnimatedVisibility(visible = showCollapseContent) {
// collapse content
@@ -148,7 +156,7 @@ fun PostScreen(
.fillMaxWidth()
) {
CommentsSection(lazyPagingItems = lazyPagingItems, scrollState) {
CommentsSection(lazyPagingItems = lazyPagingItems, scrollState, onLike = {}) {
showCollapseContent = it
}
}
@@ -158,7 +166,7 @@ fun PostScreen(
}
@Composable
fun Header() {
fun Header(accountProfile: AccountProfile?) {
val navController = LocalNavController.current
Row(
modifier = Modifier
@@ -177,15 +185,22 @@ fun Header() {
)
Spacer(modifier = Modifier.width(8.dp))
Image(
painter = painterResource(id = R.drawable.default_avatar), // Replace with your image resource
contentDescription = "Profile Picture",
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
)
accountProfile?.let {
AsyncImage(
accountProfile.avatar,
contentDescription = "Profile Picture",
modifier = Modifier
.size(40.dp)
.clip(CircleShape),
contentScale = ContentScale.Crop
)
}
Spacer(modifier = Modifier.width(8.dp))
Text(text = "Diego Morata", fontWeight = FontWeight.Bold)
accountProfile?.let {
Text(text = accountProfile.nickName, fontWeight = FontWeight.Bold)
}
Box(
modifier = Modifier
.height(20.dp)
@@ -269,25 +284,23 @@ fun PostDetails(
momentItem: MomentItem?
) {
Column(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth()
.wrapContentHeight()
) {
Text(
text = momentItem?.momentTextContent ?:"",
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
)
Text(text = "12-11 发布")
Spacer(modifier = Modifier.height(8.dp))
Text(text = "共231条评论")
}
Column(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth()
.wrapContentHeight()
) {
Text(
text = momentItem?.momentTextContent ?: "",
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
)
Text(text = "12-11 发布")
Spacer(modifier = Modifier.height(8.dp))
Text(text = "共231条评论")
}
}
@@ -296,6 +309,7 @@ fun PostDetails(
fun CommentsSection(
lazyPagingItems: LazyPagingItems<Comment>,
scrollState: LazyListState = rememberLazyListState(),
onLike: (Comment) -> Unit,
onWillCollapse: (Boolean) -> Unit
) {
LazyColumn(
@@ -305,7 +319,9 @@ fun CommentsSection(
) {
items(lazyPagingItems.itemCount) { idx ->
val item = lazyPagingItems[idx] ?: return@items
CommentItem(item)
CommentItem(item,onLike={
onLike(item)
})
}
}
@@ -323,15 +339,16 @@ fun CommentsSection(
@Composable
fun CommentItem(comment: Comment) {
fun CommentItem(comment: Comment,onLike:()->Unit = {}) {
Column {
Row(modifier = Modifier.padding(vertical = 8.dp)) {
Image(
painter = painterResource(id = R.drawable.default_avatar), // Replace with your image resource
AsyncImage(
comment.avatar,
contentDescription = "Comment Profile Picture",
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
.clip(CircleShape),
contentScale = ContentScale.Crop
)
Spacer(modifier = Modifier.width(8.dp))
Column {
@@ -341,7 +358,9 @@ fun CommentItem(comment: Comment) {
}
Spacer(modifier = Modifier.weight(1f))
Column(horizontalAlignment = Alignment.CenterHorizontally) {
IconButton(onClick = { /*TODO*/ }) {
IconButton(onClick = {
onLike()
}) {
Icon(Icons.Filled.Favorite, contentDescription = "Like")
}
Text(text = comment.likes.toString())

View File

@@ -37,18 +37,22 @@ fun AccountProfile(id:String) {
// val model = MyProfileViewModel
val userService: UserService = TestUserServiceImpl()
var userProfile by remember { mutableStateOf<AccountProfile?>(null) }
var momentListPagingSource = MomentPagingSource(
MomentRemoteDataSource(TestMomentServiceImpl())
)
val momentsFlow: Flow<PagingData<MomentItem>> = Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = { momentListPagingSource }
).flow
val momentService = TestMomentServiceImpl()
var momentsFlow by remember { mutableStateOf<Flow<PagingData<MomentItem>>?>(null) }
LaunchedEffect(Unit) {
userProfile = userService.getUserProfile(id)
momentsFlow = Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = {
MomentPagingSource(
MomentRemoteDataSource(momentService),
author = id.toInt()
)
}
).flow
}
val items = momentsFlow.collectAsLazyPagingItems()
val items = momentsFlow?.collectAsLazyPagingItems()
val systemUiController = rememberSystemUiController()
LaunchedEffect(Unit) {
systemUiController.setNavigationBarColor(
@@ -70,13 +74,14 @@ fun AccountProfile(id:String) {
CarGroup()
userProfile?.let {
UserInformation(isSelf = false, accountProfile = it)
}
RidingStyle()
}
items(items.itemCount) { idx ->
val momentItem = items[idx] ?: return@items
MomentPostUnit(momentItem)
if (items != null) {
items(items.itemCount) { idx ->
val momentItem = items[idx] ?: return@items
MomentPostUnit(momentItem)
}
}
}
}