From 952df91619ed473beae5326e318c75343cef18ca Mon Sep 17 00:00:00 2001 From: klaus Date: Fri, 1 Dec 2023 03:37:23 +0900 Subject: [PATCH] =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EB=B8=8C=20=EB=B0=A9=20-=20?= =?UTF-8?q?=EB=A3=B0=EB=A0=9B=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 8 +- .../co/vividnext/sodalive/common/Constants.kt | 1 + .../java/kr/co/vividnext/sodalive/di/AppDI.kt | 6 + .../sodalive/live/room/LiveRoomActivity.kt | 22 ++ .../live/roulette/GetRouletteResponse.kt | 14 ++ .../live/roulette/RouletteRepository.kt | 19 ++ .../config/CreateOrUpdateRouletteRequest.kt | 10 + .../live/roulette/config/RouletteApi.kt | 24 +++ .../roulette/config/RouletteConfigActivity.kt | 64 ++++++ .../live/roulette/config/RouletteOption.kt | 3 + .../config/RouletteSettingsFragment.kt | 163 ++++++++++++++ .../config/RouletteSettingsViewModel.kt | 201 ++++++++++++++++++ .../config/RouletteWinningDetailsFragment.kt | 19 ++ app/src/main/res/drawable-xxhdpi/btn_add.png | Bin 0 -> 3632 bytes .../drawable-xxhdpi/btn_minus_round_rect.png | Bin 0 -> 2438 bytes .../drawable-xxhdpi/btn_plus_round_rect.png | Bin 0 -> 2874 bytes .../main/res/drawable-xxhdpi/ic_roulette.png | Bin 0 -> 4914 bytes .../drawable-xxhdpi/ic_roulette_settings.png | Bin 0 -> 5631 bytes .../drawable/bg_round_corner_10_3bb9f1.xml | 8 + .../bg_round_corner_10_transparent_3bb9f1.xml | 8 + .../res/drawable/bg_round_corner_8_ff5c49.xml | 8 + .../main/res/layout/activity_live_room.xml | 62 ++++-- .../res/layout/activity_roulette_config.xml | 32 +++ .../res/layout/fragment_roulette_settings.xml | 176 +++++++++++++++ .../fragment_roulette_winning_details.xml | 6 + .../res/layout/layout_roulette_option.xml | 92 ++++++++ 26 files changed, 928 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/live/roulette/GetRouletteResponse.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/live/roulette/RouletteRepository.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/CreateOrUpdateRouletteRequest.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteApi.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteConfigActivity.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteOption.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteSettingsFragment.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteSettingsViewModel.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteWinningDetailsFragment.kt create mode 100644 app/src/main/res/drawable-xxhdpi/btn_add.png create mode 100644 app/src/main/res/drawable-xxhdpi/btn_minus_round_rect.png create mode 100644 app/src/main/res/drawable-xxhdpi/btn_plus_round_rect.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_roulette.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_roulette_settings.png create mode 100644 app/src/main/res/drawable/bg_round_corner_10_3bb9f1.xml create mode 100644 app/src/main/res/drawable/bg_round_corner_10_transparent_3bb9f1.xml create mode 100644 app/src/main/res/drawable/bg_round_corner_8_ff5c49.xml create mode 100644 app/src/main/res/layout/activity_roulette_config.xml create mode 100644 app/src/main/res/layout/fragment_roulette_settings.xml create mode 100644 app/src/main/res/layout/fragment_roulette_winning_details.xml create mode 100644 app/src/main/res/layout/layout_roulette_option.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5d851b4..75bbdd2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -125,6 +125,7 @@ + + android:stopWithTask="false" /> + android:foregroundServiceType="mediaPlayback" + android:stopWithTask="false" /> (ActivityLiveRoomB } } + private val rouletteConfigResult = registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { result -> + val resultCode = result.resultCode + val isActiveRoulette = result.data?.getBooleanExtra(Constants.EXTRA_RESULT_ROULETTE, false) + + if (resultCode == RESULT_OK && isActiveRoulette != null) { + // TODO 룰렛 활성화 / 비활성화 설정 리스너에게 알림 + } + } + override fun onCreate(savedInstanceState: Bundle?) { agora = Agora( context = this, @@ -660,6 +672,16 @@ class LiveRoomActivity : BaseActivity(ActivityLiveRoomB response.creatorId == SharedPreferenceManager.userId && SharedPreferenceManager.role == MemberRole.CREATOR.name ) { + binding.flRoulette.visibility = View.GONE + binding.flRouletteSettings.visibility = View.VISIBLE + binding.flRouletteSettings.setOnClickListener { + rouletteConfigResult.launch( + Intent( + applicationContext, + RouletteConfigActivity::class.java + ) + ) + } binding.flDonationMessageList.visibility = View.VISIBLE binding.flDonationMessageList.setOnClickListener { LiveRoomDonationMessageDialog( diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/GetRouletteResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/GetRouletteResponse.kt new file mode 100644 index 0000000..547ad30 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/GetRouletteResponse.kt @@ -0,0 +1,14 @@ +package kr.co.vividnext.sodalive.live.roulette + +import com.google.gson.annotations.SerializedName + +data class GetRouletteResponse( + @SerializedName("can") val can: Int, + @SerializedName("isActive") val isActive: Boolean, + @SerializedName("items") val items: List +) + +data class RouletteItem( + @SerializedName("title") val title: String, + @SerializedName("weight") val weight: Int +) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/RouletteRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/RouletteRepository.kt new file mode 100644 index 0000000..67aa2ac --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/RouletteRepository.kt @@ -0,0 +1,19 @@ +package kr.co.vividnext.sodalive.live.roulette + +import kr.co.vividnext.sodalive.live.roulette.config.CreateOrUpdateRouletteRequest +import kr.co.vividnext.sodalive.live.roulette.config.RouletteApi + +class RouletteRepository(private val api: RouletteApi) { + fun createOrUpdateRoulette( + request: CreateOrUpdateRouletteRequest, + token: String + ) = api.createOrUpdateRoulette( + request = request, + authHeader = token + ) + + fun getRoulette(creatorId: Long, token: String) = api.getRoulette( + creatorId = creatorId, + authHeader = token + ) +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/CreateOrUpdateRouletteRequest.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/CreateOrUpdateRouletteRequest.kt new file mode 100644 index 0000000..aced332 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/CreateOrUpdateRouletteRequest.kt @@ -0,0 +1,10 @@ +package kr.co.vividnext.sodalive.live.roulette.config + +import com.google.gson.annotations.SerializedName +import kr.co.vividnext.sodalive.live.roulette.RouletteItem + +data class CreateOrUpdateRouletteRequest( + @SerializedName("can") val can: Int, + @SerializedName("isActive") val isActive: Boolean, + @SerializedName("items") val items: List +) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteApi.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteApi.kt new file mode 100644 index 0000000..f0ac76e --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteApi.kt @@ -0,0 +1,24 @@ +package kr.co.vividnext.sodalive.live.roulette.config + +import io.reactivex.rxjava3.core.Single +import kr.co.vividnext.sodalive.common.ApiResponse +import kr.co.vividnext.sodalive.live.roulette.GetRouletteResponse +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.Header +import retrofit2.http.POST +import retrofit2.http.Query + +interface RouletteApi { + @POST("/roulette") + fun createOrUpdateRoulette( + @Body request: CreateOrUpdateRouletteRequest, + @Header("Authorization") authHeader: String + ): Single> + + @GET("/roulette") + fun getRoulette( + @Query("creatorId") creatorId: Long, + @Header("Authorization") authHeader: String + ): Single> +} 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 new file mode 100644 index 0000000..88a0a13 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteConfigActivity.kt @@ -0,0 +1,64 @@ +package kr.co.vividnext.sodalive.live.roulette.config + +import android.os.Bundle +import com.google.android.material.tabs.TabLayout +import kr.co.vividnext.sodalive.R +import kr.co.vividnext.sodalive.base.BaseActivity +import kr.co.vividnext.sodalive.databinding.ActivityRouletteConfigBinding + +class RouletteConfigActivity : BaseActivity( + ActivityRouletteConfigBinding::inflate +) { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + changeFragment("settings") + } + + override fun setupView() { + binding.toolbar.tvBack.text = "룰렛설정" + binding.toolbar.tvBack.setOnClickListener { finish() } + + val tabs = binding.tabs + tabs.addTab(tabs.newTab().setText("룰렛설정").setTag("settings")) + tabs.addTab(tabs.newTab().setText("당첨내역").setTag("winning-details")) + tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { + override fun onTabSelected(tab: TabLayout.Tab) { + val tag = tab.tag as String + changeFragment(tag) + } + + override fun onTabUnselected(tab: TabLayout.Tab) { + } + + override fun onTabReselected(tab: TabLayout.Tab) { + } + }) + } + + private fun changeFragment(tag: String) { + val fragmentManager = supportFragmentManager + val fragmentTransaction = fragmentManager.beginTransaction() + + val currentFragment = fragmentManager.primaryNavigationFragment + if (currentFragment != null) { + fragmentTransaction.hide(currentFragment) + } + + var fragment = fragmentManager.findFragmentByTag(tag) + if (fragment == null) { + fragment = if (tag == "settings") { + RouletteSettingsFragment() + } else { + RouletteWinningDetailsFragment() + } + + fragmentTransaction.add(R.id.container, fragment, tag) + } else { + fragmentTransaction.show(fragment) + } + + fragmentTransaction.setPrimaryNavigationFragment(fragment) + fragmentTransaction.setReorderingAllowed(true) + fragmentTransaction.commitNow() + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteOption.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteOption.kt new file mode 100644 index 0000000..4e89fec --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteOption.kt @@ -0,0 +1,3 @@ +package kr.co.vividnext.sodalive.live.roulette.config + +data class RouletteOption(var title: String, var weight: Int, var percentage: Int = 50) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteSettingsFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteSettingsFragment.kt new file mode 100644 index 0000000..f1f0e2d --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteSettingsFragment.kt @@ -0,0 +1,163 @@ +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.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.TextView +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.BaseFragment +import kr.co.vividnext.sodalive.common.Constants +import kr.co.vividnext.sodalive.common.LoadingDialog +import kr.co.vividnext.sodalive.databinding.FragmentRouletteSettingsBinding +import org.koin.android.ext.android.inject +import java.util.concurrent.TimeUnit + +class RouletteSettingsFragment : BaseFragment( + FragmentRouletteSettingsBinding::inflate +) { + private val viewModel: RouletteSettingsViewModel by inject() + + private lateinit var imm: InputMethodManager + private lateinit var loadingDialog: LoadingDialog + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setupView() + bindData() + viewModel.getRoulette() + } + + private fun setupView() { + loadingDialog = LoadingDialog(requireActivity(), layoutInflater) + imm = requireActivity().getSystemService( + Service.INPUT_METHOD_SERVICE + ) as InputMethodManager + + 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 { + + } + + binding.tvSave.setOnClickListener { _ -> + imm.hideSoftInputFromWindow(view?.windowToken, 0) + viewModel.createOrUpdateRoulette { + val resultIntent = Intent().apply { putExtra(Constants.EXTRA_RESULT_ROULETTE, it) } + requireActivity().setResult(Activity.RESULT_OK, resultIntent) + requireActivity().finish() + } + } + } + + private fun bindData() { + viewModel.isActiveLiveData.observe(viewLifecycleOwner) { + binding.ivRouletteIsActive.setImageResource( + if (it) R.drawable.btn_toggle_on_big else R.drawable.btn_toggle_off_big + ) + } + + viewModel.optionsLiveData.observe(viewLifecycleOwner) { updateOptionUi(it) } + + viewModel.toastLiveData.observe(viewLifecycleOwner) { it?.let { showToast(it) } } + + viewModel.canLiveData.observe(viewLifecycleOwner) { binding.etSetPrice.setText("$it") } + + viewModel.isLoading.observe(viewLifecycleOwner) { + if (it) { + loadingDialog.show(screenWidth) + } else { + loadingDialog.dismiss() + } + } + + 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("", 1) + 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(context) + .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 tvPercentage = optionView.findViewById(R.id.tv_option_percentage) + val ivMinus = optionView.findViewById(R.id.iv_minus) + val ivPlus = optionView.findViewById(R.id.iv_plus) + val tvDelete = optionView.findViewById(R.id.tv_delete) + + etOption.setText(option.title) + tvOptionTitle.text = "옵션 ${index + 1}" + tvPercentage.text = "${option.percentage}%" + ivMinus.setOnClickListener { viewModel.subtractWeight(index) } + ivPlus.setOnClickListener { viewModel.plusWeight(index) } + + 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()) + } + ) + + return optionView + } +} 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 new file mode 100644 index 0000000..eaf9ede --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteSettingsViewModel.kt @@ -0,0 +1,201 @@ +package kr.co.vividnext.sodalive.live.roulette.config + +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 +import kr.co.vividnext.sodalive.live.roulette.RouletteItem +import kr.co.vividnext.sodalive.live.roulette.RouletteRepository + +class RouletteSettingsViewModel(private val repository: RouletteRepository) : BaseViewModel() { + + private var _isLoading = MutableLiveData(false) + val isLoading: LiveData + get() = _isLoading + + private val _toastLiveData = MutableLiveData() + val toastLiveData: LiveData + get() = _toastLiveData + + private val _optionsLiveData = MutableLiveData>(listOf()) + val optionsLiveData: LiveData> + get() = _optionsLiveData + + private val _isActiveLiveData = MutableLiveData(false) + val isActiveLiveData: LiveData + get() = _isActiveLiveData + + private val _canLiveData = MutableLiveData(5) + val canLiveData: LiveData + get() = _canLiveData + + private val options = mutableListOf() + var can = 5 + var isActive = false + + fun plusWeight(optionIndex: Int) { + val currentOption = options[optionIndex] + options[optionIndex] = currentOption.copy(weight = currentOption.weight + 1) + recalculatePercentages(options) + } + + fun subtractWeight(optionIndex: Int) { + if (options[optionIndex].weight > 1) { + val currentOption = options[optionIndex] + options[optionIndex] = currentOption.copy(weight = currentOption.weight - 1) + recalculatePercentages(options) + } + } + + fun addOption(newOption: RouletteOption) { + if (options.size >= 6) return + + options.add(newOption) + recalculatePercentages(options) + } + + fun deleteOption(index: Int) { + val updatedOptions = options.filterIndexed { currentIndex, _ -> currentIndex != index } + removeAllAndAddOptions(updatedOptions) + recalculatePercentages(updatedOptions) + } + + fun inputOption(optionIndex: Int, title: String) { + val currentOption = options[optionIndex] + options[optionIndex] = currentOption.copy(title = title) + } + + private fun recalculatePercentages(options: List) { + val totalWeight = options.sumOf { it.weight } + val updatedOptions = options.asSequence().map { option -> + option.copy(percentage = (option.weight.toDouble() / totalWeight * 100).toInt()) + }.toList() + _optionsLiveData.value = updatedOptions + } + + fun toggleIsActive() { + isActive = !isActive + _isActiveLiveData.postValue(isActive) + } + + fun createOrUpdateRoulette(onSuccess: (Boolean) -> Unit) { + if (!_isLoading.value!!) { + _isLoading.value = true + + val items = mutableListOf() + for (option in options) { + if (option.title.trim().isEmpty()) { + _toastLiveData.value = "옵션은 빈칸을 할 수 없습니다." + _isLoading.value = false + return + } + + items.add(RouletteItem(title = option.title, weight = option.weight)) + } + + val request = CreateOrUpdateRouletteRequest( + can = can, + isActive = isActive, + items = items + ) + + compositeDisposable.add( + repository.createOrUpdateRoulette( + request = request, + token = "Bearer ${SharedPreferenceManager.token}" + ) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + _isLoading.value = false + if (it.success && it.data != null && it.data is Boolean) { + _toastLiveData.postValue("룰렛이 설정되었습니다.") + onSuccess(it.data) + } 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 getRoulette() { + if (!_isLoading.value!!) { + _isLoading.value = true + compositeDisposable.add( + repository.getRoulette( + creatorId = SharedPreferenceManager.userId, + token = "Bearer ${SharedPreferenceManager.token}" + ) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + if (it.success) { + val data = it.data + + if (data != null && data.items.isNotEmpty()) { + _isActiveLiveData.value = data.isActive + _canLiveData.value = data.can + + isActive = data.isActive + can = data.can + + val options = data.items.asSequence().map { item -> + RouletteOption(title = item.title, weight = item.weight) + }.toList() + removeAllAndAddOptions(options = options) + recalculatePercentages(options) + } else { + _isActiveLiveData.value = false + _canLiveData.value = 5 + + isActive = false + can = 5 + + options.add(RouletteOption(title = "", weight = 1)) + options.add(RouletteOption(title = "", weight = 1)) + recalculatePercentages(options) + } + } 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("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.") + } + ) + ) + } + } + + private fun removeAllAndAddOptions(options: List) { + this.options.clear() + this.options.addAll(options) + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteWinningDetailsFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteWinningDetailsFragment.kt new file mode 100644 index 0000000..d826b32 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/roulette/config/RouletteWinningDetailsFragment.kt @@ -0,0 +1,19 @@ +package kr.co.vividnext.sodalive.live.roulette.config + +import android.os.Bundle +import android.view.View +import kr.co.vividnext.sodalive.base.BaseFragment +import kr.co.vividnext.sodalive.databinding.FragmentRouletteWinningDetailsBinding + +class RouletteWinningDetailsFragment : BaseFragment( + FragmentRouletteWinningDetailsBinding::inflate +) { + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setupView() + } + + private fun setupView() { + } +} diff --git a/app/src/main/res/drawable-xxhdpi/btn_add.png b/app/src/main/res/drawable-xxhdpi/btn_add.png new file mode 100644 index 0000000000000000000000000000000000000000..b36e9b56700e8558d56a911dc4b818addfe4d46d GIT binary patch literal 3632 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 Y7}4}FA;!crG=T>g>Y5?m=s3px9}9<$o&W#< literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/btn_minus_round_rect.png b/app/src/main/res/drawable-xxhdpi/btn_minus_round_rect.png new file mode 100644 index 0000000000000000000000000000000000000000..ae6a88e2742f1e865ea57bc318cef43ca38bb04d GIT binary patch literal 2438 zcmb7G`9Bkm8=uL2tuf?Il24bTXvo;iRm?dohVo_Q3Y#NGCR>h3j>d=22TO8Ixe~&J z5IH{1+?3fY9cag>@d^2^vv)q4K@vgwPMKFm)AOkdbUf zdgaiKyC;K`x$Kaw{5%5Pr$zZ-mqSsi3um5!Zzk}kyC&#rI!DP>YAMK`%Fw`$l>f@k z3Ej6$?HZmjnYEU2ata9v2|Hq=o6FXAG@Q?D=3U$iByxE)rE1o@0|-5p;-tfArS8bf zTAfL4;4H83sypcZhqcW%ByA#GNH{r5@6AkYfV%V8WsHp&2rfY;W>6|kT~7L=5qs7Y zUZg4>K#~p|rWNrxA1-nq1pUC*>+C-l#uZf8strpmm{JQFI;;kHozVM_{Ijy7Y#d3 znUIqe_Rq%lau*C*Yjl&{)|{*BP$E*x?aX+=q9>%W-MyQ~v0kf6AYZ;)PWu^M*!aTN z&ev%m?8}Lj&@^-Z)(V$m*;V}7^=C%Zby(?n@SfR5yZRVq-(lvB2iayHMG2*TBSwQ0 zCBy>8ABBigzJv|DFN*$kT^q3g6@VHNr~ZXLGvA5D_J(~k8`Z%b5{D3lrX|8FXP^)V z*fsbp7MO{mQy&|qqx!FCTNRwkESyJ8=jB2Lky`W8kX$3)JN(6K(*$d^T2*0N6(43g zH$wpz4bskED?lV{Z8Pp!6hzhh)2IvR{$D3TI};DyM0m6??5$&x^n0>+5+f zI@yo}XB|R8s~$VUVh-KJa>`TBn)p10Ti{FRmwY1#?HD`Rw@oi817~~PABrLyIlVWA zyfAg0bW}8bn9Y(-AnX+C)6Z+CKSVC0rrq+Ifyl;ICmB#D>&R8(pSUyzeh!d!dHYD5 z?22C5oHAad6pMBJX{4tMDlM{$RwR?Oc)&d%b2Vcns&Fhx>%{*K(xsB__xD`lwd*)bmCF*2q;pA*=MXg7YQfbQ zOy9a^NKYp;ZXU0C+RYC^o{@7z?ul0_zOZ*P_g8#!OGl`#%v8)$KVjg7;{!bHxYJ9yOrRW$3GA?>|_j~MyK0Q(2)|NKWmBM0G= zR&VN%$iKJd+tunYn|_pua(x=zn|1?7TR6BWuyNCq7U34XsDfZNJU~AR^^=R6P^+~n>AdD- zZ|s)R0Mv}m&-J$E4rfIbg?DiV>D}8=;pK;A`0zH(Pd>1d1oDS4P$AJ@ysWft65Gok z5iv6vf)gFFf4#x&PS&ij#h=*i8I;P)cA>PW6=9!+CEpEC4dSPO_g%}4)JyB=%&)KC zj&xA#M4qf&$ZpT|yQiXxlQjs__#-r`OBtpRa@U*<03mpk}EOQPUtg7gU^C#`p7IDrTN5L#1cTe?nBow!@2{2GIDgg3Dj&_#sE)mOKIG76INzb$d0F`# z;FU)3E;fcs8Cx%jt~!rnnN10q#Qy#K`_Jm;+*otI67sM-#P&?2oEOGZdYUlq&f!?> z#|~=I2^rGosblv^w!-@C_`BDi0|%#i_r=QnZ+@9nqrR$>T!vTvA+bvNAaA7dq&SxN z?aTVYt83&Acvd(-b;G}{Jj0}p!Gb$>y>i;8k)s!;I8<=D+RqFXELh0iDnJsJ4 zzy1huqj&y3C%*SiE_bH3jSin9-i4^j$H$}dJ2pa$&JK+P-i93}@PDVf$Uu^}K5j5s zL1(44$>rP?E1V($5o6%kU#%=YA-1f%6w7z!_sQT|;alV~kk03<`6c`}6=&qZ8+=dF zb|EbRZt*l;)XLCVIwd&DevVF$tRBhWl1_WHK^Puv>se9txVH=h>HRQt>Y1&=ph6Aj zKNpsHi_)zPZ)3g+(1m6TYL^AT!p-eV6Q>RqdU#H`+3t*BTx5^cPl)2Qm^BMwxgO1g zCLO{Yb?hK~4=ZsP!)I@qU&IyGVgn1)MTv=nADc z*O*x*s>+)@@QO~Z(dUU%;HB{m!P#^L_2O9)X!oG{SxG{T*27ay1G)ER*LJQX+{zZb U%?eiMyiEWL6BP0_!sF3@0sU->DF6Tf literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/btn_plus_round_rect.png b/app/src/main/res/drawable-xxhdpi/btn_plus_round_rect.png new file mode 100644 index 0000000000000000000000000000000000000000..a22155e15cc787c862ac41799a63c67a8745b371 GIT binary patch literal 2874 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_roulette_settings.png b/app/src/main/res/drawable-xxhdpi/ic_roulette_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..8d10a95ac0c35fe761fcaec7fd179ba7afc0cd16 GIT binary patch literal 5631 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 Z{{tO%DHo#d`KAB>002ovPDHLkV1jU-zPSJZ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/bg_round_corner_10_3bb9f1.xml b/app/src/main/res/drawable/bg_round_corner_10_3bb9f1.xml new file mode 100644 index 0000000..099aa25 --- /dev/null +++ b/app/src/main/res/drawable/bg_round_corner_10_3bb9f1.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/src/main/res/drawable/bg_round_corner_10_transparent_3bb9f1.xml b/app/src/main/res/drawable/bg_round_corner_10_transparent_3bb9f1.xml new file mode 100644 index 0000000..83f3219 --- /dev/null +++ b/app/src/main/res/drawable/bg_round_corner_10_transparent_3bb9f1.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/src/main/res/drawable/bg_round_corner_8_ff5c49.xml b/app/src/main/res/drawable/bg_round_corner_8_ff5c49.xml new file mode 100644 index 0000000..ed5ce37 --- /dev/null +++ b/app/src/main/res/drawable/bg_round_corner_8_ff5c49.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/src/main/res/layout/activity_live_room.xml b/app/src/main/res/layout/activity_live_room.xml index d4bd5a2..6620e76 100644 --- a/app/src/main/res/layout/activity_live_room.xml +++ b/app/src/main/res/layout/activity_live_room.xml @@ -250,12 +250,12 @@ android:id="@+id/ll_view_users" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginStart="8dp" android:background="@drawable/bg_round_corner_15_transparent_bbbbbb" android:orientation="horizontal" android:paddingHorizontal="11dp" - android:visibility="gone" android:paddingVertical="7dp" - android:layout_marginStart="8dp" + android:visibility="gone" tools:ignore="RelativeOverlap"> + + + + + + + + + + @@ -412,12 +446,12 @@ android:layout_height="wrap_content" android:layout_marginBottom="13.3dp" android:background="@drawable/bg_round_corner_10_99525252" - android:padding="11.7dp"> + android:padding="10dp"> @@ -429,11 +463,11 @@ android:layout_height="wrap_content" android:layout_marginBottom="13.3dp" android:background="@drawable/bg_round_corner_10_99525252" - android:padding="11.7dp"> + android:padding="10dp"> @@ -445,13 +479,13 @@ android:layout_height="wrap_content" android:layout_marginBottom="13.3dp" android:background="@drawable/bg_round_corner_10_99525252" - android:padding="11.7dp" + android:padding="10dp" android:visibility="gone"> diff --git a/app/src/main/res/layout/activity_roulette_config.xml b/app/src/main/res/layout/activity_roulette_config.xml new file mode 100644 index 0000000..03d60d3 --- /dev/null +++ b/app/src/main/res/layout/activity_roulette_config.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_roulette_settings.xml b/app/src/main/res/layout/fragment_roulette_settings.xml new file mode 100644 index 0000000..75f1c6b --- /dev/null +++ b/app/src/main/res/layout/fragment_roulette_settings.xml @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_roulette_winning_details.xml b/app/src/main/res/layout/fragment_roulette_winning_details.xml new file mode 100644 index 0000000..1354408 --- /dev/null +++ b/app/src/main/res/layout/fragment_roulette_winning_details.xml @@ -0,0 +1,6 @@ + + + + diff --git a/app/src/main/res/layout/layout_roulette_option.xml b/app/src/main/res/layout/layout_roulette_option.xml new file mode 100644 index 0000000..12835fa --- /dev/null +++ b/app/src/main/res/layout/layout_roulette_option.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + +