动态、热门界面UI调整

This commit is contained in:
2025-10-22 18:52:46 +08:00
parent eb8119b775
commit 2a5174cbb6
26 changed files with 250 additions and 169 deletions

View File

@@ -56,15 +56,14 @@ fun AnimatedFavouriteIcon(
}) {
Image(
painter = if (isFavourite) {
painterResource(id = R.drawable.rider_pro_favourited)
painterResource(id = R.mipmap.icon_variant_2)
} else {
painterResource(id = R.drawable.rider_pro_favourite)
painterResource(id = R.mipmap.icon_collect)
},
contentDescription = "Favourite",
modifier = modifier.graphicsLayer {
rotationZ = animatableRotation.value
},
colorFilter = ColorFilter.tint(AppColors.text)
)
}
}

View File

@@ -364,16 +364,6 @@ fun MomentContentGroup(
onPageChange: (Int) -> Unit = {}
) {
val AppColors = LocalAppTheme.current
if (momentEntity.momentTextContent.isNotEmpty()) {
Text(
text = momentEntity.momentTextContent,
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, bottom = 8.dp),
fontSize = 16.sp,
color = AppColors.text
)
}
if (momentEntity.relMoment != null) {
RelPostCard(
momentEntity = momentEntity.relMoment!!,
@@ -389,6 +379,17 @@ fun MomentContentGroup(
)
}
}
if (momentEntity.momentTextContent.isNotEmpty()) {
Text(
text = momentEntity.momentTextContent,
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, top = 8.dp),
fontSize = 16.sp,
color = AppColors.text
)
}
}
@@ -401,14 +402,15 @@ fun MomentOperateBtn(@DrawableRes icon: Int, count: String) {
.size(width = 24.dp, height = 24.dp),
painter = painterResource(id = icon),
contentDescription = "",
colorFilter = ColorFilter.tint(AppColors.text)
)
Text(
text = count,
modifier = Modifier.padding(start = 7.dp),
fontSize = 14.sp,
color = AppColors.text
)
if (count.isNotEmpty()) {
Text(
text = count,
modifier = Modifier.padding(start = 7.dp),
fontSize = 14.sp,
color = AppColors.text
)
}
}
}
@@ -510,49 +512,11 @@ fun MomentBottomOperateRowGroup(
.weight(1f),
verticalAlignment = Alignment.CenterVertically
) {
Box(
modifier = Modifier
.weight(1f)
.fillMaxHeight(),
contentAlignment = Alignment.CenterStart
) {
MomentOperateBtn(count = momentEntity.favoriteCount.toString()) {
AnimatedFavouriteIcon(
modifier = Modifier.size(24.dp),
isFavourite = momentEntity.isFavorite
) {
onFavoriteClick()
}
}
}
Box(
modifier = Modifier
.wrapContentWidth()
.fillMaxHeight()
.noRippleClickable {
val currentTime = System.currentTimeMillis()
if (currentTime - lastClickTime.value > clickDelay) {
lastClickTime.value = currentTime
onCommentClick()
}
},
contentAlignment = Alignment.CenterEnd
) {
MomentOperateBtn(
icon = R.drawable.rider_pro_comment,
count = momentEntity.commentCount.toString()
)
}
Spacer(modifier = Modifier.width(24.dp))
Box(
modifier = Modifier
.wrapContentWidth()
.fillMaxHeight(),
contentAlignment = Alignment.CenterEnd
Row(
modifier = Modifier.weight(1f).fillMaxHeight(),
verticalAlignment = Alignment.CenterVertically
) {
// 点赞按钮
MomentOperateBtn(count = momentEntity.likeCount.toString()) {
AnimatedLikeIcon(
modifier = Modifier.size(24.dp),
@@ -561,6 +525,44 @@ fun MomentBottomOperateRowGroup(
onLikeClick()
}
}
Spacer(modifier = Modifier.width(10.dp))
// 评论按钮
Box(
modifier = Modifier.noRippleClickable {
val currentTime = System.currentTimeMillis()
if (currentTime - lastClickTime.value > clickDelay) {
lastClickTime.value = currentTime
onCommentClick()
}
}
) {
MomentOperateBtn(
icon = R.mipmap.icon_comment,
count = momentEntity.commentCount.toString()
)
}
Spacer(modifier = Modifier.width(28.dp))
// 转发按钮
Box(
modifier = Modifier.noRippleClickable {
// TODO: 实现转发功能
}
) {
MomentOperateBtn(
icon = R.mipmap.icon_share,
count = ""
)
}
}
// 收藏按钮
MomentOperateBtn(count = momentEntity.favoriteCount.toString()) {
AnimatedFavouriteIcon(
modifier = Modifier.size(24.dp),
isFavourite = momentEntity.isFavorite
) {
onFavoriteClick()
}
}
}
}

View File

@@ -168,6 +168,7 @@ fun Dynamic() {
)
}
}
PullRefreshIndicator(model.refreshing, state, Modifier.align(Alignment.TopCenter))
}
}
}

