dm-6
This commit is contained in:
parent
284e89924a
commit
c22bbbcaa0
1 changed files with 125 additions and 68 deletions
|
|
@ -2,6 +2,7 @@ package com.example.login_v3.home.Message.UI
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedContentTransitionScope
|
import androidx.compose.animation.AnimatedContentTransitionScope
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.foundation.Canvas
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
|
|
@ -11,6 +12,7 @@ import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
|
@ -273,7 +275,7 @@ fun Loaded_Tg_Message(
|
||||||
room = room,
|
room = room,
|
||||||
onClick = onRoomClick
|
onClick = onRoomClick
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
Spacer(modifier = Modifier.height(6.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -296,92 +298,147 @@ fun RoomItem(
|
||||||
.clickable { onClick(room.roomId) },
|
.clickable { onClick(room.roomId) },
|
||||||
shape = RoundedCornerShape(16.dp), // 較大的圓角看起來更現代
|
shape = RoundedCornerShape(16.dp), // 較大的圓角看起來更現代
|
||||||
colors = CardDefaults.cardColors(
|
colors = CardDefaults.cardColors(
|
||||||
containerColor = Color.White.copy(alpha = 0.85f) // 半透明白色,透出後方的漸層背景
|
containerColor = Color.Transparent // ✅ 透明背景
|
||||||
),
|
),
|
||||||
elevation = CardDefaults.cardElevation(
|
elevation = CardDefaults.cardElevation(
|
||||||
defaultElevation = 0.dp // 增加輕微陰影
|
defaultElevation = 0.dp // 增加輕微陰影
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Row(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxSize()
|
||||||
.background(Color.Transparent)
|
){
|
||||||
.padding(16.dp), // Card 內部的填充
|
//glass effect
|
||||||
verticalAlignment = Alignment.CenterVertically
|
Box(
|
||||||
) {
|
|
||||||
|
|
||||||
// 1. 頭像
|
|
||||||
val imageUrl = room.roomIconUrl ?: room.partner?.fullContactAvatarUrl
|
|
||||||
AsyncImage(
|
|
||||||
model = imageUrl,
|
|
||||||
contentDescription = "Avatar",
|
|
||||||
contentScale = ContentScale.Crop,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(56.dp) // 稍微加大一點
|
.matchParentSize()
|
||||||
.clip(CircleShape)
|
.blur(10.dp)
|
||||||
.border(1.dp, Color.White, CircleShape) // 頭像加個細白邊
|
)
|
||||||
.background(Color.LightGray)
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.matchParentSize()
|
||||||
|
.background(
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
RoundedCornerShape(16.dp)
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
1.dp,
|
||||||
|
Color.White.copy(alpha = 0.3f),
|
||||||
|
RoundedCornerShape(16.dp)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(16.dp))
|
|
||||||
|
|
||||||
// 2. 中間內容
|
Row(
|
||||||
Column(modifier = Modifier.weight(1f)) {
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
Text(
|
modifier = Modifier.padding(12.dp),
|
||||||
text = room.roomName.orEmpty().ifEmpty {
|
) {
|
||||||
room.partner?.displayName ?: "Unknown"
|
// 1. 頭像
|
||||||
},
|
val imageUrl = room.roomIconUrl ?: room.partner?.fullContactAvatarUrl
|
||||||
style = MaterialTheme.typography.titleMedium,
|
AsyncImage(
|
||||||
fontWeight = FontWeight.Bold,
|
model = imageUrl,
|
||||||
color = Color(0xFF333333),
|
contentDescription = "Avatar",
|
||||||
maxLines = 1,
|
contentScale = ContentScale.Crop,
|
||||||
overflow = TextOverflow.Ellipsis
|
modifier = Modifier
|
||||||
|
.size(56.dp) // 稍微加大一點
|
||||||
|
.clip(CircleShape)
|
||||||
|
.border(1.dp, Color.White, CircleShape) // 頭像加個細白邊
|
||||||
|
.background(Color.LightGray)
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
|
|
||||||
val lastMsgText = when {
|
// 2. 中間內容
|
||||||
room.lastMessage?.isDeleted == true -> "訊息已刪除"
|
Column(
|
||||||
room.lastMessage?.content != null -> room.lastMessage.content
|
modifier = Modifier.weight(1f)
|
||||||
room.lastMessage?.attachment != null -> "[檔案] ${room.lastMessage.attachment.filename}"
|
) {
|
||||||
else -> "尚未有訊息"
|
Text(
|
||||||
|
text = room.roomName.orEmpty().ifEmpty {
|
||||||
|
room.partner?.displayName ?: "Unknown"
|
||||||
|
},
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = Color(0xFF333333),
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
|
||||||
|
val lastMsgText = when {
|
||||||
|
room.lastMessage?.isDeleted == true -> "訊息已刪除"
|
||||||
|
room.lastMessage?.content != null -> room.lastMessage.content
|
||||||
|
room.lastMessage?.attachment != null -> "[檔案] ${room.lastMessage.attachment.filename}"
|
||||||
|
else -> "尚未有訊息"
|
||||||
|
}
|
||||||
|
|
||||||
|
Row() {
|
||||||
|
Text(
|
||||||
|
text = lastMsgText,
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
color = Color.Gray,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
|
||||||
|
if (room.unreadCount > 0) {
|
||||||
|
Badge(
|
||||||
|
containerColor = Color(0xFFDA7029), // 使用你的主橘色
|
||||||
|
contentColor = Color.White
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = if (room.unreadCount > 99) "99+" else room.unreadCount.toString(),
|
||||||
|
modifier = Modifier.padding(horizontal = 4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(2.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
// 3. 右側:時間與未讀計數
|
||||||
text = lastMsgText,
|
Column(
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
verticalArrangement = Arrangement.Center
|
||||||
color = Color.Gray,
|
) {
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 右側:時間與未讀計數
|
val partner = room.partner // 先從 room 取得 partner
|
||||||
Column(
|
if (partner != null) {
|
||||||
horizontalAlignment = Alignment.End,
|
val status = UserStatus.fromString(partner.status)
|
||||||
verticalArrangement = Arrangement.Center
|
if (status != UserStatus.UNKNOWN) {
|
||||||
) {
|
Canvas(
|
||||||
val time = room.lastMessage?.createdAt?.take(10) ?: ""
|
modifier = Modifier
|
||||||
Text(
|
.size(14.dp)
|
||||||
text = time,
|
// 注意:在 Column 中 Alignment.BottomEnd 可能不適用
|
||||||
style = MaterialTheme.typography.labelSmall,
|
// 如果你要讓點跟在文字旁邊,建議用 Box 或是調整 Alignment
|
||||||
color = Color.Gray
|
.border(2.dp, Color.White, CircleShape)
|
||||||
)
|
) {
|
||||||
|
drawCircle(color = status.color)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
}
|
||||||
|
}
|
||||||
if (room.unreadCount > 0) {
|
|
||||||
Badge(
|
|
||||||
containerColor = Color(0xFFDA7029), // 使用你的主橘色
|
|
||||||
contentColor = Color.White
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = if (room.unreadCount > 99) "99+" else room.unreadCount.toString(),
|
|
||||||
modifier = Modifier.padding(horizontal = 4.dp)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class UserStatus(val color: Color) {
|
||||||
|
ONLINE(Color.Green),
|
||||||
|
AWAY(Color.Yellow),
|
||||||
|
OFFLINE(Color.Gray),
|
||||||
|
UNKNOWN(Color.DarkGray);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromString(status: String?): UserStatus {
|
||||||
|
return when (status?.lowercase()) {
|
||||||
|
"online" -> ONLINE
|
||||||
|
"away" -> AWAY
|
||||||
|
"offline" -> OFFLINE
|
||||||
|
else -> UNKNOWN
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue