dm-15
This commit is contained in:
parent
143f930b47
commit
8bbf1cfb27
3 changed files with 44 additions and 45 deletions
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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 ?: "未知錯誤")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue