This commit is contained in:
weber
2025-08-25 10:49:00 +08:00
parent 4be63f3428
commit 77033854f0
21 changed files with 721 additions and 339 deletions

View File

@@ -6,6 +6,7 @@ import com.aiosman.ravenow.entity.AgentEntity
import com.aiosman.ravenow.entity.CreatorEntity
import com.aiosman.ravenow.entity.ProfileEntity
import com.aiosman.ravenow.entity.RoomEntity
import com.aiosman.ravenow.entity.UsersEntity
import com.google.gson.annotations.SerializedName
data class Room(
@@ -38,7 +39,9 @@ data class Room(
@SerializedName("canJoin")
val canJoin: Boolean,
@SerializedName("canJoinCode")
val canJoinCode: Int
val canJoinCode: Int,
@SerializedName("users")
val users: List<Users>
) {
fun toRoomtEntity(): RoomEntity {
@@ -58,6 +61,7 @@ data class Room(
maxMemberLimit = maxMemberLimit,
canJoin = canJoin,
canJoinCode = canJoinCode,
users = users.map { it.toUsersEntity() }
)
}
}
@@ -83,6 +87,25 @@ data class Creator(
}
}
data class Users(
@SerializedName("id")
val id: Int,
@SerializedName("userId")
val userId: String,
@SerializedName("trtcUserId")
val trtcUserId: String,
@SerializedName("profile")
val profile: Profile
){
fun toUsersEntity(): UsersEntity {
return UsersEntity(
id = id,
userId = userId,
profile = profile.toProfileEntity()
)
}
}

View File

