消息列表和聊天时调整

This commit is contained in:
weber
2025-08-21 17:08:18 +08:00
parent edcab76fdb
commit 5ee1897739
22 changed files with 906 additions and 182 deletions

View File

@@ -41,7 +41,9 @@ data class AgentMomentRequestBody(
data class SingleChatRequestBody(
@SerializedName("agentOpenId")
val generateText: String,
val generateText: String? = null,
@SerializedName("agentTrtcId")
val agentTrtcId: String? = null,
)
data class GroupChatRequestBody(
@@ -561,6 +563,11 @@ interface RaveNowAPI {
@Query("isRecommended") isRecommended: Int = 1,
): Response<ListContainer<Room>>
@GET("rooms/detail")
suspend fun getRoomDetail(@Query("trtcId") trtcId: String,
): Response<DataContainer<Room>>
}

View File

@@ -0,0 +1,16 @@
package com.aiosman.ravenow.entity
data class GroupMember(
val userId: String,
val nickname: String,
val avatar: String,
val isOwner: Boolean = false
)
data class GroupInfo(
val groupId: String,
val groupName: String,
val groupAvatar: String,
val memberCount: Int,
val members: List<GroupMember>
)

View File

@@ -35,6 +35,7 @@ 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
@@ -96,6 +97,7 @@ 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")
@@ -404,6 +406,18 @@ fun NavigationController(
}
}
composable(
route = NavigationRoute.GroupChatInfo.route,
arguments = listOf(navArgument("groupId") { type = NavType.StringType })
) {
val groupId = it.arguments?.getString("groupId") ?: ""
CompositionLocalProvider(
LocalAnimatedContentScope provides this,
) {
GroupChatInfoScreen(groupId)
}
}
composable(route = NavigationRoute.CommentNoticeScreen.route) {
CompositionLocalProvider(

View File

@@ -8,6 +8,7 @@ import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@@ -49,6 +50,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.focus.onFocusChanged
@@ -229,7 +231,8 @@ fun GroupChatScreen(groupId: String,name: String,avatar: String,) {
modifier = Modifier
.size(28.dp)
.noRippleClickable {
isMenuExpanded = true
// 跳转到群聊信息页面
navController.navigate("GroupChatInfo/$groupId")
},
contentDescription = null,
colorFilter = ColorFilter.tint(AppColors.text)
@@ -276,9 +279,8 @@ fun GroupChatScreen(groupId: String,name: String,avatar: String,) {
modifier = Modifier
.fillMaxWidth()
.height(1.dp)
.background(AppColors.decentBackground)
)
Spacer(modifier = Modifier.height(8.dp))
Spacer(modifier = Modifier.height(12.dp))
GroupChatInput(
onSendImage = { uri ->
uri?.let {
@@ -294,7 +296,7 @@ fun GroupChatScreen(groupId: String,name: String,avatar: String,) {
Box(
modifier = Modifier
.fillMaxSize()
.background(AppColors.decentBackground)
.background(AppColors.background)
.padding(paddingValues)
) {
LazyColumn(
@@ -306,23 +308,31 @@ fun GroupChatScreen(groupId: String,name: String,avatar: String,) {
val chatList = groupMessagesByTime(viewModel.getDisplayChatList(), viewModel)
items(chatList.size, key = { index -> chatList[index].msgId + UUID.randomUUID().toString()}) { index ->
val item = chatList[index]
if (item.showTimeDivider) {
val calendar = java.util.Calendar.getInstance()
calendar.timeInMillis = item.timestamp
Text(
text = calendar.time.formatChatTime(context),
style = TextStyle(
color = AppColors.secondaryText,
fontSize = 14.sp,
textAlign = TextAlign.Center
),
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp)
Column {
if (item.showTimeDivider) {
val calendar = java.util.Calendar.getInstance()
calendar.timeInMillis = item.timestamp
Text(
text = calendar.time.formatChatTime(context),
style = TextStyle(
color = AppColors.secondaryText,
fontSize = 11.sp,
textAlign = TextAlign.Center
),
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp)
)
}
// 获取上一个item的userId用于判断是否显示头像和昵称
val previousItem = if (index < chatList.size - 1) chatList[index + 1] else null
val showAvatarAndNickname = previousItem?.userId != item.userId
GroupChatItem(
item = item,
currentUserId = viewModel.myProfile?.trtcUserId!!,
showAvatarAndNickname = showAvatarAndNickname
)
}
GroupChatItem(item = item, viewModel.myProfile?.trtcUserId!!)
}
}
@@ -345,7 +355,7 @@ fun GroupChatScreen(groupId: String,name: String,avatar: String,) {
text = "${goToNewCount} 条新消息",
style = TextStyle(
color = AppColors.text,
fontSize = 16.sp,
fontSize = 12.sp,
),
)
}
@@ -390,7 +400,7 @@ fun GroupChatSelfItem(item: ChatItem) {
vertical = (if (item.messageType == V2TIMMessage.V2TIM_ELEM_TYPE_TEXT) 8.dp else 0.dp),
horizontal = (if (item.messageType == V2TIMMessage.V2TIM_ELEM_TYPE_TEXT) 16.dp else 0.dp)
)
.padding(bottom = (if (item.messageType == V2TIMMessage.V2TIM_ELEM_TYPE_TEXT) 3.dp else 0.dp))
) {
when (item.messageType) {
V2TIMMessage.V2TIM_ELEM_TYPE_TEXT -> {
@@ -441,7 +451,7 @@ fun GroupChatSelfItem(item: ChatItem) {
}
@Composable
fun GroupChatOtherItem(item: ChatItem) {
fun GroupChatOtherItem(item: ChatItem, showAvatarAndNickname: Boolean = true) {
val AppColors = LocalAppTheme.current
Column(
@@ -451,30 +461,27 @@ fun GroupChatOtherItem(item: ChatItem) {
) {
Row(
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.Bottom,
modifier = Modifier.fillMaxWidth()
) {
Box(
modifier = Modifier
.size(24.dp)
.clip(RoundedCornerShape(24.dp))
) {
CustomAsyncImage(
imageUrl = item.avatar.replace("storage/avatars/", "/avatar/"),
modifier = Modifier.fillMaxSize(),
contentDescription = "avatar"
)
if (showAvatarAndNickname) {
Box(
modifier = Modifier
.size(24.dp)
.clip(RoundedCornerShape(24.dp))
) {
CustomAsyncImage(
imageUrl = item.avatar.replace("storage/avatars/", "/avatar/"),
modifier = Modifier.fillMaxSize(),
contentDescription = "avatar"
)
}
Spacer(modifier = Modifier.width(12.dp))
} else {
// 当不显示头像时,添加左边距以保持消息对齐
Spacer(modifier = Modifier.width(36.dp))
}
Spacer(modifier = Modifier.width(12.dp))
Column {
Text(
text = item.nickname,
style = TextStyle(
color = AppColors.secondaryText,
fontSize = 12.sp,
),
modifier = Modifier.padding(bottom = 2.dp)
)
Box(
modifier = Modifier
.widthIn(
@@ -487,7 +494,6 @@ fun GroupChatOtherItem(item: ChatItem) {
vertical = (if (item.messageType == V2TIMMessage.V2TIM_ELEM_TYPE_TEXT) 8.dp else 0.dp),
horizontal = (if (item.messageType == V2TIMMessage.V2TIM_ELEM_TYPE_TEXT) 16.dp else 0.dp)
)
.padding(bottom = (if (item.messageType == V2TIMMessage.V2TIM_ELEM_TYPE_TEXT) 3.dp else 0.dp))
) {
when (item.messageType) {
V2TIMMessage.V2TIM_ELEM_TYPE_TEXT -> {
@@ -520,13 +526,24 @@ fun GroupChatOtherItem(item: ChatItem) {
}
}
}
if (showAvatarAndNickname) {
Text(
text = item.nickname,
style = TextStyle(
color = AppColors.secondaryText,
fontSize = 12.sp,
),
modifier = Modifier.padding(top = 2.dp)
)
}
}
}
}
}
@Composable
fun GroupChatItem(item: ChatItem, currentUserId: String) {
fun GroupChatItem(item: ChatItem, currentUserId: String, showAvatarAndNickname: Boolean = true) {
val isCurrentUser = item.userId == currentUserId
// 管理员消息显示特殊布局
@@ -538,7 +555,7 @@ fun GroupChatItem(item: ChatItem, currentUserId: String) {
// 根据是否是当前用户显示不同样式
when (item.userId) {
currentUserId -> GroupChatSelfItem(item)
else -> GroupChatOtherItem(item)
else -> GroupChatOtherItem(item, showAvatarAndNickname)
}
}
@@ -615,20 +632,21 @@ fun GroupChatInput(
onSendImage(uri)
}
}
Box( modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp),){
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
.padding(bottom = inputBarHeight)
.clip(RoundedCornerShape(20.dp))
.background(appColors.decentBackground)
.padding(start = 16.dp, end = 8.dp, top = 2.dp, bottom = 2.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Box(
modifier = Modifier
.weight(1f)
.clip(RoundedCornerShape(16.dp))
.background(appColors.background)
.padding(horizontal = 16.dp),
contentAlignment = Alignment.CenterStart,
) {
BasicTextField(
value = text,
@@ -640,6 +658,7 @@ fun GroupChatInput(
fontSize = 16.sp
),
cursorBrush = SolidColor(appColors.text),
singleLine = true,
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp)
@@ -662,44 +681,32 @@ fun GroupChatInput(
)
)
}
Spacer(modifier = Modifier.width(16.dp))
Icon(
painter = painterResource(id = R.drawable.rider_pro_camera),
contentDescription = "发送图片",
modifier = Modifier
.size(30.dp)
.noRippleClickable {
imagePickUpLauncher.launch(
Intent.createChooser(
Intent(Intent.ACTION_GET_CONTENT).apply {
type = "image/*"
},
"选择图片"
)
)
},
tint = appColors.chatActionColor
)
Spacer(modifier = Modifier.width(8.dp))
Crossfade(
targetState = text.isNotEmpty(), animationSpec = tween(500),
label = ""
) { isNotEmpty ->
Icon(
painter = painterResource(id = R.drawable.rider_pro_video_share),
contentDescription = "发送消息",
val alpha by animateFloatAsState(
targetValue = if (isNotEmpty) 1f else 0.5f,
animationSpec = tween(300)
)
Image(
painter = painterResource(R.mipmap.rider_pro_im_send),
modifier = Modifier
.size(32.dp)
.size(24.dp)
.alpha(alpha)
.noRippleClickable {
if (text.isNotEmpty()) {
onSend(text)
text = ""
}
},
tint = if (isNotEmpty) appColors.main else appColors.chatActionColor
contentDescription = null,
)
}
}
}
}
fun groupMessagesByTime(chatList: List<ChatItem>, viewModel: GroupChatViewModel): List<ChatItem> {
@@ -711,7 +718,7 @@ fun groupMessagesByTime(chatList: List<ChatItem>, viewModel: GroupChatViewModel)
}
val currentMessage = chatList[i]
val timeDiff = currentMessage.timestamp - chatList[i - 1].timestamp
if (-timeDiff > 30 * 60 * 1000) {
if (-timeDiff > 10 * 60 * 1000) {
viewModel.showTimestampMap[currentMessage.msgId] = true
currentMessage.showTimeDivider = true
}

View File

@@ -0,0 +1,386 @@
package com.aiosman.ravenow.ui.group
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.*
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.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.compose.viewModel
import com.aiosman.ravenow.LocalAppTheme
import com.aiosman.ravenow.LocalNavController
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
@Composable
fun GroupChatInfoScreen(groupId: String) {
val navController = LocalNavController.current
val context = LocalContext.current
val AppColors = LocalAppTheme.current
val viewModel = viewModel<GroupChatInfoViewModel>(
key = "GroupChatInfoViewModel_$groupId",
factory = object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return GroupChatInfoViewModel(groupId) as T
}
}
)
Column(
modifier = Modifier
.fillMaxSize()
.background(AppColors.background)
) {
// 顶部导航栏
Column(
modifier = Modifier
.fillMaxWidth()
.background(AppColors.background)
) {
StatusBarSpacer()
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp, horizontal = 16.dp),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
Image(
painter = painterResource(R.drawable.rider_pro_back_icon),
modifier = Modifier
.size(24.dp)
.noRippleClickable {
navController.navigateUp()
},
contentDescription = null,
colorFilter = ColorFilter.tint(AppColors.text)
)
Spacer(modifier = Modifier.width(16.dp))
Text(
modifier = Modifier.fillMaxWidth(),
text = "群聊信息",
style = androidx.compose.ui.text.TextStyle(
color = AppColors.text,
fontSize = 18.sp,
fontWeight = FontWeight.Bold
)
)
Spacer(modifier = Modifier.width(40.dp))
}
}
// 内容区域
LazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(16.dp)
) {
// 群聊头像和名称
item {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
if (viewModel.groupInfo?.groupAvatar?.isNotEmpty() == true) {
CustomAsyncImage(
imageUrl = viewModel.groupInfo!!.groupAvatar,
modifier = Modifier
.size(80.dp)
.clip(CircleShape),
contentDescription = "群聊头像"
)
} else {
Box(
modifier = Modifier
.size(80.dp)
.clip(CircleShape)
.background(AppColors.decentBackground),
contentAlignment = Alignment.Center
) {
Text(
text = viewModel.groupInfo?.groupName?.firstOrNull()?.toString() ?: "",
style = androidx.compose.ui.text.TextStyle(
color = AppColors.text,
fontSize = 24.sp,
fontWeight = FontWeight.Bold
)
)
}
}
Spacer(modifier = Modifier.height(16.dp))
Text(
text = viewModel.groupInfo?.groupName ?: "群聊",
style = androidx.compose.ui.text.TextStyle(
color = AppColors.text,
fontSize = 18.sp,
fontWeight = FontWeight.Bold
)
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "更改名称和图片",
style = androidx.compose.ui.text.TextStyle(
color = Color(0xFF007AFF),
fontSize = 14.sp
),
modifier = Modifier.noRippleClickable {
// TODO: 实现更改群聊名称和图片功能
}
)
}
}
// 操作按钮
item {
Spacer(modifier = Modifier.height(32.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
// 添加其他人
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.noRippleClickable {
// TODO: 实现添加其他人功能
}
) {
Box(
modifier = Modifier
.size(48.dp)
.clip(CircleShape)
.background(Color(0xFF007AFF)),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(R.drawable.rider_pro_back_icon),
modifier = Modifier.size(24.dp),
contentDescription = null,
colorFilter = ColorFilter.tint(Color.White)
)
}
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "添加其他人",
style = androidx.compose.ui.text.TextStyle(
color = AppColors.text,
fontSize = 12.sp
)
)
}
// 通知设置
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.noRippleClickable {
// TODO: 实现通知设置功能
}
) {
Box(
modifier = Modifier
.size(48.dp)
.clip(CircleShape)
.background(Color(0xFF007AFF)),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(R.drawable.rider_pro_notice_active),
modifier = Modifier.size(24.dp),
contentDescription = null,
colorFilter = ColorFilter.tint(Color.White)
)
}
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "通知",
style = androidx.compose.ui.text.TextStyle(
color = AppColors.text,
fontSize = 12.sp
)
)
}
// 退出群聊
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.noRippleClickable {
// TODO: 实现退出群聊功能
}
) {
Box(
modifier = Modifier
.size(48.dp)
.clip(CircleShape)
.background(Color(0xFFFF3B30)),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(R.drawable.rider_pro_back_icon),
modifier = Modifier.size(24.dp),
contentDescription = null,
colorFilter = ColorFilter.tint(Color.White)
)
}
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "退出",
style = androidx.compose.ui.text.TextStyle(
color = AppColors.text,
fontSize = 12.sp
)
)
}
}
}
// 设置选项
item {
Spacer(modifier = Modifier.height(32.dp))
// 设置聊天主题
Row(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(8.dp))
.background(AppColors.decentBackground)
.padding(16.dp)
.noRippleClickable {
// TODO: 实现设置聊天主题功能
},
verticalAlignment = Alignment.CenterVertically
) {
Image(
painter = painterResource(R.drawable.rider_pro_back_icon),
modifier = Modifier.size(24.dp),
contentDescription = null,
colorFilter = ColorFilter.tint(AppColors.text)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = "设置聊天主题",
style = androidx.compose.ui.text.TextStyle(
color = AppColors.text,
fontSize = 16.sp
),
modifier = Modifier.weight(1f)
)
Image(
painter = painterResource(R.drawable.rider_pro_back_icon),
modifier = Modifier.size(16.dp),
contentDescription = null,
colorFilter = ColorFilter.tint(AppColors.secondaryText)
)
}
Spacer(modifier = Modifier.height(1.dp))
// 群聊成员
Row(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(8.dp))
.background(AppColors.decentBackground)
.padding(16.dp)
.noRippleClickable {
// TODO: 实现查看群聊成员功能
},
verticalAlignment = Alignment.CenterVertically
) {
Image(
painter = painterResource(R.drawable.rider_pro_back_icon),
modifier = Modifier.size(24.dp),
contentDescription = null,
colorFilter = ColorFilter.tint(AppColors.text)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = "群聊成员 (${viewModel.groupInfo?.memberCount ?: 0})",
style = androidx.compose.ui.text.TextStyle(
color = AppColors.text,
fontSize = 16.sp
),
modifier = Modifier.weight(1f)
)
Image(
painter = painterResource(R.drawable.rider_pro_back_icon),
modifier = Modifier.size(16.dp),
contentDescription = null,
colorFilter = ColorFilter.tint(AppColors.secondaryText)
)
}
}
// 成员列表
if (viewModel.groupInfo?.members?.isNotEmpty() == true) {
item {
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "群成员",
style = androidx.compose.ui.text.TextStyle(
color = AppColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.Bold
)
)
}
items(viewModel.groupInfo!!.members) { member ->
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
CustomAsyncImage(
imageUrl = member.avatar,
modifier = Modifier
.size(40.dp)
.clip(CircleShape),
contentDescription = "成员头像"
)
Spacer(modifier = Modifier.width(12.dp))
Column {
Text(
text = member.nickname,
style = androidx.compose.ui.text.TextStyle(
color = AppColors.text,
fontSize = 16.sp
)
)
if (member.isOwner) {
Text(
text = "群主",
style = androidx.compose.ui.text.TextStyle(
color = AppColors.secondaryText,
fontSize = 12.sp
)
)
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,60 @@
package com.aiosman.ravenow.ui.group
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.entity.GroupInfo
import com.aiosman.ravenow.entity.GroupMember
import kotlinx.coroutines.launch
class GroupChatInfoViewModel(
private val groupId: String
) : ViewModel() {
var groupInfo by mutableStateOf<GroupInfo?>(null)
var isLoading by mutableStateOf(false)
var error by mutableStateOf<String?>(null)
init {
loadGroupInfo()
}
private fun loadGroupInfo() {
viewModelScope.launch {
try {
isLoading = true
error = null
// 调用接口获取群聊详情
val response = ApiClient.api.getRoomDetail(trtcId = groupId)
// 使用接口返回的数据
val room = response.body()?.data
groupInfo = room?.let {
GroupInfo(
groupId = groupId,
groupName = it.name,
groupAvatar = room.avatar,
memberCount = room.userCount,
members = listOf(
GroupMember(
userId = room.creator.userId,
nickname = room.creator.profile.nickname,
avatar = room.creator.profile.avatar,
isOwner = true
)
)
)
}
} catch (e: Exception) {
error = e.message ?: "加载失败"
} finally {
isLoading = false
}
}
}
}

View File

@@ -21,8 +21,10 @@ 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
@@ -55,6 +57,7 @@ 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
@@ -66,6 +69,9 @@ 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
@@ -99,6 +105,10 @@ 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) {
@@ -311,12 +321,40 @@ 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

@@ -16,6 +16,8 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.systemBars
@@ -50,6 +52,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.unit.offset
import androidx.lifecycle.viewModelScope
import com.aiosman.ravenow.AppState
import com.aiosman.ravenow.AppStore
@@ -63,8 +66,11 @@ import com.aiosman.ravenow.ui.composables.TabItem
import com.aiosman.ravenow.ui.composables.TabSpacer
import com.aiosman.ravenow.ui.follower.FollowerNoticeViewModel
import com.aiosman.ravenow.ui.index.tabs.message.tab.AgentChatListScreen
import com.aiosman.ravenow.ui.index.tabs.message.tab.AgentChatListViewModel
import com.aiosman.ravenow.ui.index.tabs.message.tab.FriendChatListScreen
import com.aiosman.ravenow.ui.index.tabs.message.tab.FriendChatListViewModel
import com.aiosman.ravenow.ui.index.tabs.message.tab.GroupChatListScreen
import com.aiosman.ravenow.ui.index.tabs.message.tab.GroupChatListViewModel
import com.aiosman.ravenow.ui.like.LikeNoticeViewModel
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
import com.google.accompanist.systemuicontroller.rememberSystemUiController
@@ -77,6 +83,10 @@ import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class)
@Composable
fun NotificationsScreen() {
// 计算总未读消息数
val totalUnreadCount = AgentChatListViewModel.totalUnreadCount +
GroupChatListViewModel.totalUnreadCount +
FriendChatListViewModel.totalUnreadCount
val AppColors = LocalAppTheme.current
val navController = LocalNavController.current
val systemUiController = rememberSystemUiController()
@@ -87,6 +97,12 @@ fun NotificationsScreen() {
MessageListViewModel.viewModelScope.launch {
MessageListViewModel.initData(context, force = true, loadChat = AppState.enableChat)
}
// 刷新群聊列表以更新未读消息数
GroupChatListViewModel.refreshPager(context = context)
// 刷新智能体列表以更新未读消息数
AgentChatListViewModel.refreshPager(context = context)
// 刷新朋友列表以更新未读消息数
FriendChatListViewModel.refreshPager(context = context)
})
val navigationBarPaddings =
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + 48.dp
@@ -94,6 +110,12 @@ fun NotificationsScreen() {
LaunchedEffect(Unit) {
systemUiController.setNavigationBarColor(Color.Transparent)
MessageListViewModel.initData(context, loadChat = AppState.enableChat)
// 初始化群聊列表以获取未读消息数
GroupChatListViewModel.refreshPager(context = context)
// 初始化智能体列表以获取未读消息数
AgentChatListViewModel.refreshPager(context = context)
// 初始化朋友列表以获取未读消息数
FriendChatListViewModel.refreshPager(context = context)
}
Column(
modifier = Modifier
@@ -202,36 +224,83 @@ fun NotificationsScreen() {
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.Bottom
) {
TabItem(
text = stringResource(R.string.chat_ai),
isSelected = pagerState.currentPage == 0,
onClick = {
scope.launch {
pagerState.animateScrollToPage(0)
Box {
TabItem(
text = stringResource(R.string.chat_ai),
isSelected = pagerState.currentPage == 0,
onClick = {
scope.launch {
pagerState.animateScrollToPage(0)
}
}
)
// 智能体未读消息红点
if (AgentChatListViewModel.totalUnreadCount > 0) {
Box(
modifier = Modifier
.size(8.dp)
.background(
color = Color(0xFFFF3B30),
shape = CircleShape
)
.align(Alignment.TopEnd)
.offset(x = 8.dp, y = (-4).dp)
)
}
)
}
TabSpacer()
TabItem(
text = stringResource(R.string.chat_group),
isSelected = pagerState.currentPage == 1,
onClick = {
scope.launch {
pagerState.animateScrollToPage(1)
Box {
TabItem(
text = stringResource(R.string.chat_group),
isSelected = pagerState.currentPage == 1,
onClick = {
scope.launch {
pagerState.animateScrollToPage(1)
}
}
)
// 群聊未读消息红点
if (GroupChatListViewModel.totalUnreadCount > 0) {
Box(
modifier = Modifier
.size(8.dp)
.background(
color = Color(0xFFFF3B30),
shape = CircleShape
)
.align(Alignment.TopEnd)
.offset(x = 8.dp, y = (-4).dp)
)
}
)
}
TabSpacer()
TabItem(
text = stringResource(R.string.chat_friend),
isSelected = pagerState.currentPage == 2,
onClick = {
scope.launch {
pagerState.animateScrollToPage(2)
Box {
TabItem(
text = stringResource(R.string.chat_friend),
isSelected = pagerState.currentPage == 2,
onClick = {
scope.launch {
pagerState.animateScrollToPage(2)
}
}
)
// 朋友未读消息红点
if (FriendChatListViewModel.totalUnreadCount > 0) {
Box(
modifier = Modifier
.size(8.dp)
.background(
color = Color(0xFFFF3B30),
shape = CircleShape
)
.align(Alignment.TopEnd)
.offset(x = 8.dp, y = (-4).dp)
)
}
)
}
}
HorizontalPager(
state = pagerState,

View File

@@ -1,5 +1,6 @@
package com.aiosman.ravenow.ui.index.tabs.message.tab
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -29,7 +30,9 @@ 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.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
@@ -38,6 +41,7 @@ import androidx.compose.ui.res.stringResource
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.modifiers.noRippleClickable
@@ -82,8 +86,16 @@ fun AgentChatListScreen() {
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(80.dp))
Image(
painter = painterResource(id = R.mipmap.icon_agent_chat_empty),
contentDescription = "null data",
modifier = Modifier
.size(140.dp)
)
Spacer(modifier = Modifier.height(24.dp))
Text(
text = stringResource(R.string.agent_chat_empty_title),
color = AppColors.text,
@@ -93,7 +105,7 @@ fun AgentChatListScreen() {
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.agent_chat_empty_subtitle),
color = AppColors.secondaryText,
color = AppColors.text,
fontSize = 14.sp
)
}

View File

@@ -92,6 +92,10 @@ object AgentChatListViewModel : ViewModel() {
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) {
@@ -200,10 +204,10 @@ object AgentChatListViewModel : ViewModel() {
}
}
fun createSingleChat(
openId: String,
trtcId: String,
) {
viewModelScope.launch {
val response = ApiClient.api.createSingleChat(SingleChatRequestBody(generateText = openId))
val response = ApiClient.api.createSingleChat(SingleChatRequestBody(agentTrtcId = trtcId))
}
}

View File

@@ -1,5 +1,6 @@
package com.aiosman.ravenow.ui.index.tabs.message.tab
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
@@ -20,6 +21,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
@@ -68,6 +70,15 @@ fun FriendChatListScreen() {
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(80.dp))
Image(
painter = painterResource(id = R.mipmap.icon_friend_chat_empty),
contentDescription = "null data",
modifier = Modifier
.size(140.dp)
)
Spacer(modifier = Modifier.height(24.dp))
Text(
text = stringResource(R.string.friend_chat_empty_title),
color = AppColors.text,
@@ -77,7 +88,7 @@ fun FriendChatListScreen() {
Spacer(modifier = Modifier.height(8.dp))
Text(
text = stringResource(R.string.friend_chat_empty_subtitle),
color = AppColors.secondaryText,
color = AppColors.text,
fontSize = 14.sp
)
}

View File

@@ -86,6 +86,10 @@ object FriendChatListViewModel : ViewModel() {
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

@@ -1,6 +1,8 @@
package com.aiosman.ravenow.ui.index.tabs.message.tab
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
@@ -21,6 +23,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
@@ -78,16 +81,29 @@ fun GroupChatListScreen() {
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(80.dp))
Image(
painter = painterResource(id = if (isSystemInDarkTheme()) {
R.mipmap.icon_group_chat_empty // 深色模式图片
} else {
R.mipmap.icon_group_chat_empty // 浅色模式图片
}),
contentDescription = "null data",
modifier = Modifier
.size(140.dp)
)
Spacer(modifier = Modifier.height(24.dp))
Text(
text = "暂无群聊",
text = stringResource(R.string.group_chat_empty_title),
color = AppColors.text,
fontSize = 16.sp,
fontWeight = FontWeight.W600
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "您还没有加入任何群聊",
color = AppColors.secondaryText,
text = stringResource(R.string.group_chat_empty_subtitle),
color = AppColors.text,
fontSize = 14.sp
)
}

View File

@@ -103,6 +103,10 @@ object GroupChatListViewModel : ViewModel() {
var currentPage by mutableStateOf(1)
var error by mutableStateOf<String?>(null)
// 计算群聊总未读消息数
val totalUnreadCount: Int
get() = groupChatList.sumOf { it.unreadCount }
private val pageSize = 20
// 消息监听器

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

@@ -48,6 +48,7 @@ import androidx.compose.ui.unit.sp
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.graphicsLayer
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
import androidx.lifecycle.viewmodel.compose.viewModel
import com.aiosman.ravenow.AppStore
@@ -232,9 +233,9 @@ fun Explore() {
}
@Composable
fun AgentPage(agentItems: List<AgentItem>, page: Int) {
fun AgentPage(agentItems: List<AgentItem>, page: Int, modifier: Modifier = Modifier) {
Column(
modifier = Modifier
modifier = modifier
.fillMaxSize()
.padding(horizontal = 0.dp)
) {
@@ -268,11 +269,27 @@ fun Explore() {
) {
HorizontalPager(
state = pagerState,
modifier = Modifier.fillMaxSize()
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(
agentItems = agentItems.drop(page * itemsPerPage).take(itemsPerPage),
page = page
page = page,
modifier = Modifier
.graphicsLayer {
scaleX = scale
scaleY = scale
}
)
}
}
@@ -410,12 +427,12 @@ fun Explore() {
@Composable
fun BannerCard(bannerItem: BannerItem) {
fun BannerCard(bannerItem: BannerItem, modifier: Modifier = Modifier) {
val AppColors = LocalAppTheme.current
val context = LocalContext.current
Card(
modifier = Modifier
modifier = modifier
.fillMaxSize()
.padding(horizontal = 0.dp),
shape = RoundedCornerShape(20.dp),
@@ -595,15 +612,15 @@ fun Explore() {
) {
// 可以添加更多不同高度的内容项
// 第一块区域
item {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 6.dp),
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceEvenly
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceBetween
) {
// 第一个
// 第一个 - 靠左显示
Column(
modifier = Modifier
.clickable {
@@ -633,69 +650,75 @@ fun Explore() {
)
}
// 第二个
Column(
modifier = Modifier
.clickable {
navController.navigate(
NavigationRoute.AddAgent.route)
},
horizontalAlignment = Alignment.CenterHorizontally
// 中间两个 - 平均分布
Row(
modifier = Modifier.weight(1f),
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.SpaceEvenly
) {
Box(
// 第二个
Column(
modifier = Modifier
.size(64.dp)
.background(Color(0xFF94f9f2), RoundedCornerShape(24.dp)),
contentAlignment = Alignment.Center
.clickable {
navController.navigate(
NavigationRoute.AddAgent.route)
},
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
painter = painterResource(R.mipmap.rider_pro_agent),
contentDescription = "创建智能体",
modifier = Modifier.size(24.dp),
Box(
modifier = Modifier
.size(64.dp)
.background(Color(0xFF94f9f2), RoundedCornerShape(24.dp)),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(R.mipmap.rider_pro_agent),
contentDescription = "创建智能体",
modifier = Modifier.size(24.dp),
)
)
}
Spacer(modifier = Modifier.size(8.dp))
Text(
text = "创建Agent",
fontSize = 12.sp,
color = AppColors.text,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
}
// 第三个
Column(
modifier = Modifier
.clickable {
NewPostViewModel.asNewPost()
navController.navigate("NewPost")
},
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.size(64.dp)
.background(Color(0xFFfafd5d), RoundedCornerShape(24.dp)),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(R.mipmap.rider_pro_release),
contentDescription = "发布动态",
modifier = Modifier.size(24.dp),
)
}
Spacer(modifier = Modifier.size(8.dp))
Text(
text = "发布动态",
fontSize = 12.sp,
color = AppColors.text,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
}
Spacer(modifier = Modifier.size(8.dp))
Text(
text = "创建Agent",
fontSize = 12.sp,
color = AppColors.text,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
}
// 第三个
Column(
modifier = Modifier
.clickable {
NewPostViewModel.asNewPost()
navController.navigate("NewPost")
},
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.size(64.dp)
.background(Color(0xFFfafd5d), RoundedCornerShape(24.dp)),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(R.mipmap.rider_pro_release),
contentDescription = "发布动态",
modifier = Modifier.size(24.dp),
)
}
Spacer(modifier = Modifier.size(8.dp))
Text(
text = "发布动态",
fontSize = 12.sp,
color = AppColors.text,
fontWeight = androidx.compose.ui.text.font.FontWeight.W500
)
}
// 第四个
// 第四个 - 靠右显示
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
@@ -767,10 +790,28 @@ fun Explore() {
) {
HorizontalPager(
state = pagerState,
modifier = Modifier.fillMaxSize()
modifier = Modifier.fillMaxSize(),
contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 4.dp),
) { page ->
val bannerItem = bannerItems[page]
BannerCard(bannerItem = bannerItem)
// 计算当前页面的偏移量
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
}
)
}
}
@@ -807,7 +848,7 @@ fun Explore() {
// 标题
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(bottom = 30.dp)
modifier = Modifier.padding(bottom = 12.dp)
) {
Image(
painter = painterResource(R.mipmap.rider_pro_fire2),
@@ -848,9 +889,9 @@ fun Explore() {
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "推荐给你的Agent",
fontSize = 20.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W900,
text = "推荐给你的智能体",
fontSize = 16.sp,
fontWeight = androidx.compose.ui.text.font.FontWeight.W600,
color = AppColors.text
)
}
@@ -875,7 +916,7 @@ fun Explore() {
Image(
painter = painterResource(R.mipmap.rider_pro_hot_room),
contentDescription = "chat room",
modifier = Modifier.size(28.dp),
modifier = Modifier.size(24.dp),
)
Spacer(modifier = Modifier.width(4.dp))
Text(

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -147,8 +147,8 @@
<string name="chat_friend">朋友</string>
<string name="agent_chat_list_title">智能体聊天</string>
<string name="agent_chat_empty_title">暂无智能体聊天</string>
<string name="agent_chat_empty_subtitle">开始与智能体对话</string>
<string name="agent_chat_empty_title">AI 们在等你开启第一句对话</string>
<string name="agent_chat_empty_subtitle">去首页探索一下,主动发起一场对话</string>
<string name="agent_chat_me_prefix">我: </string>
<string name="agent_chat_image">[图片]</string>
<string name="agent_chat_voice">[语音]</string>
@@ -159,6 +159,9 @@
<string name="agent_chat_load_more_failed">加载更多失败</string>
<string name="agent_chat_user_info_failed">获取用户信息失败: %s</string>
<string name="group_chat_empty_title">没有群聊消息的宇宙太安静了</string>
<string name="group_chat_empty_subtitle">在首页探索感兴趣的主题房间</string>
<string name="friend_chat_empty_title">暂无朋友聊天</string>
<string name="friend_chat_empty_subtitle">开始与朋友对话吧</string>
<string name="friend_chat_me_prefix">我: </string>

View File

@@ -155,6 +155,8 @@
<string name="agent_chat_load_failed">加载失败</string>
<string name="agent_chat_load_more_failed">加载更多失败</string>
<string name="agent_chat_user_info_failed">获取用户信息失败: %s</string>
<string name="group_chat_empty_title">没有群聊消息的宇宙太安静了</string>
<string name="group_chat_empty_subtitle">在首页探索感兴趣的主题房间</string>
<string name="friend_chat_empty_title">暂无朋友聊天</string>
<string name="friend_chat_empty_subtitle">开始与朋友对话吧</string>
<string name="friend_chat_me_prefix">我: </string>