diff --git a/app/src/main/java/com/example/login_v3/home/Message/UI/Detail/Message_Messaging.kt b/app/src/main/java/com/example/login_v3/home/Message/UI/Detail/Message_Messaging.kt index 10e4cc8..d8caed2 100644 --- a/app/src/main/java/com/example/login_v3/home/Message/UI/Detail/Message_Messaging.kt +++ b/app/src/main/java/com/example/login_v3/home/Message/UI/Detail/Message_Messaging.kt @@ -1,6 +1,7 @@ package com.example.login_v3.home.Message.UI.Detail import android.util.Log +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -18,6 +19,7 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.AccountCircle import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api @@ -32,11 +34,15 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue 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.layout.ContentScale import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController +import coil.compose.AsyncImage +import com.example.login_v3.R import com.example.login_v3.data.api.api_class.Message import com.example.login_v3.home.Message.ViewModel.Detail.ChatViewModel import com.example.login_v3.home.Message.ViewModel.Detail.MessagesUiState @@ -71,6 +77,15 @@ fun MessageMessaging( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp) ) { + //avatar + if (uiState is MessagesUiState.Success) { + val successState = uiState as MessagesUiState.Success + UserAvatar( + avatarUrl = successState.partnerAvatarUrl, + modifier = Modifier.size(36.dp) // 適中的 TopBar 頭像大小 + ) + } + Text(text = topBarTitle) // ✨ 如果是 Success 狀態,且對方是在線狀態(ONLINE),就顯示綠色小圓點 @@ -88,14 +103,6 @@ fun MessageMessaging( } } } - }, - navigationIcon = { - IconButton(onClick = onBackClick) { - Icon( - imageVector = Icons.Default.ArrowBack, - contentDescription = "返回" - ) - } } ) } @@ -115,8 +122,10 @@ fun MessageMessaging( if (state.messages.isEmpty()) { Text("目前沒有新訊息") } else { - // ⚠️ 記得把原來的 state.messages 傳進去 - MessageList(messages = state.messages) + MessageList( + messages = state.messages, + partnerAvatarUrl = state.partnerAvatarUrl + ) } } is MessagesUiState.Error -> { @@ -132,6 +141,7 @@ fun MessageMessaging( @Composable fun MessageList( + partnerAvatarUrl: Any?, messages: List, modifier: Modifier = Modifier ) { @@ -144,7 +154,11 @@ fun MessageList( ) { items(messages) { message -> val isMe = message.senderId == currentUserId - MessageRow(message = message, isMe = isMe) + MessageRow( + message = message, + partnerAvatarUrl = partnerAvatarUrl, + isMe = isMe + ) } } } @@ -152,12 +166,23 @@ fun MessageList( @Composable fun MessageRow( message: Message, - isMe: Boolean + isMe: Boolean, + partnerAvatarUrl: Any? ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = if (isMe) Arrangement.End else Arrangement.Start ) { + // ✨ 如果是對方發的訊息,在對話框左邊顯示頭像 + if (!isMe) { + UserAvatar( + avatarUrl = partnerAvatarUrl, + modifier = Modifier + .padding(end = 8.dp) + .size(32.dp) // 訊息旁的頭像稍微小一點 + ) + } + Box( modifier = Modifier .widthIn(max = 280.dp) @@ -187,4 +212,20 @@ fun MessageRow( } } } +} + + +@Composable +fun UserAvatar( + avatarUrl: Any?, // ✨ 改成 Any? + modifier: Modifier = Modifier +) { + AsyncImage( + model = avatarUrl ?: R.drawable.avatar_v1, // 如果為 null,就用預設圖 + contentDescription = "用戶頭像", + modifier = modifier + .background(Color.LightGray, shape = CircleShape) + .clip(CircleShape), + contentScale = ContentScale.Crop + ) } \ No newline at end of file diff --git a/app/src/main/java/com/example/login_v3/home/Message/ViewModel/Detail/Message_Messaging_ViewModel.kt b/app/src/main/java/com/example/login_v3/home/Message/ViewModel/Detail/Message_Messaging_ViewModel.kt index 6658d76..f58adf3 100644 --- a/app/src/main/java/com/example/login_v3/home/Message/ViewModel/Detail/Message_Messaging_ViewModel.kt +++ b/app/src/main/java/com/example/login_v3/home/Message/ViewModel/Detail/Message_Messaging_ViewModel.kt @@ -4,11 +4,13 @@ package com.example.login_v3.home.Message.ViewModel.Detail import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.example.login_v3.R import com.example.login_v3.data.repository.dm.ChatRoomsRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import javax.inject.Inject import com.example.login_v3.data.api.api_class.Message +import com.example.login_v3.data.api.api_class.fullContactAvatarUrl import com.example.login_v3.home.Message.ViewModel.UserStatus import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -20,8 +22,10 @@ sealed interface MessagesUiState { data class Success( val roomTitle: String, val partnerStatus: UserStatus, + val partnerAvatarUrl: Any?, val messages: List ) : MessagesUiState + data class Error(val message: String) : MessagesUiState } @@ -46,18 +50,22 @@ class ChatViewModel @Inject constructor( // 2. 根據房間資訊決定標題邏輯 val room = roomResult.getOrNull() - val (title, status) = if (room != null) { + // ✨ 這裡改用 Any? 來接收擴充屬性的結果 + val (title, status, avatarUrl: Any?) = if (room != null) { val name = room.partner?.displayName ?: room.partner?.username ?: "未知用戶" val userStatus = UserStatus.fromString(room.partner?.status) - Pair(name, userStatus) + // 👇 直接呼叫你寫好的擴充屬性 + val avatar = room.partner?.fullContactAvatarUrl + Triple(name, userStatus, avatar) } else { - // 如果真的拿不到房間資訊,給個安全預設值 - Pair("聊天室", UserStatus.UNKNOWN) + // 如果沒有房間資訊,就給預設的頭像資源 + Triple("聊天室", UserStatus.UNKNOWN, R.drawable.avatar_v1) } _uiState.value = MessagesUiState.Success( roomTitle = title, partnerStatus = status, + partnerAvatarUrl = avatarUrl, // ✨ 這裡就會是完整的網址或 R.drawable.avatar_v1 messages = messagesResponse.messages )