diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bd5338e..aeaf415 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -153,9 +153,10 @@
+
+
-
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 061e8c8..d9dd0f3 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
@@ -320,6 +320,14 @@ interface AudioContentApi {
@Header("Authorization") authHeader: String
): Single>
+ @GET("/v2/audio-content/main/alarm/all")
+ fun getContentMainAlarmAll(
+ @Query("theme") theme: String,
+ @Query("page") page: Int,
+ @Query("size") size: Int,
+ @Header("Authorization") authHeader: String
+ ): Single>>
+
@GET("/v2/audio-content/main/asmr")
fun getContentMainAsmr(
@Header("Authorization") authHeader: String
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/new_content/AudioContentMainNewContentThemeAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/new_content/AudioContentMainNewContentThemeAdapter.kt
index c0aa457..feb56c2 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/new_content/AudioContentMainNewContentThemeAdapter.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/new_content/AudioContentMainNewContentThemeAdapter.kt
@@ -48,8 +48,7 @@ class AudioContentMainNewContentThemeAdapter(
}
@SuppressLint("NotifyDataSetChanged")
- fun addItems(themeList: List, selectedTheme: String = "") {
- this.selectedTheme = selectedTheme
+ fun addItems(themeList: List) {
this.themeList.clear()
this.themeList.addAll(themeList)
notifyDataSetChanged()
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/alarm/AudioContentMainTabAlarmFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/alarm/AudioContentMainTabAlarmFragment.kt
index 71d3304..e4ed85f 100644
--- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/alarm/AudioContentMainTabAlarmFragment.kt
+++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/alarm/AudioContentMainTabAlarmFragment.kt
@@ -16,13 +16,13 @@ import com.zhpan.bannerview.BaseBannerAdapter
import com.zhpan.indicator.enums.IndicatorSlideMode
import com.zhpan.indicator.enums.IndicatorStyle
import kr.co.vividnext.sodalive.R
-import kr.co.vividnext.sodalive.audio_content.all.AudioContentNewAllActivity
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
import kr.co.vividnext.sodalive.audio_content.main.AudioContentBannerType
import kr.co.vividnext.sodalive.audio_content.main.AudioContentMainContentAdapter
import kr.co.vividnext.sodalive.audio_content.main.banner.AudioContentMainBannerAdapter
import kr.co.vividnext.sodalive.audio_content.main.new_content.AudioContentMainNewContentThemeAdapter
import kr.co.vividnext.sodalive.audio_content.main.v2.AudioContentMainContentCurationAdapter
+import kr.co.vividnext.sodalive.audio_content.main.v2.alarm.all.AlarmContentAllActivity
import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity
import kr.co.vividnext.sodalive.base.BaseFragment
import kr.co.vividnext.sodalive.common.Constants
@@ -150,6 +150,7 @@ class AudioContentMainTabAlarmFragment : BaseFragment Logger.e(message) }
+ _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
+ }
+ )
+ )
+ }
}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/alarm/all/AlarmContentAllActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/alarm/all/AlarmContentAllActivity.kt
new file mode 100644
index 0000000..cba5a00
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/alarm/all/AlarmContentAllActivity.kt
@@ -0,0 +1,158 @@
+package kr.co.vividnext.sodalive.audio_content.main.v2.alarm.all
+
+import android.content.Intent
+import android.graphics.Rect
+import android.os.Bundle
+import android.view.View
+import android.widget.Toast
+import androidx.annotation.OptIn
+import androidx.media3.common.util.UnstableApi
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import kr.co.vividnext.sodalive.audio_content.all.AudioContentNewAllAdapter
+import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
+import kr.co.vividnext.sodalive.audio_content.main.new_content.AudioContentMainNewContentThemeAdapter
+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.ActivityAlarmContentAllBinding
+import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
+import kr.co.vividnext.sodalive.extensions.dpToPx
+import org.koin.android.ext.android.inject
+
+@OptIn(UnstableApi::class)
+class AlarmContentAllActivity : BaseActivity(
+ ActivityAlarmContentAllBinding::inflate
+) {
+ private val viewModel: AlarmContentAllViewModel by inject()
+
+ private lateinit var loadingDialog: LoadingDialog
+
+ private lateinit var newContentThemeAdapter: AudioContentMainNewContentThemeAdapter
+ private lateinit var newContentAdapter: AudioContentNewAllAdapter
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ bindData()
+ viewModel.getContentMainAlarmAll()
+
+ newContentThemeAdapter.addItems(listOf("전체", "모닝콜", "슬립콜", "알람"))
+ }
+
+ override fun setupView() {
+ loadingDialog = LoadingDialog(this, layoutInflater)
+ binding.toolbar.tvBack.text = "새로운 알람"
+ binding.toolbar.tvBack.setOnClickListener { finish() }
+
+ setupNewContentTheme()
+ setupNewContent()
+ }
+
+ private fun setupNewContentTheme() {
+ newContentThemeAdapter = AudioContentMainNewContentThemeAdapter {
+ newContentAdapter.clear()
+ viewModel.selectTheme(it)
+ }
+
+ binding.rvNewContentTheme.layoutManager = LinearLayoutManager(
+ this,
+ LinearLayoutManager.HORIZONTAL,
+ false
+ )
+
+ binding.rvNewContentTheme.addItemDecoration(object : RecyclerView.ItemDecoration() {
+ override fun getItemOffsets(
+ outRect: Rect,
+ view: View,
+ parent: RecyclerView,
+ state: RecyclerView.State
+ ) {
+ super.getItemOffsets(outRect, view, parent, state)
+
+ when (parent.getChildAdapterPosition(view)) {
+ 0 -> {
+ outRect.left = 0
+ outRect.right = 4f.dpToPx().toInt()
+ }
+
+ newContentThemeAdapter.itemCount - 1 -> {
+ outRect.left = 4f.dpToPx().toInt()
+ outRect.right = 0
+ }
+
+ else -> {
+ outRect.left = 4f.dpToPx().toInt()
+ outRect.right = 4f.dpToPx().toInt()
+ }
+ }
+ }
+ })
+
+ binding.rvNewContentTheme.adapter = newContentThemeAdapter
+ }
+
+ private fun setupNewContent() {
+ val spanCount = 3
+ val spacing = 40
+ newContentAdapter = AudioContentNewAllAdapter(
+ itemWidth = (screenWidth - (spacing * (spanCount + 1))) / 3,
+ onClickItem = {
+ startActivity(
+ Intent(this, AudioContentDetailActivity::class.java).apply {
+ putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, it)
+ }
+ )
+ },
+ onClickCreator = {
+ startActivity(
+ Intent(this, UserProfileActivity::class.java).apply {
+ putExtra(Constants.EXTRA_USER_ID, it)
+ }
+ )
+ }
+ )
+
+ binding.rvContent.layoutManager = GridLayoutManager(this, spanCount)
+ binding.rvContent.addItemDecoration(GridSpacingItemDecoration(spanCount, spacing, true))
+
+ binding.rvContent.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.getContentMainAlarmAll()
+ }
+ }
+ })
+
+ binding.rvContent.adapter = newContentAdapter
+ }
+
+ private fun bindData() {
+ viewModel.isLoading.observe(this) {
+ if (it) {
+ loadingDialog.show(screenWidth)
+ } else {
+ loadingDialog.dismiss()
+ }
+ }
+
+ viewModel.toastLiveData.observe(this) {
+ it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
+ }
+
+ viewModel.newContentListLiveData.observe(this) {
+ newContentAdapter.addItems(it)
+ }
+ }
+}
diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/alarm/all/AlarmContentAllViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/alarm/all/AlarmContentAllViewModel.kt
new file mode 100644
index 0000000..c743dcc
--- /dev/null
+++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/alarm/all/AlarmContentAllViewModel.kt
@@ -0,0 +1,87 @@
+package kr.co.vividnext.sodalive.audio_content.main.v2.alarm.all
+
+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.main.GetAudioContentMainItem
+import kr.co.vividnext.sodalive.audio_content.main.v2.alarm.AudioContentMainTabAlarmRepository
+import kr.co.vividnext.sodalive.base.BaseViewModel
+import kr.co.vividnext.sodalive.common.SharedPreferenceManager
+
+class AlarmContentAllViewModel(
+ private val repository: AudioContentMainTabAlarmRepository
+) : BaseViewModel() {
+ private val _toastLiveData = MutableLiveData()
+ val toastLiveData: LiveData
+ get() = _toastLiveData
+
+ private var _isLoading = MutableLiveData(false)
+ val isLoading: LiveData
+ get() = _isLoading
+
+ private var _newContentListLiveData = MutableLiveData>()
+ val newContentListLiveData: LiveData>
+ get() = _newContentListLiveData
+
+ private var isLast = false
+ private var page = 1
+ private val size = 10
+ private var selectedTheme = ""
+
+ fun getContentMainAlarmAll() {
+ if (!_isLoading.value!! && !isLast) {
+ _isLoading.value = true
+
+ compositeDisposable.add(
+ repository.getContentMainAlarmAll(
+ theme = if (selectedTheme == "전체") {
+ ""
+ } else {
+ selectedTheme
+ },
+ page = page,
+ size = size,
+ token = "Bearer ${SharedPreferenceManager.token}"
+ )
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(
+ {
+ if (it.success && it.data != null) {
+ if (it.data.isNotEmpty()) {
+ page += 1
+ _newContentListLiveData.value = it.data!!
+ } else {
+ isLast = true
+ }
+ } else {
+ if (it.message != null) {
+ _toastLiveData.postValue(it.message)
+ } else {
+ _toastLiveData.postValue(
+ "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
+ )
+ }
+ }
+
+ _isLoading.value = false
+ },
+ {
+ _isLoading.value = false
+ it.message?.let { message -> Logger.e(message) }
+ _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
+ }
+ )
+ )
+ }
+ }
+
+ fun selectTheme(theme: String) {
+ isLast = false
+ page = 1
+ selectedTheme = theme
+ getContentMainAlarmAll()
+ }
+}
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 88b053c..d097972 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
@@ -25,6 +25,7 @@ import kr.co.vividnext.sodalive.audio_content.main.ranking.AudioContentMainRanki
import kr.co.vividnext.sodalive.audio_content.main.recommend_series.AudioContentMainRecommendSeriesViewModel
import kr.co.vividnext.sodalive.audio_content.main.v2.alarm.AudioContentMainTabAlarmRepository
import kr.co.vividnext.sodalive.audio_content.main.v2.alarm.AudioContentMainTabAlarmViewModel
+import kr.co.vividnext.sodalive.audio_content.main.v2.alarm.all.AlarmContentAllViewModel
import kr.co.vividnext.sodalive.audio_content.main.v2.asmr.AudioContentMainTabAsmrRepository
import kr.co.vividnext.sodalive.audio_content.main.v2.asmr.AudioContentMainTabAsmrViewModel
import kr.co.vividnext.sodalive.audio_content.main.v2.content.AudioContentMainTabContentRepository
@@ -318,6 +319,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
viewModel { OriginalAudioDramaContentAllViewModel(get()) }
viewModel { IntroduceCreatorViewModel(get()) }
viewModel { CompletedSeriesViewModel(get()) }
+ viewModel { AlarmContentAllViewModel(get()) }
}
private val repositoryModule = module {
diff --git a/app/src/main/res/layout/activity_alarm_content_all.xml b/app/src/main/res/layout/activity_alarm_content_all.xml
new file mode 100644
index 0000000..18e0822
--- /dev/null
+++ b/app/src/main/res/layout/activity_alarm_content_all.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+