20250723-Test Push

This commit is contained in:
weber
2025-07-23 19:07:29 +08:00
parent 9f93e6dc14
commit 6ec732b996
36 changed files with 730 additions and 155 deletions

View File

@@ -16,10 +16,10 @@ import com.aiosman.ravenow.entity.AccountProfileEntity
import com.aiosman.ravenow.ui.favourite.FavouriteListViewModel
import com.aiosman.ravenow.ui.favourite.FavouriteNoticeViewModel
import com.aiosman.ravenow.ui.follower.FollowerNoticeViewModel
import com.aiosman.ravenow.ui.follower.FollowingListViewModel
import com.aiosman.ravenow.ui.index.IndexViewModel
import com.aiosman.ravenow.ui.index.tabs.message.MessageListViewModel
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre.MomentExploreViewModel
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.hot.HotMomentViewModel
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.timeline.TimelineMomentViewModel
import com.aiosman.ravenow.ui.index.tabs.profile.MyProfileViewModel
import com.aiosman.ravenow.ui.index.tabs.search.DiscoverViewModel
@@ -152,6 +152,8 @@ object AppState {
// 重置动态列表页面
TimelineMomentViewModel.ResetModel()
MomentExploreViewModel.ResetModel()
HotMomentViewModel.ResetModel()
// 重置我的页面
MyProfileViewModel.ResetModel()
// 重置发现页面

View File

@@ -25,6 +25,7 @@ open class AppThemeData(
var checkedBackground: Color,
var checkedText: Color,
var chatActionColor: Color,
var brandColorsColor: Color,
)
class LightThemeColors : AppThemeData(
@@ -33,7 +34,7 @@ class LightThemeColors : AppThemeData(
basicMain = Color(0xfff0f0f0),
nonActive = Color(0xfff5f5f5),
text = Color(0xff333333),
nonActiveText = Color(0xff333333),
nonActiveText = Color(0xff3C3C43),
secondaryText = Color(0x99000000),
loadingMain = Color(0xFFD95757),
loadingText = Color(0xffffffff),
@@ -46,7 +47,8 @@ class LightThemeColors : AppThemeData(
checkedBackground = Color(0xff000000),
checkedText = Color(0xffFFFFFF),
decentBackground = Color(0xfff5f5f5),
chatActionColor = Color(0xffe0e0e0)
chatActionColor = Color(0xffe0e0e0),
brandColorsColor = Color(0xffD80264),
)
@@ -69,5 +71,6 @@ class DarkThemeColors : AppThemeData(
checkedBackground = Color(0xffffffff),
checkedText = Color(0xff000000),
decentBackground = Color(0xFF171717),
chatActionColor = Color(0xFF3D3D3D)
chatActionColor = Color(0xFF3D3D3D),
brandColorsColor = Color(0xffD80264),
)

View File

@@ -30,7 +30,7 @@ fun showLikeNotification(context: Context, title: String, message: String, postI
)
val notificationBuilder = NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.rider_pro_favoriate)
.setSmallIcon(R.drawable.rider_pro_favourite)
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)

View File

@@ -23,7 +23,7 @@ import com.aiosman.ravenow.ui.modifiers.noRippleClickable
@Composable
fun FollowButton(
isFollowing: Boolean,
fontSize: TextUnit = 12.sp,
fontSize: TextUnit = 14.sp,
onFollowClick: () -> Unit,
){
val AppColors = LocalAppTheme.current
@@ -45,7 +45,7 @@ fun FollowButton(
R.string.follow_upper
),
fontSize = fontSize,
color = if (isFollowing) AppColors.mainText else AppColors.nonActiveText,
color = if (isFollowing) AppColors.mainText else AppColors.text,
style = TextStyle(fontWeight = FontWeight.Bold)
)
}

View File

