From 790e42035fd2acfe1130ebd62465c4f7b8cd99c0 Mon Sep 17 00:00:00 2001 From: klaus Date: Mon, 30 Sep 2024 21:10:35 +0900 Subject: [PATCH] =?UTF-8?q?=ED=81=AC=EB=A6=AC=EC=97=90=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=20=EC=B1=84=EB=84=90=20-=20=EB=A3=B0=EB=A0=9B=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EB=A9=94=EB=89=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 +- .../co/vividnext/sodalive/common/Constants.kt | 1 + .../explorer/profile/UserProfileActivity.kt | 32 +- .../roulette/config/RouletteConfigActivity.kt | 341 +++++++++++++++++- .../config/RouletteSettingsViewModel.kt | 13 +- .../res/layout/activity_roulette_config.xml | 330 ++++++++++++++++- .../res/layout/layout_user_profile_live.xml | 26 +- 7 files changed, 712 insertions(+), 35 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7c8f48c..04a3d3b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -35,8 +35,8 @@ android { applicationId "kr.co.vividnext.sodalive" minSdk 23 targetSdk 34 - versionCode 108 - versionName "1.19.1" + versionCode 109 + versionName "1.19.2" } buildTypes { diff --git a/app/src/main/java/kr/co/vividnext/sodalive/common/Constants.kt b/app/src/main/java/kr/co/vividnext/sodalive/common/Constants.kt index 334695f..0878264 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/common/Constants.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/common/Constants.kt @@ -70,4 +70,5 @@ object Constants { const val EXTRA_COMMUNITY_POST_COMMENT = "community_post_comment_id" const val EXTRA_ALARM_ID = "alarm_id" + const val EXTRA_ROULETTE_AVAILABLE_ACTIVE = "roulette_available_active" } 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 743f28b..d72a1ab 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 @@ -56,6 +56,7 @@ import kr.co.vividnext.sodalive.live.reservation.complete.LiveReservationComplet import kr.co.vividnext.sodalive.live.room.LiveRoomActivity import kr.co.vividnext.sodalive.live.room.dialog.LivePaymentDialog import kr.co.vividnext.sodalive.live.room.dialog.LiveRoomPasswordDialog +import kr.co.vividnext.sodalive.live.roulette.config.RouletteConfigActivity import kr.co.vividnext.sodalive.report.CheersReportDialog import kr.co.vividnext.sodalive.report.ProfileReportDialog import kr.co.vividnext.sodalive.report.ReportType @@ -782,10 +783,35 @@ class UserProfileActivity : BaseActivity( @SuppressLint("NotifyDataSetChanged") private fun setLiveRoomList(liveRoomList: List) { - if (liveRoomList.isEmpty()) { - binding.layoutUserProfileLive.root.visibility = View.GONE - } else { + if (userId == SharedPreferenceManager.userId) { binding.layoutUserProfileLive.root.visibility = View.VISIBLE + binding.layoutUserProfileLive.llRouletteMenu.visibility = View.VISIBLE + + if (liveRoomList.isEmpty()) { + binding.layoutUserProfileLive.rvLive.visibility = View.GONE + } else { + binding.layoutUserProfileLive.rvLive.visibility = View.VISIBLE + } + + binding.layoutUserProfileLive.tvSettingRoulette.setOnClickListener { + startActivity( + Intent(applicationContext, RouletteConfigActivity::class.java).apply { + putExtra(Constants.EXTRA_ROULETTE_AVAILABLE_ACTIVE, false) + } + ) + } + } else { + binding.layoutUserProfileLive.llRouletteMenu.visibility = View.GONE + + if (liveRoomList.isEmpty()) { + binding.layoutUserProfileLive.root.visibility = View.GONE + } else { + binding.layoutUserProfileLive.root.visibility = View.VISIBLE + binding.layoutUserProfileLive.rvLive.visibility = View.VISIBLE + } + } + + if (liveRoomList.isNotEmpty()) { liveAdapter.items.clear() liveAdapter.items.addAll(liveRoomList) liveAdapter.notifyDataSetChanged() diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteConfigActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteConfigActivity.kt index d578578..05e4221 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteConfigActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteConfigActivity.kt @@ -1,36 +1,347 @@ package kr.co.vividnext.sodalive.live.roulette.config +import android.annotation.SuppressLint +import android.app.Activity +import android.app.Service +import android.content.Intent import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.text.InputFilter +import android.view.LayoutInflater +import android.view.View +import android.view.inputmethod.InputMethodManager +import android.widget.EditText +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.content.ContextCompat +import com.jakewharton.rxbinding4.widget.textChanges +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.schedulers.Schedulers import kr.co.vividnext.sodalive.R 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.ActivityRouletteConfigBinding +import kr.co.vividnext.sodalive.live.roulette.RoulettePreviewDialog +import org.koin.android.ext.android.inject +import java.util.Locale +import java.util.concurrent.TimeUnit class RouletteConfigActivity : BaseActivity( ActivityRouletteConfigBinding::inflate ) { + private val viewModel: RouletteSettingsViewModel by inject() + + private lateinit var imm: InputMethodManager + private lateinit var loadingDialog: LoadingDialog + + private val handler = Handler(Looper.getMainLooper()) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - changeFragment() + val availableActive = intent.getBooleanExtra( + Constants.EXTRA_ROULETTE_AVAILABLE_ACTIVE, + true + ) + + binding.rlRouletteIsActive.visibility = if (availableActive) { + View.VISIBLE + } else { + View.GONE + } + + viewModel.availableActive = availableActive + + bindData() + viewModel.getAllRoulette() } override fun setupView() { - binding.toolbar.tvBack.text = "룰렛설정" - binding.toolbar.tvBack.setOnClickListener { finish() } - } + binding.tvBack.text = "룰렛설정" + binding.tvBack.setOnClickListener { finish() } - private fun changeFragment(tag: String = "settings") { - val fragmentManager = supportFragmentManager - val fragmentTransaction = fragmentManager.beginTransaction() + loadingDialog = LoadingDialog(this, layoutInflater) + imm = getSystemService( + Service.INPUT_METHOD_SERVICE + ) as InputMethodManager - val currentFragment = fragmentManager.primaryNavigationFragment - if (currentFragment != null) { - fragmentTransaction.hide(currentFragment) + binding.etSetPrice.filters = arrayOf(InputFilter { source, start, end, _, _, _ -> + // Only allow numeric input + for (i in start until end) { + if (!Character.isDigit(source[i])) { + return@InputFilter "" + } + } + null + }) + + binding.ivRouletteIsActive.setOnClickListener { viewModel.toggleIsActive() } + binding.ivAddOption.setOnClickListener { addOption() } + + binding.tvPreview.setOnClickListener { + handler.postDelayed({ + imm.hideSoftInputFromWindow(currentFocus?.windowToken, 0) + }, 100) + viewModel.onClickPreview() } - val fragment = RouletteSettingsFragment() - fragmentTransaction.add(R.id.container, fragment, tag) - fragmentTransaction.setPrimaryNavigationFragment(fragment) - fragmentTransaction.setReorderingAllowed(true) - fragmentTransaction.commitNow() + binding.tvSave.setOnClickListener { _ -> + handler.postDelayed({ + imm.hideSoftInputFromWindow(currentFocus?.windowToken, 0) + }, 100) + + viewModel.createOrUpdateRoulette { + val resultIntent = Intent().apply { putExtra(Constants.EXTRA_RESULT_ROULETTE, it) } + setResult(Activity.RESULT_OK, resultIntent) + finish() + } + } + + binding.llSelectRoulette1.setOnClickListener { + viewModel.selectRoulette( + RouletteSettingsViewModel.SelectedRoulette.ROULETTE_1 + ) + } + + binding.llSelectRoulette2.setOnClickListener { + viewModel.selectRoulette( + RouletteSettingsViewModel.SelectedRoulette.ROULETTE_2 + ) + } + + binding.llSelectRoulette3.setOnClickListener { + viewModel.selectRoulette( + RouletteSettingsViewModel.SelectedRoulette.ROULETTE_3 + ) + } + } + + @SuppressLint("SetTextI18n") + private fun bindData() { + viewModel.selectedRouletteLiveData.observe(this) { + deselectAllRoulette() + when (it) { + RouletteSettingsViewModel.SelectedRoulette.ROULETTE_2 -> selectRouletteButton( + binding.ivSelectRoulette2, + binding.llSelectRoulette2, + binding.tvSelectRoulette2 + ) + + RouletteSettingsViewModel.SelectedRoulette.ROULETTE_3 -> selectRouletteButton( + binding.ivSelectRoulette3, + binding.llSelectRoulette3, + binding.tvSelectRoulette3 + ) + + else -> selectRouletteButton( + binding.ivSelectRoulette1, + binding.llSelectRoulette1, + binding.tvSelectRoulette1 + ) + } + } + + viewModel.isActiveLiveData.observe(this) { + binding.ivRouletteIsActive.setImageResource( + if (it) R.drawable.btn_toggle_on_big else R.drawable.btn_toggle_off_big + ) + } + + viewModel.optionsLiveData.observe(this) { updateOptionUi(it) } + + viewModel.toastLiveData.observe(this) { it?.let { showToast(it) } } + + viewModel.canLiveData.observe(this) { + if (it > 0) { + binding.etSetPrice.setText("$it") + } else { + binding.etSetPrice.setText("") + } + } + + viewModel.isLoading.observe(this) { + if (it) { + loadingDialog.show(screenWidth) + } else { + loadingDialog.dismiss() + } + } + + viewModel.roulettePreviewLiveData.observe(this) { + RoulettePreviewDialog( + activity = this@RouletteConfigActivity, + previewList = listOf(it), + title = "룰렛 미리보기", + layoutInflater = layoutInflater + ).show() + } + + viewModel.totalPercentageLiveData.observe(this) { + binding.tvTotalPercentage.text = "( ${ + String.format( + Locale.KOREAN, + "%.2f%%", + it + ) + } )" + } + + compositeDisposable.add( + binding.etSetPrice.textChanges().skip(1) + .debounce(100, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.io()) + .subscribe { + if (it.trim().isNotEmpty()) { + viewModel.can = it.toString().toInt() + } + } + ) + } + + private fun addOption() { + val newOption = RouletteOption("", "") + viewModel.addOption(newOption) + } + + private fun updateOptionUi(options: List) { + binding.llRouletteOptionContainer.removeAllViews() + options.forEachIndexed { index, option -> + binding.llRouletteOptionContainer.addView(createOptionView(index, option)) + } + } + + @SuppressLint("SetTextI18n") + private fun createOptionView(index: Int, option: RouletteOption): View { + val optionView = LayoutInflater + .from(applicationContext) + .inflate( + R.layout.layout_roulette_option, + binding.llRouletteOptionContainer, + false + ) + + val etOption = optionView.findViewById(R.id.et_option) + val tvOptionTitle = optionView.findViewById(R.id.tv_option_title) + val etPercentage = optionView.findViewById(R.id.et_option_percentage) + val tvDelete = optionView.findViewById(R.id.tv_delete) + + etOption.setText(option.title) + tvOptionTitle.text = "옵션 ${index + 1}" + + try { + if (option.percentage.toFloat() > 0f) { + etPercentage.setText(option.percentage) + } else { + etPercentage.setText("") + } + } catch (e: Exception) { + etPercentage.setText("") + } + + if (index == 0 || index == 1) { + tvDelete.visibility = View.GONE + } else { + tvDelete.visibility = View.VISIBLE + tvDelete.setOnClickListener { viewModel.deleteOption(index) } + } + + compositeDisposable.add( + etOption.textChanges().skip(1) + .debounce(100, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.io()) + .subscribe { + viewModel.inputOption(index, it.toString()) + } + ) + + compositeDisposable.add( + etPercentage.textChanges().skip(1) + .debounce(100, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.io()) + .subscribe { + viewModel.inputOptionPercentage(index, it.toString()) + } + ) + + return optionView + } + + private fun deselectAllRoulette() { + binding.ivSelectRoulette1.visibility = View.GONE + binding.ivSelectRoulette2.visibility = View.GONE + binding.ivSelectRoulette3.visibility = View.GONE + + binding.llSelectRoulette1.setBackgroundResource(R.drawable.bg_round_corner_6_7_13181b) + binding.tvSelectRoulette1.setTextColor( + ContextCompat.getColor( + applicationContext, + R.color.color_3bb9f1 + ) + ) + + if (viewModel.rouletteList.size > 0) { + binding.llSelectRoulette2.setBackgroundResource(R.drawable.bg_round_corner_6_7_13181b) + binding.tvSelectRoulette2.setTextColor( + ContextCompat.getColor( + applicationContext, + R.color.color_ffcb14 + ) + ) + } else { + binding.llSelectRoulette2.setBackgroundResource(R.drawable.bg_round_corner_6_7_777777) + binding.tvSelectRoulette2.setTextColor( + ContextCompat.getColor( + applicationContext, + R.color.color_ff14d9 + ) + ) + } + + if (viewModel.rouletteList.size > 1) { + binding.llSelectRoulette3.setBackgroundResource(R.drawable.bg_round_corner_6_7_13181b) + binding.tvSelectRoulette3.setTextColor( + ContextCompat.getColor( + applicationContext, + R.color.color_3bb9f1 + ) + ) + } else { + binding.llSelectRoulette3.setBackgroundResource(R.drawable.bg_round_corner_6_7_777777) + binding.tvSelectRoulette3.setTextColor( + ContextCompat.getColor( + applicationContext, + R.color.color_555555 + ) + ) + } + } + + private fun selectRouletteButton( + ivSelectRoulette: ImageView, + llSelectRoulette: LinearLayout, + tvSelectRoulette: TextView + ) { + ivSelectRoulette.visibility = View.VISIBLE + llSelectRoulette.setBackgroundResource( + when (viewModel.selectedRouletteLiveData.value) { + RouletteSettingsViewModel.SelectedRoulette.ROULETTE_2 -> R.drawable.bg_round_corner_6_7_ffcb14 + RouletteSettingsViewModel.SelectedRoulette.ROULETTE_3 -> R.drawable.bg_round_corner_6_7_ff14d9 + else -> R.drawable.bg_round_corner_6_7_3bb9f1 + } + ) + tvSelectRoulette.setTextColor( + ContextCompat.getColor( + applicationContext, + when (viewModel.selectedRouletteLiveData.value) { + RouletteSettingsViewModel.SelectedRoulette.ROULETTE_2 -> R.color.black + else -> R.color.color_eeeeee + } + ) + ) } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteSettingsViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteSettingsViewModel.kt index 03aeb20..69cbbb7 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteSettingsViewModel.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteSettingsViewModel.kt @@ -53,6 +53,7 @@ class RouletteSettingsViewModel(private val repository: RouletteRepository) : Ba var can = 0 var isActive = false + var availableActive = false private var rouletteId = 0L private val options = mutableListOf() @@ -185,10 +186,14 @@ class RouletteSettingsViewModel(private val repository: RouletteRepository) : Ba SelectedRoulette.ROULETTE_3 -> "룰렛 3" } - val successMessage = if (isActive) { - "${selectedRouletteTitle}을 활성화 했습니다." + val successMessage = if (availableActive) { + if (isActive) { + "${selectedRouletteTitle}을 활성화 했습니다." + } else { + "${selectedRouletteTitle}을 비활성화 했습니다." + } } else { - "${selectedRouletteTitle}을 비활성화 했습니다." + "${selectedRouletteTitle}을 변경했습니다." } compositeDisposable.add( @@ -242,7 +247,7 @@ class RouletteSettingsViewModel(private val repository: RouletteRepository) : Ba } val successMessage = "$selectedRouletteTitle " + - if (isActive) "로 설정하였습니다." else "을 설정했습니다." + if (isActive || availableActive) "로 설정하였습니다." else "을 설정했습니다." compositeDisposable.add( repository.createRoulette( diff --git a/app/src/main/res/layout/activity_roulette_config.xml b/app/src/main/res/layout/activity_roulette_config.xml index 5d57258..bb961d2 100644 --- a/app/src/main/res/layout/activity_roulette_config.xml +++ b/app/src/main/res/layout/activity_roulette_config.xml @@ -1,15 +1,325 @@ - + android:background="@color/black"> - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/layout_user_profile_live.xml b/app/src/main/res/layout/layout_user_profile_live.xml index 9159c82..abe8bee 100644 --- a/app/src/main/res/layout/layout_user_profile_live.xml +++ b/app/src/main/res/layout/layout_user_profile_live.xml @@ -15,6 +15,30 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + + + + + app:layout_constraintTop_toBottomOf="@+id/ll_roulette_menu" />