feat(home): 홈 추천 ViewModel을 추가한다

This commit is contained in:
2026-06-02 13:29:01 +09:00
parent dd002e9f82
commit 4870b7377a
2 changed files with 128 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.login.LoginViewModel
import kr.co.vividnext.sodalive.user.signup.SignUpViewModel import kr.co.vividnext.sodalive.user.signup.SignUpViewModel
import kr.co.vividnext.sodalive.v2.main.MainV2ViewModel import kr.co.vividnext.sodalive.v2.main.MainV2ViewModel
import kr.co.vividnext.sodalive.v2.main.home.HomeRecommendationViewModel
import kr.co.vividnext.sodalive.v2.main.home.data.HomeRecommendationApi import kr.co.vividnext.sodalive.v2.main.home.data.HomeRecommendationApi
import kr.co.vividnext.sodalive.v2.main.home.data.HomeRecommendationRepository import kr.co.vividnext.sodalive.v2.main.home.data.HomeRecommendationRepository
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@@ -384,6 +385,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
viewModel { SearchViewModel(get()) } viewModel { SearchViewModel(get()) }
viewModel { PointStatusViewModel(get()) } viewModel { PointStatusViewModel(get()) }
viewModel { HomeViewModel(get(), get()) } viewModel { HomeViewModel(get(), get()) }
viewModel { HomeRecommendationViewModel(get()) }
viewModel { PushNotificationListViewModel(get()) } viewModel { PushNotificationListViewModel(get()) }
viewModel { CharacterTabViewModel(get()) } viewModel { CharacterTabViewModel(get()) }
viewModel { CharacterDetailViewModel(get()) } viewModel { CharacterDetailViewModel(get()) }

View File

@@ -0,0 +1,126 @@
package kr.co.vividnext.sodalive.v2.main.home
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.home.data.FollowRecommendedCreatorsRequest
import kr.co.vividnext.sodalive.v2.main.home.data.HomeRecommendationRepository
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationGenreCreatorSection
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationUiState
import kr.co.vividnext.sodalive.v2.main.home.model.toContent
class HomeRecommendationViewModel(
private val repository: HomeRecommendationRepository
) : BaseViewModel() {
private val _recommendationStateLiveData = MutableLiveData<HomeRecommendationUiState>()
val recommendationStateLiveData: LiveData<HomeRecommendationUiState>
get() = _recommendationStateLiveData
private val _toastLiveData = MutableLiveData<ToastMessage?>()
val toastLiveData: LiveData<ToastMessage?>
get() = _toastLiveData
private val _isLoading = MutableLiveData(false)
val isLoading: LiveData<Boolean>
get() = _isLoading
fun loadRecommendations() {
_isLoading.value = true
_recommendationStateLiveData.value = HomeRecommendationUiState.Loading
compositeDisposable.add(
repository.getRecommendations(token = authToken())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
_isLoading.value = false
val data = it.data
if (it.success && data != null) {
val content = data.toContent()
_recommendationStateLiveData.value = if (content.isEmpty) {
HomeRecommendationUiState.Empty
} else {
content
}
} else {
showUnknownError(it.message)
}
},
{
_isLoading.value = false
it.message?.let { message -> Logger.e(message) }
showUnknownError(it.message)
}
)
)
}
fun followCreators(sectionKey: String, creatorIds: List<Long>) {
if (creatorIds.isEmpty()) return
_isLoading.value = true
compositeDisposable.add(
repository.followRecommendedCreators(
request = FollowRecommendedCreatorsRequest(creatorIds = creatorIds),
token = authToken()
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
_isLoading.value = false
if (it.success) {
updateFollowCompleted(sectionKey)
} else {
showUnknownError(it.message)
}
},
{
_isLoading.value = false
it.message?.let { message -> Logger.e(message) }
showUnknownError(it.message)
}
)
)
}
private fun updateFollowCompleted(sectionKey: String) {
val content = _recommendationStateLiveData.value as? HomeRecommendationUiState.Content ?: return
_recommendationStateLiveData.value = when (sectionKey) {
SECTION_KEY_CHEER_CREATORS -> content.copy(
cheerCreators = content.cheerCreators.copy(isFollowCompleted = true)
)
else -> content.copy(
genreCreators = HomeRecommendationGenreCreatorSection(
groups = content.genreCreators.groups.map { group ->
if (group.genre == sectionKey || sectionKey == "$SECTION_KEY_GENRE_CREATORS:${group.genre}") {
group.copy(isFollowCompleted = true)
} else {
group
}
}
)
)
}
}
private fun showUnknownError(message: String?) {
_recommendationStateLiveData.value = HomeRecommendationUiState.Error(message = message)
_toastLiveData.postValue(ToastMessage(resId = R.string.common_error_unknown))
}
private fun authToken(): String = "Bearer ${SharedPreferenceManager.token}"
private companion object {
const val SECTION_KEY_CHEER_CREATORS = "cheerCreators"
const val SECTION_KEY_GENRE_CREATORS = "genreCreators"
}
}