@@ -19,8 +19,10 @@ import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.Icon
import androidx.compose.material3.ModalNavigationDrawer
@@ -39,6 +41,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
@@ -49,6 +52,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.aiosman.ravenow.AppState
import com.aiosman.ravenow.AppStore
import com.aiosman.ravenow.LocalAppTheme
@@ -79,7 +83,7 @@ fun IndexScreen() {
val navController = LocalNavController.current
val item = listOf(
NavigationItem.Home,
NavigationItem.Search,
NavigationItem.Ai,
NavigationItem.Add,
NavigationItem.Notification,
NavigationItem.Profile
@@ -171,6 +175,26 @@ fun IndexScreen() {
.background(AppColors.divider)
)
}
NavItem(
iconRes = R.drawable.rave_now_nav_about,
label = stringResource(R.string.blocked),
modifier = Modifier.noRippleClickable {
coroutineScope.launch {
drawerState.close()
navController.navigate(NavigationRoute.AboutScreen.route)
}
}
)
NavItem(
iconRes = R.drawable.rave_now_nav_about,
label = stringResource(R.string.feedback),
modifier = Modifier.noRippleClickable {
coroutineScope.launch {
drawerState.close()
navController.navigate(NavigationRoute.AboutScreen.route)
}
}
)
NavItem(
iconRes = R.drawable.rave_now_nav_about,
label = stringResource(R.string.about_rave_now),
@@ -233,15 +257,16 @@ fun IndexScreen() {
bottomBar = {
NavigationBar(
modifier = Modifier.height(56.dp + navigationBarHeight),
containerColor = Color.Black
containerColor = AppColors.background
) {
item.forEachIndexed { idx, it ->
val isSelected = model.tabIndex == idx
val iconTint by animateColorAsState(
targetValue = if (isSelected) Color.White else Color.White,
targetValue = if (isSelected) AppColors.brandColorsColor else AppColors.text,
animationSpec = tween(durationMillis = 250), label = ""
)
NavigationBarItem(
modifier = Modifier.padding(top = 6.dp),
selected = isSelected,
onClick = {
if (it.route === NavigationItem.Add.route) {
@@ -256,7 +281,7 @@ fun IndexScreen() {
},
colors = NavigationBarItemColors(
selectedTextColor = Color.Red,
selectedIndicatorColor = Color.Black,
selectedIndicatorColor = Color.Transparent,
unselectedTextColor = Color.Red,
disabledIconColor = Color.Red,
disabledTextColor = Color.Red,
@@ -264,13 +289,33 @@ fun IndexScreen() {
unselectedIconColor = iconTint,
),
icon = {
Icon(
modifier = Modifier.size(24.dp),
imageVector = if (isSelected) it.selectedIcon() else it.icon(),
contentDescription = null,
tint = iconTint
Box(
modifier = Modifier
.width(46.dp)
.height(30.dp)
.background(
color = if (isSelected) AppColors.brandColorsColor.copy(alpha = 0.1f) else Color.Transparent ,
shape = RoundedCornerShape(10.dp)
),
contentAlignment = Alignment.Center
) {
Icon(
modifier = Modifier.size(24.dp),
imageVector = if (isSelected) it.selectedIcon() else it.icon(),
contentDescription = null,
tint = iconTint
)
}
},
label = {
Text(
modifier = Modifier.padding(0.dp),
text = it.label(),
fontSize = 9.sp,
color = if (isSelected) AppColors.brandColorsColor else AppColors.text,
)
}
)
}
}

View File

@@ -1,47 +1,59 @@
package com.aiosman.ravenow.ui.index
import android.graphics.Color
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import com.aiosman.ravenow.R
sealed class NavigationItem(
val route: String,
val icon: @Composable () -> ImageVector,
val selectedIcon: @Composable () -> ImageVector = icon
val selectedIcon: @Composable () -> ImageVector = icon,
val label: @Composable () -> String
) {
data object Home : NavigationItem("Home",
icon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_home) },
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_home_hl) }
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_home_hl) },
label = { stringResource(R.string.main_home) }
)
data object Street : NavigationItem("Street",
icon = { ImageVector.vectorResource(R.drawable.rider_pro_location) },
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_location_filed) }
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_location_filed) },
label = { stringResource(R.string.main_home) }
)
data object Add : NavigationItem("Add",
icon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_post_hl) },
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_post_hl) }
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_post_hl) },
label = { "" }
)
data object Message : NavigationItem("Message",
icon = { ImageVector.vectorResource(R.drawable.rider_pro_video_outline) },
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_video) }
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_video) },
label = { stringResource(R.string.main_home) }
)
data object Notification : NavigationItem("Notification",
icon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_notification)},
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_notification_hl) }
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_notification) },
label = { stringResource(R.string.main_message) }
)
data object Profile : NavigationItem("Profile",
icon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_profile) },
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_profile_hl) }
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_profile_hl) },
label = { stringResource(R.string.main_profile) }
)
data object Search : NavigationItem("Search",
data object Ai : NavigationItem("Ai",
icon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_search) },
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_search_hl) }
selectedIcon = { ImageVector.vectorResource(R.drawable.rider_pro_nav_search_hl) },
label = { stringResource(R.string.main_ai) }
)
}

