更新消息功能
- 新增下拉刷新功能 - 优化消息列表UI - 调整消息列表item布局
This commit is contained in:
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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 ->
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user