feat(chat): 채팅방 ViewModel을 추가한다

This commit is contained in:
2026-06-10 12:00:27 +09:00
parent ed8a0e9a09
commit bb17f0014a
3 changed files with 453 additions and 0 deletions

View File

@@ -177,6 +177,7 @@ import kr.co.vividnext.sodalive.user.find_password.FindPasswordViewModel
import kr.co.vividnext.sodalive.user.login.LoginViewModel
import kr.co.vividnext.sodalive.user.signup.SignUpViewModel
import kr.co.vividnext.sodalive.v2.main.MainV2ViewModel
import kr.co.vividnext.sodalive.v2.main.chat.ChatMainViewModel
import kr.co.vividnext.sodalive.v2.main.chat.data.ChatRoomApi
import kr.co.vividnext.sodalive.v2.main.chat.data.ChatRoomRepository
import kr.co.vividnext.sodalive.v2.main.home.HomeCreatorRankingViewModel
@@ -392,6 +393,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
viewModel { SearchViewModel(get()) }
viewModel { PointStatusViewModel(get()) }
viewModel { HomeViewModel(get(), get()) }
viewModel { ChatMainViewModel(get()) }
viewModel { HomeCreatorRankingViewModel(get()) }
viewModel { HomeRecommendationViewModel(get()) }
viewModel { PushNotificationListViewModel(get()) }

View File

@@ -0,0 +1,154 @@
package kr.co.vividnext.sodalive.v2.main.chat
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.orhanobut.logger.Logger
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.base.BaseViewModel
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.common.ToastMessage
import kr.co.vividnext.sodalive.v2.main.chat.data.ChatRoomListPageResponse
import kr.co.vividnext.sodalive.v2.main.chat.data.ChatRoomRepository
import kr.co.vividnext.sodalive.v2.main.chat.model.ChatRoomFilter
import kr.co.vividnext.sodalive.v2.main.chat.model.ChatRoomListUiItem
import kr.co.vividnext.sodalive.v2.main.chat.model.ChatRoomListUiState
import kr.co.vividnext.sodalive.v2.main.chat.model.toUiItems
class ChatMainViewModel(
private val repository: ChatRoomRepository
) : BaseViewModel() {
private var currentFilter: ChatRoomFilter = ChatRoomFilter.ALL
private var currentItems: List<ChatRoomListUiItem> = emptyList()
private var nextCursor: String? = null
private var hasMore: Boolean = false
private var requestGeneration: Long = 0L
private val _chatRoomStateLiveData = MutableLiveData<ChatRoomListUiState>()
val chatRoomStateLiveData: LiveData<ChatRoomListUiState>
get() = _chatRoomStateLiveData
private val _toastLiveData = MutableLiveData<ToastMessage?>()
val toastLiveData: LiveData<ToastMessage?>
get() = _toastLiveData
private val _isLoading = MutableLiveData(false)
val isLoading: LiveData<Boolean>
get() = _isLoading
private val _isAppending = MutableLiveData(false)
val isAppending: LiveData<Boolean>
get() = _isAppending
fun loadFirstPage(filter: ChatRoomFilter = currentFilter) {
currentFilter = filter
requestGeneration += 1L
val generation = requestGeneration
currentItems = emptyList()
nextCursor = null
hasMore = false
_isLoading.value = true
_isAppending.value = false
_chatRoomStateLiveData.value = ChatRoomListUiState.Loading
compositeDisposable.add(
repository.getChatRooms(
token = authToken(),
filter = currentFilter.apiValue,
cursor = null
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
if (generation != requestGeneration) return@subscribe
_isLoading.value = false
val data = it.data
if (it.success && data != null) {
handleFirstPageSuccess(data)
} else {
showUnknownError(it.message)
}
},
{
if (generation != requestGeneration) return@subscribe
_isLoading.value = false
it.message?.let { message -> Logger.e(message) }
showUnknownError(it.message)
}
)
)
}
fun selectFilter(filter: ChatRoomFilter) {
if (filter == currentFilter) return
loadFirstPage(filter)
}
fun loadNextPage() {
val cursor = nextCursor
if (_isLoading.value == true || _isAppending.value == true || !hasMore || cursor == null) return
val generation = requestGeneration
_isAppending.value = true
_chatRoomStateLiveData.value = ChatRoomListUiState.Content(
items = currentItems,
isAppending = true
)
compositeDisposable.add(
repository.getChatRooms(
token = authToken(),
filter = currentFilter.apiValue,
cursor = cursor
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
if (generation != requestGeneration) return@subscribe
_isAppending.value = false
val data = it.data
if (it.success && data != null) {
handleNextPageSuccess(data)
} else {
showUnknownError(it.message)
}
},
{
if (generation != requestGeneration) return@subscribe
_isAppending.value = false
it.message?.let { message -> Logger.e(message) }
showUnknownError(it.message)
}
)
)
}
private fun handleFirstPageSuccess(data: ChatRoomListPageResponse) {
currentItems = data.rooms.toUiItems()
hasMore = data.hasMore
nextCursor = data.nextCursor
_chatRoomStateLiveData.value = if (currentItems.isEmpty()) {
ChatRoomListUiState.Empty
} else {
ChatRoomListUiState.Content(items = currentItems)
}
}
private fun handleNextPageSuccess(data: ChatRoomListPageResponse) {
currentItems = currentItems + data.rooms.toUiItems()
hasMore = data.hasMore
nextCursor = data.nextCursor
_chatRoomStateLiveData.value = ChatRoomListUiState.Content(items = currentItems)
}
private fun showUnknownError(message: String?) {
_chatRoomStateLiveData.value = ChatRoomListUiState.Error(message = message)
_toastLiveData.value = ToastMessage(resId = R.string.common_error_unknown)
}
private fun authToken(): String = "Bearer ${SharedPreferenceManager.token}"
}