From 7c91795fb5f568207d52f86505ef015446890e94 Mon Sep 17 00:00:00 2001 From: klaus Date: Fri, 26 Jul 2024 00:52:34 +0900 Subject: [PATCH] =?UTF-8?q?=EC=95=8C=EB=9E=8C=20-=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EC=8A=AC=EB=A1=AF=20=EA=B5=AC=EB=A7=A4=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/kr/co/vividnext/sodalive/di/AppDI.kt | 6 ++ .../sodalive/mypage/alarm/AddAlarmActivity.kt | 16 ---- .../mypage/alarm/AlarmListActivity.kt | 62 +++++++++++-- .../sodalive/mypage/alarm/AlarmListApi.kt | 17 ++++ .../mypage/alarm/AlarmListRepository.kt | 7 ++ .../mypage/alarm/AlarmListViewModel.kt | 93 +++++++++++++++++++ .../sodalive/mypage/alarm/AlarmViewModel.kt | 31 +------ .../alarm/GetSlotQuantityAndPriceResponse.kt | 8 ++ .../sodalive/settings/SettingsActivity.kt | 3 +- .../main/res/layout/activity_alarm_list.xml | 84 +++++++++++++++-- app/src/main/res/layout/item_alarm.xml | 5 +- 11 files changed, 266 insertions(+), 66 deletions(-) create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListApi.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListRepository.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListViewModel.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/GetSlotQuantityAndPriceResponse.kt 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 d2b1770..450109e 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 @@ -75,6 +75,9 @@ import kr.co.vividnext.sodalive.message.text.TextMessageWriteViewModel import kr.co.vividnext.sodalive.message.voice.VoiceMessageViewModel import kr.co.vividnext.sodalive.message.voice.VoiceMessageWriteViewModel import kr.co.vividnext.sodalive.mypage.MyPageViewModel +import kr.co.vividnext.sodalive.mypage.alarm.AlarmListApi +import kr.co.vividnext.sodalive.mypage.alarm.AlarmListRepository +import kr.co.vividnext.sodalive.mypage.alarm.AlarmListViewModel import kr.co.vividnext.sodalive.mypage.auth.AuthApi import kr.co.vividnext.sodalive.mypage.auth.AuthRepository import kr.co.vividnext.sodalive.mypage.can.CanApi @@ -162,6 +165,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) { .build() } + single { ApiBuilder().build(get(), AlarmListApi::class.java) } single { ApiBuilder().build(get(), CanApi::class.java) } single { ApiBuilder().build(get(), CanTempApi::class.java) } single { ApiBuilder().build(get(), AuthApi::class.java) } @@ -251,6 +255,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) { viewModel { CreatorCommunityModifyViewModel(get()) } viewModel { CanCouponViewModel(get()) } viewModel { CanChargeIapViewModel(get()) } + viewModel { AlarmListViewModel(get()) } } private val repositoryModule = module { @@ -277,6 +282,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) { factory { UserProfileFantalkAllViewModel(get(), get()) } factory { RouletteRepository(get()) } factory { CreatorCommunityRepository(get()) } + factory { AlarmListRepository(get()) } } private val moduleList = listOf( diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AddAlarmActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AddAlarmActivity.kt index 2940cc7..f88fbdd 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AddAlarmActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AddAlarmActivity.kt @@ -10,7 +10,6 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels import kr.co.vividnext.sodalive.base.BaseActivity import kr.co.vividnext.sodalive.common.Constants -import kr.co.vividnext.sodalive.common.LoadingDialog import kr.co.vividnext.sodalive.databinding.ActivityAddAlarmBinding import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm import kr.co.vividnext.sodalive.mypage.alarm.select_audio_content.AlarmSelectAudioContentActivity @@ -21,7 +20,6 @@ class AddAlarmActivity : BaseActivity( ) { private val alarmViewModel: AlarmViewModel by viewModels() - private lateinit var loadingDialog: LoadingDialog private lateinit var activityResultLauncher: ActivityResultLauncher private lateinit var dayCheckBoxes: List @@ -54,13 +52,9 @@ class AddAlarmActivity : BaseActivity( alarmId = intent.getIntExtra(Constants.EXTRA_ALARM_ID, -1) super.onCreate(savedInstanceState) - - bindData() } override fun setupView() { - loadingDialog = LoadingDialog(this, layoutInflater) - dayCheckBoxes = listOf( binding.chkSun, binding.chkMon, @@ -152,16 +146,6 @@ class AddAlarmActivity : BaseActivity( return calendar.timeInMillis } - private fun bindData() { - alarmViewModel.isLoading.observe(this) { - if (it) { - loadingDialog.show(screenWidth, "") - } else { - loadingDialog.dismiss() - } - } - } - private fun validate(): Boolean { if ( selectedContentId <= 0 || diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListActivity.kt index 1a44c48..d4de90a 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListActivity.kt @@ -17,13 +17,16 @@ import kr.co.vividnext.sodalive.base.SodaDialog import kr.co.vividnext.sodalive.common.Constants import kr.co.vividnext.sodalive.common.LoadingDialog import kr.co.vividnext.sodalive.databinding.ActivityAlarmListBinding +import kr.co.vividnext.sodalive.extensions.moneyFormat import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm +import org.koin.android.ext.android.inject class AlarmListActivity : BaseActivity( ActivityAlarmListBinding::inflate ) { private val alarmViewModel: AlarmViewModel by viewModels() + private val viewModel: AlarmListViewModel by inject() private lateinit var alarmAdapter: AlarmAdapter private lateinit var loadingDialog: LoadingDialog @@ -68,24 +71,55 @@ class AlarmListActivity : BaseActivity( @SuppressLint("NotifyDataSetChanged") private fun adapterRefresh() { - alarmViewModel.refresh() alarmAdapter.notifyDataSetChanged() } private fun bindData() { alarmViewModel.allAlarms.observe(this) { alarms -> alarms?.let { - binding.ivPlus.visibility = if (it.size >= 3) { - View.GONE - } else { + alarmAdapter.submitList(it) + binding.scrollView.visibility = + if (it.isEmpty()) View.GONE else View.VISIBLE + binding.tvEmptyAlarms.visibility = + if (it.isEmpty()) View.VISIBLE else View.GONE + + + viewModel.getSlotQuantityAndPrice() + } + } + + viewModel.toastLiveData.observe(this) { + Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() + } + + viewModel.isLoading.observe(this) { + if (it) { + loadingDialog.show(screenWidth, "") + } else { + loadingDialog.dismiss() + } + } + + viewModel.maxAlarmSlotLiveData.observe(this) { + if (it > 0 && alarmAdapter.itemCount >= it) { + binding.ivPlus.visibility = View.GONE + binding.llBuyExtraSlot.visibility = View.VISIBLE + binding.tvInfinity.visibility = if (it - 3 >= 2) { View.VISIBLE + } else { + View.GONE } - alarmAdapter.submitList(it) - binding.rvAlarm.visibility = if (it.isEmpty()) View.GONE else View.VISIBLE - binding.tvEmptyAlarms.visibility = if (it.isEmpty()) View.VISIBLE else View.GONE + binding.llBuyExtraSlot.setOnClickListener { showBuyConfirm() } + } else { + binding.ivPlus.visibility = View.VISIBLE + binding.llBuyExtraSlot.visibility = View.GONE } } + + viewModel.extraSlotPriceLiveData.observe(this) { + binding.tvPrice.text = it.moneyFormat() + } } private fun checkPermissions() { @@ -135,14 +169,26 @@ class AlarmListActivity : BaseActivity( confirmButtonTitle = "삭제", confirmButtonClick = { alarmViewModel.delete(alarm) - adapterRefresh() Toast.makeText( applicationContext, "알람이 삭제되었습니다.", Toast.LENGTH_SHORT ).show() + adapterRefresh() }, cancelButtonTitle = "취소", ).show(screenWidth) } + + private fun showBuyConfirm() { + SodaDialog( + this, + layoutInflater, + title = "알림", + desc = "추가 슬롯을 구매하시겠습니까?", + confirmButtonTitle = "구매", + confirmButtonClick = { viewModel.buyExtraSlot() }, + cancelButtonTitle = "취소", + ).show(screenWidth) + } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListApi.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListApi.kt new file mode 100644 index 0000000..5b157e4 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListApi.kt @@ -0,0 +1,17 @@ +package kr.co.vividnext.sodalive.mypage.alarm + +import io.reactivex.rxjava3.core.Single +import kr.co.vividnext.sodalive.common.ApiResponse +import retrofit2.http.GET +import retrofit2.http.Header +import retrofit2.http.POST + +interface AlarmListApi { + @GET("/alarm") + fun getSlotQuantityAndPrice( + @Header("Authorization") authHeader: String + ): Single> + + @POST("/alarm/buy-slot/aos") + fun buyExtraSlot(@Header("Authorization") authHeader: String): Single> +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListRepository.kt new file mode 100644 index 0000000..317c84a --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListRepository.kt @@ -0,0 +1,7 @@ +package kr.co.vividnext.sodalive.mypage.alarm + +class AlarmListRepository(private val api: AlarmListApi) { + fun getSlotQuantityAndPrice(token: String) = api.getSlotQuantityAndPrice(authHeader = token) + + fun buyExtraSlot(token: String) = api.buyExtraSlot(authHeader = token) +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListViewModel.kt new file mode 100644 index 0000000..9c6a620 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmListViewModel.kt @@ -0,0 +1,93 @@ +package kr.co.vividnext.sodalive.mypage.alarm + +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 AlarmListViewModel(private val repository: AlarmListRepository) : BaseViewModel() { + private val _toastLiveData = MutableLiveData() + val toastLiveData: LiveData + get() = _toastLiveData + + private var _isLoading = MutableLiveData(false) + val isLoading: LiveData + get() = _isLoading + + private var _maxAlarmSlotLiveData = MutableLiveData(3) + val maxAlarmSlotLiveData: LiveData + get() = _maxAlarmSlotLiveData + + private var _extraSlotPriceLiveData = MutableLiveData(0) + val extraSlotPriceLiveData: LiveData + get() = _extraSlotPriceLiveData + + fun getSlotQuantityAndPrice() { + _isLoading.value = true + compositeDisposable.add( + repository.getSlotQuantityAndPrice("Bearer ${SharedPreferenceManager.token}") + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + _isLoading.value = false + if (it.success && it.data != null) { + if (it.data.slotQuantity >= 3) { + _maxAlarmSlotLiveData.value = 0 + } else { + _maxAlarmSlotLiveData.value = 3 + it.data.slotQuantity + } + + _extraSlotPriceLiveData.value = it.data.price + } else { + if (it.message != null) { + _toastLiveData.postValue(it.message) + } else { + _toastLiveData.postValue( + "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요." + ) + } + } + }, + { + _isLoading.value = false + it.message?.let { message -> Logger.e(message) } + _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.") + } + ) + ) + } + + fun buyExtraSlot() { + _isLoading.value = true + compositeDisposable.add( + repository.buyExtraSlot("Bearer ${SharedPreferenceManager.token}") + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + _isLoading.value = false + if (it.success) { + getSlotQuantityAndPrice() + } else { + if (it.message != null) { + _toastLiveData.postValue(it.message) + } else { + _toastLiveData.postValue( + "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요." + ) + } + } + }, + { + _isLoading.value = false + it.message?.let { message -> Logger.e(message) } + _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.") + } + ) + ) + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmViewModel.kt index 370642a..5c83b4b 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmViewModel.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/AlarmViewModel.kt @@ -3,7 +3,6 @@ package kr.co.vividnext.sodalive.mypage.alarm import android.app.Application import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch @@ -15,10 +14,6 @@ class AlarmViewModel(application: Application) : AndroidViewModel(application) { private val repository: AlarmRepository private val scheduler: AlarmScheduler - private var _isLoading = MutableLiveData(false) - val isLoading: LiveData - get() = _isLoading - init { val alarmDao = AlarmDatabase.getDatabase(application).alarmDao() repository = AlarmRepository(alarmDao) @@ -27,43 +22,25 @@ class AlarmViewModel(application: Application) : AndroidViewModel(application) { var allAlarms = repository.allAlarms.asLiveData() - fun refresh() = viewModelScope.launch { - _isLoading.value = true - repository.allAlarms.asLiveData() - _isLoading.value = false - } - fun insert(alarm: Alarm) = viewModelScope.launch { - _isLoading.value = true - repository.insert(alarm) if (alarm.isEnabled) { scheduler.setAlarm(alarm) } - - _isLoading.value = false } fun update(alarm: Alarm) = viewModelScope.launch { - _isLoading.value = true - repository.update(alarm) scheduler.cancelAlarm(alarm) if (alarm.isEnabled) { scheduler.setAlarm(alarm) } - - _isLoading.value = false } fun delete(alarm: Alarm) = viewModelScope.launch { - _isLoading.value = true - repository.delete(alarm) scheduler.cancelAlarm(alarm) - - _isLoading.value = false } fun truncate() = viewModelScope.launch { @@ -71,12 +48,6 @@ class AlarmViewModel(application: Application) : AndroidViewModel(application) { } fun getAlarmById(id: Int): LiveData { - _isLoading.value = true - - val alarm = repository.getAlarmById(id) - - _isLoading.value = false - - return alarm + return repository.getAlarmById(id) } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/GetSlotQuantityAndPriceResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/GetSlotQuantityAndPriceResponse.kt new file mode 100644 index 0000000..6d1bc2f --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/alarm/GetSlotQuantityAndPriceResponse.kt @@ -0,0 +1,8 @@ +package kr.co.vividnext.sodalive.mypage.alarm + +import com.google.gson.annotations.SerializedName + +data class GetSlotQuantityAndPriceResponse( + @SerializedName("slotQuantity") val slotQuantity: Int, + @SerializedName("price") val price: Int +) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/settings/SettingsActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/settings/SettingsActivity.kt index 28ccdc6..556dad2 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/settings/SettingsActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/settings/SettingsActivity.kt @@ -5,6 +5,7 @@ import android.content.Intent import android.graphics.Paint import android.os.Bundle import android.widget.Toast +import androidx.activity.viewModels import com.google.android.gms.oss.licenses.OssLicensesMenuActivity import kr.co.vividnext.sodalive.BuildConfig import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService @@ -51,7 +52,7 @@ class SettingsActivity : BaseActivity(ActivitySettingsB } private val viewModel: SettingsViewModel by inject() - private val alarmViewModel: AlarmViewModel by inject() + private val alarmViewModel: AlarmViewModel by viewModels() private lateinit var loadingDialog: LoadingDialog diff --git a/app/src/main/res/layout/activity_alarm_list.xml b/app/src/main/res/layout/activity_alarm_list.xml index 0719567..c2e99a4 100644 --- a/app/src/main/res/layout/activity_alarm_list.xml +++ b/app/src/main/res/layout/activity_alarm_list.xml @@ -37,7 +37,8 @@ android:layout_alignParentEnd="true" android:layout_centerVertical="true" android:contentDescription="@null" - android:src="@drawable/ic_plus_no_bg" /> + android:src="@drawable/ic_plus_no_bg" + android:visibility="gone" /> + android:textSize="13sp" /> - + android:visibility="gone"> + + + + + + + + + + + + + + + + + + android:textSize="18sp" + android:visibility="gone" /> diff --git a/app/src/main/res/layout/item_alarm.xml b/app/src/main/res/layout/item_alarm.xml index d95e5f7..571b107 100644 --- a/app/src/main/res/layout/item_alarm.xml +++ b/app/src/main/res/layout/item_alarm.xml @@ -4,8 +4,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/black" - android:orientation="vertical" - android:paddingHorizontal="8dp"> + android:orientation="vertical">