diff --git a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageList.kt b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageList.kt index 44f8228..0277334 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageList.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageList.kt @@ -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) + ) } } + } } \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageListViewModel.kt b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageListViewModel.kt index be9b233..4ba6af9 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageListViewModel.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/message/MessageListViewModel.kt @@ -30,22 +30,12 @@ object MessageListViewModel : ViewModel() { private val commentService: CommentService = CommentServiceImpl() private val _commentItemsFlow = MutableStateFlow>(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 -> diff --git a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/moment/MomentViewModel.kt b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/moment/MomentViewModel.kt index 9fc321f..c22bd5b 100644 --- a/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/moment/MomentViewModel.kt +++ b/app/src/main/java/com/aiosman/riderpro/ui/index/tabs/moment/MomentViewModel.kt @@ -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