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> {
|
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 {
|
return try {
|
||||||
val response = api.deleteMessage(roomId, messageId)
|
val response = api.deleteMessage(roomId, messageId)
|
||||||
|
|
||||||
if (response.isSuccessful) {
|
if (response.isSuccessful) {
|
||||||
// 💡 既然刪除了,本地也一併砍掉,UI 就會立刻同步消失
|
// 真正成功了!因為本地已經提早刪除了,所以什麼都不用做,直接回傳 Unit
|
||||||
messageDao.deleteById(messageId)
|
|
||||||
Result.success(Unit)
|
Result.success(Unit)
|
||||||
} else {
|
} 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) {
|
} catch (e: Exception) {
|
||||||
|
// 網路斷線、Timeout 或伺服器崩潰:一樣把備份資料塞回去,讓 UI 訊息彈回來
|
||||||
|
backupEntity?.let { messageDao.insertOrUpdate(it) }
|
||||||
Result.failure(e)
|
Result.failure(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,21 +182,30 @@ class ChatViewModel @Inject constructor(
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
// 💡 核心改造三:刪除訊息
|
// 💡 核心改造三:刪除訊息
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
|
// =====================================================================
|
||||||
|
// 💡 核心改造三:刪除訊息(配合樂觀更新優化)
|
||||||
|
// =====================================================================
|
||||||
fun deleteMessage(roomId: String, messageId: String) {
|
fun deleteMessage(roomId: String, messageId: String) {
|
||||||
|
// 1. 🌟 樂觀更新的核心精神:立刻關閉長按選單(Action Menu)
|
||||||
|
// 因為訊息在下一行就會從資料庫消失,選單如果還開著會點不到東西或出錯
|
||||||
|
clearActionMessage()
|
||||||
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
// 2. 💡 注意:這裡「不要」在 UI 顯示阻擋式的 Loading 轉圈圈。
|
||||||
|
// 這裡的 Loading 狀態只留在背景,或者用於特定的微小 UI 提示(例如標題列小藍點)。
|
||||||
_deleteMessageState.value = DeleteMessageState.Loading
|
_deleteMessageState.value = DeleteMessageState.Loading
|
||||||
|
|
||||||
val result = repository.deleteMessage(roomId, messageId)
|
val result = repository.deleteMessage(roomId, messageId)
|
||||||
|
|
||||||
result.onSuccess {
|
result.onSuccess {
|
||||||
_deleteMessageState.value = DeleteMessageState.Success
|
_deleteMessageState.value = DeleteMessageState.Success
|
||||||
clearActionMessage()
|
// 🌟 刪除成功!本地早就不見了,Flow 也早已更新,這裡乾淨俐落。
|
||||||
|
|
||||||
// 🌟 刪除成功!Repository 已經把本地 Room 的資料刪除
|
|
||||||
// Flow 會自動發送全新的列表給 UI,這裡「完全不需要」再手動 map 改 content 了!
|
|
||||||
}.onFailure { error ->
|
}.onFailure { error ->
|
||||||
Log.e("ChatViewModel", "Delete message failed", error)
|
Log.e("ChatViewModel", "Delete message failed", error)
|
||||||
_deleteMessageState.value = DeleteMessageState.Error(error.message ?: "刪除訊息失敗")
|
_deleteMessageState.value = DeleteMessageState.Error(error.message ?: "刪除訊息失敗")
|
||||||
|
|
||||||
|
// 3. 🌟 失敗處理:因為 Repository 把訊息彈回來了,我們可以讓 UI 知道
|
||||||
|
// 這裡可以透過監聽 deleteMessageState 的 Error,在 Activity/Fragment/Compose 彈出 Toast 提示:「刪除失敗,請檢查網路」
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue