20250723-Test Push
This commit is contained in:
@@ -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()
|
||||
// 重置发现页面
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
)
|
||||
}
|
||||
@@ -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
|
||||
) {
|
||||
// 左侧 Column:label 居中显示
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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 = "",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user