智能体列表,全部
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package com.aiosman.ravenow.data
|
package com.aiosman.ravenow.data
|
||||||
|
|
||||||
|
import com.aiosman.ravenow.AppStore
|
||||||
import com.aiosman.ravenow.data.api.ApiClient
|
import com.aiosman.ravenow.data.api.ApiClient
|
||||||
import com.aiosman.ravenow.entity.AgentEntity
|
import com.aiosman.ravenow.entity.AgentEntity
|
||||||
import com.aiosman.ravenow.entity.ProfileEntity
|
import com.aiosman.ravenow.entity.ProfileEntity
|
||||||
@@ -22,8 +23,6 @@ data class Agent(
|
|||||||
val isPublic: Boolean,
|
val isPublic: Boolean,
|
||||||
@SerializedName("openId")
|
@SerializedName("openId")
|
||||||
val openId: String,
|
val openId: String,
|
||||||
@SerializedName("profile")
|
|
||||||
val profile: Profile,
|
|
||||||
@SerializedName("title")
|
@SerializedName("title")
|
||||||
val title: String,
|
val title: String,
|
||||||
@SerializedName("updatedAt")
|
@SerializedName("updatedAt")
|
||||||
@@ -38,13 +37,12 @@ data class Agent(
|
|||||||
desc = desc,
|
desc = desc,
|
||||||
createdAt = createdAt,
|
createdAt = createdAt,
|
||||||
updatedAt = updatedAt,
|
updatedAt = updatedAt,
|
||||||
avatar = "${ApiClient.BASE_SERVER}$avatar",
|
avatar = "${ApiClient.BASE_API_URL+"/outside"}$avatar"+"?token="+"Bearer ${AppStore.token}",
|
||||||
author = author,
|
//author = author,
|
||||||
isPublic = isPublic,
|
isPublic = isPublic,
|
||||||
openId = openId,
|
openId = openId,
|
||||||
breakMode = breakMode,
|
breakMode = breakMode,
|
||||||
useCount = useCount,
|
useCount = useCount,
|
||||||
profile = profile.toProfileEntity(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,11 @@ data class AgentMomentRequestBody(
|
|||||||
val sessionId: String
|
val sessionId: String
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class SingleChatRequestBody(
|
||||||
|
@SerializedName("agentOpenId")
|
||||||
|
val generateText: String,
|
||||||
|
)
|
||||||
|
|
||||||
data class LoginUserRequestBody(
|
data class LoginUserRequestBody(
|
||||||
@SerializedName("username")
|
@SerializedName("username")
|
||||||
val username: String? = null,
|
val username: String? = null,
|
||||||
@@ -470,12 +475,14 @@ interface RaveNowAPI {
|
|||||||
suspend fun getAgent(
|
suspend fun getAgent(
|
||||||
@Query("page") page: Int = 1,
|
@Query("page") page: Int = 1,
|
||||||
@Query("pageSize") pageSize: Int = 20,
|
@Query("pageSize") pageSize: Int = 20,
|
||||||
): Response<ListContainer<Agent>>
|
@Query("withWorkflow") withWorkflow: Int = 1,
|
||||||
|
): Response<DataContainer<ListContainer<Agent>>>
|
||||||
|
|
||||||
@GET("outside/my/prompts")
|
@GET("outside/my/prompts")
|
||||||
suspend fun getMyAgent(
|
suspend fun getMyAgent(
|
||||||
@Query("page") page: Int = 1,
|
@Query("page") page: Int = 1,
|
||||||
@Query("pageSize") pageSize: Int = 20,
|
@Query("pageSize") pageSize: Int = 20,
|
||||||
|
@Query("withWorkflow") withWorkflow: Int = 1,
|
||||||
): Response<ListContainer<Agent>>
|
): Response<ListContainer<Agent>>
|
||||||
|
|
||||||
@Multipart
|
@Multipart
|
||||||
@@ -483,12 +490,25 @@ interface RaveNowAPI {
|
|||||||
suspend fun createAgent(
|
suspend fun createAgent(
|
||||||
@Part avatar: MultipartBody.Part?,
|
@Part avatar: MultipartBody.Part?,
|
||||||
@Part("title") title: RequestBody?,
|
@Part("title") title: RequestBody?,
|
||||||
|
@Part("value") value: RequestBody?,
|
||||||
@Part("desc") desc: RequestBody?,
|
@Part("desc") desc: RequestBody?,
|
||||||
|
@Part("workflowId") workflowId: RequestBody?,
|
||||||
|
@Part("public") isPublic: RequestBody?,
|
||||||
|
@Part("breakMode") breakMode: RequestBody?,
|
||||||
|
@Part("useWorkflow") useWorkflow: RequestBody?,
|
||||||
|
@Part("workflowInputs") workflowInputs: RequestBody?,
|
||||||
): Response<DataContainer<Agent>>
|
): Response<DataContainer<Agent>>
|
||||||
|
|
||||||
|
|
||||||
@POST("generate/postText")
|
@POST("generate/postText")
|
||||||
suspend fun agentMoment(@Body body: AgentMomentRequestBody): Response<DataContainer<String>>
|
suspend fun agentMoment(@Body body: AgentMomentRequestBody): Response<DataContainer<String>>
|
||||||
|
|
||||||
|
@POST("outside/rooms/create-single-chat")
|
||||||
|
suspend fun createSingleChat(@Body body: SingleChatRequestBody): Response<DataContainer<Unit>>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,35 +7,48 @@ import com.aiosman.ravenow.data.AgentService
|
|||||||
import com.aiosman.ravenow.data.ServiceException
|
import com.aiosman.ravenow.data.ServiceException
|
||||||
import com.aiosman.ravenow.data.UploadImage
|
import com.aiosman.ravenow.data.UploadImage
|
||||||
import com.aiosman.ravenow.data.api.ApiClient
|
import com.aiosman.ravenow.data.api.ApiClient
|
||||||
|
import okhttp3.MediaType
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.RequestBody.Companion.asRequestBody
|
import okhttp3.RequestBody.Companion.asRequestBody
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import retrofit2.http.Part
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 智能体
|
* 智能体
|
||||||
*/
|
*/
|
||||||
|
|
||||||
suspend fun createAgent(
|
suspend fun createAgent(
|
||||||
title: String,
|
title: String,
|
||||||
desc: String,
|
desc: String,
|
||||||
avatar: UploadImage? = null,
|
avatar: UploadImage? = null,
|
||||||
|
workflowId:Int = 1,
|
||||||
|
isPublic:Boolean = true,
|
||||||
|
breakMode:Boolean = false,
|
||||||
|
useWorkflow:Boolean = true,
|
||||||
): AgentEntity {
|
): AgentEntity {
|
||||||
val textTitle = title.toRequestBody("text/plain".toMediaTypeOrNull())
|
val textTitle = title.toRequestBody("text/plain".toMediaTypeOrNull())
|
||||||
val textDesc = desc.toRequestBody("text/plain".toMediaTypeOrNull())
|
val textDesc = desc.toRequestBody("text/plain".toMediaTypeOrNull())
|
||||||
|
val workflowIdRequestBody = workflowId.toString().toRequestBody("text/plain".toMediaTypeOrNull())
|
||||||
|
val isPublicRequestBody = isPublic.toString().toRequestBody("text/plain".toMediaTypeOrNull())
|
||||||
|
val breakModeRequestBody = breakMode.toString().toRequestBody("text/plain".toMediaTypeOrNull())
|
||||||
|
val useWorkflowRequestBody = useWorkflow.toString().toRequestBody("text/plain".toMediaTypeOrNull())
|
||||||
|
val workflowInputsValue = "{\"si\":\"$desc\"}"
|
||||||
|
val workflowInputsRequestBody = workflowInputsValue.toRequestBody("text/plain".toMediaTypeOrNull())
|
||||||
|
|
||||||
val avatarField: MultipartBody.Part? = avatar?.let {
|
val avatarField: MultipartBody.Part? = avatar?.let {
|
||||||
createMultipartBody(it.file, it.filename, "avatar")
|
createMultipartBody(it.file, it.filename, "avatar")
|
||||||
}
|
}
|
||||||
val response = ApiClient.api.createAgent(avatarField, textTitle ,textDesc)
|
val response = ApiClient.api.createAgent(avatarField, textTitle ,textDesc,textDesc,workflowIdRequestBody,isPublicRequestBody,breakModeRequestBody,useWorkflowRequestBody,workflowInputsRequestBody)
|
||||||
val body = response.body()?.data ?: throw ServiceException("Failed to create agent")
|
val body = response.body()?.data ?: throw ServiceException("Failed to create agent")
|
||||||
return body.toAgentEntity()
|
return body.toAgentEntity()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AgentEntity(
|
data class AgentEntity(
|
||||||
val author: String,
|
//val author: String,
|
||||||
val avatar: String,
|
val avatar: String,
|
||||||
val breakMode: Boolean,
|
val breakMode: Boolean,
|
||||||
val createdAt: String,
|
val createdAt: String,
|
||||||
@@ -43,7 +56,7 @@ data class AgentEntity(
|
|||||||
val id: Int,
|
val id: Int,
|
||||||
val isPublic: Boolean,
|
val isPublic: Boolean,
|
||||||
val openId: String,
|
val openId: String,
|
||||||
val profile: ProfileEntity,
|
//val profile: ProfileEntity,
|
||||||
val title: String,
|
val title: String,
|
||||||
val updatedAt: String,
|
val updatedAt: String,
|
||||||
val useCount: Int
|
val useCount: Int
|
||||||
@@ -80,8 +93,8 @@ class AgentLoader : DataLoader<AgentEntity,AgentLoaderExtraArgs>() {
|
|||||||
)
|
)
|
||||||
val data = result.body()?.let {
|
val data = result.body()?.let {
|
||||||
ListContainer(
|
ListContainer(
|
||||||
list = it.list.map { it.toAgentEntity()},
|
list = it.data.list.map { it.toAgentEntity()},
|
||||||
total = it.total,
|
total = it.data.total,
|
||||||
page = page,
|
page = page,
|
||||||
pageSize = pageSize
|
pageSize = pageSize
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -230,6 +230,8 @@ fun AddAgentScreen() {
|
|||||||
if (result != null) {
|
if (result != null) {
|
||||||
println("AddAgent: Agent created successfully, closing page")
|
println("AddAgent: Agent created successfully, closing page")
|
||||||
// 创建成功,关闭页面
|
// 创建成功,关闭页面
|
||||||
|
model.name = ""
|
||||||
|
model.desc = ""
|
||||||
navController.popBackStack()
|
navController.popBackStack()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ fun AgentCard(
|
|||||||
text = agentEntity.title,
|
text = agentEntity.title,
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
style = TextStyle(fontWeight = FontWeight.Bold)
|
style = TextStyle(fontWeight = FontWeight.W700)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Row(
|
Row(
|
||||||
@@ -93,6 +93,7 @@ fun AgentCard(
|
|||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
text = agentEntity.desc,
|
text = agentEntity.desc,
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
|
maxLines = 1,
|
||||||
fontSize = 12.sp
|
fontSize = 12.sp
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import com.aiosman.ravenow.LocalNavController
|
|||||||
import com.aiosman.ravenow.R
|
import com.aiosman.ravenow.R
|
||||||
import com.aiosman.ravenow.ui.NavigationRoute
|
import com.aiosman.ravenow.ui.NavigationRoute
|
||||||
import com.aiosman.ravenow.ui.index.tabs.ai.tabs.mine.MineAgent
|
import com.aiosman.ravenow.ui.index.tabs.ai.tabs.mine.MineAgent
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.ai.tabs.hot.HotAgent
|
||||||
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@@ -134,7 +135,7 @@ fun Agent() {
|
|||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.agent_mine),
|
text = stringResource(R.string.agent_mine),
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
color = if (pagerState.currentPage == 0) AppColors.checkedText else AppColors.text,
|
color = if (pagerState.currentPage == 0) AppColors.mainText else AppColors.checkedBackground,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(RoundedCornerShape(8.dp))
|
.clip(RoundedCornerShape(8.dp))
|
||||||
.background(if (pagerState.currentPage == 0) AppColors.checkedBackground else AppColors.unCheckedBackground)
|
.background(if (pagerState.currentPage == 0) AppColors.checkedBackground else AppColors.unCheckedBackground)
|
||||||
@@ -158,7 +159,7 @@ fun Agent() {
|
|||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.agent_hot),
|
text = stringResource(R.string.agent_hot),
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
color = if (pagerState.currentPage == 1) AppColors.checkedText else AppColors.text,
|
color = if (pagerState.currentPage == 1) AppColors.mainText else AppColors.checkedBackground,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(RoundedCornerShape(8.dp))
|
.clip(RoundedCornerShape(8.dp))
|
||||||
.background(if (pagerState.currentPage == 1) AppColors.checkedBackground else AppColors.unCheckedBackground)
|
.background(if (pagerState.currentPage == 1) AppColors.checkedBackground else AppColors.unCheckedBackground)
|
||||||
@@ -182,7 +183,7 @@ fun Agent() {
|
|||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.agent_recommend),
|
text = stringResource(R.string.agent_recommend),
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
color = if (pagerState.currentPage == 2) AppColors.checkedText else AppColors.text,
|
color = if (pagerState.currentPage == 2) AppColors.mainText else AppColors.checkedBackground,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(RoundedCornerShape(8.dp))
|
.clip(RoundedCornerShape(8.dp))
|
||||||
.background(if (pagerState.currentPage == 2) AppColors.checkedBackground else AppColors.unCheckedBackground)
|
.background(if (pagerState.currentPage == 2) AppColors.checkedBackground else AppColors.unCheckedBackground)
|
||||||
@@ -206,7 +207,7 @@ fun Agent() {
|
|||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.agent_other),
|
text = stringResource(R.string.agent_other),
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
color = if (pagerState.currentPage == 3) AppColors.checkedText else AppColors.text,
|
color = if (pagerState.currentPage == 3) AppColors.mainText else AppColors.checkedBackground,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(RoundedCornerShape(8.dp))
|
.clip(RoundedCornerShape(8.dp))
|
||||||
.background(if (pagerState.currentPage == 3) AppColors.checkedBackground else AppColors.unCheckedBackground)
|
.background(if (pagerState.currentPage == 3) AppColors.checkedBackground else AppColors.unCheckedBackground)
|
||||||
@@ -231,7 +232,7 @@ fun Agent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
1 -> {
|
1 -> {
|
||||||
|
HotAgent()
|
||||||
}
|
}
|
||||||
|
|
||||||
2 -> {
|
2 -> {
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
package com.aiosman.ravenow.ui.index.tabs.ai.tabs.hot
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
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.rememberLazyListState
|
||||||
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
|
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||||
|
import androidx.compose.material.pullrefresh.pullRefresh
|
||||||
|
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
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 com.aiosman.ravenow.LocalAppTheme
|
||||||
|
import com.aiosman.ravenow.R
|
||||||
|
import com.aiosman.ravenow.ui.composables.AgentCard
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
|
@Composable
|
||||||
|
fun HotAgent() {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
val model = HotAgentViewModel
|
||||||
|
var agentList = model.agentList
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val state = rememberPullRefreshState(model.refreshing, onRefresh = {
|
||||||
|
model.refreshPager(pullRefresh = true)
|
||||||
|
})
|
||||||
|
val listState = rememberLazyListState()
|
||||||
|
|
||||||
|
// observe list scrolling
|
||||||
|
val reachedBottom by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
val lastVisibleItem = listState.layoutInfo.visibleItemsInfo.lastOrNull()
|
||||||
|
lastVisibleItem?.index != 0 && lastVisibleItem?.index == listState.layoutInfo.totalItemsCount - 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// load more if scrolled to bottom
|
||||||
|
LaunchedEffect(reachedBottom) {
|
||||||
|
if (reachedBottom && !model.isLoading && model.hasNext) {
|
||||||
|
model.loadMore()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
model.refreshPager()
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
if(agentList.isEmpty() && !model.isLoading) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize(),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.mipmap.rider_pro_following_empty),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(140.dp)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.size(32.dp))
|
||||||
|
Text(
|
||||||
|
text = "您还没有创建任何智能体",
|
||||||
|
color = AppColors.text,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight.W600
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.size(16.dp))
|
||||||
|
Text(
|
||||||
|
text = "点击开始创建您的第一个智能体",
|
||||||
|
color = AppColors.text,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight.W400
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Box(Modifier.pullRefresh(state)) {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
state = listState
|
||||||
|
) {
|
||||||
|
items(
|
||||||
|
agentList.size,
|
||||||
|
key = { idx -> idx }
|
||||||
|
) { idx ->
|
||||||
|
val agentItem = agentList[idx]
|
||||||
|
AgentCard(agentEntity = agentItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载更多指示器
|
||||||
|
if (model.isLoading && agentList.isNotEmpty()) {
|
||||||
|
item {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
color = AppColors.main
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PullRefreshIndicator(model.refreshing, state, Modifier.align(Alignment.TopCenter))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 错误信息显示
|
||||||
|
model.error?.let { error ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = error,
|
||||||
|
color = AppColors.error,
|
||||||
|
fontSize = 14.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package com.aiosman.ravenow.ui.index.tabs.ai.tabs.hot
|
||||||
|
|
||||||
|
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.data.api.ApiClient
|
||||||
|
import com.aiosman.ravenow.data.ServiceException
|
||||||
|
import com.aiosman.ravenow.entity.AgentEntity
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
object HotAgentViewModel : ViewModel() {
|
||||||
|
var agentList by mutableStateOf<List<AgentEntity>>(emptyList())
|
||||||
|
var refreshing by mutableStateOf(false)
|
||||||
|
var isLoading by mutableStateOf(false)
|
||||||
|
var hasNext by mutableStateOf(true)
|
||||||
|
var currentPage by mutableStateOf(1)
|
||||||
|
var error by mutableStateOf<String?>(null)
|
||||||
|
|
||||||
|
private val pageSize = 20
|
||||||
|
|
||||||
|
init {
|
||||||
|
refreshPager()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refreshPager(pullRefresh: Boolean = false) {
|
||||||
|
if (isLoading && !pullRefresh) return
|
||||||
|
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
isLoading = true
|
||||||
|
refreshing = pullRefresh
|
||||||
|
error = null
|
||||||
|
|
||||||
|
val response = ApiClient.api.getAgent(
|
||||||
|
page = 1,
|
||||||
|
pageSize = pageSize
|
||||||
|
)
|
||||||
|
|
||||||
|
val body = response.body()
|
||||||
|
if (body != null) {
|
||||||
|
val newAgents = body.data.list.map { it.toAgentEntity() }
|
||||||
|
agentList = newAgents
|
||||||
|
currentPage = 1
|
||||||
|
hasNext = newAgents.size == pageSize
|
||||||
|
} else {
|
||||||
|
throw ServiceException("Failed to load agents")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
error = e.message ?: "加载失败"
|
||||||
|
e.printStackTrace()
|
||||||
|
} finally {
|
||||||
|
isLoading = false
|
||||||
|
refreshing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadMore() {
|
||||||
|
if (isLoading || !hasNext) return
|
||||||
|
|
||||||
|
viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
isLoading = true
|
||||||
|
error = null
|
||||||
|
|
||||||
|
val response = ApiClient.api.getAgent(
|
||||||
|
page = currentPage + 1,
|
||||||
|
pageSize = pageSize
|
||||||
|
)
|
||||||
|
|
||||||
|
val body = response.body()
|
||||||
|
if (body != null) {
|
||||||
|
val newAgents = body.data.list.map { it.toAgentEntity() }
|
||||||
|
agentList = agentList + newAgents
|
||||||
|
currentPage += 1
|
||||||
|
hasNext = newAgents.size == pageSize
|
||||||
|
} else {
|
||||||
|
throw ServiceException("Failed to load more agents")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
error = e.message ?: "加载更多失败"
|
||||||
|
e.printStackTrace()
|
||||||
|
} finally {
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,10 +5,18 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.navigation.NavHostController
|
||||||
import com.aiosman.ravenow.data.api.ApiClient
|
import com.aiosman.ravenow.data.api.ApiClient
|
||||||
import com.aiosman.ravenow.data.ServiceException
|
import com.aiosman.ravenow.data.ServiceException
|
||||||
|
import com.aiosman.ravenow.data.api.AgentMomentRequestBody
|
||||||
|
import com.aiosman.ravenow.data.api.SingleChatRequestBody
|
||||||
import com.aiosman.ravenow.entity.AgentEntity
|
import com.aiosman.ravenow.entity.AgentEntity
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.message.Conversation
|
||||||
|
import com.aiosman.ravenow.ui.index.tabs.message.MessageListViewModel.userService
|
||||||
|
import com.aiosman.ravenow.ui.navigateToChat
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
|
||||||
object MineAgentViewModel : ViewModel() {
|
object MineAgentViewModel : ViewModel() {
|
||||||
var agentList by mutableStateOf<List<AgentEntity>>(emptyList())
|
var agentList by mutableStateOf<List<AgentEntity>>(emptyList())
|
||||||
@@ -87,4 +95,22 @@ object MineAgentViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun createSingleChat(
|
||||||
|
openId: String,
|
||||||
|
): String {
|
||||||
|
val response = ApiClient.api.createSingleChat(SingleChatRequestBody(generateText = openId))
|
||||||
|
val body = response.body()?.data ?: throw ServiceException("Failed to create single chat")
|
||||||
|
return body.toString()
|
||||||
|
|
||||||
|
}
|
||||||
|
fun goToChat(
|
||||||
|
conversation: Conversation,
|
||||||
|
navController: NavHostController
|
||||||
|
) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
val profile = userService.getUserProfileByTrtcUserId(conversation.trtcUserId)
|
||||||
|
navController.navigateToChat(profile.id.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user