View File

@@ -4,6 +4,7 @@ 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.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.aspectRatio
@@ -13,11 +14,12 @@ 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.grid.items
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
import androidx.compose.foundation.lazy.staggeredgrid.items
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.pullrefresh.PullRefreshIndicator
@@ -39,6 +41,7 @@ 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.compose.ui.unit.sp
import androidx.compose.runtime.collectAsState
import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController
@@ -104,8 +107,8 @@ fun DiscoverView() {
val isLoading by model.isLoading.collectAsState()
val context = LocalContext.current
val navController = LocalNavController.current
val gridState = rememberLazyGridState()
val gridState = rememberLazyStaggeredGridState()
val AppColors = LocalAppTheme.current
// 监听滚动到底部,自动加载更多
LaunchedEffect(gridState, moments.size) {
snapshotFlow {
@@ -124,18 +127,40 @@ fun DiscoverView() {
}
}
LazyVerticalGrid(
columns = GridCells.Fixed(3),
LazyVerticalStaggeredGrid(
columns = StaggeredGridCells.Fixed(2),
state = gridState,
modifier = Modifier.fillMaxSize().padding(bottom = 8.dp),
// contentPadding = PaddingValues(8.dp)
contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 8.dp, vertical = 4.dp)
) {
items(moments) { momentItem ->
val debouncer = rememberDebouncer()
val textContent = momentItem.momentTextContent
val textLines = if (textContent.isNotEmpty()) {
val estimatedCharsPerLine = 20
val estimatedLines = (textContent.length / estimatedCharsPerLine) + 1
minOf(estimatedLines, 2) // 最多2行
} else {
0
}
val baseHeight = 200.dp
val singleLineTextHeight = 20.dp
val doubleLineTextHeight = 40.dp
val authorInfoHeight = 25.dp
val paddingHeight = 10.dp
val paddingHeight2 =3.dp
val totalHeight = baseHeight + when (textLines) {
0 -> authorInfoHeight + paddingHeight
1 -> singleLineTextHeight + authorInfoHeight + paddingHeight
else -> doubleLineTextHeight + authorInfoHeight +paddingHeight2
}
Box(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(1f)
.height(totalHeight)
.padding(2.dp)
.noRippleClickable {
debouncer {
@@ -147,14 +172,68 @@ fun DiscoverView() {
}
}
) {
CustomAsyncImage(
imageUrl = momentItem.images[0].thumbnail,
contentDescription = "",
modifier = Modifier
.fillMaxSize(),
context = context,
showShimmer = true
)
Column(
modifier = Modifier.fillMaxSize().background(AppColors.secondaryBackground, RoundedCornerShape(12.dp))
) {
CustomAsyncImage(
imageUrl = momentItem.images[0].thumbnail,
contentDescription = "",
modifier = Modifier
.fillMaxWidth()
.height(baseHeight)
.clip(RoundedCornerShape(
topStart = 12.dp,
topEnd = 12.dp,
bottomStart = 0.dp,
bottomEnd = 0.dp)),
context = context,
showShimmer = true
)
Column(
modifier = Modifier
.fillMaxWidth()
.height(totalHeight - baseHeight)
.padding(horizontal = 8.dp, vertical = 8.dp)
) {
if (momentItem.momentTextContent.isNotEmpty()) {
androidx.compose.material3.Text(
text = momentItem.momentTextContent,
modifier = Modifier.fillMaxWidth(),
fontSize = 12.sp,
color = AppColors.text,
maxLines = 2,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(top = 5.dp),
verticalAlignment = Alignment.CenterVertically
) {
CustomAsyncImage(
imageUrl = momentItem.avatar,
contentDescription = "",
modifier = Modifier
.size(16.dp)
.clip(RoundedCornerShape(8.dp)),
context = context,
showShimmer = true
)
androidx.compose.material3.Text(
text = momentItem.nickname,
modifier = Modifier.padding(start = 4.dp),
fontSize = 11.sp,
color = AppColors.text.copy(alpha = 0.6f),
maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
)
}
}
}
if (momentItem.images.size > 1) {
Box(
modifier = Modifier

View File

@@ -65,94 +65,94 @@ fun UserAgentsRow(
viewModel.loadUserAgents(userId)
}
// 总是显示智能体区域,即使没有数据也显示标题和状态
Column(
modifier = modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
) {
Text(
text = if (isSelf) "我的智能体" else "TA的智能体",
fontSize = 16.sp,
fontWeight = FontWeight.W600,
color = AppColors.text,
modifier = Modifier.padding(bottom = 12.dp)
)
when {
viewModel.isLoading -> {
// 显示加载状态
Box(
modifier = Modifier
.fillMaxWidth()
.height(60.dp),
contentAlignment = Alignment.Center
) {
Text(
text = "加载中...",
fontSize = 14.sp,
color = AppColors.text.copy(alpha = 0.6f)
)
}
}
viewModel.error != null -> {
// 显示错误状态
Box(
modifier = Modifier
.fillMaxWidth()
.height(60.dp),
contentAlignment = Alignment.Center
) {
Text(
text = "加载失败: ${viewModel.error}",
fontSize = 14.sp,
color = AppColors.text.copy(alpha = 0.6f)
)
}
}
viewModel.agents.isEmpty() -> {
// 显示空状态
Box(
modifier = Modifier
.fillMaxWidth()
.height(60.dp),
contentAlignment = Alignment.Center
) {
Text(
text = if (isSelf) "您还没有创建智能体" else "TA还没有创建智能体",
fontSize = 14.sp,
color = AppColors.text.copy(alpha = 0.6f)
)
}
}
else -> {
// 显示智能体列表
LazyRow(
horizontalArrangement = Arrangement.spacedBy(12.dp),
modifier = Modifier.fillMaxWidth()
) {
// 显示智能体项目
items(viewModel.agents) { agent ->
AgentItem(
agent = agent,
onClick = { onAgentClick(agent) },
onAvatarClick = { onAvatarClick(agent) },
onLongClick = { onAgentLongClick(agent) }
)
}
// 添加"更多"按钮
item {
MoreAgentItem(
onClick = onMoreClick
)
}
}
}
}
Spacer(modifier = Modifier.height(16.dp))
}
// // 总是显示智能体区域,即使没有数据也显示标题和状态
// Column(
// modifier = modifier
// .fillMaxWidth()
// .padding(horizontal = 16.dp)
// ) {
// Text(
// text = if (isSelf) "我的智能体" else "TA的智能体",
// fontSize = 16.sp,
// fontWeight = FontWeight.W600,
// color = AppColors.text,
// modifier = Modifier.padding(bottom = 12.dp)
// )
//
// when {
// viewModel.isLoading -> {
// // 显示加载状态
// Box(
// modifier = Modifier
// .fillMaxWidth()
// .height(60.dp),
// contentAlignment = Alignment.Center
// ) {
// Text(
// text = "加载中...",
// fontSize = 14.sp,
// color = AppColors.text.copy(alpha = 0.6f)
// )
// }
// }
// viewModel.error != null -> {
// // 显示错误状态
// Box(
// modifier = Modifier
// .fillMaxWidth()
// .height(60.dp),
// contentAlignment = Alignment.Center
// ) {
// Text(
// text = "加载失败: ${viewModel.error}",
// fontSize = 14.sp,
// color = AppColors.text.copy(alpha = 0.6f)
// )
// }
// }
// viewModel.agents.isEmpty() -> {
// // 显示空状态
// Box(
// modifier = Modifier
// .fillMaxWidth()
// .height(60.dp),
// contentAlignment = Alignment.Center
// ) {
// Text(
// text = if (isSelf) "您还没有创建智能体" else "TA还没有创建智能体",
// fontSize = 14.sp,
// color = AppColors.text.copy(alpha = 0.6f)
// )
// }
// }
// else -> {
// // 显示智能体列表
// LazyRow(
// horizontalArrangement = Arrangement.spacedBy(12.dp),
// modifier = Modifier.fillMaxWidth()
// ) {
// // 显示智能体项目
// items(viewModel.agents) { agent ->
// AgentItem(
// agent = agent,
// onClick = { onAgentClick(agent) },
// onAvatarClick = { onAvatarClick(agent) },
// onLongClick = { onAgentLongClick(agent) }
// )
// }
//
// // 添加"更多"按钮
// item {
// MoreAgentItem(
// onClick = onMoreClick
// )
// }
// }
// }
// }
//
// Spacer(modifier = Modifier.height(16.dp))
// }
}
@OptIn(ExperimentalFoundationApi::class)

View File

@@ -62,7 +62,7 @@ fun UserAuthScreen() {
val AppColors = LocalAppTheme.current
var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var rememberMe by remember { mutableStateOf(false) }
var rememberMe by remember { mutableStateOf(true) }
val accountService: AccountService = AccountServiceImpl()
val captchaService: CaptchaService = CaptchaServiceImpl()
val scope = rememberCoroutineScope()