热门聊天室实现;首页UI调整

This commit is contained in:
2025-10-20 16:54:23 +08:00
parent 54df6c088b
commit f839a793a3
9 changed files with 725 additions and 104 deletions

View File

@@ -81,7 +81,9 @@ data class CreateGroupChatRequestBody(
data class JoinGroupChatRequestBody(
@SerializedName("trtcId")
val trtcId: String,
val trtcId: String? = null,
@SerializedName("roomId")
val roomId: Int? = null,
)
data class LoginUserRequestBody(
@@ -271,6 +273,127 @@ data class RemoveAccountRequestBody(
val password: String,
)
// API 错误响应(用于加入房间等接口的错误处理)
data class ApiErrorResponse(
@SerializedName("err")
val error: String,
@SerializedName("success")
val success: Boolean
)
// 群聊中的用户信息
data class GroupChatUser(
@SerializedName("ID")
val id: Int,
@SerializedName("CreatedAt")
val createdAt: String,
@SerializedName("UpdatedAt")
val updatedAt: String,
@SerializedName("DeletedAt")
val deletedAt: String?,
@SerializedName("userSessionId")
val userSessionId: String,
@SerializedName("sessions")
val sessions: Any?, // 根据实际需要可以定义具体类型
@SerializedName("prompts")
val prompts: Any?, // 根据实际需要可以定义具体类型
@SerializedName("isAgent")
val isAgent: Boolean
)
// 智能体角色信息
data class GroupChatPrompt(
@SerializedName("ID")
val id: Int,
@SerializedName("CreatedAt")
val createdAt: String,
@SerializedName("UpdatedAt")
val updatedAt: String,
@SerializedName("DeletedAt")
val deletedAt: String?,
@SerializedName("Title")
val title: String,
@SerializedName("Desc")
val desc: String,
@SerializedName("Value")
val value: String,
@SerializedName("Enable")
val enable: Boolean,
@SerializedName("UserSessions")
val userSessions: Any?, // 根据实际需要可以定义具体类型
@SerializedName("Avatar")
val avatar: String,
@SerializedName("AuthorId")
val authorId: Int?,
@SerializedName("Author")
val author: Any?, // 根据实际需要可以定义具体类型
@SerializedName("TokenCount")
val tokenCount: Int,
@SerializedName("OpenId")
val openId: String,
@SerializedName("Public")
val public: Boolean,
@SerializedName("BreakMode")
val breakMode: Boolean,
@SerializedName("DocNamespace")
val docNamespace: String,
@SerializedName("UseRag")
val useRag: Boolean,
@SerializedName("RagThreshold")
val ragThreshold: Double,
@SerializedName("WorkflowId")
val workflowId: Int?,
@SerializedName("Workflow")
val workflow: Any?, // 根据实际需要可以定义具体类型
@SerializedName("WorkflowInputs")
val workflowInputs: Any?, // 根据实际需要可以定义具体类型
@SerializedName("Source")
val source: String,
@SerializedName("categories")
val categories: Any? // 根据实际需要可以定义具体类型
)
// 群聊详细信息响应
data class GroupChatResponse(
@SerializedName("ID")
val id: Int,
@SerializedName("CreatedAt")
val createdAt: String,
@SerializedName("UpdatedAt")
val updatedAt: String,
@SerializedName("DeletedAt")
val deletedAt: String?,
@SerializedName("name")
val name: String,
@SerializedName("description")
val description: String,
@SerializedName("creatorId")
val creatorId: Int,
@SerializedName("creator")
val creator: Any?, // 根据实际需要可以定义具体类型
@SerializedName("trtcRoomId")
val trtcRoomId: String,
@SerializedName("trtcType")
val trtcType: String,
@SerializedName("cover")
val cover: String,
@SerializedName("avatar")
val avatar: String,
@SerializedName("recommendBanner")
val recommendBanner: String,
@SerializedName("isRecommended")
val isRecommended: Boolean,
@SerializedName("allowInHot")
val allowInHot: Boolean,
@SerializedName("users")
val users: List<GroupChatUser>,
@SerializedName("prompts")
val prompts: List<GroupChatPrompt>,
@SerializedName("source")
val source: String
)
data class CategoryTranslation(
@SerializedName("name")
val name: String?,
@@ -677,7 +800,10 @@ interface RaveNowAPI {
suspend fun agentMoment(@Body body: AgentMomentRequestBody): Response<DataContainer<String>>
@GET("outside/rooms/open")
suspend fun createGroupChatAi(@Query("trtcGroupId") trtcGroupId: String): Response<DataContainer<Unit>>
suspend fun createGroupChatAi(
@Query("trtcGroupId") trtcGroupId: String? = null,
@Query("roomId") roomId: Int? = null
): Response<DataContainer<GroupChatResponse>>
@POST("outside/rooms/create-single-chat")
suspend fun createSingleChat(@Body body: SingleChatRequestBody): Response<DataContainer<Unit>>
@@ -692,6 +818,7 @@ interface RaveNowAPI {
suspend fun getRooms(@Query("page") page: Int = 1,
@Query("pageSize") pageSize: Int = 20,
@Query("isRecommended") isRecommended: Int = 1,
@Query("random") random: Int? = null,
): Response<ListContainer<Room>>
@GET("outside/rooms/detail")

View File

@@ -80,7 +80,12 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.compose.foundation.lazy.grid.items as gridItems
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.ui.draw.alpha
// 检测是否接近列表底部的扩展函数
fun LazyListState.isScrolledToEnd(buffer: Int = 3): Boolean {
@@ -266,6 +271,53 @@ fun Agent() {
}
}
// 热门聊天室
stickyHeader(key = "hot_rooms_header") {
Row(
modifier = Modifier
.fillMaxWidth()
.background(AppColors.background)
.padding(top = 8.dp, bottom = 12.dp),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
Image(
painter = painterResource(R.mipmap.rider_pro_hot_room),
contentDescription = "chat room",
modifier = Modifier.size(28.dp)
)
Spacer(modifier = Modifier.width(4.dp))
androidx.compose.material3.Text(
text = stringResource(R.string.hot_rooms),
fontSize = 16.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W900,
color = AppColors.text
)
}
}
// 热门聊天室网格
items(viewModel.chatRooms.chunked(2)) { rowRooms ->
Row(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 12.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
rowRooms.forEach { chatRoom ->
ChatRoomCard(
chatRoom = chatRoom,
navController = LocalNavController.current,
modifier = Modifier.weight(1f)
)
}
if (rowRooms.size == 1) {
Spacer(modifier = Modifier.weight(1f))
}
}
}
item { Spacer(modifier = Modifier.height(20.dp)) }
// "发现更多" 标题 - 吸顶
stickyHeader(key = "discover_more") {
@@ -278,15 +330,15 @@ fun Agent() {
verticalAlignment = Alignment.Bottom
) {
Image(
painter = painterResource(R.mipmap.rider_pro_agent2),
painter = painterResource(R.mipmap.bars_x_buttons_home_n_copy_2),
contentDescription = "agent",
modifier = Modifier.size(28.dp),
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,
fontWeight = androidx.compose.ui.text.font.FontWeight.W900,
color = AppColors.text
)
}
@@ -347,11 +399,67 @@ fun Agent() {
}
}
}
@Composable
fun AgentGridLayout(
agentItems: List<AgentItem>,
viewModel: AgentViewModel,
navController: NavHostController
) {
Column(
modifier = Modifier.fillMaxWidth()
) {
// 将agentItems按两列分组
agentItems.chunked(2).forEachIndexed { rowIndex, rowItems ->
Row(
modifier = Modifier
.fillMaxWidth()
.padding(
top = if (rowIndex == 0) 30.dp else 20.dp, // 第一行添加更多顶部间距
bottom = 20.dp
),
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
// 第一列
Box(
modifier = Modifier.weight(1f)
) {
AgentCardSquare(
agentItem = rowItems[0],
viewModel = viewModel,
navController = navController
)
}
// 第二列(如果存在)
if (rowItems.size > 1) {
Box(
modifier = Modifier.weight(1f)
) {
AgentCardSquare(
agentItem = rowItems[1],
viewModel = viewModel,
navController = navController
)
}
} else {
// 如果只有一列,添加空白占位
Spacer(modifier = Modifier.weight(1f))
}
}
}
}
}
@SuppressLint("SuspiciousIndentation")
@Composable
fun AgentCardSquare(agentItem: AgentItem, viewModel: AgentViewModel, navController: NavHostController) {
fun AgentCardSquare(
agentItem: AgentItem,
viewModel: AgentViewModel,
navController: NavHostController
) {
val AppColors = LocalAppTheme.current
val cardHeight = 200.dp
val cardHeight = 180.dp
val avatarSize = cardHeight / 3 // 头像大小为方块高度的三分之一
// 防抖状态
@@ -360,9 +468,8 @@ fun AgentCardSquare(agentItem: AgentItem, viewModel: AgentViewModel, navControll
Box(
modifier = Modifier
.fillMaxWidth()
.padding(top = avatarSize / 2)
.height(cardHeight)
.background(AppColors.nonActive, RoundedCornerShape(12.dp)) // 修改背景颜色
.background(AppColors.secondaryBackground, RoundedCornerShape(12.dp))
.clickable {
if (DebounceUtils.simpleDebounceClick(lastClickTime, 500L) {
viewModel.goToProfile(agentItem.openId, navController)
@@ -372,12 +479,11 @@ fun AgentCardSquare(agentItem: AgentItem, viewModel: AgentViewModel, navControll
},
contentAlignment = Alignment.TopCenter
) {
// 头像,位于方块上方居中,部分悬于方块外部
Box(
modifier = Modifier
.offset(y = -avatarSize / 2)
.offset(y = 4.dp)
.size(avatarSize)
.background(Color.White, RoundedCornerShape(avatarSize / 2))
.background(AppColors.background, RoundedCornerShape(avatarSize / 2))
.clip(RoundedCornerShape(avatarSize / 2)),
contentAlignment = Alignment.Center
) {
@@ -385,9 +491,7 @@ fun AgentCardSquare(agentItem: AgentItem, viewModel: AgentViewModel, navControll
painter = painterResource(R.mipmap.group_copy),
contentDescription = "默认头像",
modifier = Modifier.size(avatarSize),
contentScale = androidx.compose.ui.layout.ContentScale.Crop
)
if (agentItem.avatar.isNotEmpty()) {
CustomAsyncImage(
imageUrl = agentItem.avatar,
@@ -404,7 +508,7 @@ fun AgentCardSquare(agentItem: AgentItem, viewModel: AgentViewModel, navControll
Column(
modifier = Modifier
.fillMaxWidth()
.padding(top = avatarSize / 2 + 8.dp, start = 8.dp, end = 8.dp, bottom = 8.dp),
.padding(top = 4.dp + avatarSize + 8.dp, start = 8.dp, end = 8.dp, bottom = 48.dp), // 为底部聊天按钮留出空间
horizontalAlignment = Alignment.CenterHorizontally
) {
androidx.compose.material3.Text(
@@ -418,30 +522,31 @@ fun AgentCardSquare(agentItem: AgentItem, viewModel: AgentViewModel, navControll
Spacer(modifier = Modifier.height(8.dp))
Box(
modifier = Modifier
.height(85.dp)
.fillMaxWidth()
) {
androidx.compose.material3.Text(
text = agentItem.desc,
fontSize = 12.sp,
color = AppColors.secondaryText,
maxLines = 5,
maxLines = 2,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
modifier = Modifier.weight(1f, fill = false)
)
}
Spacer(modifier = Modifier.height(8.dp))
// 聊天按钮,位于底部居中
// 聊天按钮
Box(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 12.dp)
.width(60.dp)
.height(32.dp)
.background(
color = Color(0X147c7480),
shape = RoundedCornerShape(8.dp)
color = AppColors.text,
shape = RoundedCornerShape(
topStart = 14.dp,
topEnd = 14.dp,
bottomStart = 0.dp,
bottomEnd = 14.dp
)
)
.clickable {
if (DebounceUtils.simpleDebounceClick(lastClickTime, 500L) {
@@ -463,13 +568,12 @@ fun AgentCardSquare(agentItem: AgentItem, viewModel: AgentViewModel, navControll
) {
androidx.compose.material3.Text(
text = stringResource(R.string.chat),
fontSize = 12.sp,
color = AppColors.text,
fontSize = 15.sp,
color = AppColors.background,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
}
}
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
@@ -644,7 +748,12 @@ fun AgentCard2(viewModel: AgentViewModel,agentItem: AgentItem,navController: Nav
.size(width = 60.dp, height = 32.dp)
.background(
color = Color(0X147c7480),
shape = RoundedCornerShape(8.dp)
shape = RoundedCornerShape(
topStart = 14.dp,
topEnd = 14.dp,
bottomStart = 0.dp,
bottomEnd = 14.dp
)
)
.clickable {
if (DebounceUtils.simpleDebounceClick(lastClickTime, 500L) {
@@ -673,3 +782,210 @@ fun AgentCard2(viewModel: AgentViewModel,agentItem: AgentItem,navController: Nav
}
}
}
@Composable
fun ChatRoomsSection(
chatRooms: List<ChatRoom>,
navController: NavHostController
) {
val AppColors = LocalAppTheme.current
Column(
modifier = Modifier.fillMaxWidth()
) {
// 标题
Row(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Image(
painter = painterResource(R.mipmap.rider_pro_hot_room),
contentDescription = "chat room",
modifier = Modifier.size(28.dp)
)
Spacer(modifier = Modifier.width(4.dp))
androidx.compose.material3.Text(
text = stringResource(R.string.hot_rooms),
fontSize = 16.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W900,
color = AppColors.text
)
}
Column(
modifier = Modifier.fillMaxWidth()
) {
chatRooms.chunked(2).forEach { rowRooms ->
Row(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 12.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
rowRooms.forEach { chatRoom ->
ChatRoomCard(
chatRoom = chatRoom,
navController = navController,
modifier = Modifier.weight(1f)
)
}
}
}
}
}
}
@Composable
fun ChatRoomCard(
chatRoom: ChatRoom,
navController: NavHostController,
modifier: Modifier = Modifier
) {
val AppColors = LocalAppTheme.current
val cardSize = 180.dp
val viewModel: AgentViewModel = viewModel()
val context = LocalContext.current
// 防抖状态
var lastClickTime by remember { mutableStateOf(0L) }
// Loading 对话框
if (viewModel.isJoiningRoom) {
Dialog(
onDismissRequest = { /* 阻止用户关闭对话框 */ },
properties = DialogProperties(
dismissOnBackPress = false,
dismissOnClickOutside = false
)
) {
Box(
modifier = Modifier
.size(120.dp)
.background(
color = AppColors.background,
shape = RoundedCornerShape(12.dp)
),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
CircularProgressIndicator(
modifier = Modifier.size(32.dp),
color = AppColors.main
)
Spacer(modifier = Modifier.height(12.dp))
androidx.compose.material3.Text(
text = "加入中...",
fontSize = 14.sp,
color = AppColors.text
)
}
}
}
}
// 正方形卡片,文字重叠在底部
Box(
modifier = modifier
.size(cardSize)
.background(AppColors.secondaryBackground, RoundedCornerShape(12.dp))
.clickable(enabled = !viewModel.isJoiningRoom) {
if (!viewModel.isJoiningRoom && DebounceUtils.simpleDebounceClick(lastClickTime, 500L) {
// 加入群聊房间
viewModel.joinRoom(
id = chatRoom.id,
name = chatRoom.name,
avatar = chatRoom.avatar,
context = context,
navController = navController,
onSuccess = {
// 成功加入房间
},
onError = { errorMsg ->
// 处理错误可以显示Toast或其他提示
}
)
}) {
lastClickTime = System.currentTimeMillis()
}
}
) {
// 优先显示banner如果没有banner则显示头像
val imageUrl = if (chatRoom.banner.isNotEmpty()) chatRoom.banner else chatRoom.avatar
if (imageUrl.isNotEmpty()) {
CustomAsyncImage(
imageUrl = imageUrl,
contentDescription = if (chatRoom.banner.isNotEmpty()) "房间banner" else "房间头像",
modifier = Modifier
.width(cardSize)
.height(120.dp)
.clip(RoundedCornerShape(
topStart = 12.dp,
topEnd = 12.dp,
bottomStart = 0.dp,
bottomEnd = 0.dp)),
contentScale = androidx.compose.ui.layout.ContentScale.Crop
)
} else {
// 默认房间图标
Image(
painter = painterResource(R.mipmap.rider_pro_agent),
contentDescription = "默认房间图标",
modifier = Modifier.size(cardSize * 0.4f),
colorFilter = ColorFilter.tint(AppColors.secondaryText)
)
}
// 房间名称,重叠在底部
Box(
modifier = Modifier
.align(Alignment.BottomCenter)
.fillMaxWidth()
.padding(bottom = 32.dp, start = 10.dp, end = 10.dp)
.clip(RoundedCornerShape(12.dp))
) {
androidx.compose.material3.Text(
text = chatRoom.name,
fontSize = 14.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W900,
color = AppColors.text,
maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
modifier = Modifier.fillMaxWidth(),
textAlign = androidx.compose.ui.text.style.TextAlign.Left
)
}
// 显示人数
Box(
modifier = Modifier
.align(Alignment.BottomCenter)
.fillMaxWidth()
.padding(bottom = 10.dp, start = 10.dp, end = 10.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Image(
painter = painterResource(R.drawable.rider_pro_nav_profile),
contentDescription = "chat",
modifier = Modifier.size(16.dp),
colorFilter = ColorFilter.tint(AppColors.secondaryText)
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "${chatRoom.memberCount} ${stringResource(R.string.chatting_now)}",
fontSize = 12.sp,
modifier = Modifier.alpha(0.6f),
color = AppColors.text,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
}
}
}
}

View File

@@ -17,6 +17,21 @@ import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.index.tabs.message.MessageListViewModel.userService
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre.AgentItem
import kotlinx.coroutines.launch
import android.util.Log
import com.aiosman.ravenow.data.Room
import com.aiosman.ravenow.AppState
import com.aiosman.ravenow.AppStore
import com.aiosman.ravenow.ConstVars
import com.aiosman.ravenow.data.api.CreateGroupChatRequestBody
import com.aiosman.ravenow.ui.index.tabs.message.tab.GroupChatListViewModel.createGroupChat
import com.aiosman.ravenow.ui.navigateToGroupChat
import com.aiosman.ravenow.data.api.ApiErrorResponse
import com.google.gson.Gson
import android.content.Context
import android.widget.Toast
import kotlinx.coroutines.launch
import com.aiosman.ravenow.data.api.JoinGroupChatRequestBody
/**
* 缓存数据结构用于存储每个分类的Agent列表
@@ -26,6 +41,13 @@ data class AgentCacheData(
val currentPage: Int,
val hasMoreData: Boolean
)
data class ChatRoom(
val id: Int,
val name: String,
val avatar: String = "",
val banner: String = "",
val memberCount: Int
)
object AgentViewModel: ViewModel() {
@@ -40,6 +62,11 @@ object AgentViewModel: ViewModel() {
var errorMessage by mutableStateOf<String?>(null)
private set
var chatRooms by mutableStateOf<List<ChatRoom>>(emptyList())
private set
var rooms by mutableStateOf<List<Room>>(emptyList())
private set
var isRefreshing by mutableStateOf(false)
private set
@@ -57,6 +84,9 @@ object AgentViewModel: ViewModel() {
var hasMoreData by mutableStateOf(true)
private set
var isJoiningRoom by mutableStateOf(false)
private set
private val pageSize = 20
private var currentCategoryId: Int? = null
@@ -66,6 +96,7 @@ object AgentViewModel: ViewModel() {
init {
loadAgentData()
loadCategories()
loadChatRooms()
}
private fun loadAgentData(categoryId: Int? = null, page: Int = 1, isLoadMore: Boolean = false, forceRefresh: Boolean = false) {
@@ -159,6 +190,41 @@ object AgentViewModel: ViewModel() {
}
}
private fun loadChatRooms() {
viewModelScope.launch {
try {
val response = apiClient.getRooms(
page = 1,
pageSize = 21,
isRecommended = 1,
random = 1
) // 请求21个确保是3的倍数
if (response.isSuccessful) {
val allRooms = response.body()?.list ?: emptyList()
// 确保房间数量是3的倍数如果不足则截取如果超出则取前几个
val targetCount = (allRooms.size / 3) * 3 // 向下取整到最近的3的倍数
rooms = allRooms.take(targetCount)
// 转换为ChatRoom格式用于兼容现有UI
chatRooms = rooms.map { room ->
ChatRoom(
id = room.id,
name = room.name,
avatar = room.avatar,
banner = ConstVars.BASE_SERVER + "/api/v1/outside/" + room.recommendBanner + "?token=${AppStore.token}",
memberCount = room.userCount
)
}
} else {
}
} catch (e: Exception) {
// 如果网络请求失败,使用默认数据
}
}
}
private fun loadCategories() {
viewModelScope.launch {
// 如果分类已经加载,不重复请求
@@ -280,6 +346,81 @@ object AgentViewModel: ViewModel() {
}
}
/**
* 加入房间
*/
fun joinRoom(
id: Int,
name: String,
avatar: String,
context: Context,
navController: NavHostController,
onSuccess: () -> Unit,
onError: (String) -> Unit
) {
// 防止重复点击
if (isJoiningRoom) return
viewModelScope.launch {
try {
isJoiningRoom = true
val response = apiClient.joinRoom(JoinGroupChatRequestBody(roomId = id))
if (response.isSuccessful) {
// 打开房间
val openRoomResponse = apiClient.createGroupChatAi(
roomId = id
)
if (openRoomResponse.isSuccessful){
val respData = openRoomResponse.body()
respData?.let {
viewModelScope.launch {
try {
// 群聊直接使用群ID进行导航
navController.navigateToGroupChat(
id = respData.data.trtcRoomId,
name = name,
avatar = avatar
)
} catch (e: Exception) {
onError("加入房间失败")
e.printStackTrace()
}
}
}
}
onSuccess()
} else {
// 处理错误响应
try {
val errorBody = response.errorBody()?.string()
if (errorBody != null) {
val gson = Gson()
val errorResponse = gson.fromJson(errorBody, ApiErrorResponse::class.java)
// 在主线程显示 Toast
Toast.makeText(context, errorResponse.error, Toast.LENGTH_LONG).show()
onError(errorResponse.error)
} else {
Toast.makeText(context, "加入房间失败", Toast.LENGTH_SHORT).show()
onError("加入房间失败")
}
} catch (parseException: Exception) {
// 如果解析错误响应失败,显示默认错误信息
Toast.makeText(context, "加入房间失败", Toast.LENGTH_SHORT).show()
onError("加入房间失败")
}
}
} catch (e: Exception) {
Toast.makeText(context, "网络请求失败:${e.message}", Toast.LENGTH_SHORT).show()
onError("网络请求失败:${e.message}")
} finally {
isJoiningRoom = false
}
}
}
/**
* 重置ViewModel状态用于登出或切换账号时清理数据
*/

View File

@@ -2,6 +2,7 @@ package com.aiosman.ravenow.ui.index.tabs.message.tab
import android.content.Context
import android.icu.util.Calendar
import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
@@ -167,10 +168,12 @@ object GroupChatListViewModel : ViewModel() {
}
fun createGroupChat(
trtcGroupId: String,
trtcGroupId: String? = null,
roomId: Int? = null
) {
viewModelScope.launch {
val response = ApiClient.api.createGroupChatAi(trtcGroupId = trtcGroupId)
val response = ApiClient.api.createGroupChatAi(trtcGroupId = trtcGroupId,roomId = roomId)
Log.d("debug",response.toString())
}
}

View File

@@ -369,6 +369,7 @@ fun Explore() {
trtcId = roomItem.trtcId.toString(),
name = roomItem.title,
avatar = roomItem.avatar,
context = context,
navController = navController,
onSuccess = {
Toast.makeText(context, enterSuccessText, Toast.LENGTH_SHORT).show()
@@ -523,7 +524,7 @@ fun Explore() {
Row(
verticalAlignment = Alignment.CenterVertically
) {
/* Image(
Image(
painter = painterResource(R.drawable.rider_pro_nav_profile),
contentDescription = "chat",
modifier = Modifier.size(16.dp),
@@ -535,7 +536,7 @@ fun Explore() {
fontSize = 12.sp,
color = Color.White,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)*/
)
}
// 底部:标题和描述
@@ -636,6 +637,7 @@ fun Explore() {
trtcId = bannerItem.trtcId.toString(),
name = bannerItem.title,
avatar = bannerItem.avatar,
context = context,
navController = navController,
onSuccess = {
Toast.makeText(context, enterSuccessText, Toast.LENGTH_SHORT).show()

View File

@@ -17,6 +17,10 @@ import com.aiosman.ravenow.ui.index.tabs.message.MessageListViewModel.userServic
import com.aiosman.ravenow.ui.index.tabs.message.tab.GroupChatListViewModel
import com.aiosman.ravenow.ui.index.tabs.message.tab.GroupChatListViewModel.createGroupChat
import com.aiosman.ravenow.ui.navigateToGroupChat
import com.aiosman.ravenow.data.api.ApiErrorResponse
import com.google.gson.Gson
import android.content.Context
import android.widget.Toast
import kotlinx.coroutines.launch
class ExploreViewModel : ViewModel() {
@@ -130,21 +134,24 @@ class ExploreViewModel : ViewModel() {
}
}
}
fun createSingleChat(
openId: String,
) {
viewModelScope.launch {
val response = ApiClient.api.createSingleChat(SingleChatRequestBody(agentOpenId = openId))
val response =
ApiClient.api.createSingleChat(SingleChatRequestBody(agentOpenId = openId))
}
}
fun goToChatAi(
openId: String,
navController: NavHostController
) {
viewModelScope.launch {
val profile = userService.getUserProfileByOpenId(openId)
createGroup2ChatAi(profile.trtcUserId,"ai_group",navController,profile.id)
createGroup2ChatAi(profile.trtcUserId, "ai_group", navController, profile.id)
}
}
@@ -152,6 +159,7 @@ class ExploreViewModel : ViewModel() {
trtcId: String,
name: String,
avatar: String,
context: Context,
navController: NavHostController,
onSuccess: () -> Unit,
onError: (String) -> Unit
@@ -164,9 +172,11 @@ class ExploreViewModel : ViewModel() {
try {
createGroupChat(trtcGroupId = trtcId)
// 群聊直接使用群ID进行导航
navController.navigateToGroupChat( id = trtcId,
navController.navigateToGroupChat(
id = trtcId,
name = name,
avatar = avatar)
avatar = avatar
)
} catch (e: Exception) {
onError("加入房间失败")
e.printStackTrace()
@@ -175,9 +185,28 @@ class ExploreViewModel : ViewModel() {
onSuccess()
} else {
// 处理错误响应
try {
val errorBody = response.errorBody()?.string()
if (errorBody != null) {
val gson = Gson()
val errorResponse = gson.fromJson(errorBody, ApiErrorResponse::class.java)
// 在主线程显示 Toast
Toast.makeText(context, errorResponse.error, Toast.LENGTH_LONG).show()
onError(errorResponse.error)
} else {
Toast.makeText(context, "加入房间失败", Toast.LENGTH_SHORT).show()
onError("加入房间失败")
}
} catch (parseException: Exception) {
// 如果解析错误响应失败,显示默认错误信息
Toast.makeText(context, "加入房间失败", Toast.LENGTH_SHORT).show()
onError("加入房间失败")
}
}
} catch (e: Exception) {
Toast.makeText(context, "网络请求失败:${e.message}", Toast.LENGTH_SHORT).show()
onError("网络请求失败:${e.message}")
}
}

View File

@@ -147,6 +147,7 @@
<string name="chat_group">グループ</string>
<string name="chat_friend">友達</string>
<string name="chat_all">すべて</string>
<string name="chatting_now">人はおしゃべりをしている…</string>
<string name="agent_chat_list_title">AIエージェントチャット</string>
<string name="agent_chat_empty_title">AIエージェントチャットがありません</string>
<string name="agent_chat_empty_subtitle">AIエージェントと対話してみましょう</string>

View File

@@ -191,9 +191,10 @@
<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_createing">创建中</string>
<string name="agent_find">发现</string>
<string name="text_error_password_too_long">密码不能超过 %1$d 个字符</string>
<string name="chatting_now">人正在热聊…</string>
<!-- Create Bottom Sheet -->
<string name="create_title">创建</string>

View File

@@ -145,6 +145,7 @@
<string name="chat_ai">Ai</string>
<string name="chat_group">Group</string>
<string name="chat_friend">Friends</string>
<string name="chatting_now">people chatting now…</string>
<string name="chat_all">All</string>
<string name="agent_chat_list_title">Agent Chat</string>
<string name="agent_chat_empty_title">No Agent Chat</string>