Refactor: 个人主页UI及智能体列表功能调整
- **个人主页UI调整:**
- "编辑个人资料"按钮样式调整为与"私信"按钮一致。
- "关注"按钮样式调整为渐变色,"已关注"状态下显示灰色边框。
- "私信"按钮样式调整为灰色背景。
- "帖子"、"粉丝"、"关注"文案调整。
- 个人主页背景色适配深色模式。
- 个人主页内容切换Tab图标化,并添加下划线指示器。
- **智能体列表功能:**
- 新增`UserAgentsList.kt`用于展示用户的智能体列表。
- 在个人主页中集成智能体列表展示(新的Tab页)。
- 调整`UserAgentsRow`组件,使其能够加载并展示当前用户或其他用户的智能体,并添加"更多"按钮。
- `MyProfileViewModel`中增加对智能体数据的加载和管理。
- `UserAgentsViewModel`调整为可以加载指定用户或当前用户的智能体数据。
- **其他:**
- `Colors.kt`中新增`profileBackground`颜色定义。
- `Agent.kt`中调整了`getAgent`方法返回类型。
This commit is contained in:
@@ -34,6 +34,7 @@ open class AppThemeData(
|
|||||||
var tabSelectedText: Color,
|
var tabSelectedText: Color,
|
||||||
var tabUnselectedText: Color,
|
var tabUnselectedText: Color,
|
||||||
var bubbleBackground: Color,
|
var bubbleBackground: Color,
|
||||||
|
var profileBackground:Color,
|
||||||
)
|
)
|
||||||
|
|
||||||
class LightThemeColors : AppThemeData(
|
class LightThemeColors : AppThemeData(
|
||||||
@@ -64,7 +65,8 @@ class LightThemeColors : AppThemeData(
|
|||||||
tabUnselectedBackground = Color(0x147C7480),
|
tabUnselectedBackground = Color(0x147C7480),
|
||||||
tabSelectedText = Color(0xffffffff),
|
tabSelectedText = Color(0xffffffff),
|
||||||
tabUnselectedText = Color(0xff000000),
|
tabUnselectedText = Color(0xff000000),
|
||||||
bubbleBackground = Color(0xfff5f5f5)
|
bubbleBackground = Color(0xfff5f5f5),
|
||||||
|
profileBackground = Color(0xffffffff)
|
||||||
)
|
)
|
||||||
|
|
||||||
class DarkThemeColors : AppThemeData(
|
class DarkThemeColors : AppThemeData(
|
||||||
@@ -95,5 +97,7 @@ class DarkThemeColors : AppThemeData(
|
|||||||
tabUnselectedBackground = Color(0xff7C7480),
|
tabUnselectedBackground = Color(0xff7C7480),
|
||||||
tabSelectedText = Color(0xff000000),
|
tabSelectedText = Color(0xff000000),
|
||||||
tabUnselectedText = Color(0xffffffff),
|
tabUnselectedText = Color(0xffffffff),
|
||||||
bubbleBackground = Color(0xfff2d2c2e)
|
bubbleBackground = Color(0xfff2d2c2e),
|
||||||
|
profileBackground = Color(0xff100c12)
|
||||||
|
|
||||||
)
|
)
|
||||||
@@ -2,8 +2,10 @@ package com.aiosman.ravenow.entity
|
|||||||
|
|
||||||
import androidx.paging.PagingSource
|
import androidx.paging.PagingSource
|
||||||
import androidx.paging.PagingState
|
import androidx.paging.PagingState
|
||||||
|
import com.aiosman.ravenow.data.Agent
|
||||||
import com.aiosman.ravenow.data.ListContainer
|
import com.aiosman.ravenow.data.ListContainer
|
||||||
import com.aiosman.ravenow.data.AgentService
|
import com.aiosman.ravenow.data.AgentService
|
||||||
|
import com.aiosman.ravenow.data.DataContainer
|
||||||
import com.aiosman.ravenow.data.MomentService
|
import com.aiosman.ravenow.data.MomentService
|
||||||
import com.aiosman.ravenow.data.ServiceException
|
import com.aiosman.ravenow.data.ServiceException
|
||||||
import com.aiosman.ravenow.data.UploadImage
|
import com.aiosman.ravenow.data.UploadImage
|
||||||
@@ -196,7 +198,7 @@ class AgentLoader : DataLoader<AgentEntity,AgentLoaderExtraArgs>() {
|
|||||||
|
|
||||||
return if (extra.authorId != null) {
|
return if (extra.authorId != null) {
|
||||||
// getAgent 返回 DataContainer<ListContainer<Agent>>
|
// getAgent 返回 DataContainer<ListContainer<Agent>>
|
||||||
val dataContainer = body as com.aiosman.ravenow.data.DataContainer<com.aiosman.ravenow.data.ListContainer<com.aiosman.ravenow.data.Agent>>
|
val dataContainer = body as DataContainer<ListContainer<Agent>>
|
||||||
val listContainer = dataContainer.data
|
val listContainer = dataContainer.data
|
||||||
ListContainer(
|
ListContainer(
|
||||||
list = listContainer.list.map { it.toAgentEntity()},
|
list = listContainer.list.map { it.toAgentEntity()},
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ import com.aiosman.ravenow.data.AccountServiceImpl
|
|||||||
import com.aiosman.ravenow.data.MomentService
|
import com.aiosman.ravenow.data.MomentService
|
||||||
import com.aiosman.ravenow.data.UploadImage
|
import com.aiosman.ravenow.data.UploadImage
|
||||||
import com.aiosman.ravenow.entity.AccountProfileEntity
|
import com.aiosman.ravenow.entity.AccountProfileEntity
|
||||||
|
import com.aiosman.ravenow.entity.AgentEntity
|
||||||
|
import com.aiosman.ravenow.entity.AgentLoader
|
||||||
|
import com.aiosman.ravenow.entity.AgentLoaderExtraArgs
|
||||||
import com.aiosman.ravenow.entity.MomentEntity
|
import com.aiosman.ravenow.entity.MomentEntity
|
||||||
import com.aiosman.ravenow.entity.MomentLoader
|
import com.aiosman.ravenow.entity.MomentLoader
|
||||||
import com.aiosman.ravenow.entity.MomentLoaderExtraArgs
|
import com.aiosman.ravenow.entity.MomentLoaderExtraArgs
|
||||||
@@ -35,11 +38,17 @@ object MyProfileViewModel : ViewModel() {
|
|||||||
val momentService: MomentService = MomentServiceImpl()
|
val momentService: MomentService = MomentServiceImpl()
|
||||||
var profile by mutableStateOf<AccountProfileEntity?>(null)
|
var profile by mutableStateOf<AccountProfileEntity?>(null)
|
||||||
var moments by mutableStateOf<List<MomentEntity>>(emptyList())
|
var moments by mutableStateOf<List<MomentEntity>>(emptyList())
|
||||||
|
var agents by mutableStateOf<List<AgentEntity>>(emptyList())
|
||||||
val momentLoader: MomentLoader = MomentLoader().apply {
|
val momentLoader: MomentLoader = MomentLoader().apply {
|
||||||
onListChanged = {
|
onListChanged = {
|
||||||
moments = it
|
moments = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val agentLoader: AgentLoader = AgentLoader().apply {
|
||||||
|
onListChanged = {
|
||||||
|
agents = it
|
||||||
|
}
|
||||||
|
}
|
||||||
var refreshing by mutableStateOf(false)
|
var refreshing by mutableStateOf(false)
|
||||||
var firstLoad = true
|
var firstLoad = true
|
||||||
|
|
||||||
@@ -64,6 +73,7 @@ object MyProfileViewModel : ViewModel() {
|
|||||||
profile?.let {
|
profile?.let {
|
||||||
try {
|
try {
|
||||||
momentLoader.loadData(extra = MomentLoaderExtraArgs(authorId = it.id))
|
momentLoader.loadData(extra = MomentLoaderExtraArgs(authorId = it.id))
|
||||||
|
agentLoader.loadData(extra = AgentLoaderExtraArgs(authorId = it.id))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("MyProfileViewModel", "loadProfile: ", e)
|
Log.e("MyProfileViewModel", "loadProfile: ", e)
|
||||||
}
|
}
|
||||||
@@ -152,6 +162,7 @@ object MyProfileViewModel : ViewModel() {
|
|||||||
fun ResetModel() {
|
fun ResetModel() {
|
||||||
profile = null
|
profile = null
|
||||||
momentLoader.clear()
|
momentLoader.clear()
|
||||||
|
agentLoader.clear()
|
||||||
firstLoad = true
|
firstLoad = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ import com.aiosman.ravenow.LocalNavController
|
|||||||
import com.aiosman.ravenow.MainActivity
|
import com.aiosman.ravenow.MainActivity
|
||||||
import com.aiosman.ravenow.R
|
import com.aiosman.ravenow.R
|
||||||
import com.aiosman.ravenow.entity.AccountProfileEntity
|
import com.aiosman.ravenow.entity.AccountProfileEntity
|
||||||
|
import com.aiosman.ravenow.entity.AgentEntity
|
||||||
import com.aiosman.ravenow.entity.MomentEntity
|
import com.aiosman.ravenow.entity.MomentEntity
|
||||||
import com.aiosman.ravenow.ui.NavigationRoute
|
import com.aiosman.ravenow.ui.NavigationRoute
|
||||||
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
||||||
@@ -88,6 +89,7 @@ import com.aiosman.ravenow.ui.index.tabs.profile.composable.MomentPostUnit
|
|||||||
import com.aiosman.ravenow.ui.index.tabs.profile.composable.OtherProfileAction
|
import com.aiosman.ravenow.ui.index.tabs.profile.composable.OtherProfileAction
|
||||||
import com.aiosman.ravenow.ui.index.tabs.profile.composable.SelfProfileAction
|
import com.aiosman.ravenow.ui.index.tabs.profile.composable.SelfProfileAction
|
||||||
import com.aiosman.ravenow.ui.index.tabs.profile.composable.UserAgentsRow
|
import com.aiosman.ravenow.ui.index.tabs.profile.composable.UserAgentsRow
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.profile.composable.UserAgentsList
|
||||||
import com.aiosman.ravenow.ui.index.tabs.profile.composable.UserContentPageIndicator
|
import com.aiosman.ravenow.ui.index.tabs.profile.composable.UserContentPageIndicator
|
||||||
import com.aiosman.ravenow.ui.index.tabs.profile.composable.UserItem
|
import com.aiosman.ravenow.ui.index.tabs.profile.composable.UserItem
|
||||||
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||||
@@ -107,11 +109,13 @@ fun ProfileV3(
|
|||||||
onFollowClick: () -> Unit = {},
|
onFollowClick: () -> Unit = {},
|
||||||
onChatClick: () -> Unit = {},
|
onChatClick: () -> Unit = {},
|
||||||
moments: List<MomentEntity>,
|
moments: List<MomentEntity>,
|
||||||
|
agents: List<AgentEntity> = emptyList(),
|
||||||
isSelf: Boolean = true,
|
isSelf: Boolean = true,
|
||||||
isMain:Boolean = false,
|
isMain:Boolean = false,
|
||||||
onLoadMore: () -> Unit = {},
|
onLoadMore: () -> Unit = {},
|
||||||
onLike: (MomentEntity) -> Unit = {},
|
onLike: (MomentEntity) -> Unit = {},
|
||||||
onComment: (MomentEntity) -> Unit = {},
|
onComment: (MomentEntity) -> Unit = {},
|
||||||
|
onAgentClick: (AgentEntity) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val model = MyProfileViewModel
|
val model = MyProfileViewModel
|
||||||
val state = rememberCollapsingToolbarScaffoldState()
|
val state = rememberCollapsingToolbarScaffoldState()
|
||||||
@@ -195,7 +199,7 @@ fun ProfileV3(
|
|||||||
CollapsingToolbarScaffold(
|
CollapsingToolbarScaffold(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(AppColors.decentBackground),
|
.background(AppColors.profileBackground),
|
||||||
state = state,
|
state = state,
|
||||||
scrollStrategy = ScrollStrategy.ExitUntilCollapsed,
|
scrollStrategy = ScrollStrategy.ExitUntilCollapsed,
|
||||||
toolbarScrollable = true,
|
toolbarScrollable = true,
|
||||||
@@ -206,7 +210,7 @@ fun ProfileV3(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(miniToolbarHeight.dp)
|
.height(miniToolbarHeight.dp)
|
||||||
// 保持在最低高度和当前高度之间
|
// 保持在最低高度和当前高度之间
|
||||||
.background(AppColors.decentBackground)
|
.background(AppColors.profileBackground)
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
// header
|
// header
|
||||||
@@ -214,7 +218,8 @@ fun ProfileV3(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.parallax(0.5f)
|
.parallax(0.5f)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(600.dp)
|
.height(700.dp)
|
||||||
|
.background(AppColors.profileBackground)
|
||||||
.verticalScroll(toolbarScrollState)
|
.verticalScroll(toolbarScrollState)
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
@@ -232,7 +237,7 @@ fun ProfileV3(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(bannerHeight.dp)
|
.height(bannerHeight.dp)
|
||||||
.background(AppColors.decentBackground)
|
.background(AppColors.profileBackground)
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -319,12 +324,13 @@ fun ProfileV3(
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(AppColors.decentBackground)
|
.background(AppColors.profileBackground)
|
||||||
) {
|
) {
|
||||||
// user info
|
// user info
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|
||||||
) {
|
) {
|
||||||
// Spacer(modifier = Modifier.height(16.dp))
|
// Spacer(modifier = Modifier.height(16.dp))
|
||||||
// 个人信息
|
// 个人信息
|
||||||
@@ -332,7 +338,10 @@ fun ProfileV3(
|
|||||||
modifier = Modifier.padding(horizontal = 16.dp)
|
modifier = Modifier.padding(horizontal = 16.dp)
|
||||||
) {
|
) {
|
||||||
profile?.let {
|
profile?.let {
|
||||||
UserItem(it)
|
UserItem(
|
||||||
|
accountProfileEntity = it,
|
||||||
|
postCount = moments.size
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(20.dp))
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
@@ -366,8 +375,16 @@ fun ProfileV3(
|
|||||||
|
|
||||||
// 添加用户智能体行
|
// 添加用户智能体行
|
||||||
UserAgentsRow(
|
UserAgentsRow(
|
||||||
userId = profile?.id,
|
userId = if (isSelf) null else profile?.id,
|
||||||
modifier = Modifier.padding(top = 16.dp)
|
modifier = Modifier.padding(top = 16.dp),
|
||||||
|
onMoreClick = {
|
||||||
|
// 导航到智能体列表页面
|
||||||
|
// TODO: 实现导航逻辑
|
||||||
|
},
|
||||||
|
onAgentClick = { agent ->
|
||||||
|
// 导航到智能体详情页面
|
||||||
|
// TODO: 实现导航逻辑
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,7 +401,7 @@ fun ProfileV3(
|
|||||||
.graphicsLayer {
|
.graphicsLayer {
|
||||||
alpha = 1 - state.toolbarState.progress
|
alpha = 1 - state.toolbarState.progress
|
||||||
}
|
}
|
||||||
.background(AppColors.decentBackground)
|
.background(AppColors.profileBackground)
|
||||||
.onGloballyPositioned {
|
.onGloballyPositioned {
|
||||||
miniToolbarHeight = with(density) {
|
miniToolbarHeight = with(density) {
|
||||||
it.size.height.toDp().value.toInt()
|
it.size.height.toDp().value.toInt()
|
||||||
@@ -462,7 +479,7 @@ fun ProfileV3(
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(AppColors.decentBackground)
|
.background(AppColors.profileBackground)
|
||||||
) {
|
) {
|
||||||
UserContentPageIndicator(
|
UserContentPageIndicator(
|
||||||
pagerState = pagerState,
|
pagerState = pagerState,
|
||||||
@@ -521,38 +538,14 @@ fun ProfileV3(
|
|||||||
}
|
}
|
||||||
|
|
||||||
1 ->
|
1 ->
|
||||||
LazyColumn(
|
UserAgentsList(
|
||||||
modifier = Modifier
|
agents = agents,
|
||||||
.fillMaxSize(),
|
onAgentClick = onAgentClick,
|
||||||
state = listState
|
modifier = Modifier.fillMaxSize()
|
||||||
) {
|
|
||||||
if (moments.isEmpty() && isSelf) {
|
|
||||||
item {
|
|
||||||
EmptyMomentPostUnit()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
item {
|
|
||||||
for (element in moments) {
|
|
||||||
element.let {
|
|
||||||
MomentPostUnit(
|
|
||||||
it,
|
|
||||||
onLikeClick = {
|
|
||||||
onLike(it)
|
|
||||||
},
|
|
||||||
onCommentClick = {
|
|
||||||
onComment(it)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item {
|
|
||||||
Spacer(modifier = Modifier.height(120.dp))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
PullRefreshIndicator(
|
PullRefreshIndicator(
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ fun ProfileWrap(
|
|||||||
},
|
},
|
||||||
profile = MyProfileViewModel.profile,
|
profile = MyProfileViewModel.profile,
|
||||||
moments = MyProfileViewModel.moments,
|
moments = MyProfileViewModel.moments,
|
||||||
|
agents = MyProfileViewModel.agents,
|
||||||
onLoadMore = {
|
onLoadMore = {
|
||||||
MyProfileViewModel.loadMoreMoment()
|
MyProfileViewModel.loadMoreMoment()
|
||||||
},
|
},
|
||||||
@@ -33,6 +34,9 @@ fun ProfileWrap(
|
|||||||
},
|
},
|
||||||
onComment = {
|
onComment = {
|
||||||
navController.navigateToPost(it.id)
|
navController.navigateToPost(it.id)
|
||||||
|
},
|
||||||
|
onAgentClick = { agent ->
|
||||||
|
// TODO: 处理Agent点击事件,导航到聊天页面
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,11 @@ package com.aiosman.ravenow.ui.index.tabs.profile.composable
|
|||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
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.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
@@ -18,6 +20,8 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@@ -37,78 +41,88 @@ fun OtherProfileAction(
|
|||||||
onChat: (() -> Unit)? = null
|
onChat: (() -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
|
// 定义渐变色
|
||||||
|
val followGradient = Brush.horizontalGradient(
|
||||||
|
colors = listOf(
|
||||||
|
Color(0xFFE53E3E), // 红色
|
||||||
|
Color(0xFF9F7AEA) // 紫色
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.Center,
|
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
|
// 关注按钮 - 渐变样式
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.Center,
|
horizontalArrangement = Arrangement.Center,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(RoundedCornerShape(32.dp))
|
.weight(1f)
|
||||||
.background(if (profile.isFollowing) AppColors.main else AppColors.basicMain)
|
.clip(RoundedCornerShape(8.dp))
|
||||||
.padding(horizontal = 16.dp, vertical = 4.dp)
|
.let { modifier ->
|
||||||
|
if (profile.isFollowing) {
|
||||||
|
// 已关注状态 - 透明背景
|
||||||
|
modifier.background(Color.Transparent)
|
||||||
|
} else {
|
||||||
|
// 未关注状态 - 渐变背景
|
||||||
|
modifier.background(brush = followGradient)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.let { modifier ->
|
||||||
|
if (profile.isFollowing) {
|
||||||
|
modifier.border(
|
||||||
|
width = 1.dp,
|
||||||
|
color = AppColors.text.copy(alpha = 0.3f),
|
||||||
|
shape = RoundedCornerShape(8.dp)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
modifier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
onFollow?.invoke()
|
onFollow?.invoke()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
if (profile.isFollowing) {
|
|
||||||
Icon(
|
|
||||||
Icons.Default.Clear,
|
|
||||||
contentDescription = "",
|
|
||||||
modifier = Modifier.size(24.dp),
|
|
||||||
tint = AppColors.mainText
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Icon(
|
|
||||||
Icons.Default.Add,
|
|
||||||
contentDescription = "",
|
|
||||||
modifier = Modifier.size(24.dp),
|
|
||||||
tint = AppColors.mainText
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(if (profile.isFollowing) R.string.unfollow_upper else R.string.follow_upper),
|
text = if (profile.isFollowing) "已关注" else stringResource(R.string.follow_upper),
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.W600,
|
fontWeight = FontWeight.W600,
|
||||||
color = if (profile.isFollowing) AppColors.mainText else AppColors.text,
|
color = if (profile.isFollowing) {
|
||||||
modifier = Modifier.padding(8.dp),
|
// 已关注状态 - 灰色文字
|
||||||
|
AppColors.text.copy(alpha = 0.6f)
|
||||||
|
} else {
|
||||||
|
// 未关注状态 - 白色文字
|
||||||
|
Color.White
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 私信按钮 - 灰色背景样式
|
||||||
if (AppState.enableChat) {
|
if (AppState.enableChat) {
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.Center,
|
horizontalArrangement = Arrangement.Center,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(RoundedCornerShape(32.dp))
|
.weight(1f)
|
||||||
.background(AppColors.basicMain)
|
.clip(RoundedCornerShape(8.dp))
|
||||||
.padding(horizontal = 16.dp, vertical = 4.dp)
|
.background(AppColors.nonActive) // 使用主题灰色背景
|
||||||
|
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
onChat?.invoke()
|
onChat?.invoke()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Image(
|
|
||||||
painter = painterResource(id = R.drawable.rider_pro_comment),
|
|
||||||
contentDescription = "",
|
|
||||||
modifier = Modifier.size(24.dp),
|
|
||||||
colorFilter = ColorFilter.tint(AppColors.text)
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.chat_upper),
|
text = stringResource(R.string.chat_upper),
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.W600,
|
fontWeight = FontWeight.W600,
|
||||||
color = AppColors.text,
|
color = AppColors.text, // 使用主题文字颜色
|
||||||
modifier = Modifier.padding(8.dp),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// 按钮
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -3,14 +3,9 @@ package com.aiosman.ravenow.ui.index.tabs.profile.composable
|
|||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.Edit
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@@ -29,34 +24,25 @@ fun SelfProfileAction(
|
|||||||
onEditProfile: () -> Unit
|
onEditProfile: () -> Unit
|
||||||
) {
|
) {
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
// 按钮
|
|
||||||
|
// 编辑个人资料按钮 - 参考私信按钮样式
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.Center,
|
horizontalArrangement = Arrangement.Center,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(RoundedCornerShape(32.dp))
|
.fillMaxWidth()
|
||||||
.background(
|
.clip(RoundedCornerShape(8.dp))
|
||||||
AppColors.basicMain
|
.background(AppColors.nonActive) // 使用主题灰色背景
|
||||||
)
|
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||||
.padding(horizontal = 16.dp, vertical = 4.dp)
|
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
onEditProfile()
|
onEditProfile()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Icon(
|
|
||||||
Icons.Default.Edit,
|
|
||||||
contentDescription = "",
|
|
||||||
modifier = Modifier.size(24.dp),
|
|
||||||
tint = AppColors.text
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.edit_profile),
|
text = stringResource(R.string.edit_profile),
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.W600,
|
fontWeight = FontWeight.W600,
|
||||||
color = AppColors.text,
|
color = AppColors.text, // 使用主题文字颜色
|
||||||
modifier = Modifier.padding(8.dp)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
package com.aiosman.ravenow.ui.index.tabs.profile.composable
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
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
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
|
import com.aiosman.ravenow.R
|
||||||
|
import com.aiosman.ravenow.entity.AgentEntity
|
||||||
|
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
||||||
|
import com.aiosman.ravenow.utils.DebounceUtils
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun UserAgentsList(
|
||||||
|
agents: List<AgentEntity>,
|
||||||
|
onAgentClick: (AgentEntity) -> Unit = {},
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
|
LazyColumn(
|
||||||
|
modifier = modifier.fillMaxSize(),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
if (agents.isEmpty()) {
|
||||||
|
item {
|
||||||
|
EmptyAgentsView()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
items(agents) { agent ->
|
||||||
|
UserAgentCard(
|
||||||
|
agent = agent,
|
||||||
|
onAgentClick = onAgentClick
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 底部间距
|
||||||
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(120.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun UserAgentCard(
|
||||||
|
agent: AgentEntity,
|
||||||
|
onAgentClick: (AgentEntity) -> Unit
|
||||||
|
) {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
|
// 防抖状态
|
||||||
|
var lastClickTime by remember { mutableStateOf(0L) }
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
// 左侧头像
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(48.dp)
|
||||||
|
.background(AppColors.nonActive, RoundedCornerShape(24.dp)),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
if (agent.avatar.isNotEmpty()) {
|
||||||
|
CustomAsyncImage(
|
||||||
|
imageUrl = agent.avatar,
|
||||||
|
contentDescription = "Agent头像",
|
||||||
|
modifier = Modifier
|
||||||
|
.size(48.dp)
|
||||||
|
.clip(RoundedCornerShape(24.dp)),
|
||||||
|
contentScale = ContentScale.Crop
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(R.mipmap.rider_pro_agent),
|
||||||
|
contentDescription = "默认头像",
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
colorFilter = ColorFilter.tint(AppColors.secondaryText)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(12.dp))
|
||||||
|
|
||||||
|
// 中间文字内容
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(end = 8.dp)
|
||||||
|
) {
|
||||||
|
// 标题
|
||||||
|
Text(
|
||||||
|
text = agent.title,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.W600,
|
||||||
|
color = AppColors.text,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
// 描述
|
||||||
|
Text(
|
||||||
|
text = agent.desc,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = AppColors.secondaryText,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧聊天按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(width = 60.dp, height = 32.dp)
|
||||||
|
.background(
|
||||||
|
color = AppColors.nonActive,
|
||||||
|
shape = RoundedCornerShape(8.dp)
|
||||||
|
)
|
||||||
|
.clickable {
|
||||||
|
if (DebounceUtils.simpleDebounceClick(lastClickTime, 500L) {
|
||||||
|
onAgentClick(agent)
|
||||||
|
}) {
|
||||||
|
lastClickTime = System.currentTimeMillis()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.chat),
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = AppColors.text,
|
||||||
|
fontWeight = FontWeight.W500
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun EmptyAgentsView() {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 60.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(R.mipmap.rider_pro_agent),
|
||||||
|
contentDescription = "暂无Agent",
|
||||||
|
modifier = Modifier.size(48.dp),
|
||||||
|
colorFilter = ColorFilter.tint(AppColors.secondaryText.copy(alpha = 0.5f))
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "暂无创建的智能体",
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = AppColors.secondaryText,
|
||||||
|
fontWeight = FontWeight.W500
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "去创建你的第一个智能体吧",
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = AppColors.secondaryText.copy(alpha = 0.7f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.aiosman.ravenow.ui.index.tabs.profile.composable
|
package com.aiosman.ravenow.ui.index.tabs.profile.composable
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -15,6 +16,7 @@ import androidx.compose.foundation.lazy.items
|
|||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -26,70 +28,142 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.aiosman.ravenow.LocalAppTheme
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
|
import com.aiosman.ravenow.R
|
||||||
import com.aiosman.ravenow.entity.AgentEntity
|
import com.aiosman.ravenow.entity.AgentEntity
|
||||||
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
||||||
|
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UserAgentsRow(
|
fun UserAgentsRow(
|
||||||
userId: Int?,
|
userId: Int?,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier,
|
||||||
|
onMoreClick: () -> Unit = {},
|
||||||
|
onAgentClick: (AgentEntity) -> Unit = {}
|
||||||
) {
|
) {
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
val viewModel: UserAgentsViewModel = viewModel()
|
val viewModel: UserAgentsViewModel = viewModel()
|
||||||
|
val isSelf = userId == null
|
||||||
|
|
||||||
// 加载用户的智能体数据
|
// 加载用户的智能体数据
|
||||||
LaunchedEffect(userId) {
|
LaunchedEffect(userId) {
|
||||||
if (userId != null) {
|
// 无论userId是否为null都加载数据
|
||||||
|
// null表示加载当前用户自己的智能体
|
||||||
|
println("UserAgentsRow: LaunchedEffect 触发, userId = $userId, isSelf = $isSelf")
|
||||||
|
println("UserAgentsRow: 准备调用 viewModel.loadUserAgents")
|
||||||
viewModel.loadUserAgents(userId)
|
viewModel.loadUserAgents(userId)
|
||||||
} else {
|
println("UserAgentsRow: 已调用 viewModel.loadUserAgents")
|
||||||
viewModel.clearAgents()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewModel.agents.isNotEmpty()) {
|
// 总是显示智能体区域,即使没有数据也显示标题和状态
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "我的智能体",
|
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 {
|
||||||
|
viewModel.isLoading -> {
|
||||||
|
// 显示加载状态
|
||||||
|
println("UserAgentsRow: 显示加载状态")
|
||||||
|
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 -> {
|
||||||
|
// 显示错误状态
|
||||||
|
println("UserAgentsRow: 显示错误状态, error = ${viewModel.error}")
|
||||||
|
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() -> {
|
||||||
|
// 显示空状态
|
||||||
|
println("UserAgentsRow: 显示空状态, agents.size = ${viewModel.agents.size}")
|
||||||
|
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 -> {
|
||||||
|
// 显示智能体列表
|
||||||
|
println("UserAgentsRow: 显示智能体列表, agents.size = ${viewModel.agents.size}")
|
||||||
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(agent = agent)
|
AgentItem(
|
||||||
|
agent = agent,
|
||||||
|
onClick = { onAgentClick(agent) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加"更多"按钮
|
||||||
|
item {
|
||||||
|
MoreAgentItem(
|
||||||
|
onClick = onMoreClick
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun AgentItem(
|
private fun AgentItem(
|
||||||
agent: AgentEntity,
|
agent: AgentEntity,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier,
|
||||||
|
onClick: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
modifier = modifier
|
modifier = modifier.noRippleClickable { onClick() }
|
||||||
) {
|
) {
|
||||||
// 头像
|
// 头像
|
||||||
Box(
|
Box(
|
||||||
@@ -122,3 +196,46 @@ private fun AgentItem(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun MoreAgentItem(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onClick: () -> Unit = {}
|
||||||
|
) {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
modifier = modifier.noRippleClickable { onClick() }
|
||||||
|
) {
|
||||||
|
// 圆形右箭头按钮
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(48.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(AppColors.background),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.rave_now_nav_right),
|
||||||
|
contentDescription = "更多",
|
||||||
|
tint = AppColors.text,
|
||||||
|
modifier = Modifier.size(20.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
// "更多"文字
|
||||||
|
Text(
|
||||||
|
text = "更多",
|
||||||
|
fontSize = 12.sp,
|
||||||
|
fontWeight = FontWeight.W500,
|
||||||
|
color = AppColors.text,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
modifier = Modifier.width(48.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,15 +26,19 @@ class UserAgentsViewModel : ViewModel() {
|
|||||||
var error by mutableStateOf<String?>(null)
|
var error by mutableStateOf<String?>(null)
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun loadUserAgents(userId: Int) {
|
fun loadUserAgents(userId: Int?) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
isLoading = true
|
isLoading = true
|
||||||
error = null
|
error = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
println("UserAgentsViewModel: 开始加载智能体数据, userId = $userId")
|
||||||
agentLoader.loadData(AgentLoaderExtraArgs(authorId = userId))
|
agentLoader.loadData(AgentLoaderExtraArgs(authorId = userId))
|
||||||
|
println("UserAgentsViewModel: 加载完成, agents.size = ${agents.size}")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
error = e.message ?: "加载失败"
|
error = e.message ?: "加载失败"
|
||||||
|
println("UserAgentsViewModel: 加载失败, error = $error")
|
||||||
|
e.printStackTrace()
|
||||||
} finally {
|
} finally {
|
||||||
isLoading = false
|
isLoading = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,20 @@ package com.aiosman.ravenow.ui.index.tabs.profile.composable
|
|||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.pager.PagerState
|
import androidx.compose.foundation.pager.PagerState
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
@@ -19,6 +24,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -35,55 +41,78 @@ fun UserContentPageIndicator(
|
|||||||
){
|
){
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
Column(
|
||||||
.verticalScroll(rememberScrollState())
|
modifier = Modifier.fillMaxWidth()
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 16.dp),
|
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.Center,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(RoundedCornerShape(32.dp))
|
.fillMaxWidth()
|
||||||
.background(if (pagerState.currentPage == 0) AppColors.background else Color.Transparent)
|
.padding(horizontal = 16.dp),
|
||||||
.padding(horizontal = 16.dp, vertical = 4.dp)
|
horizontalArrangement = Arrangement.SpaceEvenly
|
||||||
|
) {
|
||||||
|
// 图片/相册 Tab
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
// switch to gallery
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
pagerState.scrollToPage(0)
|
pagerState.scrollToPage(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.padding(vertical = 12.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Icon(
|
||||||
text = stringResource(R.string.gallery),
|
painter = painterResource(id = R.drawable.rider_pro_images),
|
||||||
fontSize = 14.sp,
|
contentDescription = "Gallery",
|
||||||
fontWeight = FontWeight.W600,
|
tint = if (pagerState.currentPage == 0) AppColors.text else AppColors.text.copy(alpha = 0.6f),
|
||||||
color = AppColors.text,
|
modifier = Modifier.size(24.dp)
|
||||||
modifier = Modifier.padding(8.dp),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
|
||||||
Row(
|
// Agent Tab
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
Column(
|
||||||
horizontalArrangement = Arrangement.Center,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(RoundedCornerShape(32.dp))
|
.weight(1f)
|
||||||
.background(if (pagerState.currentPage == 1) AppColors.background else Color.Transparent)
|
|
||||||
.padding(horizontal = 16.dp, vertical = 4.dp)
|
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
// switch to moments
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
pagerState.scrollToPage(1)
|
pagerState.scrollToPage(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.padding(vertical = 12.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Icon(
|
||||||
text = stringResource(R.string.moment),
|
painter = painterResource(id = R.drawable.rider_pro_nav_ai),
|
||||||
fontSize = 14.sp,
|
contentDescription = "Agents",
|
||||||
fontWeight = FontWeight.W600,
|
tint = if (pagerState.currentPage == 1) AppColors.text else AppColors.text.copy(alpha = 0.6f),
|
||||||
color = AppColors.text,
|
modifier = Modifier.size(24.dp)
|
||||||
modifier = Modifier.padding(8.dp)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下划线指示器
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.height(2.dp)
|
||||||
|
.background(
|
||||||
|
if (pagerState.currentPage == 0) AppColors.text else Color.Transparent
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.height(2.dp)
|
||||||
|
.background(
|
||||||
|
if (pagerState.currentPage == 1) AppColors.text else Color.Transparent
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,10 @@ import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
|||||||
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UserItem(accountProfileEntity: AccountProfileEntity) {
|
fun UserItem(
|
||||||
|
accountProfileEntity: AccountProfileEntity,
|
||||||
|
postCount: Int = 0
|
||||||
|
) {
|
||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
@@ -56,8 +59,26 @@ fun UserItem(accountProfileEntity: AccountProfileEntity) {
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
) {
|
) {
|
||||||
|
// 帖子数
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = postCount.toString(),
|
||||||
|
fontWeight = FontWeight.W600,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = AppColors.text
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
Text(
|
||||||
|
text = "帖子",
|
||||||
|
color = AppColors.text
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 粉丝数
|
||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
@@ -78,12 +99,14 @@ fun UserItem(accountProfileEntity: AccountProfileEntity) {
|
|||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.followers_upper),
|
text = "粉丝",
|
||||||
color = AppColors.text
|
color = AppColors.text
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 关注数
|
||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.Center,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
@@ -93,8 +116,7 @@ fun UserItem(accountProfileEntity: AccountProfileEntity) {
|
|||||||
accountProfileEntity.id.toString()
|
accountProfileEntity.id.toString()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = accountProfileEntity.followingCount.toString(),
|
text = accountProfileEntity.followingCount.toString(),
|
||||||
@@ -104,17 +126,10 @@ fun UserItem(accountProfileEntity: AccountProfileEntity) {
|
|||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.following_upper),
|
text = "关注",
|
||||||
color = AppColors.text
|
color = AppColors.text
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Column(
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
|||||||
Reference in New Issue
Block a user