diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/TalkApi.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/TalkApi.kt index 74d1cc3b..4549ebd5 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/TalkApi.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/TalkApi.kt @@ -4,6 +4,7 @@ import io.reactivex.rxjava3.core.Single import kr.co.vividnext.sodalive.chat.talk.room.ChatMessagePurchaseRequest import kr.co.vividnext.sodalive.chat.talk.room.ChatMessagesResponse import kr.co.vividnext.sodalive.chat.talk.room.ChatRoomEnterResponse +import kr.co.vividnext.sodalive.chat.talk.room.ChatRoomResetRequest import kr.co.vividnext.sodalive.chat.talk.room.CreateChatRoomRequest import kr.co.vividnext.sodalive.chat.talk.room.CreateChatRoomResponse import kr.co.vividnext.sodalive.chat.talk.room.SendChatMessageResponse @@ -35,7 +36,8 @@ interface TalkApi { @POST("/api/chat/room/{roomId}/reset") fun resetChatRoom( @Header("Authorization") authHeader: String, - @Path("roomId") roomId: Long + @Path("roomId") roomId: Long, + @Body request: ChatRoomResetRequest ): Single> // 통합 채팅방 입장 API diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRepository.kt index ea07006b..641e8b04 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRepository.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRepository.kt @@ -43,7 +43,13 @@ class ChatRepository( .flatMap { response -> // 1) 로컬에 사용자 메시지 상태를 SENT로 업데이트 val updateStatus = Completable.fromAction { - kotlinx.coroutines.runBlocking { chatDao.updateStatusByLocalId(roomId, localId, MessageStatus.SENT.name) } + kotlinx.coroutines.runBlocking { + chatDao.updateStatusByLocalId( + roomId, + localId, + MessageStatus.SENT.name + ) + } } // 2) 서버 응답 메시지들을 로컬 DB에 저장(중복 방지: 동일 ID는 REPLACE) val insertServers = Completable.fromAction { @@ -86,8 +92,16 @@ class ChatRepository( * 통합 채팅방 입장: 서버 캐릭터 정보 + 최신 메시지 수신 후 로컬 DB 업데이트 * - 로컬 데이터가 없더라도 서버 응답을 기준으로 동기화 */ - fun enterChatRoom(token: String, roomId: Long, characterImageId: Long?): Single { - return talkApi.enterChatRoom(authHeader = token, roomId = roomId, characterImageId = characterImageId) + fun enterChatRoom( + token: String, + roomId: Long, + characterImageId: Long? + ): Single { + return talkApi.enterChatRoom( + authHeader = token, + roomId = roomId, + characterImageId = characterImageId + ) .subscribeOn(Schedulers.io()) .flatMap { response -> val data = ensureSuccess(response) @@ -106,7 +120,12 @@ class ChatRepository( * 점진적 메시지 로딩: 커서 기반으로 이전 메시지를 조회 */ fun loadMoreMessages(token: String, roomId: Long, cursor: Long?): Single { - return talkApi.getChatRoomMessages(authHeader = token, roomId = roomId, cursor = cursor, limit = 20) + return talkApi.getChatRoomMessages( + authHeader = token, + roomId = roomId, + cursor = cursor, + limit = 20 + ) .subscribeOn(Schedulers.io()) .flatMap { response -> val data = ensureMessagesSuccess(response) @@ -132,10 +151,20 @@ class ChatRepository( /** * localId 기반 상태 업데이트(SENDING→SENT/FAILED) */ - fun updateMessageStatusByLocalId(roomId: Long, localId: String, newStatus: MessageStatus): Completable { + fun updateMessageStatusByLocalId( + roomId: Long, + localId: String, + newStatus: MessageStatus + ): Completable { return Completable.fromAction { // enum을 문자열로 변환하여 쿼리 파라미터로 전달 - kotlinx.coroutines.runBlocking { chatDao.updateStatusByLocalId(roomId, localId, newStatus.name) } + kotlinx.coroutines.runBlocking { + chatDao.updateStatusByLocalId( + roomId, + localId, + newStatus.name + ) + } }.subscribeOn(Schedulers.io()) } @@ -206,7 +235,11 @@ class ChatRepository( * 대화 초기화: 서버에 리셋 요청 → 새 채팅방 ID 반환 */ fun resetChatRoom(token: String, roomId: Long): Single { - return talkApi.resetChatRoom(authHeader = token, roomId = roomId) + return talkApi.resetChatRoom( + authHeader = token, + roomId = roomId, + request = ChatRoomResetRequest() + ) .subscribeOn(Schedulers.io()) .map { ensureSuccess(it) } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRoomActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRoomActivity.kt index bd4a76b8..143c3cdb 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRoomActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRoomActivity.kt @@ -20,6 +20,7 @@ import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.base.BaseActivity import kr.co.vividnext.sodalive.base.SodaDialog import kr.co.vividnext.sodalive.chat.character.detail.detail.CharacterType +import kr.co.vividnext.sodalive.common.LoadingDialog import kr.co.vividnext.sodalive.common.SharedPreferenceManager import kr.co.vividnext.sodalive.databinding.ActivityChatRoomBinding import kr.co.vividnext.sodalive.extensions.dpToPx @@ -890,6 +891,12 @@ class ChatRoomActivity : BaseActivity( desc = desc, confirmButtonTitle = "초기화", confirmButtonClick = { + val loadingDialog = LoadingDialog(this, layoutInflater) + loadingDialog.show( + screenWidth, + "대화 초기화 중..." + ) + val token = "Bearer ${SharedPreferenceManager.token}" val disposable = chatRepository.resetChatRoom(token = token, roomId = roomId) .flatMap { response -> @@ -899,6 +906,7 @@ class ChatRoomActivity : BaseActivity( .andThen(io.reactivex.rxjava3.core.Single.just(response)) } .observeOn(AndroidSchedulers.mainThread()) + .doFinally { loadingDialog.dismiss() } .subscribe({ response -> val intent = newIntent(this, response.chatRoomId) startActivity(intent) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRoomResetRequest.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRoomResetRequest.kt new file mode 100644 index 00000000..9c03ab5d --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRoomResetRequest.kt @@ -0,0 +1,9 @@ +package kr.co.vividnext.sodalive.chat.talk.room + +import androidx.annotation.Keep +import com.google.gson.annotations.SerializedName + +@Keep +data class ChatRoomResetRequest( + @SerializedName("container") val container: String = "aos" +)