dm-13
This commit is contained in:
parent
b7ae279347
commit
003d742a01
2 changed files with 171 additions and 14 deletions
|
|
@ -1,23 +1,149 @@
|
|||
package com.example.login_v3.home.Message.UI.Detail
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
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
|
||||
import com.example.login_v3.navigation.Screen
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun MessageMessaging(
|
||||
navController: NavController
|
||||
roomId: String,
|
||||
navController: NavController,
|
||||
onBackClick: () -> Unit,
|
||||
viewModel: ChatViewModel = viewModel()
|
||||
) {
|
||||
Column(
|
||||
val uiState by viewModel.uiState
|
||||
|
||||
LaunchedEffect(roomId) {
|
||||
viewModel.loadMessages(roomId)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text("聊天室 ($roomId)") },
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onBackClick) {
|
||||
Text("<")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
.padding(innerPadding),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(text = "MessageMessaging")
|
||||
when (val state = uiState) {
|
||||
is MessagesUiState.Loading -> {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
is MessagesUiState.Success -> {
|
||||
if (state.messages.isEmpty()) {
|
||||
Text("目前沒有新訊息")
|
||||
} else {
|
||||
MessageList(messages = state.messages)
|
||||
}
|
||||
}
|
||||
is MessagesUiState.Error -> {
|
||||
Text(
|
||||
text = "載入失敗:${state.message}",
|
||||
color = MaterialTheme.colorScheme.error
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MessageList(
|
||||
messages: List<Message>, // 這裡是正確的 Message
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val currentUserId = "user_123"
|
||||
|
||||
LazyColumn(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
// items 內部拿到的 message 會依循 List<Message> 的型態
|
||||
items(messages) { message ->
|
||||
val isMe = message.senderId == currentUserId
|
||||
MessageRow(message = message, isMe = isMe)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MessageRow(
|
||||
message: Message, // ✅ 修正這裡:將 Screen.Message 改為 Message
|
||||
isMe: Boolean
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = if (isMe) Arrangement.End else Arrangement.Start
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.widthIn(max = 280.dp)
|
||||
.background(
|
||||
color = if (isMe) Color(0xFFDCF8C6) else Color(0xFFECEFF1),
|
||||
shape = RoundedCornerShape(
|
||||
topStart = 12.dp,
|
||||
topEnd = 12.dp,
|
||||
bottomStart = if (isMe) 12.dp else 0.dp,
|
||||
bottomEnd = if (isMe) 0.dp else 12.dp
|
||||
)
|
||||
)
|
||||
.padding(horizontal = 12.dp, vertical = 8.dp)
|
||||
) {
|
||||
Column {
|
||||
if (!isMe) {
|
||||
Text(
|
||||
text = message.senderId, // ✅ 這樣型態對了,就能抓到欄位了!
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = Color.Gray
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = message.content, // ✅ 這樣型態對了,就能抓到欄位了!
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.example.login_v3.home.Message.UI
|
||||
|
||||
import android.R.attr.type
|
||||
import androidx.compose.animation.AnimatedContentTransitionScope
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.Canvas
|
||||
|
|
@ -65,9 +66,11 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import androidx.compose.ui.unit.sp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.navigation.navArgument
|
||||
import coil.compose.AsyncImage
|
||||
import com.example.login_v3.data.api.api_class.ChatRoom
|
||||
import com.example.login_v3.data.api.api_class.fullContactAvatarUrl
|
||||
|
|
@ -84,7 +87,14 @@ sealed class Screen(val route: String) {
|
|||
object CreateContact : Screen("create_contact")
|
||||
object FriendsList : Screen("friends_list")
|
||||
object ScanQRcode : Screen("scan_QRcode")
|
||||
object MessageMessaging : Screen("Message_Messaging")
|
||||
object MessageMessaging : Screen("message_messaging/{roomId}") {
|
||||
// 這是給上一頁 Loaded_Tg_Message 跳轉時產生的真實路徑
|
||||
fun createRoute(roomId: String): String {
|
||||
// 建議加上 URL 編碼,防止 roomId 含有斜線或特殊字元導致二次閃退
|
||||
val encodedId = java.net.URLEncoder.encode(roomId, "UTF-8")
|
||||
return "message_messaging/$encodedId"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -94,6 +104,7 @@ fun Tg_Message(
|
|||
val navController = rememberNavController()
|
||||
|
||||
NavHost(
|
||||
|
||||
navController = navController,
|
||||
startDestination = Screen.Messages.route,
|
||||
// 進入時的動畫(新頁面出現)
|
||||
|
|
@ -149,9 +160,25 @@ fun Tg_Message(
|
|||
}
|
||||
|
||||
//Message detail
|
||||
composable(Screen.MessageMessaging.route) {
|
||||
MessageMessaging(navController)
|
||||
// 這樣寫就完全沒問題了!因為 route 內部已經包含了 /{roomId}
|
||||
composable(
|
||||
route = Screen.MessageMessaging.route,
|
||||
arguments = listOf(
|
||||
navArgument("roomId") { type = NavType.StringType }
|
||||
)
|
||||
) { backStackEntry ->
|
||||
// 安全取出參數
|
||||
val roomId = backStackEntry.arguments?.getString("roomId").orEmpty()
|
||||
|
||||
MessageMessaging(
|
||||
roomId = roomId,
|
||||
navController = navController,
|
||||
onBackClick = {
|
||||
navController.popBackStack()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -279,10 +306,10 @@ fun Loaded_Tg_Message(
|
|||
key = { it.roomId } // 增加效能,防止列表閃爍
|
||||
) { room ->
|
||||
RoomItem(
|
||||
navController = navController,
|
||||
room = room,
|
||||
onClick = {
|
||||
onRoomClick(room.roomId) // 執行原本的點擊邏輯 (依你的定義傳入對應的 String)
|
||||
navController.navigate(Screen.MessageMessaging.route) // 執行導頁
|
||||
onRoomClick(room.roomId)
|
||||
}
|
||||
)
|
||||
Spacer(modifier = Modifier.height(6.dp))
|
||||
|
|
@ -298,6 +325,7 @@ fun Loaded_Tg_Message(
|
|||
|
||||
@Composable
|
||||
fun RoomItem(
|
||||
navController: NavController,
|
||||
room: ChatRoom,
|
||||
onClick: (String) -> Unit
|
||||
) {
|
||||
|
|
@ -305,7 +333,10 @@ fun RoomItem(
|
|||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 12.dp, vertical = 6.dp) // 增加外邊距,讓 Card 之間有呼吸感
|
||||
.clickable { onClick(room.roomId) },
|
||||
.clickable {
|
||||
// 💡 修改這裡:動態帶入真實的 roomId
|
||||
navController.navigate(Screen.MessageMessaging.createRoute(room.roomId))
|
||||
},
|
||||
shape = RoundedCornerShape(16.dp), // 較大的圓角看起來更現代
|
||||
colors = CardDefaults.cardColors(
|
||||
containerColor = Color.Transparent // ✅ 透明背景
|
||||
|
|
|
|||
Loading…
Reference in a new issue