消息列表和聊天时调整

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

@@ -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
}