feat(ui): viewmodel, repository, api 추가

This commit is contained in:
2025-08-04 22:24:13 +09:00
parent 47717002e8
commit f0eda41c7c
6 changed files with 81 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
package kr.co.vividnext.sodalive.chat.character
import io.reactivex.rxjava3.core.Single
import kr.co.vividnext.sodalive.common.ApiResponse
import retrofit2.http.GET
import retrofit2.http.Header
interface CharacterApi {
@GET("/api/chat/character/main")
fun getCharacterMain(
@Header("Authorization") authHeader: String
): Single<ApiResponse<CharacterHomeResponse>>
}

View File

@@ -0,0 +1,5 @@
package kr.co.vividnext.sodalive.chat.character
data class CharacterHomeResponse(
val id: Long
)

View File

@@ -30,12 +30,15 @@ import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
import kr.co.vividnext.sodalive.extensions.dpToPx import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.main.MainActivity import kr.co.vividnext.sodalive.main.MainActivity
import kr.co.vividnext.sodalive.settings.event.EventDetailActivity import kr.co.vividnext.sodalive.settings.event.EventDetailActivity
import org.koin.android.ext.android.inject
// 캐릭터 탭 프래그먼트 // 캐릭터 탭 프래그먼트
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
class CharacterTabFragment : BaseFragment<FragmentCharacterTabBinding>( class CharacterTabFragment : BaseFragment<FragmentCharacterTabBinding>(
FragmentCharacterTabBinding::inflate FragmentCharacterTabBinding::inflate
) { ) {
private val viewModel: CharacterTabViewModel by inject()
private lateinit var contentBannerAdapter: AudioContentMainBannerAdapter private lateinit var contentBannerAdapter: AudioContentMainBannerAdapter
private lateinit var recentCharacterAdapter: RecentCharacterAdapter private lateinit var recentCharacterAdapter: RecentCharacterAdapter
private lateinit var popularCharacterAdapter: CharacterAdapter private lateinit var popularCharacterAdapter: CharacterAdapter
@@ -46,6 +49,8 @@ class CharacterTabFragment : BaseFragment<FragmentCharacterTabBinding>(
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
setupView() setupView()
loadData() loadData()
viewModel.fetchData()
} }
private fun setupView() { private fun setupView() {

View File

@@ -0,0 +1,7 @@
package kr.co.vividnext.sodalive.chat.character
class CharacterTabRepository(private val api: CharacterApi) {
fun getCharacterMain(
token: String
) = api.getCharacterMain(authHeader = token)
}

View File

@@ -0,0 +1,45 @@
package kr.co.vividnext.sodalive.chat.character
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.base.BaseViewModel
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
class CharacterTabViewModel(
private val repository: CharacterTabRepository
) : BaseViewModel() {
private var _isLoading = MutableLiveData(false)
val isLoading: LiveData<Boolean>
get() = _isLoading
private val _toastLiveData = MutableLiveData<String?>()
val toastLiveData: LiveData<String?>
get() = _toastLiveData
fun fetchData() {
_isLoading.value = true
compositeDisposable.add(
repository.getCharacterMain(token = "Bearer ${SharedPreferenceManager.token}")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
_isLoading.value = false
val data = it.data
if (it.success && data != null) {
}
},
{
_isLoading.value = false
it.message?.let { message -> Logger.e(message) }
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
}
)
)
}
}

View File

@@ -64,6 +64,9 @@ import kr.co.vividnext.sodalive.audition.AuditionRepository
import kr.co.vividnext.sodalive.audition.AuditionViewModel import kr.co.vividnext.sodalive.audition.AuditionViewModel
import kr.co.vividnext.sodalive.audition.detail.AuditionDetailViewModel import kr.co.vividnext.sodalive.audition.detail.AuditionDetailViewModel
import kr.co.vividnext.sodalive.audition.role.AuditionRoleDetailViewModel import kr.co.vividnext.sodalive.audition.role.AuditionRoleDetailViewModel
import kr.co.vividnext.sodalive.chat.character.CharacterApi
import kr.co.vividnext.sodalive.chat.character.CharacterTabRepository
import kr.co.vividnext.sodalive.chat.character.CharacterTabViewModel
import kr.co.vividnext.sodalive.common.ApiBuilder import kr.co.vividnext.sodalive.common.ApiBuilder
import kr.co.vividnext.sodalive.common.ObjectBox import kr.co.vividnext.sodalive.common.ObjectBox
import kr.co.vividnext.sodalive.explorer.ExplorerApi import kr.co.vividnext.sodalive.explorer.ExplorerApi
@@ -245,6 +248,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
single { ApiBuilder().build(get(), SearchApi::class.java) } single { ApiBuilder().build(get(), SearchApi::class.java) }
single { ApiBuilder().build(get(), PointStatusApi::class.java) } single { ApiBuilder().build(get(), PointStatusApi::class.java) }
single { ApiBuilder().build(get(), HomeApi::class.java) } single { ApiBuilder().build(get(), HomeApi::class.java) }
single { ApiBuilder().build(get(), CharacterApi::class.java) }
} }
private val viewModelModule = module { private val viewModelModule = module {
@@ -342,6 +346,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 { CharacterTabViewModel(get()) }
} }
private val repositoryModule = module { private val repositoryModule = module {
@@ -386,6 +391,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
factory { UserEventRepository(get()) } factory { UserEventRepository(get()) }
factory { PointStatusRepository(get()) } factory { PointStatusRepository(get()) }
factory { HomeRepository(get()) } factory { HomeRepository(get()) }
factory { CharacterTabRepository(get()) }
} }