diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6343a53..6307490 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -86,7 +86,6 @@ - @@ -153,6 +152,9 @@ + + + diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentApi.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentApi.kt index c0bfc11..9e7c897 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentApi.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentApi.kt @@ -27,6 +27,7 @@ import kr.co.vividnext.sodalive.audio_content.main.v2.series.GetContentMainTabSe import kr.co.vividnext.sodalive.audio_content.order.GetAudioContentOrderListResponse import kr.co.vividnext.sodalive.audio_content.order.OrderRequest import kr.co.vividnext.sodalive.audio_content.player.GenerateUrlResponse +import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse import kr.co.vividnext.sodalive.audio_content.upload.theme.GetAudioContentThemeResponse import kr.co.vividnext.sodalive.common.ApiResponse import kr.co.vividnext.sodalive.explorer.profile.GetAudioContentListResponse @@ -262,6 +263,13 @@ interface AudioContentApi { @Header("Authorization") authHeader: String ): Single> + @GET("/v2/audio-content/main/series/original") + fun getOriginalAudioDramaList( + @Query("page") page: Int, + @Query("size") size: Int, + @Header("Authorization") authHeader: String + ): Single> + @GET("/v2/audio-content/main/content") fun getContentMainContent( @Header("Authorization") authHeader: String diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/series/origianl_audio_drama/OriginalAudioDramaContentAllActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/series/origianl_audio_drama/OriginalAudioDramaContentAllActivity.kt new file mode 100644 index 0000000..e37923e --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/series/origianl_audio_drama/OriginalAudioDramaContentAllActivity.kt @@ -0,0 +1,109 @@ +package kr.co.vividnext.sodalive.audio_content.main.v2.series.origianl_audio_drama + +import android.content.Intent +import android.os.Bundle +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import kr.co.vividnext.sodalive.audio_content.series.SeriesListAdapter +import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity +import kr.co.vividnext.sodalive.base.BaseActivity +import kr.co.vividnext.sodalive.common.Constants +import kr.co.vividnext.sodalive.common.DifferentSpacingItemDecoration +import kr.co.vividnext.sodalive.common.LoadingDialog +import kr.co.vividnext.sodalive.databinding.ActivityOriginalAudioDramaContentAllBinding +import kr.co.vividnext.sodalive.extensions.dpToPx +import org.koin.android.ext.android.inject +import kotlin.math.roundToInt + +class OriginalAudioDramaContentAllActivity : + BaseActivity( + ActivityOriginalAudioDramaContentAllBinding::inflate + ) { + private val viewModel: OriginalAudioDramaContentAllViewModel by inject() + + private lateinit var loadingDialog: LoadingDialog + private lateinit var adapter: SeriesListAdapter + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + bindData() + + viewModel.getOriginalAudioDramaList() + } + + override fun setupView() { + loadingDialog = LoadingDialog(this, layoutInflater) + binding.toolbar.tvBack.text = "오리지널 오디오 드라마" + binding.toolbar.tvBack.setOnClickListener { finish() } + + setupOriginalAudioDramaListView() + } + + private fun setupOriginalAudioDramaListView() { + val spacing = 13.3f.dpToPx().roundToInt() + + adapter = SeriesListAdapter( + itemWidth = ((screenWidth - spacing * 3) / 2f).roundToInt(), + onClickItem = { + startActivity( + Intent(applicationContext, SeriesDetailActivity::class.java).apply { + putExtra(Constants.EXTRA_SERIES_ID, it) + } + ) + }, + onClickCreator = {}, + isVisibleCreator = false + ) + + val spanCount = 2 + val recyclerView = binding.rvSeries + recyclerView.layoutManager = GridLayoutManager(this, spanCount) + + recyclerView.addItemDecoration( + DifferentSpacingItemDecoration( + spanCount = spanCount, + horizontalSpacing = spacing, + verticalSpacing = spacing, + includeEdge = true + ) + ) + + recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + + val lastVisibleItemPosition = (recyclerView.layoutManager as LinearLayoutManager?)!! + .findLastCompletelyVisibleItemPosition() + val itemTotalCount = recyclerView.adapter!!.itemCount - 1 + + // 스크롤이 끝에 도달했는지 확인 + if (!recyclerView.canScrollVertically(1) && + lastVisibleItemPosition == itemTotalCount + ) { + viewModel.getOriginalAudioDramaList() + } + } + }) + + recyclerView.adapter = adapter + } + + private fun bindData() { + viewModel.toastLiveData.observe(this) { + it?.let { showToast(it) } + } + + viewModel.isLoading.observe(this) { + if (it) { + loadingDialog.show(screenWidth) + } else { + loadingDialog.dismiss() + } + } + + viewModel.originalAudioDramaLiveData.observe(this) { + adapter.addItems(it) + } + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/series/origianl_audio_drama/OriginalAudioDramaContentAllRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/series/origianl_audio_drama/OriginalAudioDramaContentAllRepository.kt new file mode 100644 index 0000000..2028c77 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/series/origianl_audio_drama/OriginalAudioDramaContentAllRepository.kt @@ -0,0 +1,15 @@ +package kr.co.vividnext.sodalive.audio_content.main.v2.series.origianl_audio_drama + +import kr.co.vividnext.sodalive.audio_content.AudioContentApi + +class OriginalAudioDramaContentAllRepository(private val api: AudioContentApi) { + fun getOriginalAudioDramaList( + page: Int, + size: Int, + token: String + ) = api.getOriginalAudioDramaList( + page = page - 1, + size = size, + authHeader = token + ) +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/series/origianl_audio_drama/OriginalAudioDramaContentAllViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/series/origianl_audio_drama/OriginalAudioDramaContentAllViewModel.kt new file mode 100644 index 0000000..5a0fb79 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/series/origianl_audio_drama/OriginalAudioDramaContentAllViewModel.kt @@ -0,0 +1,74 @@ +package kr.co.vividnext.sodalive.audio_content.main.v2.series.origianl_audio_drama + +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.audio_content.series.GetSeriesListResponse +import kr.co.vividnext.sodalive.base.BaseViewModel +import kr.co.vividnext.sodalive.common.SharedPreferenceManager + +class OriginalAudioDramaContentAllViewModel( + private val repository: OriginalAudioDramaContentAllRepository +) : BaseViewModel() { + private val _toastLiveData = MutableLiveData() + val toastLiveData: LiveData + get() = _toastLiveData + + private var _isLoading = MutableLiveData(false) + val isLoading: LiveData + get() = _isLoading + + private var _originalAudioDramaLiveData = + MutableLiveData>() + val originalAudioDramaLiveData: LiveData> + get() = _originalAudioDramaLiveData + + var isLast = false + var page = 1 + private val size = 15 + + fun getOriginalAudioDramaList() { + if (!_isLoading.value!! && !isLast) { + _isLoading.value = true + + compositeDisposable.add( + repository.getOriginalAudioDramaList( + page = page, + size = size, + token = "Bearer ${SharedPreferenceManager.token}" + ) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + if (it.success && it.data != null) { + page += 1 + + if (it.data.items.isNotEmpty()) { + _originalAudioDramaLiveData.value = it.data.items + } else { + isLast = true + } + } else { + if (it.message != null) { + _toastLiveData.value = it.message + } else { + _toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요." + + } + } + + _isLoading.value = false + }, + { + _isLoading.value = false + it.message?.let { message -> Logger.e(message) } + _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.") + } + ) + ) + } + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAdapter.kt index 7b7a294..1c54eb2 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAdapter.kt @@ -4,7 +4,7 @@ import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.constraintlayout.widget.ConstraintLayout +import android.widget.LinearLayout import androidx.recyclerview.widget.RecyclerView import coil.load import coil.transform.CircleCropTransformation @@ -27,10 +27,10 @@ class SeriesListAdapter( ) : RecyclerView.ViewHolder(binding.root) { @SuppressLint("SetTextI18n") fun bind(item: GetSeriesListResponse.SeriesListItem) { - val lp = binding.ivCover.layoutParams as ConstraintLayout.LayoutParams + val lp = binding.clCover.layoutParams as LinearLayout.LayoutParams lp.width = itemWidth lp.height = itemWidth * 432 / 306 - binding.ivCover.layoutParams = lp + binding.clCover.layoutParams = lp binding.ivCover.load(item.coverImage) { crossfade(true) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt b/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt index 7e42d3b..b2c0795 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt @@ -37,6 +37,8 @@ import kr.co.vividnext.sodalive.audio_content.main.v2.replay.AudioContentMainTab import kr.co.vividnext.sodalive.audio_content.main.v2.replay.AudioContentMainTabReplayViewModel import kr.co.vividnext.sodalive.audio_content.main.v2.series.AudioContentMainTabSeriesRepository import kr.co.vividnext.sodalive.audio_content.main.v2.series.AudioContentMainTabSeriesViewModel +import kr.co.vividnext.sodalive.audio_content.main.v2.series.origianl_audio_drama.OriginalAudioDramaContentAllRepository +import kr.co.vividnext.sodalive.audio_content.main.v2.series.origianl_audio_drama.OriginalAudioDramaContentAllViewModel import kr.co.vividnext.sodalive.audio_content.modify.AudioContentModifyViewModel import kr.co.vividnext.sodalive.audio_content.order.AudioContentOrderListViewModel import kr.co.vividnext.sodalive.audio_content.player.AudioContentGenerateUrlRepository @@ -311,6 +313,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) { viewModel { AudioContentMainTabAsmrViewModel(get()) } viewModel { AudioContentMainTabReplayViewModel(get()) } viewModel { AudioContentMainTabFreeViewModel(get()) } + viewModel { OriginalAudioDramaContentAllViewModel(get()) } } private val repositoryModule = module { @@ -349,6 +352,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) { factory { AudioContentMainTabAsmrRepository(get()) } factory { AudioContentMainTabReplayRepository(get()) } factory { AudioContentMainTabFreeRepository(get()) } + factory { OriginalAudioDramaContentAllRepository(get()) } } private val moduleList = listOf( diff --git a/app/src/main/res/layout/activity_original_audio_drama_content_all.xml b/app/src/main/res/layout/activity_original_audio_drama_content_all.xml new file mode 100644 index 0000000..b0f2ea1 --- /dev/null +++ b/app/src/main/res/layout/activity_original_audio_drama_content_all.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/app/src/main/res/layout/item_series_list.xml b/app/src/main/res/layout/item_series_list.xml index 675d821..7db27d7 100644 --- a/app/src/main/res/layout/item_series_list.xml +++ b/app/src/main/res/layout/item_series_list.xml @@ -1,117 +1,119 @@ - + android:layout_height="wrap_content" + android:orientation="vertical"> - - - - - - - - - - - - + android:layout_height="wrap_content"> + + + + + + + + + + + + + + - +