动态、热门界面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( Image(
painter = if (isFavourite) { painter = if (isFavourite) {
painterResource(id = R.drawable.rider_pro_favourited) painterResource(id = R.mipmap.icon_variant_2)
} else { } else {
painterResource(id = R.drawable.rider_pro_favourite) painterResource(id = R.mipmap.icon_collect)
}, },
contentDescription = "Favourite", contentDescription = "Favourite",
modifier = modifier.graphicsLayer { modifier = modifier.graphicsLayer {
rotationZ = animatableRotation.value rotationZ = animatableRotation.value
}, },
colorFilter = ColorFilter.tint(AppColors.text)
) )
} }
} }

View File

@@ -364,16 +364,6 @@ fun MomentContentGroup(
onPageChange: (Int) -> Unit = {} onPageChange: (Int) -> Unit = {}
) { ) {
val AppColors = LocalAppTheme.current 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) { if (momentEntity.relMoment != null) {
RelPostCard( RelPostCard(
momentEntity = momentEntity.relMoment!!, 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,8 +402,8 @@ fun MomentOperateBtn(@DrawableRes icon: Int, count: String) {
.size(width = 24.dp, height = 24.dp), .size(width = 24.dp, height = 24.dp),
painter = painterResource(id = icon), painter = painterResource(id = icon),
contentDescription = "", contentDescription = "",
colorFilter = ColorFilter.tint(AppColors.text)
) )
if (count.isNotEmpty()) {
Text( Text(
text = count, text = count,
modifier = Modifier.padding(start = 7.dp), modifier = Modifier.padding(start = 7.dp),
@@ -410,6 +411,7 @@ fun MomentOperateBtn(@DrawableRes icon: Int, count: String) {
color = AppColors.text color = AppColors.text
) )
} }
}
} }
@Composable @Composable
@@ -510,49 +512,11 @@ fun MomentBottomOperateRowGroup(
.weight(1f), .weight(1f),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Box( Row(
modifier = Modifier modifier = Modifier.weight(1f).fillMaxHeight(),
.weight(1f) verticalAlignment = Alignment.CenterVertically
.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
) { ) {
// 点赞按钮
MomentOperateBtn(count = momentEntity.likeCount.toString()) { MomentOperateBtn(count = momentEntity.likeCount.toString()) {
AnimatedLikeIcon( AnimatedLikeIcon(
modifier = Modifier.size(24.dp), modifier = Modifier.size(24.dp),
@@ -561,6 +525,44 @@ fun MomentBottomOperateRowGroup(
onLikeClick() 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.background
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.aspectRatio 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.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.staggeredgrid.items
import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.pullrefresh.PullRefreshIndicator 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.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import com.aiosman.ravenow.LocalAppTheme import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController import com.aiosman.ravenow.LocalNavController
@@ -104,8 +107,8 @@ fun DiscoverView() {
val isLoading by model.isLoading.collectAsState() val isLoading by model.isLoading.collectAsState()
val context = LocalContext.current val context = LocalContext.current
val navController = LocalNavController.current val navController = LocalNavController.current
val gridState = rememberLazyGridState() val gridState = rememberLazyStaggeredGridState()
val AppColors = LocalAppTheme.current
// 监听滚动到底部,自动加载更多 // 监听滚动到底部,自动加载更多
LaunchedEffect(gridState, moments.size) { LaunchedEffect(gridState, moments.size) {
snapshotFlow { snapshotFlow {
@@ -124,18 +127,40 @@ fun DiscoverView() {
} }
} }
LazyVerticalGrid( LazyVerticalStaggeredGrid(
columns = GridCells.Fixed(3), columns = StaggeredGridCells.Fixed(2),
state = gridState, state = gridState,
modifier = Modifier.fillMaxSize().padding(bottom = 8.dp), 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 -> items(moments) { momentItem ->
val debouncer = rememberDebouncer() 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( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.aspectRatio(1f) .height(totalHeight)
.padding(2.dp) .padding(2.dp)
.noRippleClickable { .noRippleClickable {
debouncer { debouncer {
@@ -146,15 +171,69 @@ fun DiscoverView() {
) )
} }
} }
) {
Column(
modifier = Modifier.fillMaxSize().background(AppColors.secondaryBackground, RoundedCornerShape(12.dp))
) { ) {
CustomAsyncImage( CustomAsyncImage(
imageUrl = momentItem.images[0].thumbnail, imageUrl = momentItem.images[0].thumbnail,
contentDescription = "", contentDescription = "",
modifier = Modifier modifier = Modifier
.fillMaxSize(), .fillMaxWidth()
.height(baseHeight)
.clip(RoundedCornerShape(
topStart = 12.dp,
topEnd = 12.dp,
bottomStart = 0.dp,
bottomEnd = 0.dp)),
context = context, context = context,
showShimmer = true 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) { if (momentItem.images.size > 1) {
Box( Box(
modifier = Modifier modifier = Modifier

View File

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

View File

@@ -62,7 +62,7 @@ fun UserAuthScreen() {
val AppColors = LocalAppTheme.current val AppColors = LocalAppTheme.current
var email by remember { mutableStateOf("") } var email by remember { mutableStateOf("") }
var password 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 accountService: AccountService = AccountServiceImpl()
val captchaService: CaptchaService = CaptchaServiceImpl() val captchaService: CaptchaService = CaptchaServiceImpl()
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1007 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 975 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B