更新消息功能

- 新增下拉刷新功能
- 优化消息列表UI
- 调整消息列表item布局
This commit is contained in:
2024-09-06 02:39:45 +08:00
parent 3d315b1ac3
commit 1e12eb42f7
3 changed files with 136 additions and 120 deletions

View File

@@ -15,14 +15,22 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
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
@@ -31,9 +39,10 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewModelScope
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import com.aiosman.riderpro.LocalNavController import com.aiosman.riderpro.LocalNavController
import com.aiosman.riderpro.R import com.aiosman.riderpro.R
@@ -44,17 +53,24 @@ import com.aiosman.riderpro.ui.composables.BottomNavigationPlaceholder
import com.aiosman.riderpro.ui.composables.CustomAsyncImage import com.aiosman.riderpro.ui.composables.CustomAsyncImage
import com.aiosman.riderpro.ui.modifiers.noRippleClickable import com.aiosman.riderpro.ui.modifiers.noRippleClickable
import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.accompanist.systemuicontroller.rememberSystemUiController
import kotlinx.coroutines.launch
/** /**
* 消息列表界面 * 消息列表界面
*/ */
@OptIn(ExperimentalMaterialApi::class)
@Composable @Composable
fun NotificationsScreen() { fun NotificationsScreen() {
val navController = LocalNavController.current val navController = LocalNavController.current
val systemUiController = rememberSystemUiController() val systemUiController = rememberSystemUiController()
var dataFlow = MessageListViewModel.commentItemsFlow var dataFlow = MessageListViewModel.commentItemsFlow
var comments = dataFlow.collectAsLazyPagingItems() var comments = dataFlow.collectAsLazyPagingItems()
val state = rememberPullRefreshState(MessageListViewModel.isLoading, onRefresh = {
MessageListViewModel.viewModelScope.launch {
MessageListViewModel.initData()
}
})
val navigationBarPaddings = val navigationBarPaddings =
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + 48.dp WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + 48.dp
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
@@ -63,13 +79,19 @@ fun NotificationsScreen() {
} }
Column( Column(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
) { ) {
Spacer( Spacer(
modifier = Modifier.padding( modifier = Modifier.padding(
bottom = navigationBarPaddings bottom = navigationBarPaddings
) )
) )
Box(modifier = Modifier
.fillMaxWidth()
.weight(1f)
.pullRefresh(state)) {
Column(
modifier = Modifier.fillMaxSize(),
) {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -118,7 +140,7 @@ fun NotificationsScreen() {
) { ) {
items(comments.itemCount) { index -> items(comments.itemCount) { index ->
comments[index]?.let { comment -> comments[index]?.let { comment ->
CommentItem(comment) { CommentNoticeItem(comment) {
MessageListViewModel.updateReadStatus(comment.id) MessageListViewModel.updateReadStatus(comment.id)
navController.navigate( navController.navigate(
NavigationRoute.Post.route.replace( NavigationRoute.Post.route.replace(
@@ -134,6 +156,15 @@ fun NotificationsScreen() {
} }
} }
} }
PullRefreshIndicator(
MessageListViewModel.isLoading,
state,
Modifier.align(Alignment.TopCenter)
)
}
}
} }
@@ -237,14 +268,14 @@ fun NotificationCounterItem(count: Int) {
@Composable @Composable
fun CommentItem( fun CommentNoticeItem(
commentItem: CommentEntity, commentItem: CommentEntity,
onPostClick: () -> Unit = {}, onPostClick: () -> Unit = {},
) { ) {
val navController = LocalNavController.current val navController = LocalNavController.current
val context = LocalContext.current val context = LocalContext.current
Row( Row(
modifier = Modifier.padding(16.dp) modifier = Modifier.padding(vertical = 20.dp, horizontal = 16.dp)
) { ) {
Box { Box {
CustomAsyncImage( CustomAsyncImage(
@@ -253,7 +284,7 @@ fun CommentItem(
contentDescription = commentItem.name, contentDescription = commentItem.name,
modifier = Modifier modifier = Modifier
.size(48.dp) .size(48.dp)
.clip(RoundedCornerShape(4.dp)) .clip(CircleShape)
.noRippleClickable { .noRippleClickable {
navController.navigate( navController.navigate(
NavigationRoute.AccountProfile.route.replace( NavigationRoute.AccountProfile.route.replace(
@@ -267,7 +298,7 @@ fun CommentItem(
Row( Row(
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.padding(start = 16.dp) .padding(start = 12.dp)
.noRippleClickable { .noRippleClickable {
onPostClick() onPostClick()
} }
@@ -277,59 +308,41 @@ fun CommentItem(
) { ) {
Text( Text(
text = commentItem.name, text = commentItem.name,
fontSize = 16.sp, fontSize = 18.sp,
modifier = Modifier.padding(start = 16.dp) modifier = Modifier
) )
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(4.dp))
Row {
Text( Text(
text = commentItem.comment, text = commentItem.comment,
fontSize = 14.sp, fontSize = 14.sp,
modifier = Modifier.padding(start = 16.dp),
maxLines = 1, maxLines = 1,
color = Color(0x99000000) color = Color(0x99000000),
modifier = Modifier.weight(1f),
overflow = TextOverflow.Ellipsis
) )
} Spacer(modifier = Modifier.width(4.dp))
// Spacer(modifier = Modifier.weight(1f))
Column(
horizontalAlignment = Alignment.End
) {
Row {
if (commentItem.unread) {
Box(
modifier = Modifier
.clip(RoundedCornerShape(12.dp))
.background(Color(0xFFE53935))
.padding(4.dp)
) {
Text(
text = "new",
color = Color.White,
fontSize = 12.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.align(Alignment.Center)
)
}
Spacer(modifier = Modifier.width(8.dp))
}
Text( Text(
text = commentItem.date.timeAgo(context), text = commentItem.date.timeAgo(context),
fontSize = 14.sp, fontSize = 14.sp,
color = Color(0x66000000) color = Color(0x66000000)
) )
} }
Spacer(modifier = Modifier.height(4.dp))
}
Spacer(modifier = Modifier.width(24.dp))
// Spacer(modifier = Modifier.weight(1f))
commentItem.post?.let { commentItem.post?.let {
CustomAsyncImage( CustomAsyncImage(
context = context, context = context,
imageUrl = it.images[0].thumbnail, imageUrl = it.images[0].thumbnail,
contentDescription = "Post Image", contentDescription = "Post Image",
modifier = Modifier modifier = Modifier
.size(32.dp) .size(48.dp)
.clip(RoundedCornerShape(4.dp)),
) )
} }
} }
}
} }
} }

View File

@@ -30,22 +30,12 @@ object MessageListViewModel : ViewModel() {
private val commentService: CommentService = CommentServiceImpl() private val commentService: CommentService = CommentServiceImpl()
private val _commentItemsFlow = MutableStateFlow<PagingData<CommentEntity>>(PagingData.empty()) private val _commentItemsFlow = MutableStateFlow<PagingData<CommentEntity>>(PagingData.empty())
val commentItemsFlow = _commentItemsFlow.asStateFlow() val commentItemsFlow = _commentItemsFlow.asStateFlow()
var isLoading by mutableStateOf(false)
suspend fun initData() { suspend fun initData() {
isLoading = true
val info = accountService.getMyNoticeInfo() val info = accountService.getMyNoticeInfo()
noticeInfo = info noticeInfo = info
}
val likeNoticeCount
get() = noticeInfo?.likeCount ?: 0
val followNoticeCount
get() = noticeInfo?.followCount ?: 0
val favouriteNoticeCount
get() = noticeInfo?.favoriteCount ?: 0
val commentNoticeCount
get() = noticeInfo?.commentCount ?: 0
init {
viewModelScope.launch { viewModelScope.launch {
Pager( Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false), config = PagingConfig(pageSize = 5, enablePlaceholders = false),
@@ -59,8 +49,18 @@ object MessageListViewModel : ViewModel() {
_commentItemsFlow.value = it _commentItemsFlow.value = it
} }
} }
isLoading = false
} }
val likeNoticeCount
get() = noticeInfo?.likeCount ?: 0
val followNoticeCount
get() = noticeInfo?.followCount ?: 0
val favouriteNoticeCount
get() = noticeInfo?.favoriteCount ?: 0
val commentNoticeCount
get() = noticeInfo?.commentCount ?: 0
private fun updateIsRead(id: Int) { private fun updateIsRead(id: Int) {
val currentPagingData = _commentItemsFlow.value val currentPagingData = _commentItemsFlow.value
val updatedPagingData = currentPagingData.map { commentEntity -> val updatedPagingData = currentPagingData.map { commentEntity ->

View File

@@ -1,5 +1,8 @@
package com.aiosman.riderpro.ui.index.tabs.moment 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.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.paging.Pager import androidx.paging.Pager