diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 01bf13f..7b668b2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -133,6 +133,7 @@
+
>
+}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/series/CreatorChannelSeriesAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAdapter.kt
similarity index 88%
rename from app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/series/CreatorChannelSeriesAdapter.kt
rename to app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAdapter.kt
index 8f919af..430213e 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/series/CreatorChannelSeriesAdapter.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAdapter.kt
@@ -1,4 +1,4 @@
-package kr.co.vividnext.sodalive.explorer.profile.series
+package kr.co.vividnext.sodalive.audio_content.series
import android.annotation.SuppressLint
import android.view.LayoutInflater
@@ -9,15 +9,14 @@ import coil.load
import coil.transform.CircleCropTransformation
import coil.transform.RoundedCornersTransformation
import kr.co.vividnext.sodalive.R
-import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse
import kr.co.vividnext.sodalive.databinding.ItemSeriesListBinding
import kr.co.vividnext.sodalive.extensions.dpToPx
-class CreatorChannelSeriesAdapter(
+class SeriesListAdapter(
private val onClickItem: (Long) -> Unit,
private val onClickCreator: (Long) -> Unit,
private val isVisibleCreator: Boolean
-) : RecyclerView.Adapter() {
+) : RecyclerView.Adapter() {
val items = mutableListOf()
@@ -85,4 +84,14 @@ class CreatorChannelSeriesAdapter(
}
override fun getItemCount() = items.count()
+
+ @SuppressLint("NotifyDataSetChanged")
+ fun addItems(items: List) {
+ this.items.addAll(items)
+ notifyDataSetChanged()
+ }
+
+ fun clear() {
+ this.items.clear()
+ }
}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAllActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAllActivity.kt
new file mode 100644
index 0000000..400d24c
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAllActivity.kt
@@ -0,0 +1,105 @@
+package kr.co.vividnext.sodalive.audio_content.series
+
+import android.os.Bundle
+import android.widget.Toast
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import kr.co.vividnext.sodalive.base.BaseActivity
+import kr.co.vividnext.sodalive.common.Constants
+import kr.co.vividnext.sodalive.common.GridSpacingItemDecoration
+import kr.co.vividnext.sodalive.common.LoadingDialog
+import kr.co.vividnext.sodalive.databinding.ActivitySeriesListAllBinding
+import org.koin.android.ext.android.inject
+
+class SeriesListAllActivity : BaseActivity(
+ ActivitySeriesListAllBinding::inflate
+) {
+
+ private val viewModel: SeriesListAllViewModel by inject()
+
+ private lateinit var loadingDialog: LoadingDialog
+ private lateinit var seriesAdapter: SeriesListAdapter
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val creatorId = intent.getLongExtra(Constants.EXTRA_USER_ID, 0)
+ if (creatorId <= 0) {
+ Toast.makeText(applicationContext, "잘못된 요청입니다.", Toast.LENGTH_LONG).show()
+ finish()
+ }
+
+ bindData()
+
+ viewModel.creatorId = creatorId
+ viewModel.getSeriesList()
+ }
+
+ override fun setupView() {
+ loadingDialog = LoadingDialog(this, layoutInflater)
+ binding.toolbar.tvBack.text = "시리즈 전체보기"
+ binding.toolbar.tvBack.setOnClickListener { finish() }
+
+ seriesAdapter = SeriesListAdapter(
+ onClickItem = {},
+ onClickCreator = {},
+ isVisibleCreator = false
+ )
+
+ val spanCount = 3
+ val spacing = 40
+ val recyclerView = binding.rvSeriesAll
+ recyclerView.layoutManager = GridLayoutManager(this, spanCount)
+
+ recyclerView.addItemDecoration(
+ GridSpacingItemDecoration(
+ spanCount,
+ spacing,
+ 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.getSeriesList()
+ }
+ }
+ })
+
+ recyclerView.adapter = seriesAdapter
+ }
+
+ private fun bindData() {
+ viewModel.toastLiveData.observe(this) {
+ it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
+ }
+
+ viewModel.isLoading.observe(this) {
+ if (it) {
+ loadingDialog.show(screenWidth, "")
+ } else {
+ loadingDialog.dismiss()
+ }
+ }
+
+ viewModel.seriesListLiveData.observe(this) {
+ if (viewModel.page - 1 == 1) {
+ seriesAdapter.clear()
+ binding.rvSeriesAll.scrollToPosition(0)
+ }
+
+ seriesAdapter.addItems(it)
+ }
+ }
+}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAllViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAllViewModel.kt
new file mode 100644
index 0000000..1f5473e
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesListAllViewModel.kt
@@ -0,0 +1,80 @@
+package kr.co.vividnext.sodalive.audio_content.series
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.google.gson.annotations.SerializedName
+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 SeriesListAllViewModel(private val repository: SeriesRepository) : BaseViewModel() {
+
+ enum class SeriesSortType {
+ @SerializedName("NEWEST") NEWEST,
+ @SerializedName("POPULAR") POPULAR
+ }
+
+ private val _toastLiveData = MutableLiveData()
+ val toastLiveData: LiveData
+ get() = _toastLiveData
+
+ private var _isLoading = MutableLiveData(false)
+ val isLoading: LiveData
+ get() = _isLoading
+
+ private var _seriesListLiveData = MutableLiveData>()
+ val seriesListLiveData: LiveData>
+ get() = _seriesListLiveData
+
+ var creatorId = 0L
+ var isLast = false
+ var page = 1
+ private val size = 10
+
+ fun getSeriesList() {
+ if (!_isLoading.value!! && !isLast) {
+ _isLoading.value = true
+
+ compositeDisposable.add(
+ repository.getSeriesList(
+ creatorId = creatorId,
+ sortType = SeriesSortType.NEWEST,
+ 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()) {
+ _seriesListLiveData.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/SeriesRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesRepository.kt
new file mode 100644
index 0000000..a9f12cb
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/series/SeriesRepository.kt
@@ -0,0 +1,17 @@
+package kr.co.vividnext.sodalive.audio_content.series
+
+class SeriesRepository(private val api: SeriesApi) {
+ fun getSeriesList(
+ creatorId: Long,
+ sortType: SeriesListAllViewModel.SeriesSortType,
+ page: Int,
+ size: Int,
+ token: String
+ ) = api.getSeriesList(
+ creatorId = creatorId,
+ sortType = sortType,
+ page = page - 1,
+ size = size,
+ authHeader = token
+ )
+}
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 afa26ca..b64b5c6 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
@@ -24,6 +24,9 @@ import kr.co.vividnext.sodalive.audio_content.main.order.AudioContentMainOrderLi
import kr.co.vividnext.sodalive.audio_content.main.ranking.AudioContentMainRankingViewModel
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.series.SeriesApi
+import kr.co.vividnext.sodalive.audio_content.series.SeriesListAllViewModel
+import kr.co.vividnext.sodalive.audio_content.series.SeriesRepository
import kr.co.vividnext.sodalive.audio_content.upload.AudioContentUploadViewModel
import kr.co.vividnext.sodalive.audio_content.upload.theme.AudioContentThemeViewModel
import kr.co.vividnext.sodalive.common.ApiBuilder
@@ -161,6 +164,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
single { ApiBuilder().build(get(), LiveApi::class.java) }
single { ApiBuilder().build(get(), TermsApi::class.java) }
single { ApiBuilder().build(get(), EventApi::class.java) }
+ single { ApiBuilder().build(get(), SeriesApi::class.java) }
single { ApiBuilder().build(get(), ReportApi::class.java) }
single { ApiBuilder().build(get(), LiveRecommendApi::class.java) }
single { ApiBuilder().build(get(), ExplorerApi::class.java) }
@@ -204,6 +208,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
viewModel { EventViewModel(get()) }
viewModel { NotificationSettingsViewModel(get()) }
viewModel { SettingsViewModel(get()) }
+ viewModel { SeriesListAllViewModel(get()) }
viewModel { TextMessageDetailViewModel(get()) }
viewModel { LiveReservationStatusViewModel(get()) }
viewModel { AudioContentMainBannerViewModel(get()) }
@@ -242,6 +247,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
private val repositoryModule = module {
factory { UserRepository(get()) }
factory { TermsRepository(get()) }
+ factory { SeriesRepository(get()) }
factory { LiveRepository(get(), get(), get()) }
factory { EventRepository(get()) }
factory { LiveRecommendRepository(get()) }
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileActivity.kt
index 834e0ac..949ec2a 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileActivity.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileActivity.kt
@@ -43,7 +43,8 @@ import kr.co.vividnext.sodalive.explorer.profile.donation.UserProfileDonationAda
import kr.co.vividnext.sodalive.explorer.profile.donation.UserProfileDonationAllViewActivity
import kr.co.vividnext.sodalive.explorer.profile.fantalk.UserProfileFantalkAllViewActivity
import kr.co.vividnext.sodalive.explorer.profile.follow.UserFollowerListActivity
-import kr.co.vividnext.sodalive.explorer.profile.series.CreatorChannelSeriesAdapter
+import kr.co.vividnext.sodalive.audio_content.series.SeriesListAdapter
+import kr.co.vividnext.sodalive.audio_content.series.SeriesListAllActivity
import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.extensions.loadUrl
import kr.co.vividnext.sodalive.extensions.moneyFormat
@@ -72,7 +73,7 @@ class UserProfileActivity : BaseActivity(
private lateinit var loadingDialog: LoadingDialog
private lateinit var liveAdapter: UserProfileLiveAdapter
private lateinit var audioContentAdapter: AudioContentAdapter
- private lateinit var seriesAdapter: CreatorChannelSeriesAdapter
+ private lateinit var seriesAdapter: SeriesListAdapter
private lateinit var donationAdapter: UserProfileDonationAdapter
private lateinit var cheersAdapter: UserProfileCheersAdapter
@@ -420,7 +421,13 @@ class UserProfileActivity : BaseActivity(
}
private fun setupSeriesListView() {
- binding.layoutCreatorChannelSeries.tvAll.setOnClickListener { }
+ binding.layoutCreatorChannelSeries.tvAll.setOnClickListener {
+ startActivity(
+ Intent(applicationContext, SeriesListAllActivity::class.java).apply {
+ putExtra(Constants.EXTRA_USER_ID, userId)
+ }
+ )
+ }
val recyclerView = binding.layoutCreatorChannelSeries.rvSeries
recyclerView.layoutManager = LinearLayoutManager(
@@ -429,7 +436,7 @@ class UserProfileActivity : BaseActivity(
false
)
- seriesAdapter = CreatorChannelSeriesAdapter(
+ seriesAdapter = SeriesListAdapter(
onClickItem = {},
onClickCreator = {},
isVisibleCreator = false
diff --git a/app/src/main/res/layout/activity_series_list_all.xml b/app/src/main/res/layout/activity_series_list_all.xml
new file mode 100644
index 0000000..7b0e966
--- /dev/null
+++ b/app/src/main/res/layout/activity_series_list_all.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/detail_toolbar.xml b/app/src/main/res/layout/detail_toolbar.xml
index 1005f86..13d80d3 100644
--- a/app/src/main/res/layout/detail_toolbar.xml
+++ b/app/src/main/res/layout/detail_toolbar.xml
@@ -14,6 +14,8 @@
android:layout_centerVertical="true"
android:drawablePadding="6.7dp"
android:fontFamily="@font/gmarket_sans_bold"
+ android:gravity="center"
+ android:minHeight="48dp"
android:textColor="@color/color_eeeeee"
android:textSize="18.3sp"
app:drawableStartCompat="@drawable/ic_back"
diff --git a/app/src/main/res/layout/item_series_list.xml b/app/src/main/res/layout/item_series_list.xml
index e3f16d2..992fe6a 100644
--- a/app/src/main/res/layout/item_series_list.xml
+++ b/app/src/main/res/layout/item_series_list.xml
@@ -7,8 +7,8 @@