라이브 방 - 룰렛 설정 추가
This commit is contained in:
parent
b359ca58ba
commit
952df91619
|
@ -125,6 +125,7 @@
|
||||||
<activity android:name=".audio_content.curation.AudioContentCurationActivity" />
|
<activity android:name=".audio_content.curation.AudioContentCurationActivity" />
|
||||||
<activity android:name=".audio_content.all.AudioContentNewAllActivity" />
|
<activity android:name=".audio_content.all.AudioContentNewAllActivity" />
|
||||||
<activity android:name=".audio_content.all.AudioContentRankingAllActivity" />
|
<activity android:name=".audio_content.all.AudioContentRankingAllActivity" />
|
||||||
|
<activity android:name=".live.roulette.config.RouletteConfigActivity" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
|
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
|
||||||
|
@ -135,14 +136,13 @@
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".common.SodaLiveService"
|
android:name=".common.SodaLiveService"
|
||||||
android:stopWithTask="false"
|
|
||||||
android:foregroundServiceType="microphone|mediaPlayback"
|
android:foregroundServiceType="microphone|mediaPlayback"
|
||||||
/>
|
android:stopWithTask="false" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".audio_content.AudioContentPlayService"
|
android:name=".audio_content.AudioContentPlayService"
|
||||||
android:stopWithTask="false"
|
android:foregroundServiceType="mediaPlayback"
|
||||||
android:foregroundServiceType="mediaPlayback" />
|
android:stopWithTask="false" />
|
||||||
|
|
||||||
<!-- [START firebase_service] -->
|
<!-- [START firebase_service] -->
|
||||||
<service
|
<service
|
||||||
|
|
|
@ -29,6 +29,7 @@ object Constants {
|
||||||
const val EXTRA_MESSAGE_BOX = "extra_message_box"
|
const val EXTRA_MESSAGE_BOX = "extra_message_box"
|
||||||
const val EXTRA_TEXT_MESSAGE = "extra_text_message"
|
const val EXTRA_TEXT_MESSAGE = "extra_text_message"
|
||||||
const val EXTRA_LIVE_TIME_NOW = "extra_live_time_now"
|
const val EXTRA_LIVE_TIME_NOW = "extra_live_time_now"
|
||||||
|
const val EXTRA_RESULT_ROULETTE = "extra_result_roulette"
|
||||||
const val EXTRA_GO_TO_PREV_PAGE = "extra_go_to_prev_page"
|
const val EXTRA_GO_TO_PREV_PAGE = "extra_go_to_prev_page"
|
||||||
const val EXTRA_SELECT_RECIPIENT = "extra_select_recipient"
|
const val EXTRA_SELECT_RECIPIENT = "extra_select_recipient"
|
||||||
const val EXTRA_ROOM_CHANNEL_NAME = "extra_room_channel_name"
|
const val EXTRA_ROOM_CHANNEL_NAME = "extra_room_channel_name"
|
||||||
|
|
|
@ -43,6 +43,9 @@ import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationMessageViewMo
|
||||||
import kr.co.vividnext.sodalive.live.room.tag.LiveTagRepository
|
import kr.co.vividnext.sodalive.live.room.tag.LiveTagRepository
|
||||||
import kr.co.vividnext.sodalive.live.room.tag.LiveTagViewModel
|
import kr.co.vividnext.sodalive.live.room.tag.LiveTagViewModel
|
||||||
import kr.co.vividnext.sodalive.live.room.update.LiveRoomEditViewModel
|
import kr.co.vividnext.sodalive.live.room.update.LiveRoomEditViewModel
|
||||||
|
import kr.co.vividnext.sodalive.live.roulette.RouletteRepository
|
||||||
|
import kr.co.vividnext.sodalive.live.roulette.config.RouletteApi
|
||||||
|
import kr.co.vividnext.sodalive.live.roulette.config.RouletteSettingsViewModel
|
||||||
import kr.co.vividnext.sodalive.main.MainViewModel
|
import kr.co.vividnext.sodalive.main.MainViewModel
|
||||||
import kr.co.vividnext.sodalive.message.MessageApi
|
import kr.co.vividnext.sodalive.message.MessageApi
|
||||||
import kr.co.vividnext.sodalive.message.MessageRepository
|
import kr.co.vividnext.sodalive.message.MessageRepository
|
||||||
|
@ -145,6 +148,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
|
||||||
single { ApiBuilder().build(get(), AudioContentApi::class.java) }
|
single { ApiBuilder().build(get(), AudioContentApi::class.java) }
|
||||||
single { ApiBuilder().build(get(), FaqApi::class.java) }
|
single { ApiBuilder().build(get(), FaqApi::class.java) }
|
||||||
single { ApiBuilder().build(get(), MemberTagApi::class.java) }
|
single { ApiBuilder().build(get(), MemberTagApi::class.java) }
|
||||||
|
single { ApiBuilder().build(get(), RouletteApi::class.java) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val viewModelModule = module {
|
private val viewModelModule = module {
|
||||||
|
@ -197,6 +201,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
|
||||||
viewModel { AudioContentCurationViewModel(get()) }
|
viewModel { AudioContentCurationViewModel(get()) }
|
||||||
viewModel { AudioContentNewAllViewModel(get()) }
|
viewModel { AudioContentNewAllViewModel(get()) }
|
||||||
viewModel { AudioContentRankingAllViewModel(get()) }
|
viewModel { AudioContentRankingAllViewModel(get()) }
|
||||||
|
viewModel { RouletteSettingsViewModel(get()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val repositoryModule = module {
|
private val repositoryModule = module {
|
||||||
|
@ -219,6 +224,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
|
||||||
factory { FaqRepository(get()) }
|
factory { FaqRepository(get()) }
|
||||||
factory { MemberTagRepository(get()) }
|
factory { MemberTagRepository(get()) }
|
||||||
factory { UserProfileFantalkAllViewModel(get(), get()) }
|
factory { UserProfileFantalkAllViewModel(get(), get()) }
|
||||||
|
factory { RouletteRepository(get()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val moduleList = listOf(
|
private val moduleList = listOf(
|
||||||
|
|
|
@ -72,6 +72,7 @@ import kr.co.vividnext.sodalive.live.room.profile.LiveRoomProfileDialog
|
||||||
import kr.co.vividnext.sodalive.live.room.profile.LiveRoomProfileListAdapter
|
import kr.co.vividnext.sodalive.live.room.profile.LiveRoomProfileListAdapter
|
||||||
import kr.co.vividnext.sodalive.live.room.profile.LiveRoomUserProfileDialog
|
import kr.co.vividnext.sodalive.live.room.profile.LiveRoomUserProfileDialog
|
||||||
import kr.co.vividnext.sodalive.live.room.update.LiveRoomInfoEditDialog
|
import kr.co.vividnext.sodalive.live.room.update.LiveRoomInfoEditDialog
|
||||||
|
import kr.co.vividnext.sodalive.live.roulette.config.RouletteConfigActivity
|
||||||
import kr.co.vividnext.sodalive.report.ProfileReportDialog
|
import kr.co.vividnext.sodalive.report.ProfileReportDialog
|
||||||
import kr.co.vividnext.sodalive.report.ReportType
|
import kr.co.vividnext.sodalive.report.ReportType
|
||||||
import kr.co.vividnext.sodalive.report.UserReportDialog
|
import kr.co.vividnext.sodalive.report.UserReportDialog
|
||||||
|
@ -179,6 +180,17 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(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?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
agora = Agora(
|
agora = Agora(
|
||||||
context = this,
|
context = this,
|
||||||
|
@ -660,6 +672,16 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
|
||||||
response.creatorId == SharedPreferenceManager.userId &&
|
response.creatorId == SharedPreferenceManager.userId &&
|
||||||
SharedPreferenceManager.role == MemberRole.CREATOR.name
|
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.visibility = View.VISIBLE
|
||||||
binding.flDonationMessageList.setOnClickListener {
|
binding.flDonationMessageList.setOnClickListener {
|
||||||
LiveRoomDonationMessageDialog(
|
LiveRoomDonationMessageDialog(
|
||||||
|
|
|
@ -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<RouletteItem>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class RouletteItem(
|
||||||
|
@SerializedName("title") val title: String,
|
||||||
|
@SerializedName("weight") val weight: Int
|
||||||
|
)
|
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
|
@ -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<RouletteItem>
|
||||||
|
)
|
|
@ -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<ApiResponse<Any>>
|
||||||
|
|
||||||
|
@GET("/roulette")
|
||||||
|
fun getRoulette(
|
||||||
|
@Query("creatorId") creatorId: Long,
|
||||||
|
@Header("Authorization") authHeader: String
|
||||||
|
): Single<ApiResponse<GetRouletteResponse>>
|
||||||
|
}
|
|
@ -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>(
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
|
@ -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>(
|
||||||
|
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<RouletteOption>) {
|
||||||
|
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<EditText>(R.id.et_option)
|
||||||
|
val tvOptionTitle = optionView.findViewById<TextView>(R.id.tv_option_title)
|
||||||
|
val tvPercentage = optionView.findViewById<TextView>(R.id.tv_option_percentage)
|
||||||
|
val ivMinus = optionView.findViewById<ImageView>(R.id.iv_minus)
|
||||||
|
val ivPlus = optionView.findViewById<ImageView>(R.id.iv_plus)
|
||||||
|
val tvDelete = optionView.findViewById<TextView>(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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<Boolean>
|
||||||
|
get() = _isLoading
|
||||||
|
|
||||||
|
private val _toastLiveData = MutableLiveData<String?>()
|
||||||
|
val toastLiveData: LiveData<String?>
|
||||||
|
get() = _toastLiveData
|
||||||
|
|
||||||
|
private val _optionsLiveData = MutableLiveData<List<RouletteOption>>(listOf())
|
||||||
|
val optionsLiveData: LiveData<List<RouletteOption>>
|
||||||
|
get() = _optionsLiveData
|
||||||
|
|
||||||
|
private val _isActiveLiveData = MutableLiveData(false)
|
||||||
|
val isActiveLiveData: LiveData<Boolean>
|
||||||
|
get() = _isActiveLiveData
|
||||||
|
|
||||||
|
private val _canLiveData = MutableLiveData(5)
|
||||||
|
val canLiveData: LiveData<Int>
|
||||||
|
get() = _canLiveData
|
||||||
|
|
||||||
|
private val options = mutableListOf<RouletteOption>()
|
||||||
|
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<RouletteOption>) {
|
||||||
|
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<RouletteItem>()
|
||||||
|
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<RouletteOption>) {
|
||||||
|
this.options.clear()
|
||||||
|
this.options.addAll(options)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>(
|
||||||
|
FragmentRouletteWinningDetailsBinding::inflate
|
||||||
|
) {
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
setupView()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupView() {
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="@color/color_3bb9f1" />
|
||||||
|
<corners android:radius="10dp" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="@color/color_3bb9f1" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="@android:color/transparent" />
|
||||||
|
<corners android:radius="10dp" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="@color/color_3bb9f1" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="@color/color_ff5c49" />
|
||||||
|
<corners android:radius="8dp" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="@color/color_ff5c49" />
|
||||||
|
</shape>
|
|
@ -250,12 +250,12 @@
|
||||||
android:id="@+id/ll_view_users"
|
android:id="@+id/ll_view_users"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
android:background="@drawable/bg_round_corner_15_transparent_bbbbbb"
|
android:background="@drawable/bg_round_corner_15_transparent_bbbbbb"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingHorizontal="11dp"
|
android:paddingHorizontal="11dp"
|
||||||
android:visibility="gone"
|
|
||||||
android:paddingVertical="7dp"
|
android:paddingVertical="7dp"
|
||||||
android:layout_marginStart="8dp"
|
android:visibility="gone"
|
||||||
tools:ignore="RelativeOverlap">
|
tools:ignore="RelativeOverlap">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -388,19 +388,53 @@
|
||||||
app:layout_constraintBottom_toTopOf="@+id/rl_input_chat"
|
app:layout_constraintBottom_toTopOf="@+id/rl_input_chat"
|
||||||
app:layout_constraintEnd_toEndOf="parent">
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/fl_roulette"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="13.3dp"
|
||||||
|
android:background="@drawable/bg_round_corner_10_99525252"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/ic_roulette" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/fl_roulette_settings"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="13.3dp"
|
||||||
|
android:background="@drawable/bg_round_corner_10_99525252"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/ic_roulette_settings" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/fl_microphone_mute"
|
android:id="@+id/fl_microphone_mute"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="13.3dp"
|
android:layout_marginBottom="13.3dp"
|
||||||
android:background="@drawable/bg_round_corner_10_99525252"
|
android:background="@drawable/bg_round_corner_10_99525252"
|
||||||
android:padding="11.7dp"
|
android:padding="10dp"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/iv_microphone_mute"
|
android:id="@+id/iv_microphone_mute"
|
||||||
android:layout_width="26.7dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="26.7dp"
|
android:layout_height="24dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/ic_mic_on" />
|
android:src="@drawable/ic_mic_on" />
|
||||||
|
@ -412,12 +446,12 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="13.3dp"
|
android:layout_marginBottom="13.3dp"
|
||||||
android:background="@drawable/bg_round_corner_10_99525252"
|
android:background="@drawable/bg_round_corner_10_99525252"
|
||||||
android:padding="11.7dp">
|
android:padding="10dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/iv_speaker_mute"
|
android:id="@+id/iv_speaker_mute"
|
||||||
android:layout_width="26.7dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="26.7dp"
|
android:layout_height="24dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/ic_speaker_on" />
|
android:src="@drawable/ic_speaker_on" />
|
||||||
|
@ -429,11 +463,11 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="13.3dp"
|
android:layout_marginBottom="13.3dp"
|
||||||
android:background="@drawable/bg_round_corner_10_99525252"
|
android:background="@drawable/bg_round_corner_10_99525252"
|
||||||
android:padding="11.7dp">
|
android:padding="10dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="26.7dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="26.7dp"
|
android:layout_height="24dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/ic_donation" />
|
android:src="@drawable/ic_donation" />
|
||||||
|
@ -445,13 +479,13 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="13.3dp"
|
android:layout_marginBottom="13.3dp"
|
||||||
android:background="@drawable/bg_round_corner_10_99525252"
|
android:background="@drawable/bg_round_corner_10_99525252"
|
||||||
android:padding="11.7dp"
|
android:padding="10dp"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/iv_donation_message_list"
|
android:id="@+id/iv_donation_message_list"
|
||||||
android:layout_width="26.7dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="26.7dp"
|
android:layout_height="24dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/ic_donation_message_list" />
|
android:src="@drawable/ic_donation_message_list" />
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
layout="@layout/detail_toolbar" />
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabLayout
|
||||||
|
android:id="@+id/tabs"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
app:tabIndicatorColor="@color/color_9970ff"
|
||||||
|
app:tabIndicatorFullWidth="true"
|
||||||
|
app:tabIndicatorHeight="1.3dp"
|
||||||
|
app:tabSelectedTextColor="@color/color_eeeeee"
|
||||||
|
app:tabTextAppearance="@style/tabText"
|
||||||
|
app:tabTextColor="@color/color_777777" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="@color/color_88909090" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,176 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:background="@color/black">
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/ll_actions"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingHorizontal="13.3dp">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="26.7dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:text="룰렛을 활성화 하시겠습니까?"
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_roulette_is_active"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
tools:src="@drawable/btn_toggle_off_big" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="26.7dp"
|
||||||
|
android:layout_marginBottom="13.3dp"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:text="룰렛 금액 설정"
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/et_set_price"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_toStartOf="@+id/tv_price_unit"
|
||||||
|
android:background="@drawable/bg_round_corner_6_7_222222"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:hint="룰렛 금액을 입력해 주세요.(최소 5캔)"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="numberSigned"
|
||||||
|
android:paddingHorizontal="13.3dp"
|
||||||
|
android:paddingVertical="16.7dp"
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textColorHint="@color/color_777777"
|
||||||
|
android:textCursorDrawable="@drawable/edit_text_cursor"
|
||||||
|
android:textSize="13.3sp"
|
||||||
|
android:theme="@style/EditTextStyle"
|
||||||
|
tools:ignore="LabelFor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_price_unit"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:text="캔"
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textSize="16.7sp" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="26.7dp"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:text="룰렛 옵션 설정"
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="21.3dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:text="※ 룰렛 옵션은 최소 2개,\n최대 6개까지 설정할 수 있습니다."
|
||||||
|
android:textColor="@color/color_ff5c49"
|
||||||
|
android:textSize="13.3sp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_add_option"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/btn_add" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/ll_roulette_option_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="21.3dp"
|
||||||
|
android:orientation="vertical" />
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/ll_actions"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/bg_top_round_corner_16_7_222222"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="13.3dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_preview"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_round_corner_10_transparent_3bb9f1"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingVertical="16dp"
|
||||||
|
android:text="미리보기"
|
||||||
|
android:textColor="@color/color_3bb9f1"
|
||||||
|
android:textSize="18.3sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_save"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="13.3dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_round_corner_10_3bb9f1"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingVertical="16dp"
|
||||||
|
android:text="설정완료"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="18.3sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,92 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="21.3dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:background="@color/black">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_option_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textSize="14.7sp"
|
||||||
|
tools:ignore="RelativeOverlap"
|
||||||
|
tools:text="옵션1" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_delete"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="삭제"
|
||||||
|
android:textColor="@color/color_ff5c49"
|
||||||
|
android:textSize="14.7sp" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="6.7dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/et_option"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_round_corner_6_7_222222"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:hint="옵션을 입력하세요"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textWebEditText"
|
||||||
|
android:paddingHorizontal="13.3dp"
|
||||||
|
android:paddingVertical="16.7dp"
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textColorHint="@color/color_777777"
|
||||||
|
android:textCursorDrawable="@drawable/edit_text_cursor"
|
||||||
|
android:textSize="14.7sp"
|
||||||
|
android:theme="@style/EditTextStyle"
|
||||||
|
tools:ignore="LabelFor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_option_percentage"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:background="@drawable/bg_round_corner_6_7_222222"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingHorizontal="13.3dp"
|
||||||
|
android:paddingVertical="16.7dp"
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textSize="14.7sp"
|
||||||
|
tools:text="50%" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_minus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/btn_minus_round_rect" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_plus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/btn_plus_round_rect" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
Loading…
Reference in New Issue