dm-105
This commit is contained in:
parent
6d9c94b12e
commit
aee829876f
2 changed files with 40 additions and 8 deletions
|
|
@ -374,18 +374,41 @@ class ChatRoomsRepository @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
// 刪除訊息
|
||||
|
||||
// 刪除訊息(樂觀更新版本)
|
||||
suspend fun deleteMessage(roomId: String, messageId: String): Result<Unit> {
|
||||
// 1. 先從本地資料庫撈出原本的訊息作為備份
|
||||
val backupEntity = try {
|
||||
messageDao.getMessageById(messageId)
|
||||
} catch (e: Exception) {
|
||||
null // 如果本地查詢就失敗,雖然機率極低,但我們還是設為 null 防呆
|
||||
}
|
||||
|
||||
// 2. 樂觀更新:立刻從本地砍掉,UI 的 Flow 會在「一瞬間」同步消失,體驗極佳
|
||||
try {
|
||||
messageDao.deleteById(messageId)
|
||||
} catch (e: Exception) {
|
||||
// 如果本地 Room 刪除指令本身就失敗,直接回傳錯誤,不繼續往下戳 API
|
||||
return Result.failure(e)
|
||||
}
|
||||
|
||||
// 3. 呼叫後端 API 進行實際刪除
|
||||
return try {
|
||||
val response = api.deleteMessage(roomId, messageId)
|
||||
|
||||
if (response.isSuccessful) {
|
||||
// 💡 既然刪除了,本地也一併砍掉,UI 就會立刻同步消失
|
||||
messageDao.deleteById(messageId)
|
||||
// 真正成功了!因為本地已經提早刪除了,所以什麼都不用做,直接回傳 Unit
|
||||
Result.success(Unit)
|
||||
} else {
|
||||
Result.failure(Exception("Delete failed"))
|
||||
// 後端回報失敗(例如:沒權限、訊息已被他人刪除):把剛才備份的資料塞回去
|
||||
backupEntity?.let { messageDao.insertOrUpdate(it) }
|
||||
|
||||
val errorMsg = response.errorBody()?.string() ?: "未知錯誤"
|
||||
Result.failure(Exception("刪除失敗,錯誤碼: ${response.code()}, 訊息: $errorMsg"))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// 網路斷線、Timeout 或伺服器崩潰:一樣把備份資料塞回去,讓 UI 訊息彈回來
|
||||
backupEntity?.let { messageDao.insertOrUpdate(it) }
|
||||
Result.failure(e)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,21 +182,30 @@ class ChatViewModel @Inject constructor(
|
|||
// =====================================================================
|
||||
// 💡 核心改造三:刪除訊息
|
||||
// =====================================================================
|
||||
// =====================================================================
|
||||
// 💡 核心改造三:刪除訊息(配合樂觀更新優化)
|
||||
// =====================================================================
|
||||
fun deleteMessage(roomId: String, messageId: String) {
|
||||
// 1. 🌟 樂觀更新的核心精神:立刻關閉長按選單(Action Menu)
|
||||
// 因為訊息在下一行就會從資料庫消失,選單如果還開著會點不到東西或出錯
|
||||
clearActionMessage()
|
||||
|
||||
viewModelScope.launch {
|
||||
// 2. 💡 注意:這裡「不要」在 UI 顯示阻擋式的 Loading 轉圈圈。
|
||||
// 這裡的 Loading 狀態只留在背景,或者用於特定的微小 UI 提示(例如標題列小藍點)。
|
||||
_deleteMessageState.value = DeleteMessageState.Loading
|
||||
|
||||
val result = repository.deleteMessage(roomId, messageId)
|
||||
|
||||
result.onSuccess {
|
||||
_deleteMessageState.value = DeleteMessageState.Success
|
||||
clearActionMessage()
|
||||
|
||||
// 🌟 刪除成功!Repository 已經把本地 Room 的資料刪除
|
||||
// Flow 會自動發送全新的列表給 UI,這裡「完全不需要」再手動 map 改 content 了!
|
||||
// 🌟 刪除成功!本地早就不見了,Flow 也早已更新,這裡乾淨俐落。
|
||||
}.onFailure { error ->
|
||||
Log.e("ChatViewModel", "Delete message failed", error)
|
||||
_deleteMessageState.value = DeleteMessageState.Error(error.message ?: "刪除訊息失敗")
|
||||
|
||||
// 3. 🌟 失敗處理:因為 Repository 把訊息彈回來了,我們可以讓 UI 知道
|
||||
// 這裡可以透過監聽 deleteMessageState 的 Error,在 Activity/Fragment/Compose 彈出 Toast 提示:「刪除失敗,請檢查網路」
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue