This commit is contained in:
Eric85710 2026-06-29 14:48:28 +08:00
parent a11db10fca
commit a2fc422519

View file

@ -15,15 +15,20 @@ import com.example.login_v3.data.api.api_class.MessageReactionUsersResponse
import com.example.login_v3.data.api.api_class.MessageResponse 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.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.Moshi
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -36,15 +41,67 @@ import java.util.UUID
import javax.inject.Inject 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.use import kotlin.use
@Singleton @Singleton
class ChatRoomsRepository @Inject constructor( class ChatRoomsRepository @Inject constructor(
private val api: TecnologiaApi, private val api: TecnologiaApi,
private val messageDao: MessageDao, private val messageDao: MessageDao,
private val webSocketManager: ChatWebSocketManager, // 👈 1. 注入 Socket 管理器
private val moshi: Moshi, // 👈 用於解析 Socket 傳來的 JSON
@ApplicationContext private val context: Context // 注入 ApplicationContext 用於處理 Uri 檔案 @ApplicationContext private val context: Context // 注入 ApplicationContext 用於處理 Uri 檔案
) { ) {
// 建立一個跟著 Repository 生命週期走的 Scope
private val repositoryScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
init {
// 👈 2. 在初始化時,開始默默監聽全域的 WebSocket 訊息
observeWebSocketIncomingData()
}
private fun observeWebSocketIncomingData() {
repositoryScope.launch {
webSocketManager.incomingMessages.collect { jsonString ->
try {
// 1. 🎯 精準對齊:使用你的 Message::class.java 進行解析
val networkMessage = moshi.adapter(Message::class.java).fromJson(jsonString)
if (networkMessage != null) {
// 2. 將 Message 轉換為你的 MessageEntity
val entity = MessageEntity(
id = networkMessage.id,
chatRoomId = networkMessage.chatRoomId, // 👈 完美對齊你的欄位名稱
senderId = networkMessage.senderId,
content = networkMessage.content,
type = networkMessage.type,
createdAt = networkMessage.createdAt,
isEdited = networkMessage.isEdited,
isDeleted = networkMessage.isDeleted,
replyToId = networkMessage.replyToId,
status = MessageStatus.SUCCESS, // WebSocket 推過來的必定是成功發送的
reactions = networkMessage.reactions
)
// 3. 寫入本地資料庫,觸發 UI Flow 更新
messageDao.insertOrUpdate(entity)
}
} catch (e: Exception) {
Log.e("ChatRoomsRepository", "解析或寫入 WebSocket 即時訊息失敗", e)
}
}
}
}
// 👈 4. 新增:提供給 ViewModel 在進入聊天室時呼叫的啟動連線功能
fun startChatSession(roomId: String) {
val webSocketUrl = "wss://tg.technologia-tw.com/api/ws?token=\$jwt"
// 2. 啟動連線
webSocketManager.connect(webSocketUrl)
}
suspend fun fetchRooms(): Result<RoomListResponse> { suspend fun fetchRooms(): Result<RoomListResponse> {
return try { return try {
val response = api.getChatRooms() val response = api.getChatRooms()