From 637595e8cdf98e1f641aa5dc605c8ebced0e6d5c Mon Sep 17 00:00:00 2001 From: klaus Date: Wed, 13 Aug 2025 23:26:01 +0900 Subject: [PATCH] =?UTF-8?q?feat(chat-room):=207.1=20=EC=B4=88=EA=B8=B0=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=A1=9C=EB=94=A9=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B0=8F=20ServerChatMessage=20=EB=A7=A4=ED=8D=BC?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - enterChatRoom API 연동하여 캐릭터/메시지 초기 로딩 - ServerChatMessage -> ChatMessage 매퍼 추가(toDomain) - ChatRoomActivity에서 어댑터에 초기 메시지 세팅 및 헤더 갱신 - hasMore/nextCursor 상태 갱신 및 오류 처리 --- .../talk/room/ChatMessageEntityMappers.kt | 14 ++++++ .../chat/talk/room/ChatRoomActivity.kt | 47 +++++++++++++++++-- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessageEntityMappers.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessageEntityMappers.kt index 05cd0a65..11ccf9d5 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessageEntityMappers.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessageEntityMappers.kt @@ -45,3 +45,17 @@ fun ServerChatMessage.toEntity(roomId: Long): ChatMessageEntity { createdAt = createdAt ) } + +@Keep +fun ServerChatMessage.toDomain(): ChatMessage { + return ChatMessage( + messageId = messageId, + message = message, + profileImageUrl = profileImageUrl, + mine = mine, + createdAt = createdAt, + status = MessageStatus.SENT, + localId = null, + isGrouped = false + ) +} 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 f8fb092d..da1ac217 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 @@ -17,6 +17,7 @@ import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.base.BaseActivity import kr.co.vividnext.sodalive.chat.character.detail.CharacterType import kr.co.vividnext.sodalive.databinding.ActivityChatRoomBinding +import org.koin.android.ext.android.inject class ChatRoomActivity : BaseActivity( ActivityChatRoomBinding::inflate @@ -25,6 +26,9 @@ class ChatRoomActivity : BaseActivity( private lateinit var chatAdapter: ChatMessageAdapter private lateinit var layoutManager: LinearLayoutManager + // Repository 주입 (7.1 초기 데이터 로딩) + private val chatRepository: ChatRepository by inject() + // 5.2 무한 스크롤/자동 스크롤 상태 private val items: MutableList = mutableListOf() private var isLoading: Boolean = false @@ -348,11 +352,44 @@ class ChatRoomActivity : BaseActivity( // endregion 6.2 Send flow private fun loadInitialMessages() { - // 7.x에서 Repository 연동 및 초기 로딩 구현 예정 - items.clear() - chatAdapter.setItems(items) - // 초기 진입 시 최신 메시지로 스크롤 (하단) - scrollToBottom() + // 7.1 초기 데이터 로딩 구현: 통합 API 호출 + 로컬 동기화 결과를 UI에 반영 + isLoading = true + val token = "Bearer ${kr.co.vividnext.sodalive.common.SharedPreferenceManager.token}" + + val disposable = chatRepository.enterChatRoom(token = token, roomId = roomId) + .observeOn(io.reactivex.rxjava3.android.schedulers.AndroidSchedulers.mainThread()) + .subscribe({ response -> + // 캐릭터 정보 바인딩 + setCharacterInfo(response.character) + + // 메시지 정렬(오래된 -> 최신) 후 도메인/UI 모델로 변환 + val sorted = response.messages.sortedBy { it.createdAt } + val chatItems = sorted.map { serverMsg -> + val domain = serverMsg.toDomain() + if (domain.mine) { + ChatListItem.UserMessage(domain) + } else { + ChatListItem.AiMessage(domain, response.character.name) + } + } + + items.clear() + items.addAll(chatItems) + chatAdapter.setItems(items) + + // 페이지 상태 갱신 + hasMoreMessages = response.hasMoreMessages + nextCursor = sorted.firstOrNull()?.createdAt + + // 최신 메시지 위치로 + scrollToBottom() + isLoading = false + }, { error -> + isLoading = false + showToast(error.message ?: "채팅방 데이터를 불러오지 못했습니다.") + }) + + compositeDisposable.add(disposable) } // region 5.2 helper methods