This commit is contained in:
Eric85710 2026-05-18 15:39:29 +08:00
parent 143f930b47
commit 8bbf1cfb27
3 changed files with 44 additions and 45 deletions

View file

@ -1,5 +1,6 @@
package com.example.login_v3.home.Message.UI.Detail package com.example.login_v3.home.Message.UI.Detail
import android.util.Log
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@ -27,6 +28,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import com.example.login_v3.data.api.api_class.Message import com.example.login_v3.data.api.api_class.Message
@ -40,12 +43,15 @@ fun MessageMessaging(
roomId: String, roomId: String,
navController: NavController, navController: NavController,
onBackClick: () -> Unit, onBackClick: () -> Unit,
viewModel: ChatViewModel = viewModel() viewModel: ChatViewModel = hiltViewModel()
) { ) {
val uiState by viewModel.uiState // 加上 collectAsStateWithLifecycle() 轉換它
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
LaunchedEffect(roomId) { LaunchedEffect(roomId) {
viewModel.loadMessages(roomId) viewModel.loadMessages(roomId)
Log.d("ChatDebug", "UI State 變更為: ${uiState::class.simpleName}")
} }
Scaffold( Scaffold(

View file

@ -87,12 +87,11 @@ sealed class Screen(val route: String) {
object CreateContact : Screen("create_contact") object CreateContact : Screen("create_contact")
object FriendsList : Screen("friends_list") object FriendsList : Screen("friends_list")
object ScanQRcode : Screen("scan_QRcode") object ScanQRcode : Screen("scan_QRcode")
object MessageMessaging : Screen("message_messaging/{roomId}") { object MessageMessaging : Screen("message_messaging?roomId={roomId}") {
// 這是給上一頁 Loaded_Tg_Message 跳轉時產生的真實路徑
fun createRoute(roomId: String): String { fun createRoute(roomId: String): String {
// 建議加上 URL 編碼,防止 roomId 含有斜線或特殊字元導致二次閃退
val encodedId = java.net.URLEncoder.encode(roomId, "UTF-8") val encodedId = java.net.URLEncoder.encode(roomId, "UTF-8")
return "message_messaging/$encodedId" // 2. 修改這裡:帶入對應的格式
return "message_messaging?roomId=$encodedId"
} }
} }
} }
@ -104,41 +103,20 @@ fun Tg_Message(
val navController = rememberNavController() val navController = rememberNavController()
NavHost( NavHost(
navController = navController, navController = navController,
startDestination = Screen.Messages.route, startDestination = Screen.Messages.route,
// 進入時的動畫(新頁面出現)
enterTransition = {
slideIntoContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Left,
animationSpec = tween(700)
)
},
// 退出時的動畫(舊頁面消失)
exitTransition = {
slideOutOfContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Left,
animationSpec = tween(700)
)
},
// 按返回鍵進入時的動畫
popEnterTransition = {
slideIntoContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Right,
animationSpec = tween(700)
)
},
// 按返回鍵退出時的動畫
popExitTransition = {
slideOutOfContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Right,
animationSpec = tween(700)
)
}
) { ) {
// 你的訊息主頁面
// 你的訊息主頁面 // 你的訊息主頁面
composable(Screen.Messages.route) { composable(Screen.Messages.route) {
Loaded_Tg_Message(navController) Loaded_Tg_Message(
navController = navController,
onRoomClick = { roomId ->
// ✅ 使用你寫好的 createRoute(roomId) 帶入參數並導航
val route = Screen.MessageMessaging.createRoute(roomId)
navController.navigate(route)
}
)
} }
// 新建聯絡頁面 // 新建聯絡頁面
@ -160,15 +138,24 @@ fun Tg_Message(
} }
//Message detail //Message detail
// 這樣寫就完全沒問題了!因為 route 內部已經包含了 /{roomId}
composable( composable(
route = Screen.MessageMessaging.route, route = Screen.MessageMessaging.route, // 現在是 "message_messaging?roomId={roomId}"
arguments = listOf( arguments = listOf(
navArgument("roomId") { type = NavType.StringType } navArgument("roomId") {
type = NavType.StringType
nullable = true // 查詢參數建議改為允許為空
defaultValue = "" // 給予預設值
}
) )
) { backStackEntry -> ) { backStackEntry ->
// 安全取出參數 // 這裡維持你寫好的安全解碼邏輯
val roomId = backStackEntry.arguments?.getString("roomId").orEmpty() val encodedRoomId = backStackEntry.arguments?.getString("roomId").orEmpty()
val roomId = try {
java.net.URLDecoder.decode(encodedRoomId, "UTF-8")
} catch (e: Exception) {
encodedRoomId
}
MessageMessaging( MessageMessaging(
roomId = roomId, roomId = roomId,

View file

@ -1,6 +1,7 @@
package com.example.login_v3.home.Message.ViewModel.Detail package com.example.login_v3.home.Message.ViewModel.Detail
import android.util.Log
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.login_v3.data.repository.dm.ChatRoomsRepository import com.example.login_v3.data.repository.dm.ChatRoomsRepository
@ -24,22 +25,27 @@ class ChatViewModel @Inject constructor(
private val repository: ChatRoomsRepository private val repository: ChatRoomsRepository
) : ViewModel() { ) : ViewModel() {
// 1. 使用 MutableStateFlow,並設定初始值
private val _uiState = MutableStateFlow<MessagesUiState>(MessagesUiState.Loading) private val _uiState = MutableStateFlow<MessagesUiState>(MessagesUiState.Loading)
// 2. 使用 asStateFlow() 公開唯讀的 StateFlow
val uiState: StateFlow<MessagesUiState> = _uiState.asStateFlow() val uiState: StateFlow<MessagesUiState> = _uiState.asStateFlow()
fun loadMessages(roomId: String) { fun loadMessages(roomId: String) {
// 🔴 Debug 1: 檢查傳進來的 roomId 是不是正確的,還是空的、被錯誤編碼的?
Log.d("ChatDebug", "ViewModel: loadMessages 開始執行, roomId = '$roomId'")
viewModelScope.launch { viewModelScope.launch {
_uiState.value = MessagesUiState.Loading _uiState.value = MessagesUiState.Loading
repository.getChatMessages(roomId) repository.getChatMessages(roomId)
.onSuccess { response -> .onSuccess { response ->
// 3. 更新 Flow 的值 // 🔴 Debug 2: 檢查後端有沒有正確回傳,數量是多少?
Log.d("ChatDebug", "ViewModel: API 請求成功, 訊息數量 = ${response.messages.size}")
_uiState.value = MessagesUiState.Success(messages = response.messages) _uiState.value = MessagesUiState.Success(messages = response.messages)
} }
.onFailure { exception -> .onFailure { exception ->
// 🔴 Debug 3: 檢查是不是 API 報錯(例如 404, 500)或是解析 JSON 失敗
Log.e("ChatDebug", "ViewModel: API 請求失敗", exception)
_uiState.value = MessagesUiState.Error(message = exception.message ?: "未知錯誤") _uiState.value = MessagesUiState.Error(message = exception.message ?: "未知錯誤")
} }
} }