用户信息调整
This commit is contained in:
@@ -89,7 +89,8 @@ interface AgentService {
|
||||
*/
|
||||
suspend fun getAgent(
|
||||
pageNumber: Int,
|
||||
pageSize: Int = 20
|
||||
pageSize: Int = 20,
|
||||
authorId: Int? = null
|
||||
): ListContainer<AgentEntity>
|
||||
|
||||
}
|
||||
|
||||
@@ -523,6 +523,7 @@ interface RaveNowAPI {
|
||||
@Query("page") page: Int = 1,
|
||||
@Query("pageSize") pageSize: Int = 20,
|
||||
@Query("withWorkflow") withWorkflow: Int = 1,
|
||||
@Query("authorId") authorId: Int? = null,
|
||||
): Response<DataContainer<ListContainer<Agent>>>
|
||||
|
||||
@GET("outside/my/prompts")
|
||||
|
||||
@@ -54,12 +54,14 @@ suspend fun createAgent(
|
||||
*/
|
||||
class AgentPagingSource(
|
||||
private val agentRemoteDataSource: AgentRemoteDataSource,
|
||||
private val authorId: Int? = null
|
||||
) : PagingSource<Int, AgentEntity>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, AgentEntity> {
|
||||
return try {
|
||||
val currentPage = params.key ?: 1
|
||||
val users = agentRemoteDataSource.getAgent(
|
||||
pageNumber = currentPage
|
||||
pageNumber = currentPage,
|
||||
authorId = authorId
|
||||
)
|
||||
LoadResult.Page(
|
||||
data = users.list,
|
||||
@@ -83,9 +85,11 @@ class AgentRemoteDataSource(
|
||||
) {
|
||||
suspend fun getAgent(
|
||||
pageNumber: Int,
|
||||
authorId: Int? = null
|
||||
): ListContainer<AgentEntity> {
|
||||
return agentService.getAgent(
|
||||
pageNumber = pageNumber
|
||||
pageNumber = pageNumber,
|
||||
authorId = authorId
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -93,10 +97,10 @@ class AgentRemoteDataSource(
|
||||
class AgentServiceImpl() : AgentService {
|
||||
val agentBackend = AgentBackend()
|
||||
|
||||
override suspend fun getAgent(pageNumber: Int, pageSize: Int): ListContainer<AgentEntity> {
|
||||
override suspend fun getAgent(pageNumber: Int, pageSize: Int, authorId: Int?): ListContainer<AgentEntity> {
|
||||
return agentBackend.getAgent(
|
||||
pageNumber = pageNumber,
|
||||
|
||||
authorId = authorId
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -105,20 +109,44 @@ class AgentServiceImpl() : AgentService {
|
||||
val DataBatchSize = 20
|
||||
suspend fun getAgent(
|
||||
pageNumber: Int,
|
||||
|
||||
authorId: Int? = null
|
||||
): ListContainer<AgentEntity> {
|
||||
val resp = ApiClient.api.getMyAgent(
|
||||
pageSize = DataBatchSize,
|
||||
page = pageNumber,
|
||||
val resp = if (authorId != null) {
|
||||
ApiClient.api.getAgent(
|
||||
page = pageNumber,
|
||||
pageSize = DataBatchSize,
|
||||
authorId = authorId
|
||||
)
|
||||
} else {
|
||||
ApiClient.api.getMyAgent(
|
||||
page = pageNumber,
|
||||
pageSize = DataBatchSize
|
||||
)
|
||||
}
|
||||
|
||||
)
|
||||
val body = resp.body() ?: throw ServiceException("Failed to get moments")
|
||||
return ListContainer(
|
||||
total = body.total,
|
||||
page = pageNumber,
|
||||
pageSize = DataBatchSize,
|
||||
list = body.list.map { it.toAgentEntity() }
|
||||
)
|
||||
val body = resp.body() ?: throw ServiceException("Failed to get agents")
|
||||
|
||||
// 处理不同的返回类型
|
||||
return if (authorId != null) {
|
||||
// getAgent 返回 DataContainer<ListContainer<Agent>>
|
||||
val dataContainer = body as com.aiosman.ravenow.data.DataContainer<com.aiosman.ravenow.data.ListContainer<com.aiosman.ravenow.data.Agent>>
|
||||
val listContainer = dataContainer.data
|
||||
ListContainer(
|
||||
total = listContainer.total,
|
||||
page = pageNumber,
|
||||
pageSize = DataBatchSize,
|
||||
list = listContainer.list.map { it.toAgentEntity() }
|
||||
)
|
||||
} else {
|
||||
// getMyAgent 返回 ListContainer<Agent>
|
||||
val listContainer = body as com.aiosman.ravenow.data.ListContainer<com.aiosman.ravenow.data.Agent>
|
||||
ListContainer(
|
||||
total = listContainer.total,
|
||||
page = pageNumber,
|
||||
pageSize = DataBatchSize,
|
||||
list = listContainer.list.map { it.toAgentEntity() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +171,7 @@ fun createMultipartBody(file: File, filename: String, name: String): MultipartBo
|
||||
return MultipartBody.Part.createFormData(name, filename, requestFile)
|
||||
}
|
||||
class AgentLoaderExtraArgs(
|
||||
|
||||
val authorId: Int? = null
|
||||
)
|
||||
class AgentLoader : DataLoader<AgentEntity,AgentLoaderExtraArgs>() {
|
||||
override suspend fun fetchData(
|
||||
@@ -151,24 +179,40 @@ class AgentLoader : DataLoader<AgentEntity,AgentLoaderExtraArgs>() {
|
||||
pageSize: Int,
|
||||
extra: AgentLoaderExtraArgs
|
||||
): ListContainer<AgentEntity> {
|
||||
val result = ApiClient.api.getAgent(
|
||||
page = page,
|
||||
pageSize = pageSize,
|
||||
|
||||
)
|
||||
val data = result.body()?.let {
|
||||
ListContainer(
|
||||
list = it.data.list.map { it.toAgentEntity()},
|
||||
total = it.data.total,
|
||||
val result = if (extra.authorId != null) {
|
||||
ApiClient.api.getAgent(
|
||||
page = page,
|
||||
pageSize = pageSize,
|
||||
authorId = extra.authorId
|
||||
)
|
||||
} else {
|
||||
ApiClient.api.getMyAgent(
|
||||
page = page,
|
||||
pageSize = pageSize
|
||||
)
|
||||
}
|
||||
if (data == null) {
|
||||
throw ServiceException("Failed to get agent")
|
||||
|
||||
val body = result.body() ?: throw ServiceException("Failed to get agent")
|
||||
|
||||
return if (extra.authorId != null) {
|
||||
// getAgent 返回 DataContainer<ListContainer<Agent>>
|
||||
val dataContainer = body as com.aiosman.ravenow.data.DataContainer<com.aiosman.ravenow.data.ListContainer<com.aiosman.ravenow.data.Agent>>
|
||||
val listContainer = dataContainer.data
|
||||
ListContainer(
|
||||
list = listContainer.list.map { it.toAgentEntity()},
|
||||
total = listContainer.total,
|
||||
page = page,
|
||||
pageSize = pageSize
|
||||
)
|
||||
} else {
|
||||
// getMyAgent 返回 ListContainer<Agent>
|
||||
val listContainer = body as com.aiosman.ravenow.data.ListContainer<com.aiosman.ravenow.data.Agent>
|
||||
ListContainer(
|
||||
list = listContainer.list.map { it.toAgentEntity()},
|
||||
total = listContainer.total,
|
||||
page = page,
|
||||
pageSize = pageSize
|
||||
)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -42,6 +42,7 @@ import com.aiosman.ravenow.ui.NavigationRoute
|
||||
import com.aiosman.ravenow.ui.account.AccountEditViewModel
|
||||
import com.aiosman.ravenow.ui.comment.NoticeScreenHeader
|
||||
import com.aiosman.ravenow.ui.comment.ScreenHeader
|
||||
import com.aiosman.ravenow.ui.comment.ScreenHeader2
|
||||
import com.aiosman.ravenow.ui.composables.ActionButton
|
||||
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
||||
import com.aiosman.ravenow.ui.composables.StatusBarSpacer
|
||||
@@ -96,7 +97,7 @@ fun AddAgentScreen() {
|
||||
modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp)
|
||||
.background(color = appColors.decentBackground)
|
||||
) {
|
||||
ScreenHeader (
|
||||
ScreenHeader2 (
|
||||
title = stringResource(R.string.agent_add),
|
||||
moreIcon = false
|
||||
) {
|
||||
@@ -207,7 +208,7 @@ fun AddAgentScreen() {
|
||||
backgroundColor = Color.Transparent,
|
||||
text = stringResource(R.string.agent_create),
|
||||
isLoading = model.isUpdating,
|
||||
loadingText = "创建中...",
|
||||
loadingText = stringResource(R.string.agent_createing),
|
||||
enabled = !model.isUpdating && model.validate() == null
|
||||
) {
|
||||
// 验证输入
|
||||
|
||||
@@ -157,6 +157,52 @@ fun ScreenHeader(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ScreenHeader2(
|
||||
title:String,
|
||||
moreIcon: Boolean = true,
|
||||
rightIcon: @Composable (() -> Unit)? = null
|
||||
) {
|
||||
val nav = LocalNavController.current
|
||||
val AppColors = LocalAppTheme.current
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.rider_pro_back_icon,),
|
||||
contentDescription = title,
|
||||
modifier = Modifier.size(24.dp).clickable(
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
) {
|
||||
nav.navigateUp()
|
||||
},
|
||||
colorFilter = ColorFilter.tint(AppColors.text)
|
||||
)
|
||||
Spacer(modifier = Modifier.size(12.dp))
|
||||
Text(title,
|
||||
fontWeight = FontWeight.W600,
|
||||
modifier = Modifier.weight(1f),
|
||||
textAlign = TextAlign.Center,
|
||||
fontSize = 17.sp,
|
||||
color = AppColors.text)
|
||||
Spacer(modifier = Modifier.size(12.dp))
|
||||
if (moreIcon) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.rider_pro_more_horizon),
|
||||
contentDescription = "More",
|
||||
modifier = Modifier
|
||||
.size(24.dp),
|
||||
)
|
||||
}
|
||||
if (rightIcon != null) {
|
||||
//rightIcon()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CommentsItem() {
|
||||
Box(
|
||||
|
||||
@@ -134,8 +134,8 @@ fun Agent() {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(280.dp)
|
||||
.padding(vertical = 16.dp)
|
||||
.height(260.dp)
|
||||
.padding(vertical = 8.dp)
|
||||
|
||||
) {
|
||||
// 标题
|
||||
@@ -162,7 +162,7 @@ fun Agent() {
|
||||
AgentViewPagerSection(agentItems = viewModel.agentItems.take(9),viewModel)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(5.dp))
|
||||
Spacer(modifier = Modifier.height(0.dp))
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -171,6 +171,20 @@ fun Agent() {
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
verticalAlignment = Alignment.Bottom
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.mipmap.rider_pro_agent2),
|
||||
contentDescription = "agent",
|
||||
modifier = Modifier.size(28.dp),
|
||||
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
androidx.compose.material3.Text(
|
||||
text = stringResource(R.string.agent_find),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
|
||||
color = AppColors.text
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
TabItem(
|
||||
text = stringResource(R.string.agent_mine),
|
||||
isSelected = pagerState.currentPage == 0,
|
||||
|
||||
@@ -23,8 +23,6 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
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.unit.dp
|
||||
@@ -69,16 +67,6 @@ fun HotAgent() {
|
||||
}
|
||||
}
|
||||
|
||||
val context = LocalContext.current
|
||||
|
||||
// 当智能体列表加载完成后,预加载图片
|
||||
LaunchedEffect(agentList) {
|
||||
if (agentList.isNotEmpty()) {
|
||||
model.preloadImages(context)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
@@ -122,7 +110,7 @@ fun HotAgent() {
|
||||
) {
|
||||
items(
|
||||
agentList.size,
|
||||
key = { idx -> agentList[idx].id } // 使用智能体ID作为key,避免重新创建
|
||||
key = { idx -> idx }
|
||||
) { idx ->
|
||||
val agentItem = agentList[idx]
|
||||
AgentCard(
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||
@@ -23,16 +24,19 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.LoadState
|
||||
import com.aiosman.ravenow.LocalAppTheme
|
||||
import com.aiosman.ravenow.LocalNavController
|
||||
import com.aiosman.ravenow.R
|
||||
import com.aiosman.ravenow.ui.composables.AgentCard
|
||||
import com.aiosman.ravenow.ui.index.tabs.message.tab.GroupChatItem
|
||||
import com.aiosman.ravenow.ui.index.tabs.message.tab.GroupChatListViewModel
|
||||
import java.util.UUID
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
@@ -40,34 +44,21 @@ fun MineAgent() {
|
||||
val AppColors = LocalAppTheme.current
|
||||
val navController = LocalNavController.current
|
||||
val model = MineAgentViewModel
|
||||
|
||||
val agentList = model.agentList.collectAsLazyPagingItems()
|
||||
val scope = rememberCoroutineScope()
|
||||
val state = rememberPullRefreshState(model.refreshing, onRefresh = {
|
||||
model.refreshPager(
|
||||
//pullRefresh = true
|
||||
)
|
||||
//model.refreshPager(pullRefresh = true)
|
||||
})
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
var dataFlow = model.agentList
|
||||
var agentList = dataFlow.collectAsLazyPagingItems()
|
||||
// observe list scrolling
|
||||
val reachedBottom by remember {
|
||||
derivedStateOf {
|
||||
val lastVisibleItem = listState.layoutInfo.visibleItemsInfo.lastOrNull()
|
||||
lastVisibleItem?.index != 0 && lastVisibleItem?.index == listState.layoutInfo.totalItemsCount - 2
|
||||
}
|
||||
}
|
||||
// Paging 库会自动处理加载更多,无需手动监听滚动
|
||||
|
||||
// load more if scrolled to bottom
|
||||
LaunchedEffect(reachedBottom) {
|
||||
if (reachedBottom) {
|
||||
// 只在首次加载时刷新,避免从AddAgent返回时重复刷新
|
||||
LaunchedEffect(Unit) {
|
||||
if (agentList.itemCount == 0 && !model.isLoading) {
|
||||
model.refreshPager()
|
||||
}
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
model.refreshPager()
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@@ -110,21 +101,21 @@ fun MineAgent() {
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
state = listState
|
||||
) {
|
||||
items(agentList.itemCount) { index ->
|
||||
|
||||
items(count = agentList.itemCount, key = { index -> agentList[index]?.id ?: index }) { index ->
|
||||
agentList[index]?.let { agent ->
|
||||
AgentCard(
|
||||
agentEntity = agent,
|
||||
onClick = {
|
||||
model.createSingleChat(agent.openId)
|
||||
model.goToChatAi(agent.openId, navController)
|
||||
model.goToChatAi(agent.openId,navController)
|
||||
},
|
||||
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 加载更多指示器
|
||||
if (model.isLoading && agentList.itemCount != 0) {
|
||||
if (agentList.loadState.append is LoadState.Loading) {
|
||||
item {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
|
||||
@@ -31,6 +31,7 @@ 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.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@@ -93,8 +94,8 @@ fun MomentsList() {
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.index_worldwide),
|
||||
fontSize = 16.sp,
|
||||
color = if (pagerState.currentPage == 0) AppColors.text else AppColors.nonActiveText,
|
||||
fontSize = if (pagerState.currentPage == 0)18.sp else 16.sp,
|
||||
color = if (pagerState.currentPage == 0) AppColors.text else Color(0X993c3c43),
|
||||
fontWeight = FontWeight.W600)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
|
||||
@@ -123,8 +124,8 @@ fun MomentsList() {
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.index_dynamic),
|
||||
fontSize = 16.sp,
|
||||
color = if (pagerState.currentPage == 1) AppColors.text else AppColors.nonActiveText,
|
||||
fontSize = if (pagerState.currentPage == 1)18.sp else 16.sp,
|
||||
color = if (pagerState.currentPage == 1) AppColors.text else Color(0X993c3c43),
|
||||
fontWeight = FontWeight.W600)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
|
||||
@@ -153,8 +154,8 @@ fun MomentsList() {
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.index_following),
|
||||
fontSize = 16.sp,
|
||||
color = if (pagerState.currentPage == 2) AppColors.text else AppColors.nonActiveText,
|
||||
fontSize = if (pagerState.currentPage == 2)18.sp else 16.sp,
|
||||
color = if (pagerState.currentPage == 2) AppColors.text else Color(0X993c3c43),
|
||||
fontWeight = FontWeight.W600)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
|
||||
@@ -184,8 +185,8 @@ fun MomentsList() {
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.index_hot),
|
||||
fontSize = 16.sp,
|
||||
color = if (pagerState.currentPage == 3) AppColors.text else AppColors.nonActiveText,
|
||||
fontSize = if (pagerState.currentPage == 3)18.sp else 16.sp,
|
||||
color = if (pagerState.currentPage == 3) AppColors.text else Color(0X993c3c43),
|
||||
fontWeight = FontWeight.W600)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ fun Explore() {
|
||||
.padding(horizontal = 4.dp)
|
||||
.size(3.dp)
|
||||
.background(
|
||||
color = if (pagerState.currentPage == index) AppColors.main else AppColors.secondaryText.copy(alpha = 0.3f),
|
||||
color = if (pagerState.currentPage == index) AppColors.text else AppColors.secondaryText.copy(alpha = 0.3f),
|
||||
shape = androidx.compose.foundation.shape.CircleShape
|
||||
)
|
||||
)
|
||||
@@ -876,7 +876,7 @@ fun Explore() {
|
||||
.padding(horizontal = 4.dp)
|
||||
.size(3.dp)
|
||||
.background(
|
||||
color = if (pagerState.currentPage == index) AppColors.main else AppColors.secondaryText.copy(alpha = 0.3f),
|
||||
color = if (pagerState.currentPage == index) AppColors.text else AppColors.secondaryText.copy(alpha = 0.3f),
|
||||
shape = androidx.compose.foundation.shape.CircleShape
|
||||
)
|
||||
)
|
||||
|
||||
@@ -24,9 +24,8 @@ import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
|
||||
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
@@ -84,13 +83,14 @@ import com.aiosman.ravenow.ui.composables.toolbar.ScrollStrategy
|
||||
import com.aiosman.ravenow.ui.composables.toolbar.rememberCollapsingToolbarScaffoldState
|
||||
import com.aiosman.ravenow.ui.index.IndexViewModel
|
||||
import com.aiosman.ravenow.ui.index.tabs.profile.composable.EmptyMomentPostUnit
|
||||
import com.aiosman.ravenow.ui.index.tabs.profile.composable.GalleryItem
|
||||
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.SelfProfileAction
|
||||
import com.aiosman.ravenow.ui.index.tabs.profile.composable.UserAgentsRow
|
||||
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.modifiers.noRippleClickable
|
||||
import com.aiosman.ravenow.ui.navigateToPost
|
||||
import com.aiosman.ravenow.ui.post.NewPostViewModel
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -156,18 +156,7 @@ fun ProfileV3(
|
||||
}
|
||||
}
|
||||
|
||||
val gridState = rememberLazyStaggeredGridState()
|
||||
val reachedGridBottom by remember {
|
||||
derivedStateOf {
|
||||
val lastVisibleItem = gridState.layoutInfo.visibleItemsInfo.lastOrNull()
|
||||
lastVisibleItem?.index != 0 && lastVisibleItem?.index == gridState.layoutInfo.totalItemsCount - 2
|
||||
}
|
||||
}
|
||||
LaunchedEffect(reachedGridBottom) {
|
||||
if (reachedGridBottom) {
|
||||
onLoadMore()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun switchTheme() {
|
||||
// delay
|
||||
@@ -357,6 +346,12 @@ fun ProfileV3(
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 添加用户智能体行
|
||||
UserAgentsRow(
|
||||
userId = profile?.id,
|
||||
modifier = Modifier.padding(top = 16.dp)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -461,63 +456,48 @@ fun ProfileV3(
|
||||
) { idx ->
|
||||
when (idx) {
|
||||
0 ->
|
||||
LazyVerticalStaggeredGrid(
|
||||
columns = StaggeredGridCells.Fixed(2),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
horizontalArrangement = Arrangement.spacedBy(
|
||||
8.dp
|
||||
),
|
||||
verticalItemSpacing = 8.dp,
|
||||
contentPadding = PaddingValues(8.dp),
|
||||
state = gridState
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Fixed(3),
|
||||
modifier = Modifier.fillMaxSize().padding(bottom = 8.dp),
|
||||
) {
|
||||
if (isSelf) {
|
||||
items(1) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(0.75f)
|
||||
.clip(
|
||||
RoundedCornerShape(8.dp)
|
||||
|
||||
items(moments.size) { idx ->
|
||||
val moment = moments[idx] ?: return@items
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(1f)
|
||||
.padding(2.dp)
|
||||
.noRippleClickable {
|
||||
navController.navigateToPost(
|
||||
id = moment.id,
|
||||
highlightCommentId = 0,
|
||||
initImagePagerIndex = 0
|
||||
)
|
||||
.background(
|
||||
AppColors.background
|
||||
)
|
||||
.padding(8.dp)
|
||||
.noRippleClickable {
|
||||
NewPostViewModel.asNewPost()
|
||||
navController.navigate(
|
||||
NavigationRoute.NewPost.route
|
||||
)
|
||||
}
|
||||
) {
|
||||
}
|
||||
) {
|
||||
CustomAsyncImage(
|
||||
imageUrl = moment.images[0].thumbnail,
|
||||
contentDescription = "",
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
context = LocalContext.current
|
||||
)
|
||||
if (moment.images.size > 1) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.clip(
|
||||
RoundedCornerShape(8.dp)
|
||||
)
|
||||
.background(
|
||||
AppColors.decentBackground
|
||||
)
|
||||
.padding(top = 8.dp, end = 8.dp)
|
||||
.align(Alignment.TopEnd)
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Add,
|
||||
Image(
|
||||
modifier = Modifier.size(24.dp),
|
||||
painter = painterResource(R.drawable.rider_pro_picture_more),
|
||||
contentDescription = "",
|
||||
modifier = Modifier
|
||||
.size(32.dp)
|
||||
.align(Alignment.Center),
|
||||
tint = AppColors.text
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
items(moments.size) { idx ->
|
||||
val moment = moments[idx] ?: return@items
|
||||
GalleryItem(moment, idx)
|
||||
}
|
||||
items(2) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(120.dp))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.aiosman.ravenow.ui.index.tabs.profile.composable
|
||||
|
||||
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.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.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
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.entity.AgentEntity
|
||||
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
||||
|
||||
@Composable
|
||||
fun UserAgentsRow(
|
||||
userId: Int?,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val AppColors = LocalAppTheme.current
|
||||
val viewModel: UserAgentsViewModel = viewModel()
|
||||
|
||||
// 加载用户的智能体数据
|
||||
LaunchedEffect(userId) {
|
||||
if (userId != null) {
|
||||
viewModel.loadUserAgents(userId)
|
||||
} else {
|
||||
viewModel.clearAgents()
|
||||
}
|
||||
}
|
||||
|
||||
if (viewModel.agents.isNotEmpty()) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "我的智能体",
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.W600,
|
||||
color = AppColors.text,
|
||||
modifier = Modifier.padding(bottom = 12.dp)
|
||||
)
|
||||
|
||||
LazyRow(
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
items(viewModel.agents) { agent ->
|
||||
AgentItem(agent = agent)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AgentItem(
|
||||
agent: AgentEntity,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val AppColors = LocalAppTheme.current
|
||||
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = modifier
|
||||
) {
|
||||
// 头像
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(48.dp)
|
||||
.clip(CircleShape)
|
||||
) {
|
||||
CustomAsyncImage(
|
||||
context = LocalContext.current,
|
||||
imageUrl = agent.avatar,
|
||||
contentDescription = agent.title,
|
||||
modifier = Modifier.size(48.dp),
|
||||
contentScale = ContentScale.Crop,
|
||||
defaultRes = com.aiosman.ravenow.R.mipmap.rider_pro_agent
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
// 名字
|
||||
Text(
|
||||
text = agent.title,
|
||||
fontSize = 12.sp,
|
||||
fontWeight = FontWeight.W500,
|
||||
color = AppColors.text,
|
||||
textAlign = TextAlign.Center,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier.width(48.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.aiosman.ravenow.ui.index.tabs.profile.composable
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.aiosman.ravenow.entity.AgentEntity
|
||||
import com.aiosman.ravenow.entity.AgentLoader
|
||||
import com.aiosman.ravenow.entity.AgentLoaderExtraArgs
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class UserAgentsViewModel : ViewModel() {
|
||||
private val agentLoader = AgentLoader().apply {
|
||||
onListChanged = {
|
||||
agents = it
|
||||
}
|
||||
}
|
||||
|
||||
var agents by mutableStateOf<List<AgentEntity>>(emptyList())
|
||||
private set
|
||||
|
||||
var isLoading by mutableStateOf(false)
|
||||
private set
|
||||
|
||||
var error by mutableStateOf<String?>(null)
|
||||
private set
|
||||
|
||||
fun loadUserAgents(userId: Int) {
|
||||
viewModelScope.launch {
|
||||
isLoading = true
|
||||
error = null
|
||||
|
||||
try {
|
||||
agentLoader.loadData(AgentLoaderExtraArgs(authorId = userId))
|
||||
} catch (e: Exception) {
|
||||
error = e.message ?: "加载失败"
|
||||
} finally {
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clearAgents() {
|
||||
agents = emptyList()
|
||||
error = null
|
||||
agentLoader.clear()
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -132,7 +132,7 @@
|
||||
<string name="agent_hot">热门</string>
|
||||
<string name="agent_recommend">推荐</string>
|
||||
<string name="agent_other">其他</string>
|
||||
<string name="agent_add">创建Ai智能体</string>
|
||||
<string name="agent_add">创建智能体</string>
|
||||
<string name="agent_name">名称</string>
|
||||
<string name="agent_name_hint">请输入名称</string>
|
||||
<string name="agent_desc">设定描述</string>
|
||||
@@ -186,5 +186,7 @@
|
||||
<string name="group_room_enter">进入</string>
|
||||
<string name="group_room_enter_success">成功加入房间</string>
|
||||
<string name="group_room_enter_fail">加入房间失败</string>
|
||||
<string name="agent_createing">创建中...</string>
|
||||
<string name="agent_find">发现</string>
|
||||
|
||||
</resources>
|
||||
@@ -181,5 +181,7 @@
|
||||
<string name="group_room_enter">进入</string>
|
||||
<string name="group_room_enter_success">成功加入房间</string>
|
||||
<string name="group_room_enter_fail">加入房间失败</string>
|
||||
<string name="agent_createing">创建中...</string>
|
||||
<string name="agent_find">发现</string>
|
||||
|
||||
</resources>
|
||||
Reference in New Issue
Block a user