dm-177
This commit is contained in:
parent
1d92471ba1
commit
0e6999f7dd
1 changed files with 49 additions and 20 deletions
|
|
@ -7,12 +7,10 @@ import android.net.Uri
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.provider.OpenableColumns
|
import android.provider.OpenableColumns
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.datastore.core.use
|
|
||||||
import com.example.login_v3.data.api.TecnologiaApi
|
import com.example.login_v3.data.api.TecnologiaApi
|
||||||
import com.example.login_v3.data.api.api_class.ChatRoom
|
import com.example.login_v3.data.api.api_class.ChatRoom
|
||||||
import com.example.login_v3.data.api.api_class.Message
|
import com.example.login_v3.data.api.api_class.Message
|
||||||
import com.example.login_v3.data.api.api_class.MessageReactionUsersResponse
|
import com.example.login_v3.data.api.api_class.Reaction
|
||||||
import com.example.login_v3.data.api.api_class.MessageResponse
|
|
||||||
import com.example.login_v3.data.api.api_class.RoomListResponse
|
import com.example.login_v3.data.api.api_class.RoomListResponse
|
||||||
import com.example.login_v3.data.api.api_class.SendMessageRequest
|
import com.example.login_v3.data.api.api_class.SendMessageRequest
|
||||||
import com.example.login_v3.data.di.ChatWebSocketManager
|
import com.example.login_v3.data.di.ChatWebSocketManager
|
||||||
|
|
@ -20,6 +18,8 @@ import com.example.login_v3.data.repository.basic.TokenManager
|
||||||
import com.example.login_v3.home.Message.ViewModel.Detail.MessageDao
|
import com.example.login_v3.home.Message.ViewModel.Detail.MessageDao
|
||||||
import com.example.login_v3.home.Message.ViewModel.Detail.MessageEntity
|
import com.example.login_v3.home.Message.ViewModel.Detail.MessageEntity
|
||||||
import com.example.login_v3.home.Message.ViewModel.Detail.MessageStatus
|
import com.example.login_v3.home.Message.ViewModel.Detail.MessageStatus
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
@ -44,7 +44,28 @@ import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
import kotlin.io.use
|
import kotlin.io.use
|
||||||
import kotlin.jvm.java
|
import kotlin.jvm.java
|
||||||
import kotlin.use
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class WebSocketEventResponse(
|
||||||
|
@Json(name = "type") val type: String,
|
||||||
|
@Json(name = "payload") val payload: WebSocketMessagePayload? // 🎯 直接強型別對齊
|
||||||
|
)
|
||||||
|
|
||||||
|
// 這是專門給 Socket payload 用的臨時結構,用來解決 room_id 和 chat_room_id 欄位不一致的問題
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class WebSocketMessagePayload(
|
||||||
|
@Json(name = "id") val id: String,
|
||||||
|
@Json(name = "room_id") val roomId: String, // 🎯 完美吃下後端的 room_id
|
||||||
|
@Json(name = "sender_id") val senderId: String,
|
||||||
|
@Json(name = "content") val content: String,
|
||||||
|
@Json(name = "type") val type: String,
|
||||||
|
@Json(name = "created_at") val createdAt: String,
|
||||||
|
@Json(name = "is_edited") val isEdited: Boolean,
|
||||||
|
@Json(name = "is_deleted") val isDeleted: Boolean,
|
||||||
|
@Json(name = "reply_to_id") val replyToId: String? = null,
|
||||||
|
@Json(name = "reactions") val reactions: List<Reaction>? = emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class ChatRoomsRepository @Inject constructor(
|
class ChatRoomsRepository @Inject constructor(
|
||||||
|
|
@ -68,27 +89,35 @@ class ChatRoomsRepository @Inject constructor(
|
||||||
repositoryScope.launch {
|
repositoryScope.launch {
|
||||||
webSocketManager.incomingMessages.collect { jsonString ->
|
webSocketManager.incomingMessages.collect { jsonString ->
|
||||||
try {
|
try {
|
||||||
// 1. 🎯 精準對齊:使用你的 Message::class.java 進行解析
|
// 1. 一口氣全解析完畢(包含外殼與內部的 payload)
|
||||||
val networkMessage = moshi.adapter(Message::class.java).fromJson(jsonString)
|
val event = moshi.adapter(WebSocketEventResponse::class.java).fromJson(jsonString)
|
||||||
|
|
||||||
if (networkMessage != null) {
|
if (event != null && event.type == "new_message" && event.payload != null) {
|
||||||
// 2. 將 Message 轉換為你的 MessageEntity
|
val payload = event.payload
|
||||||
|
|
||||||
|
// 2. 直接拿解析好的強型別物件轉換為 MessageEntity
|
||||||
val entity = MessageEntity(
|
val entity = MessageEntity(
|
||||||
id = networkMessage.id,
|
id = payload.id,
|
||||||
chatRoomId = networkMessage.chatRoomId, // 👈 完美對齊你的欄位名稱
|
chatRoomId = payload.roomId, // 🎯 這裡百分之百能拿到後端的 room_id
|
||||||
senderId = networkMessage.senderId,
|
senderId = payload.senderId,
|
||||||
content = networkMessage.content,
|
content = payload.content,
|
||||||
type = networkMessage.type,
|
type = payload.type,
|
||||||
createdAt = networkMessage.createdAt,
|
createdAt = payload.createdAt,
|
||||||
isEdited = networkMessage.isEdited,
|
isEdited = payload.isEdited,
|
||||||
isDeleted = networkMessage.isDeleted,
|
isDeleted = payload.isDeleted,
|
||||||
replyToId = networkMessage.replyToId,
|
replyToId = payload.replyToId,
|
||||||
status = MessageStatus.SUCCESS, // WebSocket 推過來的必定是成功發送的
|
status = MessageStatus.SUCCESS,
|
||||||
reactions = networkMessage.reactions
|
reactions = payload.reactions
|
||||||
)
|
)
|
||||||
|
|
||||||
// 3. 寫入本地資料庫,觸發 UI Flow 更新
|
// 3. 寫入本地資料庫
|
||||||
messageDao.insertOrUpdate(entity)
|
messageDao.insertOrUpdate(entity)
|
||||||
|
Log.d("ChatRoomsRepository", "WebSocket 訊息成功寫入資料庫: ${entity.content}")
|
||||||
|
|
||||||
|
} else if (event?.type == "dm:typing") {
|
||||||
|
// 💡 如果未來想要解析 typing 狀態,你可以另外把 event.payload 轉成 Map 來拿資料,因為 typing 的 payload 結構不同
|
||||||
|
// 由於我們把外層改成了 WebSocketMessagePayload?,若 type 是 dm:typing,外層依然可以解析,但 payload 會是 null 或解析失敗
|
||||||
|
// 如果你同時想處理 typing,可以用 `moshi.adapter(Map::class.java)` 單獨處理該事件。
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("ChatRoomsRepository", "解析或寫入 WebSocket 即時訊息失敗", e)
|
Log.e("ChatRoomsRepository", "解析或寫入 WebSocket 即時訊息失敗", e)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue