diff --git a/app/src/main/java/com/example/login_v3/data/repository/dm/DM_Basic_Repository.kt b/app/src/main/java/com/example/login_v3/data/repository/dm/DM_Basic_Repository.kt index 8860b6c..5915571 100644 --- a/app/src/main/java/com/example/login_v3/data/repository/dm/DM_Basic_Repository.kt +++ b/app/src/main/java/com/example/login_v3/data/repository/dm/DM_Basic_Repository.kt @@ -175,7 +175,11 @@ class ChatRoomsRepository @Inject constructor( //api get message and push to local - suspend fun refreshChatMessages(roomId: String, cursor: String? = null): Result { + suspend fun refreshChatMessages( + roomId: String, + cursor: String? = null, + limit: Int? = null + ): Result { return try { // 1. 把 cursor 傳給 API val response = api.getChatMessages(roomId, cursor = cursor) 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 b288b84..15b8e53 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 @@ -121,7 +121,7 @@ class ChatViewModel @Inject constructor( private var isLoadingMore = false // 防止重複戳 API // ===================================================================== - // 💡 核心改造一:持續監聽本地資料庫的 Flow + // 💡 核心改造一:持續監聽本地資料庫的 Flow (時序修正版) // ===================================================================== fun loadMessages(roomId: String) { messageListenerJob?.cancel() @@ -155,25 +155,26 @@ class ChatViewModel @Inject constructor( Triple("聊天室", UserStatus.UNKNOWN, R.drawable.avatar_v1) } - // 持續監聽本地資料庫(即使載入更多老訊息,這裡也會自動感應並外發完整的 List) - repository.getChatMessagesFlow(roomId).collect { localMessages -> - _uiState.value = MessagesUiState.Success( - roomTitle = title, - partnerStatus = status, - partnerAvatarUrl = avatarUrl, - messages = localMessages, - currentUserId = currentLoggedInUserId - ) + // 🎯 【關鍵優化】:先啟動資料庫 Flow 的監聽,確保任何寫入都不漏接 + launch { + repository.getChatMessagesFlow(roomId).collect { localMessages -> + _uiState.value = MessagesUiState.Success( + roomTitle = title, + partnerStatus = status, + partnerAvatarUrl = avatarUrl, + messages = localMessages, + currentUserId = currentLoggedInUserId + ) + } } - } - // 🎯 修正:背景首刷,取得第一頁最新訊息,並記錄分頁標記 - viewModelScope.launch { - repository.refreshChatMessages(roomId, cursor = null) // 👈 傳入 null 代表抓最新 + // 🎯 【關鍵優化】:確定開始監聽本地了,這時候才發起網路「首刷同步」 + // 💡 加上 limit = 20 控制每頁數量 + repository.refreshChatMessages(roomId, cursor = null, limit = 20) .onSuccess { response -> - // 🌟 核心:記下這間聊天室第一頁的下一頁鑰匙 this@ChatViewModel.nextCursor = response.nextCursor this@ChatViewModel.hasMore = response.hasMore + Log.d("ChatViewModel", "首刷成功,拿到第一頁 cursor: $nextCursor, hasMore: $hasMore") repository.markAsRead(roomId).onFailure { error -> Log.e("ChatViewModel", "標記已讀失敗: ${error.message}") @@ -186,30 +187,26 @@ class ChatViewModel @Inject constructor( } // ===================================================================== - // 💡 核心新增:往上滑載入更多老訊息 + // 💡 核心新增:往上滑載入更多老訊息 (補上 limit) // ===================================================================== fun loadMoreMessages(roomId: String) { - // 1. 防禦性攔截:如果正在載入中、後端說沒更多了、或是鑰匙是空的,直接收工 if (isLoadingMore || !hasMore || nextCursor.isNullOrBlank()) return isLoadingMore = true Log.d("ChatViewModel", "觸發載入更多,當前 cursor: $nextCursor") viewModelScope.launch { - // 2. 帶著目前最老的 nextCursor 去戳 Repository - repository.refreshChatMessages(roomId, cursor = nextCursor) + // 🎯 補上 limit = 20 傳遞給 Repository 與 API + repository.refreshChatMessages(roomId, cursor = nextCursor, limit = 20) .onSuccess { response -> - // 3. 成功後,更新下一階段的分頁標記 this@ChatViewModel.nextCursor = response.nextCursor this@ChatViewModel.hasMore = response.hasMore - Log.d("ChatViewModel", "載入更多成功,下一頁 cursor: $nextCursor, hasMore: $hasMore") + Log.d("ChatViewModel", "載入更多成功,新 cursor: $nextCursor, hasMore: $hasMore") } .onFailure { error -> Log.e("ChatViewModel", "載入更多老訊息失敗", error) - // 這裡可以選擇不處理,或者透過一個單發的事件(SharedFlow)通知 UI 彈 Toast } - // 4. 解鎖 isLoadingMore = false } }