Enhance AI Agent Profile Interaction
This commit introduces several enhancements to how AI agent profiles are displayed and interacted with:
**Profile Display:**
- **AI Account Distinction:** Profile pages now differentiate between regular user accounts and AI agent accounts.
- AI agent profiles will not display the "Agents" tab in their profile.
- The profile header height is adjusted for AI accounts.
- **Navigation Parameter:** An `isAiAccount` boolean parameter is added to the `AccountProfile` navigation route to indicate if the profile being viewed belongs to an AI.
**Interaction & Navigation:**
- **Avatar Click Navigation:**
- Clicking an AI agent's avatar in various lists (Hot Agents, My Agents, User Agents Row, User Agents List) now navigates to the agent's dedicated profile page.
- When navigating to an agent's profile from an agent list, `isAiAccount` is set to `true`.
- **Chat Initiation:** Clicking the chat button on AI agent cards in the "Agent" tab (both Hot and My Agents) now correctly initiates a chat with the respective AI.
- **ViewModel Updates:**
- `AgentViewModel`, `MineAgentViewModel`, and `HotAgentViewModel` now include a `goToProfile` function to handle navigation to agent profiles, correctly passing the `isAiAccount` flag.
**Code Refinements:**
- Click handlers for agent avatars and chat buttons are now wrapped with `DebounceUtils.simpleDebounceClick` to prevent multiple rapid clicks.
- The `UserContentPageIndicator` now conditionally hides the "Agent" tab based on the `isAiAccount` status.
- `UserAgentsRow` and `UserAgentsList` now accept an `onAvatarClick` callback for navigating to agent profiles.
- `AgentItem` (used in `UserAgentsRow`) and `UserAgentCard` (used in `UserAgentsList`) now handle avatar clicks.
- The general `Agent` composable (used in `AiPostComposable`) now also supports an `onAvatarClick` callback.
This commit is contained in:
@@ -2,6 +2,7 @@ package com.aiosman.ravenow.entity
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.aiosman.ravenow.AppStore
|
||||
import com.aiosman.ravenow.data.Agent
|
||||
import com.aiosman.ravenow.data.ListContainer
|
||||
import com.aiosman.ravenow.data.AgentService
|
||||
@@ -28,24 +29,37 @@ suspend fun createAgent(
|
||||
title: String,
|
||||
desc: String,
|
||||
avatar: UploadImage? = null,
|
||||
workflowId:Int = 1,
|
||||
isPublic:Boolean = true,
|
||||
breakMode:Boolean = false,
|
||||
useWorkflow:Boolean = true,
|
||||
workflowId: Int = 1,
|
||||
isPublic: Boolean = true,
|
||||
breakMode: Boolean = false,
|
||||
useWorkflow: Boolean = true,
|
||||
): AgentEntity {
|
||||
val textTitle = title.toRequestBody("text/plain".toMediaTypeOrNull())
|
||||
val textDesc = desc.toRequestBody("text/plain".toMediaTypeOrNull())
|
||||
val workflowIdRequestBody = workflowId.toString().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 useWorkflowRequestBody =
|
||||
useWorkflow.toString().toRequestBody("text/plain".toMediaTypeOrNull())
|
||||
val workflowInputsValue = "{\"si\":\"$desc\"}"
|
||||
val workflowInputsRequestBody = workflowInputsValue.toRequestBody("text/plain".toMediaTypeOrNull())
|
||||
val workflowInputsRequestBody =
|
||||
workflowInputsValue.toRequestBody("text/plain".toMediaTypeOrNull())
|
||||
|
||||
val avatarField: MultipartBody.Part? = avatar?.let {
|
||||
createMultipartBody(it.file, it.filename, "avatar")
|
||||
}
|
||||
val response = ApiClient.api.createAgent(avatarField, textTitle ,textDesc,textDesc,workflowIdRequestBody,isPublicRequestBody,breakModeRequestBody,useWorkflowRequestBody,workflowInputsRequestBody)
|
||||
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")
|
||||
return body.toAgentEntity()
|
||||
|
||||
@@ -99,7 +113,11 @@ class AgentRemoteDataSource(
|
||||
class AgentServiceImpl() : AgentService {
|
||||
val agentBackend = AgentBackend()
|
||||
|
||||
override suspend fun getAgent(pageNumber: Int, pageSize: Int, authorId: Int?): ListContainer<AgentEntity> {
|
||||
override suspend fun getAgent(
|
||||
pageNumber: Int,
|
||||
pageSize: Int,
|
||||
authorId: Int?
|
||||
): ListContainer<AgentEntity> {
|
||||
return agentBackend.getAgent(
|
||||
pageNumber = pageNumber,
|
||||
authorId = authorId
|
||||
@@ -107,50 +125,62 @@ class AgentServiceImpl() : AgentService {
|
||||
}
|
||||
}
|
||||
|
||||
class AgentBackend {
|
||||
val DataBatchSize = 20
|
||||
suspend fun getAgent(
|
||||
pageNumber: Int,
|
||||
authorId: Int? = null
|
||||
): ListContainer<AgentEntity> {
|
||||
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 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() }
|
||||
)
|
||||
}
|
||||
class AgentBackend {
|
||||
val DataBatchSize = 20
|
||||
suspend fun getAgent(
|
||||
pageNumber: Int,
|
||||
authorId: Int? = null
|
||||
): ListContainer<AgentEntity> {
|
||||
// 如果是游客模式且获取我的Agent(authorId为null),返回空列表
|
||||
if (authorId == null && AppStore.isGuest) {
|
||||
return ListContainer(
|
||||
total = 0,
|
||||
page = pageNumber,
|
||||
pageSize = DataBatchSize,
|
||||
list = emptyList()
|
||||
)
|
||||
}
|
||||
|
||||
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 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() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class AgentEntity(
|
||||
//val author: String,
|
||||
@@ -172,15 +202,27 @@ fun createMultipartBody(file: File, filename: String, name: String): MultipartBo
|
||||
val requestFile = file.asRequestBody("image/*".toMediaTypeOrNull())
|
||||
return MultipartBody.Part.createFormData(name, filename, requestFile)
|
||||
}
|
||||
|
||||
class AgentLoaderExtraArgs(
|
||||
val authorId: Int? = null
|
||||
)
|
||||
class AgentLoader : DataLoader<AgentEntity,AgentLoaderExtraArgs>() {
|
||||
|
||||
class AgentLoader : DataLoader<AgentEntity, AgentLoaderExtraArgs>() {
|
||||
override suspend fun fetchData(
|
||||
page: Int,
|
||||
pageSize: Int,
|
||||
extra: AgentLoaderExtraArgs
|
||||
): ListContainer<AgentEntity> {
|
||||
// 如果是游客模式且获取我的Agent(authorId为null),返回空列表
|
||||
if (extra.authorId == null && AppStore.isGuest) {
|
||||
return ListContainer(
|
||||
total = 0,
|
||||
page = page,
|
||||
pageSize = pageSize,
|
||||
list = emptyList()
|
||||
)
|
||||
}
|
||||
|
||||
val result = if (extra.authorId != null) {
|
||||
ApiClient.api.getAgent(
|
||||
page = page,
|
||||
@@ -193,24 +235,25 @@ class AgentLoader : DataLoader<AgentEntity,AgentLoaderExtraArgs>() {
|
||||
pageSize = pageSize
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
val body = result.body() ?: throw ServiceException("Failed to get agent")
|
||||
|
||||
|
||||
return if (extra.authorId != null) {
|
||||
// getAgent 返回 DataContainer<ListContainer<Agent>>
|
||||
val dataContainer = body as DataContainer<ListContainer<Agent>>
|
||||
val listContainer = dataContainer.data
|
||||
ListContainer(
|
||||
list = listContainer.list.map { it.toAgentEntity()},
|
||||
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>
|
||||
val listContainer =
|
||||
body as com.aiosman.ravenow.data.ListContainer<com.aiosman.ravenow.data.Agent>
|
||||
ListContainer(
|
||||
list = listContainer.list.map { it.toAgentEntity()},
|
||||
list = listContainer.list.map { it.toAgentEntity() },
|
||||
total = listContainer.total,
|
||||
page = page,
|
||||
pageSize = pageSize
|
||||
|
||||
Reference in New Issue
Block a user