更新消息功能

- 新增下拉刷新功能
- 优化消息列表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.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
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.Text
import androidx.compose.runtime.Composable
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.Modifier
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.stringResource
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.sp
import androidx.lifecycle.viewModelScope
import androidx.paging.compose.collectAsLazyPagingItems
import com.aiosman.riderpro.LocalNavController
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.modifiers.noRippleClickable
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import kotlinx.coroutines.launch
/**
* 消息列表界面
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun NotificationsScreen() {
val navController = LocalNavController.current
val systemUiController = rememberSystemUiController()
var dataFlow = MessageListViewModel.commentItemsFlow
var comments = dataFlow.collectAsLazyPagingItems()
val state = rememberPullRefreshState(MessageListViewModel.isLoading, onRefresh = {
MessageListViewModel.viewModelScope.launch {
MessageListViewModel.initData()
}
})
val navigationBarPaddings =
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + 48.dp
LaunchedEffect(Unit) {
@@ -63,76 +79,91 @@ fun NotificationsScreen() {
}
Column(
modifier = Modifier.fillMaxSize()
) {
Spacer(
modifier = Modifier.padding(
bottom = navigationBarPaddings
)
)
Box(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp)
) {
Image(
painter = painterResource(id = R.drawable.rider_pro_message_title),
contentDescription = "Back",
modifier = Modifier.width(120.dp)
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
) {
NotificationIndicator(
MessageListViewModel.likeNoticeCount,
R.drawable.rider_pro_like,
stringResource(R.string.like_upper)
Box(modifier = Modifier
.fillMaxWidth()
.weight(1f)
.pullRefresh(state)) {
Column(
modifier = Modifier.fillMaxSize(),
) {
navController.navigate(NavigationRoute.Likes.route)
}
NotificationIndicator(
MessageListViewModel.followNoticeCount,
R.drawable.rider_pro_followers,
stringResource(R.string.followers_upper)
) {
navController.navigate(NavigationRoute.Followers.route)
}
NotificationIndicator(
MessageListViewModel.favouriteNoticeCount,
R.drawable.rider_pro_favoriate,
stringResource(R.string.favourites_upper)
) {
navController.navigate(NavigationRoute.FavouritesScreen.route)
}
}
HorizontalDivider(color = Color(0xFFEbEbEb), modifier = Modifier.padding(16.dp))
NotificationCounterItem(MessageListViewModel.commentNoticeCount)
LazyColumn(
modifier = Modifier
.weight(1f)
.fillMaxSize()
) {
items(comments.itemCount) { index ->
comments[index]?.let { comment ->
CommentItem(comment) {
MessageListViewModel.updateReadStatus(comment.id)
navController.navigate(
NavigationRoute.Post.route.replace(
"{id}",
comment.postId.toString()
)
)
Box(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp)
) {
Image(
painter = painterResource(id = R.drawable.rider_pro_message_title),
contentDescription = "Back",
modifier = Modifier.width(120.dp)
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
) {
NotificationIndicator(
MessageListViewModel.likeNoticeCount,
R.drawable.rider_pro_like,
stringResource(R.string.like_upper)
) {
navController.navigate(NavigationRoute.Likes.route)
}
NotificationIndicator(
MessageListViewModel.followNoticeCount,
R.drawable.rider_pro_followers,
stringResource(R.string.followers_upper)
) {
navController.navigate(NavigationRoute.Followers.route)
}
NotificationIndicator(
MessageListViewModel.favouriteNoticeCount,
R.drawable.rider_pro_favoriate,
stringResource(R.string.favourites_upper)
) {
navController.navigate(NavigationRoute.FavouritesScreen.route)
}
}
HorizontalDivider(color = Color(0xFFEbEbEb), modifier = Modifier.padding(16.dp))
NotificationCounterItem(MessageListViewModel.commentNoticeCount)
LazyColumn(
modifier = Modifier
.weight(1f)
.fillMaxSize()
) {
items(comments.itemCount) { index ->
comments[index]?.let { comment ->
CommentNoticeItem(comment) {
MessageListViewModel.updateReadStatus(comment.id)
navController.navigate(
NavigationRoute.Post.route.replace(
"{id}",
comment.postId.toString()
)
)
}
}
}
item {
BottomNavigationPlaceholder()
}
}
}
item {
BottomNavigationPlaceholder()
}
PullRefreshIndicator(
MessageListViewModel.isLoading,
state,
Modifier.align(Alignment.TopCenter)
)
}
}
@@ -237,14 +268,14 @@ fun NotificationCounterItem(count: Int) {
@Composable
fun CommentItem(
fun CommentNoticeItem(
commentItem: CommentEntity,
onPostClick: () -> Unit = {},
) {
val navController = LocalNavController.current
val context = LocalContext.current
Row(
modifier = Modifier.padding(16.dp)
modifier = Modifier.padding(vertical = 20.dp, horizontal = 16.dp)
) {
Box {
CustomAsyncImage(
@@ -253,7 +284,7 @@ fun CommentItem(
contentDescription = commentItem.name,
modifier = Modifier
.size(48.dp)
.clip(RoundedCornerShape(4.dp))
.clip(CircleShape)
.noRippleClickable {
navController.navigate(
NavigationRoute.AccountProfile.route.replace(
@@ -267,7 +298,7 @@ fun CommentItem(
Row(
modifier = Modifier
.weight(1f)
.padding(start = 16.dp)
.padding(start = 12.dp)
.noRippleClickable {
onPostClick()
}
@@ -277,59 +308,41 @@ fun CommentItem(
) {
Text(
text = commentItem.name,
fontSize = 16.sp,
modifier = Modifier.padding(start = 16.dp)
fontSize = 18.sp,
modifier = Modifier
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = commentItem.comment,
fontSize = 14.sp,
modifier = Modifier.padding(start = 16.dp),
maxLines = 1,
color = Color(0x99000000)
)
}
// Spacer(modifier = Modifier.weight(1f))
Column(
horizontalAlignment = Alignment.End
) {
Spacer(modifier = Modifier.height(4.dp))
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 = commentItem.comment,
fontSize = 14.sp,
maxLines = 1,
color = Color(0x99000000),
modifier = Modifier.weight(1f),
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = commentItem.date.timeAgo(context),
fontSize = 14.sp,
color = Color(0x66000000)
)
}
Spacer(modifier = Modifier.height(4.dp))
commentItem.post?.let {
CustomAsyncImage(
context = context,
imageUrl = it.images[0].thumbnail,
contentDescription = "Post Image",
modifier = Modifier
.size(32.dp)
.clip(RoundedCornerShape(4.dp)),
)
}
}
Spacer(modifier = Modifier.width(24.dp))
// Spacer(modifier = Modifier.weight(1f))
commentItem.post?.let {
CustomAsyncImage(
context = context,
imageUrl = it.images[0].thumbnail,
contentDescription = "Post Image",
modifier = Modifier
.size(48.dp)
)
}
}
}
}

View File

@@ -30,22 +30,12 @@ object MessageListViewModel : ViewModel() {
private val commentService: CommentService = CommentServiceImpl()
private val _commentItemsFlow = MutableStateFlow<PagingData<CommentEntity>>(PagingData.empty())
val commentItemsFlow = _commentItemsFlow.asStateFlow()
var isLoading by mutableStateOf(false)
suspend fun initData() {
isLoading = true
val info = accountService.getMyNoticeInfo()
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 {
Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
@@ -59,8 +49,18 @@ object MessageListViewModel : ViewModel() {
_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) {
val currentPagingData = _commentItemsFlow.value
val updatedPagingData = currentPagingData.map { commentEntity ->

View File

@@ -1,5 +1,8 @@
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.viewModelScope
import androidx.paging.Pager