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

View file

@ -87,12 +87,11 @@ 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/{roomId}") {
// 這是給上一頁 Loaded_Tg_Message 跳轉時產生的真實路徑
object MessageMessaging : Screen("message_messaging?roomId={roomId}") {
fun createRoute(roomId: String): String {
// 建議加上 URL 編碼,防止 roomId 含有斜線或特殊字元導致二次閃退
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()
NavHost(
navController = navController,
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) {
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
// 這樣寫就完全沒問題了!因為 route 內部已經包含了 /{roomId}
composable(
route = Screen.MessageMessaging.route,
route = Screen.MessageMessaging.route, // 現在是 "message_messaging?roomId={roomId}"
arguments = listOf(
navArgument("roomId") { type = NavType.StringType }
navArgument("roomId") {
type = NavType.StringType
nullable = true // 查詢參數建議改為允許為空
defaultValue = "" // 給予預設值
}
)
) { 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(
roomId = roomId,

View file

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