@@ -76,6 +76,11 @@ data class CreateGroupChatRequestBody(
val promptIds: List<String>,
)
data class JoinGroupChatRequestBody(
@SerializedName("trtcId")
val trtcId: String,
)
data class LoginUserRequestBody(
@SerializedName("username")
val username: String? = null,
@@ -567,6 +572,9 @@ interface RaveNowAPI {
suspend fun getRoomDetail(@Query("trtcId") trtcId: String,
): Response<DataContainer<Room>>
@POST("outside/rooms/join")
suspend fun joinRoom(@Body body: JoinGroupChatRequestBody,
): Response<DataContainer<Room>>

View File

@@ -12,4 +12,5 @@ data class GroupInfo(
val groupName: String,
val groupAvatar: String,
val memberCount: Int,
val isCreator: Boolean = false,
)

View File

@@ -28,6 +28,7 @@ data class RoomEntity(
val maxMemberLimit: Int,
val canJoin: Boolean,
val canJoinCode: Int,
val users: List<UsersEntity>,
)
data class CreatorEntity(
@@ -37,6 +38,12 @@ data class CreatorEntity(
val profile: ProfileEntity
)
data class UsersEntity(
val id: Int,
val userId: String,
val profile: ProfileEntity
)
data class ProfileEntity(
val id: Int,
val username: String,

View File

@@ -35,7 +35,6 @@ import com.aiosman.ravenow.ui.agent.AddAgentScreen
import com.aiosman.ravenow.ui.group.CreateGroupChatScreen
import com.aiosman.ravenow.ui.chat.ChatAiScreen
import com.aiosman.ravenow.ui.chat.ChatScreen
import com.aiosman.ravenow.ui.group.GroupChatInfoScreen
import com.aiosman.ravenow.ui.chat.GroupChatScreen
import com.aiosman.ravenow.ui.comment.CommentsScreen
import com.aiosman.ravenow.ui.comment.notice.CommentNoticeScreen
@@ -48,6 +47,7 @@ import com.aiosman.ravenow.ui.follower.FollowingListScreen
import com.aiosman.ravenow.ui.gallery.OfficialGalleryScreen
import com.aiosman.ravenow.ui.gallery.OfficialPhotographerScreen
import com.aiosman.ravenow.ui.gallery.ProfileTimelineScreen
import com.aiosman.ravenow.ui.group.GroupChatInfoScreen
import com.aiosman.ravenow.ui.index.IndexScreen
import com.aiosman.ravenow.ui.index.tabs.message.NotificationsScreen
import com.aiosman.ravenow.ui.index.tabs.search.SearchScreen
@@ -97,13 +97,13 @@ sealed class NavigationRoute(
data object Chat : NavigationRoute("Chat/{id}")
data object ChatAi : NavigationRoute("ChatAi/{id}")
data object ChatGroup : NavigationRoute("ChatGroup/{id}/{name}/{avatar}")
data object GroupChatInfo : NavigationRoute("GroupChatInfo/{groupId}")
data object CommentNoticeScreen : NavigationRoute("CommentNoticeScreen")
data object ImageCrop : NavigationRoute("ImageCrop")
data object AccountSetting : NavigationRoute("AccountSetting")
data object AboutScreen : NavigationRoute("AboutScreen")
data object AddAgent : NavigationRoute("AddAgent")
data object CreateGroupChat : NavigationRoute("CreateGroupChat")
data object GroupInfo : NavigationRoute("GroupInfo/{id}")
}
@@ -406,19 +406,6 @@ fun NavigationController(
}
}
composable(
route = NavigationRoute.GroupChatInfo.route,
arguments = listOf(navArgument("groupId") { type = NavType.StringType })
) {
val encodedId = it.arguments?.getString("groupId")
val decodedId = encodedId?.let { java.net.URLDecoder.decode(it, "UTF-8") }
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
GroupChatInfoScreen(decodedId?:"")
}
}
composable(route = NavigationRoute.CommentNoticeScreen.route) {
CompositionLocalProvider(
@@ -460,6 +447,20 @@ fun NavigationController(
CreateGroupChatScreen()
}
composable(
route = NavigationRoute.GroupInfo.route,
arguments = listOf(navArgument("id") { type = NavType.StringType })
) {
val encodedId = it.arguments?.getString("id")
val decodedId = encodedId?.let { java.net.URLDecoder.decode(it, "UTF-8") }
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
GroupChatInfoScreen(decodedId?:"")
}
}
}
}
@@ -531,15 +532,17 @@ fun NavHostController.navigateToGroupChat(id: String,name:String,avatar:String)
fun NavHostController.navigateToGroupInfo(id: String) {
val encodedId = java.net.URLEncoder.encode(id, "UTF-8")
navigate(
route = NavigationRoute.GroupChatInfo.route
.replace("{groupId}", encodedId)
route = NavigationRoute.ChatGroup.route
.replace("{id}", encodedId)
)
}
fun NavHostController.goTo(
route: NavigationRoute
) {

View File

@@ -10,6 +10,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavHostController
import com.aiosman.ravenow.ChatState
import com.aiosman.ravenow.data.AccountService
import com.aiosman.ravenow.data.AccountServiceImpl
@@ -21,8 +22,10 @@ import com.aiosman.ravenow.data.api.SingleChatRequestBody
import com.aiosman.ravenow.entity.AccountProfileEntity
import com.aiosman.ravenow.entity.ChatItem
import com.aiosman.ravenow.entity.ChatNotification
import com.aiosman.ravenow.ui.navigateToChatAi
import com.tencent.imsdk.v2.V2TIMAdvancedMsgListener
import com.tencent.imsdk.v2.V2TIMCallback
import com.tencent.imsdk.v2.V2TIMConversationOperationResult
import com.tencent.imsdk.v2.V2TIMManager
import com.tencent.imsdk.v2.V2TIMMessage
import com.tencent.imsdk.v2.V2TIMSendCallback
@@ -162,6 +165,7 @@ class ChatAiViewModel(
override fun onSuccess(p0: V2TIMMessage?) {
Log.d("ChatViewModel", "send message success")
sendChatAiMessage(myProfile?.trtcUserId!!,userProfile?.trtcUserId!!, message)
createGroup2ChatAi(userProfile?.trtcUserId!!,"ai_group")
val chatItem = ChatItem.convertToChatItem(p0!!, context, avatar = myProfile?.avatar)
chatItem?.let {
chatData = listOf(it) + chatData
@@ -171,6 +175,27 @@ class ChatAiViewModel(
}
)
}
fun createGroup2ChatAi(
trtcUserId: String,
groupName: String,
) {
val conversationIDList = listOf("c2c_${trtcUserId}")
V2TIMManager.getConversationManager().createConversationGroup(
groupName,
conversationIDList,
object : V2TIMValueCallback<List<V2TIMConversationOperationResult>> {
override fun onSuccess(v2TIMConversationOperationResults: List<V2TIMConversationOperationResult>) {
// 创建会话分组成功
}
override fun onError(code: Int, desc: String) {
// 创建会话分组失败
}
}
)
}
fun sendImageMessage(imageUri: Uri, context: Context) {
val tempFile = createTempFile(context, imageUri)

View File

@@ -196,14 +196,16 @@ fun ChatScreen(userId: String) {
Spacer(modifier = Modifier.width(8.dp))
Text(
text = viewModel.userProfile?.nickName ?: "",
modifier = Modifier.weight(1f),
modifier = Modifier.weight(1f)
,
maxLines = 1,
style = TextStyle(
color = AppColors.text,
fontSize = 18.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.Bold
)
)
Spacer(modifier = Modifier.weight(1f))
Spacer(modifier = Modifier.width(8.dp))
Box {
Image(
painter = painterResource(R.drawable.rider_pro_more_horizon),

View File

@@ -84,6 +84,7 @@ import com.aiosman.ravenow.ui.composables.DropdownMenu
import com.aiosman.ravenow.ui.composables.MenuItem
import com.aiosman.ravenow.ui.composables.StatusBarSpacer
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import com.aiosman.ravenow.ui.navigateToGroupInfo
import com.tencent.imsdk.v2.V2TIMMessage
import kotlinx.coroutines.launch
import java.util.UUID
@@ -221,7 +222,6 @@ fun GroupChatScreen(groupId: String,name: String,avatar: String,) {
fontWeight = androidx.compose.ui.text.font.FontWeight.Bold
)
)
}
Spacer(modifier = Modifier.weight(1f))
@@ -231,7 +231,7 @@ fun GroupChatScreen(groupId: String,name: String,avatar: String,) {
modifier = Modifier
.size(28.dp)
.noRippleClickable {
isMenuExpanded = true
navController.navigateToGroupInfo(groupId)
},
contentDescription = null,
colorFilter = ColorFilter.tint(AppColors.text)

View File

@@ -23,6 +23,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController
@@ -30,6 +31,7 @@ import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import com.aiosman.ravenow.ui.composables.StatusBarSpacer
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import kotlinx.coroutines.launch
@Composable
fun GroupChatInfoScreen(groupId: String) {
@@ -79,7 +81,7 @@ fun GroupChatInfoScreen(groupId: String) {
Text(
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Start,
text = "群聊信息",
text = stringResource(R.string.group_info),
style = androidx.compose.ui.text.TextStyle(
color = AppColors.text,
fontSize = 17.sp,
@@ -119,7 +121,7 @@ fun GroupChatInfoScreen(groupId: String) {
contentAlignment = Alignment.Center
) {
Text(
text = viewModel.groupInfo?.groupName?.firstOrNull()?.toString() ?: "",
text = viewModel.groupInfo?.groupName?.firstOrNull()?.toString() ?: "",
style = androidx.compose.ui.text.TextStyle(
color = AppColors.text,
fontSize = 24.sp,
@@ -184,11 +186,13 @@ fun GroupChatInfoScreen(groupId: String) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.noRippleClickable {
/* if (viewModel.notificationStrategy == "mute") {
viewModel.updateNotificationStrategy("active")
} else {
viewModel.updateNotificationStrategy("mute")
}*/
viewModel.viewModelScope.launch {
if (viewModel.notificationStrategy == "mute") {
viewModel.updateNotificationStrategy("active")
} else {
viewModel.updateNotificationStrategy("mute")
}
}
}
) {
Box(

View File

@@ -11,6 +11,7 @@ import com.aiosman.ravenow.data.api.ApiClient
import com.aiosman.ravenow.entity.ChatNotification
import com.aiosman.ravenow.entity.GroupInfo
import com.aiosman.ravenow.entity.GroupMember
import com.aiosman.ravenow.ui.index.tabs.profile.MyProfileViewModel
import kotlinx.coroutines.launch
class GroupChatInfoViewModel(
@@ -56,9 +57,10 @@ class GroupChatInfoViewModel(
)
"${ApiClient.RETROFIT_URL+"group/avatar?groupIdBase64="}${groupIdBase64}"+"&token="+"${AppStore.token}"
} else {
"${ApiClient.BASE_API_URL+"/outside/rooms/avatar/"}${it.avatar}"+"?token="+"${AppStore.token}"
"${ApiClient.BASE_API_URL+"/outside"}${it.avatar}"+"?token="+"${AppStore.token}"
},
memberCount = room.userCount,
isCreator = room.creator.userId == MyProfileViewModel.profile?.id.toString()
)
}

View File

@@ -21,10 +21,8 @@ import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.Icon
@@ -57,7 +55,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.offset
import androidx.compose.ui.unit.sp
import com.aiosman.ravenow.AppState
import com.aiosman.ravenow.AppStore
@@ -69,9 +66,6 @@ import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.index.tabs.add.AddPage
import com.aiosman.ravenow.ui.index.tabs.ai.Agent
import com.aiosman.ravenow.ui.index.tabs.message.NotificationsScreen
import com.aiosman.ravenow.ui.index.tabs.message.tab.AgentChatListViewModel
import com.aiosman.ravenow.ui.index.tabs.message.tab.FriendChatListViewModel
import com.aiosman.ravenow.ui.index.tabs.message.tab.GroupChatListViewModel
import com.aiosman.ravenow.ui.index.tabs.moment.MomentsList
import com.aiosman.ravenow.ui.index.tabs.profile.ProfileWrap
import com.aiosman.ravenow.ui.index.tabs.search.DiscoverScreen
@@ -105,10 +99,6 @@ fun IndexScreen() {
val context = LocalContext.current
LaunchedEffect(Unit) {
systemUiController.setNavigationBarColor(Color.Transparent)
// 初始化聊天列表以获取未读消息数
AgentChatListViewModel.refreshPager(context = context)
GroupChatListViewModel.refreshPager(context = context)
FriendChatListViewModel.refreshPager(context = context)
}
LaunchedEffect(model.openDrawer) {
if (model.openDrawer) {
@@ -321,40 +311,12 @@ fun IndexScreen() {
),
contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.width(24.dp)
.height(24.dp)
,
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(if (isSelected) it.selectedIcon() else it.icon()),
contentDescription = it.label(),
modifier = Modifier.size(24.dp),
colorFilter = if (!isSelected) ColorFilter.tint(AppColors.text) else null
)
// 消息按钮红点显示在图片右上角
if (it.route == NavigationItem.Notification.route) {
val totalUnreadCount =
AgentChatListViewModel.totalUnreadCount +
GroupChatListViewModel.totalUnreadCount +
FriendChatListViewModel.totalUnreadCount
if (totalUnreadCount > 0) {
Box(
modifier = Modifier
.size(8.dp)
.background(
color = Color(0xFFFF3B30),
shape = CircleShape
)
.align(Alignment.TopEnd)
.offset(x = 8.dp, y = 8.dp)
)
}
}
}
}
// 文字标签,可控制间距

View File

@@ -1,7 +1,10 @@
package com.aiosman.ravenow.ui.index.tabs.ai
import android.annotation.SuppressLint
import androidx.compose.foundation.ExperimentalFoundationApi
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
@@ -18,6 +21,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -28,19 +32,27 @@ 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.ColorFilter
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController
import com.aiosman.ravenow.R
import com.aiosman.ravenow.ui.NavigationRoute
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
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.composables.TabItem
import com.aiosman.ravenow.ui.composables.TabSpacer
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre.AgentItem
import com.aiosman.ravenow.ui.index.tabs.moment.tabs.expolre.ExploreViewModel
import kotlinx.coroutines.launch
@OptIn( ExperimentalFoundationApi::class)
@@ -53,6 +65,9 @@ fun Agent() {
val statusBarPaddingValues = WindowInsets.systemBars.asPaddingValues()
var pagerState = rememberPagerState { 2 }
var scope = rememberCoroutineScope()
val viewModel: AgentViewModel = viewModel()
Column(
modifier = Modifier
.fillMaxSize()
@@ -66,10 +81,10 @@ fun Agent() {
) {
Row(
modifier = Modifier
.height(36.dp)
.wrapContentHeight()
.fillMaxWidth(),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.Bottom
verticalAlignment = Alignment.CenterVertically
) {
// 搜索框
Row(
@@ -115,7 +130,39 @@ fun Agent() {
tint = AppColors.text
)
}
Spacer(modifier = Modifier.height(16.dp))
// 推荐Agent
Column(
modifier = Modifier
.fillMaxWidth()
.height(280.dp)
.padding(vertical = 16.dp)
) {
// 标题
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(bottom = 12.dp)
) {
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_recommend_agent),
fontSize = 16.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
color = AppColors.text
)
}
// Agent ViewPager
AgentViewPagerSection(agentItems = viewModel.agentItems.take(9),viewModel)
}
Spacer(modifier = Modifier.height(5.dp))
Row(
modifier = Modifier
.fillMaxWidth()
@@ -192,4 +239,183 @@ fun Agent() {
}
}
}
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun AgentViewPagerSection(agentItems: List<AgentItem>,viewModel: AgentViewModel) {
val AppColors = LocalAppTheme.current
// 每页显示3个agent
val itemsPerPage = 3
val totalPages = (agentItems.size + itemsPerPage - 1) / itemsPerPage
if (totalPages > 0) {
val pagerState = rememberPagerState(pageCount = { totalPages })
Column {
// Agent内容
Box(
modifier = Modifier
.height(180.dp)
) {
HorizontalPager(
state = pagerState,
modifier = Modifier.fillMaxSize(),
contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 4.dp),
pageSpacing = 0.dp
) { page ->
// 计算当前页面的偏移量
val pageOffset = (
(pagerState.currentPage - page) + pagerState
.currentPageOffsetFraction
).coerceIn(-1f, 1f)
// 根据偏移量计算缩放比例
val scale = 1f - (0.1f * kotlin.math.abs(pageOffset))
AgentPage(
viewModel = viewModel,
agentItems = agentItems.drop(page * itemsPerPage).take(itemsPerPage),
page = page,
modifier = Modifier.height(180.dp)
.graphicsLayer {
scaleX = scale
scaleY = scale
},
navController = LocalNavController.current,
)
}
}
// 指示器
Row(
modifier = Modifier
.fillMaxWidth()
.height(30.dp)
.padding(top = 12.dp),
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.Center
) {
repeat(totalPages) { index ->
Box(
modifier = Modifier
.padding(horizontal = 4.dp)
.size(3.dp)
.background(
color = if (pagerState.currentPage == index) AppColors.text else AppColors.secondaryText.copy(alpha = 0.3f),
shape = androidx.compose.foundation.shape.CircleShape
)
)
}
}
}
}
}
@Composable
fun AgentPage(viewModel: AgentViewModel,agentItems: List<AgentItem>, page: Int, modifier: Modifier = Modifier,navController: NavHostController) {
Column(
modifier = modifier
.fillMaxSize()
.padding(horizontal = 0.dp)
) {
// 显示3个agent
agentItems.forEachIndexed { index, agentItem ->
AgentCard2(agentItem = agentItem, viewModel = viewModel, navController = LocalNavController.current)
if (index < agentItems.size - 1) {
Spacer(modifier = Modifier.height(8.dp))
}
}
}
}
@SuppressLint("SuspiciousIndentation")
@Composable
fun AgentCard2(viewModel: AgentViewModel,agentItem: AgentItem,navController: NavHostController) {
val AppColors = LocalAppTheme.current
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 3.dp),
verticalAlignment = Alignment.CenterVertically
) {
// 左侧头像
Box(
modifier = Modifier
.size(48.dp)
.background(Color(0xFFF5F5F5), RoundedCornerShape(24.dp)),
contentAlignment = Alignment.Center
) {
if (agentItem.avatar.isNotEmpty()) {
CustomAsyncImage(
imageUrl = agentItem.avatar,
contentDescription = "Agent头像",
modifier = Modifier
.size(48.dp)
.clip(RoundedCornerShape(24.dp)),
contentScale = androidx.compose.ui.layout.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)
) {
// 标题
androidx.compose.material3.Text(
text = agentItem.title,
fontSize = 14.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
color = AppColors.text,
maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(8.dp))
// 描述
androidx.compose.material3.Text(
text = agentItem.desc,
fontSize = 12.sp,
color = AppColors.secondaryText,
maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
)
}
// 右侧聊天按钮
Box(
modifier = Modifier
.size(width = 60.dp, height = 32.dp)
.background(
color = Color(0X147c7480),
shape = RoundedCornerShape(8.dp)
)
.clickable {
/* viewModel.createSingleChat(agentItem.trtcId)
viewModel.goToChatAi(agentItem.trtcId, navController = navController)*/
},
contentAlignment = Alignment.Center
) {
androidx.compose.material3.Text(
text = stringResource(R.string.chat),
fontSize = 12.sp,
color = AppColors.text,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
}
}
}

View File

@@ -1,7 +1,78 @@
package com.aiosman.ravenow.ui.index.tabs.ai
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavHostController
import com.aiosman.ravenow.data.api.ApiClient
import com.aiosman.ravenow.data.api.RaveNowAPI
import com.aiosman.ravenow.data.api.SingleChatRequestBody
import com.aiosman.ravenow.ui.index.tabs.ai.tabs.mine.MineAgentViewModel.createGroup2ChatAi
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
object AgentViewModel: ViewModel() {
private val apiClient: RaveNowAPI = ApiClient.api
var agentItems by mutableStateOf<List<AgentItem>>(emptyList())
private set
var errorMessage by mutableStateOf<String?>(null)
private set
var isRefreshing by mutableStateOf(false)
private set
var isLoading by mutableStateOf(false)
private set
init {
loadAgentData()
}
private fun loadAgentData() {
viewModelScope.launch {
isLoading = true
errorMessage = null
try {
val response = apiClient.getAgent(page = 1, pageSize = 20, withWorkflow = 1)
if (response.isSuccessful) {
val agents = response.body()?.data?.list ?: emptyList()
agentItems = agents.map { agent ->
AgentItem.fromAgent(agent)
}
} else {
errorMessage = "获取Agent数据失败: ${response.code()}"
}
} catch (e: Exception) {
errorMessage = "网络请求失败: ${e.message}"
} finally {
isLoading = false
}
}
}
fun createSingleChat(
openId: String,
) {
viewModelScope.launch {
val response = ApiClient.api.createSingleChat(SingleChatRequestBody(generateText = openId))
}
}
fun goToChatAi(
openId: String,
navController: NavHostController
) {
viewModelScope.launch {
val profile = userService.getUserProfileByOpenId(openId)
createGroup2ChatAi(profile.trtcUserId,"ai_group",navController,profile.id)
}
}
}

View File

@@ -91,11 +91,11 @@ object AgentChatListViewModel : ViewModel() {
var hasNext by mutableStateOf(true)
var currentPage by mutableStateOf(1)
var error by mutableStateOf<String?>(null)
// 计算智能体总未读消息数
val totalUnreadCount: Int
get() = agentChatList.sumOf { it.unreadCount }
private val pageSize = 20
fun refreshPager(pullRefresh: Boolean = false, context: Context? = null) {

View File

@@ -85,11 +85,11 @@ object FriendChatListViewModel : ViewModel() {
var hasNext by mutableStateOf(true)
var currentPage by mutableStateOf(1)
var error by mutableStateOf<String?>(null)
// 计算朋友总未读消息数
val totalUnreadCount: Int
get() = friendChatList.sumOf { it.unreadCount }
private val pageSize = 20
fun refreshPager(pullRefresh: Boolean = false, context: Context? = null) {

View File

@@ -102,13 +102,13 @@ object GroupChatListViewModel : ViewModel() {
var hasNext by mutableStateOf(true)
var currentPage by mutableStateOf(1)
var error by mutableStateOf<String?>(null)
// 计算群聊总未读消息数
val totalUnreadCount: Int
get() = groupChatList.sumOf { it.unreadCount }
private val pageSize = 20
// 消息监听器
private var messageListener: V2TIMAdvancedMsgListener? = null
private var conversationListener: V2TIMConversationListener? = null
@@ -229,7 +229,7 @@ object GroupChatListViewModel : ViewModel() {
loadGroupChatList(context)
}
}
// 初始化消息监听器
fun initMessageListener(context: Context) {
// 消息监听器 - 监听新消息
@@ -245,7 +245,7 @@ object GroupChatListViewModel : ViewModel() {
}
}
}
// 会话监听器 - 监听会话变化
conversationListener = object : V2TIMConversationListener() {
override fun onConversationChanged(conversationList: MutableList<V2TIMConversation>?) {
@@ -259,7 +259,7 @@ object GroupChatListViewModel : ViewModel() {
}
}
}
override fun onNewConversation(conversationList: MutableList<V2TIMConversation>?) {
super.onNewConversation(conversationList)
// 新增会话,刷新群聊列表
@@ -272,12 +272,12 @@ object GroupChatListViewModel : ViewModel() {
}
}
}
// 注册监听器
V2TIMManager.getMessageManager().addAdvancedMsgListener(messageListener)
V2TIMManager.getConversationManager().addConversationListener(conversationListener)
}
// 移除消息监听器
fun removeMessageListener() {
messageListener?.let {
@@ -289,7 +289,7 @@ object GroupChatListViewModel : ViewModel() {
messageListener = null
conversationListener = null
}
// 刷新群聊列表
private fun refreshGroupChatList(context: Context) {
viewModelScope.launch {

View File

@@ -79,7 +79,7 @@ fun MomentsList() {
// center the tabs
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {//探索tab
) {
Column(
modifier = Modifier
.noRippleClickable {
@@ -108,8 +108,38 @@ fun MomentsList() {
.width(34.dp)
.height(4.dp)
)
}
Spacer(modifier = Modifier.width(16.dp))
Column(
modifier = Modifier
.noRippleClickable {
scope.launch {
pagerState.animateScrollToPage(1)
}
},
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = stringResource(R.string.index_dynamic),
fontSize = 16.sp,
color = if (pagerState.currentPage == 1) AppColors.text else AppColors.nonActiveText,
fontWeight = FontWeight.W600)
Spacer(modifier = Modifier.height(4.dp))
Image(
painter = painterResource(
if (pagerState.currentPage == 1) R.mipmap.tab_indicator_selected
else R.drawable.tab_indicator_unselected
),
contentDescription = "tab indicator",
modifier = Modifier
.width(34.dp)
.height(4.dp)
)
}
//“关注”tab
Spacer(modifier = Modifier.width(16.dp))
Column(
modifier = Modifier

View File

@@ -68,6 +68,8 @@ fun Dynamic() {
moments.size,
key = { idx -> idx }
) { idx ->
//处理下标越界
if (idx < 0 || idx >= moments.size) return@items
val momentItem = moments[idx] ?: return@items
MomentCard(momentEntity = momentItem,
onAddComment = {

View File

@@ -96,7 +96,7 @@ data class AgentItem(
val desc: String,
val avatar: String,
val useCount: Int,
//val author: String
//val trtcId: String
) {
companion object {
fun fromAgent(agent: Agent): AgentItem {
@@ -106,7 +106,7 @@ data class AgentItem(
desc = agent.desc,
avatar = "${ApiClient.BASE_API_URL+"/outside"}${agent.avatar}"+"?token="+"${AppStore.token}",
useCount = agent.useCount,
//author = agent.author
// trtcId = agent.
)
}
}
@@ -147,89 +147,89 @@ fun Explore() {
fun AgentCard2(agentItem: AgentItem) {
val AppColors = LocalAppTheme.current
Row(
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
// 左侧头像
Box(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically
.size(48.dp)
.background(Color(0xFFF5F5F5), RoundedCornerShape(24.dp)),
contentAlignment = Alignment.Center
) {
// 左侧头像
Box(
modifier = Modifier
.size(48.dp)
.background(Color(0xFFF5F5F5), RoundedCornerShape(24.dp)),
contentAlignment = Alignment.Center
) {
if (agentItem.avatar.isNotEmpty()) {
CustomAsyncImage(
imageUrl = agentItem.avatar,
contentDescription = "Agent头像",
modifier = Modifier
.size(48.dp)
.clip(RoundedCornerShape(24.dp)),
contentScale = androidx.compose.ui.layout.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 = agentItem.title,
fontSize = 14.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
color = AppColors.text,
maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
if (agentItem.avatar.isNotEmpty()) {
CustomAsyncImage(
imageUrl = agentItem.avatar,
contentDescription = "Agent头像",
modifier = Modifier
.size(48.dp)
.clip(RoundedCornerShape(24.dp)),
contentScale = androidx.compose.ui.layout.ContentScale.Crop
)
Spacer(modifier = Modifier.height(8.dp))
// 描述
Text(
text = agentItem.desc,
fontSize = 12.sp,
color = AppColors.secondaryText,
maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
)
}
// 右侧聊天按钮
Box(
modifier = Modifier
.size(width = 60.dp, height = 32.dp)
.background(
color = Color(0X147c7480),
shape = RoundedCornerShape(8.dp)
)
.clickable {
// 聊天逻辑
},
contentAlignment = Alignment.Center
) {
Text(
text = "聊天",
fontSize = 12.sp,
color = AppColors.text,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
} 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 = agentItem.title,
fontSize = 14.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
color = AppColors.text,
maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(8.dp))
// 描述
Text(
text = agentItem.desc,
fontSize = 12.sp,
color = AppColors.secondaryText,
maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis
)
}
// 右侧聊天按钮
Box(
modifier = Modifier
.size(width = 60.dp, height = 32.dp)
.background(
color = Color(0X147c7480),
shape = RoundedCornerShape(8.dp)
)
.clickable {
// 聊天逻辑
},
contentAlignment = Alignment.Center
) {
Text(
text = "聊天",
fontSize = 12.sp,
color = AppColors.text,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
}
}
}
@Composable
@@ -275,9 +275,9 @@ fun Explore() {
) { page ->
// 计算当前页面的偏移量
val pageOffset = (
(pagerState.currentPage - page) + pagerState
.currentPageOffsetFraction
).coerceIn(-1f, 1f)
(pagerState.currentPage - page) + pagerState
.currentPageOffsetFraction
).coerceIn(-1f, 1f)
// 根据偏移量计算缩放比例
val scale = 1f - (0.1f * kotlin.math.abs(pageOffset))
@@ -473,22 +473,22 @@ fun Explore() {
verticalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceBetween
) {
// 顶部:用户数量
Row(
Row(
verticalAlignment = Alignment.CenterVertically
) {
/* Image(
painter = painterResource(R.drawable.rider_pro_nav_profile),
contentDescription = "chat",
modifier = Modifier.size(16.dp),
colorFilter = ColorFilter.tint(Color.White)
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "${bannerItem.userCount}人在聊",
fontSize = 12.sp,
color = Color.White,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)*/
/* Image(
painter = painterResource(R.drawable.rider_pro_nav_profile),
contentDescription = "chat",
modifier = Modifier.size(16.dp),
colorFilter = ColorFilter.tint(Color.White)
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "${bannerItem.userCount}人在聊",
fontSize = 12.sp,
color = Color.White,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)*/
}
// 底部:标题和描述
@@ -500,7 +500,7 @@ fun Explore() {
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
fontWeight = androidx.compose.ui.text.font.FontWeight.Bold,
color = Color.White,
modifier = Modifier.padding(start = 16.dp)
modifier = Modifier.padding(start = 16.dp)
)
Spacer(modifier = Modifier.height(8.dp))
Text(
@@ -516,81 +516,81 @@ fun Explore() {
Row(
modifier = Modifier.fillMaxWidth()
.background(brush = androidx.compose.ui.graphics.Brush.verticalGradient(
colors = listOf(
Color(0x00000000), // 底部颜色(透明)
Color(0x33000000), // 顶部颜色
colors = listOf(
Color(0x00000000), // 底部颜色(透明)
Color(0x33000000), // 顶部颜色
)
)),
)
)),
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row( modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically){
// 左侧头像
Box(
modifier = Modifier
.size(24.dp)
.background(
Color.White.copy(alpha = 0.2f),
RoundedCornerShape(16.dp)
verticalAlignment = Alignment.CenterVertically){
// 左侧头像
Box(
modifier = Modifier
.size(24.dp)
.background(
Color.White.copy(alpha = 0.2f),
RoundedCornerShape(16.dp)
)
) {
CustomAsyncImage(
context = context,
imageUrl = bannerItem.imageUrl,
contentDescription = "agent Image",
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
.clip(RoundedCornerShape(24.dp)))
}
// 中间信息区域占比1
Column(
modifier = Modifier
.weight(1f)
.padding(horizontal = 8.dp)
) {
Text(
text = bannerItem.agentName,
fontSize = 10.sp,
color = Color(0xfff5f5f5).copy(alpha = 0.6f),
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
) {
CustomAsyncImage(
context = context,
imageUrl = bannerItem.imageUrl,
contentDescription = "agent Image",
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
.clip(RoundedCornerShape(24.dp)))
}
// 中间信息区域占比1
Column(
modifier = Modifier
.weight(1f)
.padding(horizontal = 8.dp)
) {
Text(
text = bannerItem.agentName,
fontSize = 10.sp,
color = Color(0xfff5f5f5).copy(alpha = 0.6f),
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
Text(
text = bannerItem.subtitle,
fontSize = 12.sp,
color = Color.White,
maxLines = 1,
fontWeight = androidx.compose.ui.text.font.FontWeight.W400,
modifier = Modifier.padding(top = 2.dp)
)
}
// 右侧进入按钮
Box(
modifier = Modifier
.width(69.dp)
.height(29.dp)
.background(
color = Color(0x7dffffff),
shape = RoundedCornerShape(8.dp)
Text(
text = bannerItem.subtitle,
fontSize = 12.sp,
color = Color.White,
maxLines = 1,
fontWeight = androidx.compose.ui.text.font.FontWeight.W400,
modifier = Modifier.padding(top = 2.dp)
)
.clickable {
// 进入房间逻辑
},
contentAlignment = Alignment.Center
) {
Text(
text = "进入",
fontSize = 14.sp,
color = Color.White,
fontWeight = androidx.compose.ui.text.font.FontWeight.W600
)
}
}
// 右侧进入按钮
Box(
modifier = Modifier
.width(69.dp)
.height(29.dp)
.background(
color = Color(0x7dffffff),
shape = RoundedCornerShape(8.dp)
)
.clickable {
// 进入房间逻辑
},
contentAlignment = Alignment.Center
) {
Text(
text = "进入",
fontSize = 14.sp,
color = Color.White,
fontWeight = androidx.compose.ui.text.font.FontWeight.W600
)
}
}
@@ -706,7 +706,7 @@ fun Explore() {
contentDescription = "发布动态",
modifier = Modifier.size(24.dp),
)
)
}
Spacer(modifier = Modifier.size(8.dp))
Text(
@@ -733,7 +733,7 @@ fun Explore() {
contentDescription = "热门智能体",
modifier = Modifier.size(24.dp),
)
)
}
Spacer(modifier = Modifier.size(8.dp))
Text(
@@ -746,96 +746,96 @@ fun Explore() {
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun BannerSection(bannerItems: List<BannerItem>) {
val AppColors = LocalAppTheme.current
val context = LocalContext.current
val scope = rememberCoroutineScope()
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun BannerSection(bannerItems: List<BannerItem>) {
val AppColors = LocalAppTheme.current
val context = LocalContext.current
val scope = rememberCoroutineScope()
val pagerState = rememberPagerState(pageCount = { bannerItems.size })
val pagerState = rememberPagerState(pageCount = { bannerItems.size })
// 预加载banner图片
LaunchedEffect(bannerItems) {
bannerItems.forEach { bannerItem ->
if (bannerItem.backgroundImageUrl.isNotEmpty()) {
// 预加载背景图片
com.aiosman.ravenow.utils.Utils.getImageLoader(context).enqueue(
coil.request.ImageRequest.Builder(context)
.data(bannerItem.backgroundImageUrl)
.memoryCachePolicy(coil.request.CachePolicy.ENABLED)
.diskCachePolicy(coil.request.CachePolicy.ENABLED)
.build()
)
}
if (bannerItem.imageUrl.isNotEmpty()) {
// 预加载头像图片
com.aiosman.ravenow.utils.Utils.getImageLoader(context).enqueue(
coil.request.ImageRequest.Builder(context)
.data(bannerItem.imageUrl)
.memoryCachePolicy(coil.request.CachePolicy.ENABLED)
.diskCachePolicy(coil.request.CachePolicy.ENABLED)
.build()
)
}
}
}
Column {
// Banner内容
Box(
modifier = Modifier
.fillMaxWidth()
.height(362.dp)
) {
HorizontalPager(
state = pagerState,
modifier = Modifier.fillMaxSize(),
contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 4.dp),
) { page ->
val bannerItem = bannerItems[page]
// 计算当前页面的偏移量
val pageOffset = (
(pagerState.currentPage - page) + pagerState
.currentPageOffsetFraction
).coerceIn(-1f, 1f)
// 根据偏移量计算缩放比例
val scale = 1f - (0.1f * kotlin.math.abs(pageOffset))
BannerCard(
bannerItem = bannerItem,
modifier = Modifier
.graphicsLayer {
scaleX = scale
scaleY = scale
// 预加载banner图片
LaunchedEffect(bannerItems) {
bannerItems.forEach { bannerItem ->
if (bannerItem.backgroundImageUrl.isNotEmpty()) {
// 预加载背景图片
com.aiosman.ravenow.utils.Utils.getImageLoader(context).enqueue(
coil.request.ImageRequest.Builder(context)
.data(bannerItem.backgroundImageUrl)
.memoryCachePolicy(coil.request.CachePolicy.ENABLED)
.diskCachePolicy(coil.request.CachePolicy.ENABLED)
.build()
)
}
)
}
}
if (bannerItem.imageUrl.isNotEmpty()) {
// 预加载头像图片
com.aiosman.ravenow.utils.Utils.getImageLoader(context).enqueue(
coil.request.ImageRequest.Builder(context)
.data(bannerItem.imageUrl)
.memoryCachePolicy(coil.request.CachePolicy.ENABLED)
.diskCachePolicy(coil.request.CachePolicy.ENABLED)
.build()
)
}
}
}
// 指示器
Row(
modifier = Modifier
.fillMaxWidth()
.padding(top = 12.dp),
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.Center
) {
bannerItems.forEachIndexed { index, _ ->
Box(
modifier = Modifier
.padding(horizontal = 4.dp)
.size(3.dp)
.background(
color = if (pagerState.currentPage == index) AppColors.main else AppColors.secondaryText.copy(alpha = 0.3f),
shape = androidx.compose.foundation.shape.CircleShape
)
)
Column {
// Banner内容
Box(
modifier = Modifier
.fillMaxWidth()
.height(362.dp)
) {
HorizontalPager(
state = pagerState,
modifier = Modifier.fillMaxSize(),
contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 4.dp),
) { page ->
val bannerItem = bannerItems[page]
// 计算当前页面的偏移量
val pageOffset = (
(pagerState.currentPage - page) + pagerState
.currentPageOffsetFraction
).coerceIn(-1f, 1f)
// 根据偏移量计算缩放比例
val scale = 1f - (0.1f * kotlin.math.abs(pageOffset))
BannerCard(
bannerItem = bannerItem,
modifier = Modifier
.graphicsLayer {
scaleX = scale
scaleY = scale
}
)
}
}
// 指示器
Row(
modifier = Modifier
.fillMaxWidth()
.padding(top = 12.dp),
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.Center
) {
bannerItems.forEachIndexed { index, _ ->
Box(
modifier = Modifier
.padding(horizontal = 4.dp)
.size(3.dp)
.background(
color = if (pagerState.currentPage == index) AppColors.main else AppColors.secondaryText.copy(alpha = 0.3f),
shape = androidx.compose.foundation.shape.CircleShape
)
)
}
}
}
}
}
}
}
// 第二块区域Banner
@@ -886,7 +886,7 @@ fun BannerSection(bannerItems: List<BannerItem>) {
contentDescription = "agent",
modifier = Modifier.size(28.dp),
)
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "推荐给你的智能体",
@@ -939,4 +939,4 @@ fun BannerSection(bannerItems: List<BannerItem>) {
modifier = Modifier.align(Alignment.TopCenter)
)
}
}
}

View File

@@ -174,5 +174,13 @@
<string name="group_info_notice_setting">通知</string>
<string name="group_info_exit">退出</string>
<string name="group_info_edit">编辑资料</string>
<string name="group_info">群聊信息</string>
<string name="hot_rooms">热门聊天室</string>
<string name="chat">聊天</string>
<string name="agent_recommend_agent">推荐给你的智能体</string>
<string name="hot_chat_room">正在高能对话中</string>
<string name="create_agent">创建智能体</string>
<string name="publish_dynamic">发布动态</string>
<string name="hot_agent">热门智能体</string>
</resources>

View File

@@ -169,5 +169,13 @@
<string name="group_info_notice_setting">通知</string>
<string name="group_info_exit">退出</string>
<string name="group_info_edit">编辑资料</string>
<string name="group_info">群聊信息</string>
<string name="hot_rooms">热门聊天室</string>
<string name="chat">聊天</string>
<string name="agent_recommend_agent">推荐给你的智能体</string>
<string name="hot_chat_room">正在高能对话中</string>
<string name="create_agent">创建智能体</string>
<string name="publish_dynamic">发布动态</string>
<string name="hot_agent">热门智能体</string>
</resources>