View File

@@ -86,9 +86,41 @@ fun NotificationsScreen() {
.weight(1f)
.pullRefresh(state)
) {
Column(
modifier = Modifier.fillMaxSize(),
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
// 左侧 Columnlabel 居中显示
Column(
modifier = Modifier
.weight(1f)
.align(Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = stringResource(R.string.main_message),
fontSize = 16.sp,
color = AppColors.text
)
}
// 右侧图片按钮:靠右显示
Image(
painter = painterResource(id = R.drawable.rider_pro_favourite),
contentDescription = stringResource(R.string.main_message),
modifier = Modifier
.size(24.dp)
.noRippleClickable {
// 点击事件
}
)
}
Row(
modifier = Modifier
.fillMaxWidth()
@@ -97,8 +129,9 @@ fun NotificationsScreen() {
) {
NotificationIndicator(
MessageListViewModel.likeNoticeCount,
R.drawable.rider_pro_moment_like,
stringResource(R.string.like_upper)
R.mipmap.rider_pro_like,
stringResource(R.string.like_upper),
Color(0xFFFAFD5D)
) {
if (MessageListViewModel.likeNoticeCount > 0) {
// 刷新点赞消息列表
@@ -110,8 +143,9 @@ fun NotificationsScreen() {
}
NotificationIndicator(
MessageListViewModel.followNoticeCount,
R.drawable.rider_pro_followers,
stringResource(R.string.followers_upper)
R.mipmap.rider_pro_followers,
stringResource(R.string.followers_upper),
Color(0xFFF470FE)
) {
if (MessageListViewModel.followNoticeCount > 0) {
// 刷新关注消息列表
@@ -122,8 +156,9 @@ fun NotificationsScreen() {
}
NotificationIndicator(
MessageListViewModel.commentNoticeCount,
R.drawable.rider_pro_comment,
stringResource(R.string.comment).uppercase()
R.mipmap.rider_pro_comment,
stringResource(R.string.comment).uppercase(),
Color(0xFF6246FF)
) {
navController.navigate(NavigationRoute.CommentNoticeScreen.route)
}
@@ -170,6 +205,7 @@ fun NotificationIndicator(
notificationCount: Int,
iconRes: Int,
label: String,
backgroundColor: Color = Color.Transparent,
onClick: () -> Unit
) {
val AppColors = LocalAppTheme.current
@@ -204,19 +240,22 @@ fun NotificationIndicator(
horizontalAlignment = Alignment.CenterHorizontally,
) {
Box(
modifier = Modifier.padding(16.dp)
modifier = Modifier
.size(64.dp)
.background(color = backgroundColor,
shape = RoundedCornerShape(16.dp)),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(id = iconRes),
contentDescription = label,
modifier = Modifier.size(24.dp),
colorFilter = ColorFilter.tint(AppColors.text)
modifier = Modifier.size(24.dp)
)
}
Box(
modifier = Modifier
) {
Text(label, modifier = Modifier.align(Alignment.Center), color = AppColors.text)
Text(label, modifier = Modifier.align(Alignment.Center).padding(top = 8.dp), color = AppColors.text)
}
}

View File

@@ -14,26 +14,36 @@ import androidx.compose.foundation.layout.fillMaxWidth
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.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Icon
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre.ExploreMomentsList
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.hot.HotMomentsList
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.timeline.TimelineMomentsList
import com.aiosman.ravenow.ui.index.tabs.search.SearchViewModel
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import kotlinx.coroutines.launch
@@ -44,10 +54,11 @@ import kotlinx.coroutines.launch
@Composable
fun MomentsList() {
val AppColors = LocalAppTheme.current
val navController = LocalNavController.current
val navigationBarPaddings =
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + 48.dp
val statusBarPaddingValues = WindowInsets.systemBars.asPaddingValues()
var pagerState = rememberPagerState { 2 }
var pagerState = rememberPagerState { 3 }
var scope = rememberCoroutineScope()
Column(
modifier = Modifier
@@ -63,7 +74,7 @@ fun MomentsList() {
.fillMaxWidth()
.height(44.dp),
// center the tabs
horizontalArrangement = Arrangement.Center,
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
Column(
@@ -72,24 +83,28 @@ fun MomentsList() {
scope.launch {
pagerState.animateScrollToPage(0)
}
},
}.padding(start = 16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = stringResource(R.string.index_worldwide), fontSize = 16.sp, color = AppColors.text,fontWeight = FontWeight.W600)
Text(
text = stringResource(R.string.index_worldwide),
fontSize = 16.sp,
color = if (pagerState.currentPage == 0) AppColors.text else AppColors.nonActiveText,
fontWeight = FontWeight.W600)
Spacer(modifier = Modifier.height(4.dp))
Box(
modifier = Modifier
.width(48.dp)
.width(34.dp)
.height(4.dp)
.clip(RoundedCornerShape(16.dp))
.background(if (pagerState.currentPage == 0) AppColors.text else AppColors.background)
.background(if (pagerState.currentPage == 0) AppColors.brandColorsColor else AppColors.background)
)
}
Spacer(modifier = Modifier.width(32.dp))
Spacer(modifier = Modifier.width(16.dp))
Column(
modifier = Modifier
.noRippleClickable {
@@ -100,18 +115,67 @@ fun MomentsList() {
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = stringResource(R.string.index_following), fontSize = 16.sp, color = AppColors.text, fontWeight = FontWeight.W600)
Text(
text = stringResource(R.string.index_following),
fontSize = 16.sp,
color = if (pagerState.currentPage == 1) AppColors.text else AppColors.nonActiveText,
fontWeight = FontWeight.W600)
Spacer(modifier = Modifier.height(4.dp))
Box(
modifier = Modifier
.width(48.dp)
.width(34.dp)
.height(4.dp)
.clip(RoundedCornerShape(16.dp))
.background(if (pagerState.currentPage == 1) AppColors.text else AppColors.background)
.background(if (pagerState.currentPage == 1) AppColors.brandColorsColor else AppColors.background)
)
}
//热门tab
Spacer(modifier = Modifier.width(16.dp))
Column(
modifier = Modifier
.noRippleClickable {
scope.launch {
pagerState.animateScrollToPage(2)
}
},
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = stringResource(R.string.index_hot),
fontSize = 16.sp,
color = if (pagerState.currentPage == 2) AppColors.text else AppColors.nonActiveText,
fontWeight = FontWeight.W600)
Spacer(modifier = Modifier.height(4.dp))
Box(
modifier = Modifier
.width(34.dp)
.height(4.dp)
.clip(RoundedCornerShape(16.dp))
.background(if (pagerState.currentPage == 2) AppColors.brandColorsColor else AppColors.background)
)
}
//搜索按钮
Column(
modifier = Modifier
.padding(bottom = 8.dp, end = 16.dp)
.fillMaxWidth(),
horizontalAlignment = Alignment.End
) {
Icon(
ImageVector.vectorResource(R.drawable.rider_pro_nav_search),
contentDescription = "Clickable Icon",
tint = AppColors.text,
modifier = Modifier.size(24.dp)
.noRippleClickable {
navController.navigate(NavigationRoute.Search.route)
}
)
}
}
HorizontalPager(
@@ -128,6 +192,11 @@ fun MomentsList() {
1 -> {
TimelineMomentsList()
}
2 -> {
HotMomentsList()
}
}
}
}

View File

@@ -0,0 +1,52 @@
package com.aiosman.ravenow.ui.index.tabs.moment.tabs.hot
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.cachedIn
import com.aiosman.ravenow.AppState
import com.aiosman.ravenow.data.MomentService
import com.aiosman.ravenow.entity.MomentEntity
import com.aiosman.ravenow.entity.MomentLoaderExtraArgs
import com.aiosman.ravenow.entity.MomentPagingSource
import com.aiosman.ravenow.entity.MomentRemoteDataSource
import com.aiosman.ravenow.entity.MomentServiceImpl
import com.aiosman.ravenow.ui.index.tabs.moment.BaseMomentModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
object HotMomentViewModel : ViewModel() {
private val momentService: MomentService = MomentServiceImpl()
private val _discoverMomentsFlow =
MutableStateFlow<PagingData<MomentEntity>>(PagingData.empty())
val discoverMomentsFlow = _discoverMomentsFlow.asStateFlow()
var firstLoad = true
fun refreshPager() {
if (!firstLoad) {
return
}
firstLoad = false
viewModelScope.launch {
Pager(
config = PagingConfig(pageSize = 5, enablePlaceholders = false),
pagingSourceFactory = {
MomentPagingSource(
MomentRemoteDataSource(momentService),
trend = true
)
}
).flow.cachedIn(viewModelScope).collectLatest {
_discoverMomentsFlow.value = it
}
}
}
fun ResetModel(){
firstLoad = true
}
}

View File

@@ -0,0 +1,145 @@
package com.aiosman.ravenow.ui.index.tabs.moment.tabs.hot
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.rememberLazyListState
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.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
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
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.paging.compose.collectAsLazyPagingItems
import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.StatusBarSpacer
import com.aiosman.ravenow.ui.index.tabs.search.SearchViewModel
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import com.aiosman.ravenow.ui.navigateToPost
/**
* 动态列表
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun HotMomentsList() {
val model = HotMomentViewModel
val AppColors = LocalAppTheme.current
val navController = LocalNavController.current
val navigationBarPaddings =
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + 48.dp
LaunchedEffect(Unit) {
HotMomentViewModel.refreshPager()
}
var refreshing by remember { mutableStateOf(false) }
val state = rememberPullRefreshState(refreshing, onRefresh = {
model.refreshPager()
})
Column(
modifier = Modifier
.fillMaxSize()
.pullRefresh(state)
) {
Column(
modifier = Modifier.fillMaxWidth().background(
AppColors.background).padding(bottom = 0.dp)
) {
}
Box(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
) {
DiscoverView()
PullRefreshIndicator(refreshing, state, Modifier.align(Alignment.TopCenter))
}
}
}
@Composable
fun DiscoverView() {
val model = HotMomentViewModel
var dataFlow = model.discoverMomentsFlow
var moments = dataFlow.collectAsLazyPagingItems()
val context = LocalContext.current
val navController = LocalNavController.current
LazyVerticalGrid(
columns = GridCells.Fixed(3),
modifier = Modifier.fillMaxSize().padding(bottom = 8.dp),
// contentPadding = PaddingValues(8.dp)
) {
items(moments.itemCount) { idx ->
val momentItem = moments[idx] ?: return@items
Box(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(1f)
.padding(2.dp)
.clip(RoundedCornerShape(8.dp))
.noRippleClickable {
navController.navigateToPost(
id = momentItem.id,
highlightCommentId = 0,
initImagePagerIndex = 0
)
}
) {
CustomAsyncImage(
imageUrl = momentItem.images[0].thumbnail,
contentDescription = "",
modifier = Modifier
.fillMaxSize(),
context = context
)
if (momentItem.images.size > 1) {
Box(
modifier = Modifier
.padding(top = 8.dp, end = 8.dp)
.align(Alignment.TopEnd)
) {
Image(
modifier = Modifier.size(24.dp),
painter = painterResource(R.drawable.rider_pro_picture_more),
contentDescription = "",
)
}
}
}
}
}
}