diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d30549d..ad5a1ca 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -55,6 +55,8 @@ + + ( layoutUserProfile.ivProfile.load(creator.profileUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(CircleCropTransformation()) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileLiveAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileLiveAdapter.kt index 186a45a..b7a41fb 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileLiveAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileLiveAdapter.kt @@ -28,7 +28,7 @@ class UserProfileLiveAdapter( fun bind(item: LiveRoomResponse) { binding.ivCover.load(item.coverImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(4.7f.dpToPx())) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileSimilarCreatorAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileSimilarCreatorAdapter.kt index e4b98c5..d3082b2 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileSimilarCreatorAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/UserProfileSimilarCreatorAdapter.kt @@ -20,7 +20,7 @@ class UserProfileSimilarCreatorAdapter( fun bind(item: SimilarCreatorResponse) { binding.ivProfile.load(item.profileImage) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(CircleCropTransformation()) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/cheers/UserProfileCheersAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/cheers/UserProfileCheersAdapter.kt index 2a87151..db1a43b 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/cheers/UserProfileCheersAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/cheers/UserProfileCheersAdapter.kt @@ -35,7 +35,7 @@ class UserProfileCheersAdapter( binding.ivProfile.load(cheers.profileUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(16.7f.dpToPx())) } binding.tvContent.text = cheers.content diff --git a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/donation/UserProfileDonationAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/donation/UserProfileDonationAdapter.kt index 404cba3..8f615b1 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/donation/UserProfileDonationAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/donation/UserProfileDonationAdapter.kt @@ -22,7 +22,7 @@ class UserProfileDonationAdapter : RecyclerView.Adapter>> + + @GET("/live/reservation") + fun getReservations( + @Query("timezone") timezone: String, + @Query("isActive") active: Boolean, + @Header("Authorization") authHeader: String + ): Single>> + + @GET("/live/reservation/{id}") + fun getReservation( + @Path("id") id: Long, + @Query("timezone") timezone: String, + @Header("Authorization") authHeader: String + ): Single> + + @PUT("/live/reservation/cancel") + fun cancelReservation( + @Body request: CancelLiveReservationRequest, + @Header("Authorization") authHeader: String + ): Single> } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/LiveRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/LiveRepository.kt index 69fd573..eda45f8 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/LiveRepository.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/LiveRepository.kt @@ -4,6 +4,7 @@ import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Single import kr.co.vividnext.sodalive.common.ApiResponse import kr.co.vividnext.sodalive.live.reservation.MakeLiveReservationRequest +import kr.co.vividnext.sodalive.live.reservation_status.CancelLiveReservationRequest import kr.co.vividnext.sodalive.live.room.CancelLiveRequest import kr.co.vividnext.sodalive.live.room.EnterOrQuitLiveRoomRequest import kr.co.vividnext.sodalive.live.room.LiveRoomStatus @@ -210,4 +211,23 @@ class LiveRepository( ) = api.donationStatus(roomId, authHeader = token) fun recentVisitRoomUsers(token: String) = api.recentVisitRoomUsers(authHeader = token) + + fun getReservations( + active: Boolean, + token: String + ) = api.getReservations(TimeZone.getDefault().id, active, authHeader = token) + + fun getReservation( + reservationId: Long, + token: String + ) = api.getReservation( + id = reservationId, + timezone = TimeZone.getDefault().id, + authHeader = token + ) + + fun cancelReservation( + request: CancelLiveReservationRequest, + token: String + ) = api.cancelReservation(request, authHeader = token) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/now/LiveNowAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/now/LiveNowAdapter.kt index 52a73a2..c99fd81 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/now/LiveNowAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/now/LiveNowAdapter.kt @@ -25,7 +25,7 @@ class LiveNowAdapter( fun bind(item: GetRoomListResponse) { binding.ivCover.load(item.coverImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(4.7f.dpToPx())) } binding.tvManager.text = item.managerNickname diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/recommend/RecommendLiveAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/recommend/RecommendLiveAdapter.kt index 4906110..9d35af8 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/recommend/RecommendLiveAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/recommend/RecommendLiveAdapter.kt @@ -28,7 +28,7 @@ class RecommendLiveAdapter( ivRecommendLive.load(data.imageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(5.3f.dpToPx())) } ivRecommendLive.layoutParams = layoutParams diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/recommend_channel/LiveRecommendChannelAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/recommend_channel/LiveRecommendChannelAdapter.kt index 75727ee..6b21cb6 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/recommend_channel/LiveRecommendChannelAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/recommend_channel/LiveRecommendChannelAdapter.kt @@ -54,7 +54,7 @@ class LiveRecommendChannelAdapter( fun bind(item: GetRecommendChannelResponse) { binding.ivRecommendChannel.load(item.profileImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(30f.dpToPx())) } binding.tvRecommendChannelNickname.text = item.nickname diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/reservation/LiveReservationAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation/LiveReservationAdapter.kt index bb2605e..2001340 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/reservation/LiveReservationAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation/LiveReservationAdapter.kt @@ -76,7 +76,7 @@ class LiveReservationAdapter( fun bind(item: GetRoomListResponse) { binding.ivCover.load(item.coverImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(4.7f.dpToPx())) } binding.tvDate.text = item.beginDateTime @@ -122,7 +122,7 @@ class LiveReservationAdapter( } binding.ivCover.load(item.coverImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(4f.dpToPx())) } binding.tvDate.text = item.beginDateTime diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/CancelLiveReservationRequest.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/CancelLiveReservationRequest.kt new file mode 100644 index 0000000..686468e --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/CancelLiveReservationRequest.kt @@ -0,0 +1,11 @@ +package kr.co.vividnext.sodalive.live.reservation_status + +import com.google.gson.annotations.SerializedName + +data class CancelLiveReservationRequest( + @SerializedName("reservationId") + val reservationId: Long, + + @SerializedName("reason") + val reason: String +) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/GetLiveReservationResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/GetLiveReservationResponse.kt new file mode 100644 index 0000000..21d2565 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/GetLiveReservationResponse.kt @@ -0,0 +1,17 @@ +package kr.co.vividnext.sodalive.live.reservation_status + +import android.os.Parcelable +import com.google.gson.annotations.SerializedName +import kotlinx.parcelize.Parcelize + +@Parcelize +data class GetLiveReservationResponse( + @SerializedName("reservationId") val reservationId: Long, + @SerializedName("roomId") val roomId: Long, + @SerializedName("title") val title: String, + @SerializedName("coverImageUrl") val coverImageUrl: String, + @SerializedName("price") val price: Int, + @SerializedName("masterNickname") val masterNickname: String, + @SerializedName("beginDateTime") val beginDateTime: String, + @SerializedName("cancelable") val cancelable: Boolean, +) : Parcelable diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/LiveReservationCancelActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/LiveReservationCancelActivity.kt new file mode 100644 index 0000000..a82df71 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/LiveReservationCancelActivity.kt @@ -0,0 +1,162 @@ +package kr.co.vividnext.sodalive.live.reservation_status + +import android.annotation.SuppressLint +import android.content.Intent +import android.os.Bundle +import android.view.View +import android.widget.Toast +import androidx.activity.OnBackPressedCallback +import coil.load +import coil.transform.RoundedCornersTransformation +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.LoadingDialog +import kr.co.vividnext.sodalive.databinding.ActivityLiveReservationCancelBinding +import kr.co.vividnext.sodalive.extensions.dpToPx +import kr.co.vividnext.sodalive.main.MainActivity +import kr.co.vividnext.sodalive.mypage.can.status.CanStatusActivity +import org.koin.android.ext.android.inject + +class LiveReservationCancelActivity : BaseActivity( + ActivityLiveReservationCancelBinding::inflate +) { + + private val viewModel: LiveReservationStatusViewModel by inject() + private lateinit var loadingDialog: LoadingDialog + private var reservationId: Long = 0 + + private val onBackPressedCallback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + setResult(RESULT_OK) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + onBackPressedDispatcher.addCallback(this, onBackPressedCallback) + + reservationId = intent.getLongExtra("reservation_id", 0) + if (reservationId <= 0) { + Toast.makeText(applicationContext, "잘못된 예약정보 입니다.", Toast.LENGTH_LONG).show() + finish() + return + } + + viewModel.isLoading.observe(this) { + if (it) { + loadingDialog.show(screenWidth, "") + } else { + loadingDialog.dismiss() + } + } + + viewModel.toastLiveData.observe(this) { + it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() } + } + + compositeDisposable.add( + binding.etReasonEtc.textChanges().skip(1) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { + if (binding.tvReason5.isSelected) { + viewModel.reason = it.toString() + } + } + ) + + viewModel.reservationId = reservationId + viewModel.getReservation { setReservation(it) } + } + + @SuppressLint("SetTextI18n") + override fun setupView() { + loadingDialog = LoadingDialog(this, layoutInflater) + binding.toolbar.tvBack.text = "예약취소" + binding.toolbar.tvBack.setOnClickListener { finish() } + + binding.tvReason1.setOnClickListener { + checkboxSelectedFalse() + binding.tvReason1.isSelected = true + viewModel.reason = binding.tvReason1.text.toString() + } + + binding.tvReason2.setOnClickListener { + checkboxSelectedFalse() + binding.tvReason2.isSelected = true + viewModel.reason = binding.tvReason2.text.toString() + } + + binding.tvReason3.setOnClickListener { + checkboxSelectedFalse() + binding.tvReason3.isSelected = true + viewModel.reason = binding.tvReason3.text.toString() + } + + binding.tvReason4.setOnClickListener { + checkboxSelectedFalse() + binding.tvReason4.isSelected = true + viewModel.reason = binding.tvReason4.text.toString() + } + + binding.tvReason5.setOnClickListener { + checkboxSelectedFalse() + binding.tvReason5.isSelected = true + viewModel.reason = binding.etReasonEtc.text.toString() + } + + binding.tvOtherSudaReservation.setOnClickListener { + finishAffinity() + startActivity(Intent(applicationContext, MainActivity::class.java)) + } + + binding.tvCheckCoinStatus.setOnClickListener { + startActivity(Intent(applicationContext, CanStatusActivity::class.java)) + } + + binding.tvCancel.setOnClickListener { + viewModel.cancelReservation { + if (binding.tvPrice.text == "무료") { + binding.tvCancelComplete.visibility = View.GONE + } else { + binding.tvCancelComplete.visibility = View.VISIBLE + binding.tvCancelComplete.text = "결제한 ${binding.tvPrice.text}이 \n환불처리 되었습니다." + } + binding.llCancelComplete.visibility = View.VISIBLE + binding.llCancelConfirm.visibility = View.GONE + binding.toolbar.tvBack.text = "예약취소 확인" + } + } + } + + private fun checkboxSelectedFalse() { + binding.tvReason1.isSelected = false + binding.tvReason2.isSelected = false + binding.tvReason3.isSelected = false + binding.tvReason4.isSelected = false + binding.tvReason5.isSelected = false + } + + @SuppressLint("SetTextI18n") + private fun setReservation(response: GetLiveReservationResponse) { + binding.tvDate.text = response.beginDateTime + binding.tvNickname.text = response.masterNickname + binding.tvTitle.text = response.title + binding.ivProfile.load(response.coverImageUrl) { + crossfade(true) + placeholder(R.drawable.ic_logo) + transformations(RoundedCornersTransformation(4.7f.dpToPx())) + } + + if (response.price > 0) { + binding.tvCheckCoinStatus.visibility = View.VISIBLE + binding.tvPrice.text = "${response.price}코인" + } else { + binding.tvCheckCoinStatus.visibility = View.GONE + binding.tvPrice.text = "무료" + } + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/LiveReservationStatusActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/LiveReservationStatusActivity.kt new file mode 100644 index 0000000..6db868c --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/LiveReservationStatusActivity.kt @@ -0,0 +1,124 @@ +package kr.co.vividnext.sodalive.live.reservation_status + +import android.annotation.SuppressLint +import android.app.Activity +import android.content.Intent +import android.graphics.Rect +import android.os.Bundle +import android.view.View +import android.widget.Toast +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import kr.co.vividnext.sodalive.base.BaseActivity +import kr.co.vividnext.sodalive.common.LoadingDialog +import kr.co.vividnext.sodalive.databinding.ActivityLiveReservationStatusBinding +import kr.co.vividnext.sodalive.extensions.dpToPx +import org.koin.android.ext.android.inject + +class LiveReservationStatusActivity : BaseActivity( + ActivityLiveReservationStatusBinding::inflate +) { + private val viewModel: LiveReservationStatusViewModel by inject() + + private lateinit var loadingDialog: LoadingDialog + private lateinit var adapter: LiveReservationStatusAdapter + private lateinit var cancelActivityResultLauncher: ActivityResultLauncher + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + cancelActivityResultLauncher = registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { + if (it.resultCode == Activity.RESULT_OK) { + adapter.items.clear() + viewModel.getLiveReservationStatus(isActive = true) + } + } + + bindData() + viewModel.getLiveReservationStatus(isActive = true) + } + + override fun setupView() { + binding.toolbar.tvBack.text = "라이브 예약 현황" + binding.toolbar.tvBack.setOnClickListener { finish() } + loadingDialog = LoadingDialog(this, layoutInflater) + + val recyclerView = binding.recyclerView + adapter = LiveReservationStatusAdapter { + val intent = Intent(applicationContext, LiveReservationCancelActivity::class.java) + intent.putExtra("reservation_id", it.reservationId) + cancelActivityResultLauncher.launch(intent) + } + + recyclerView.layoutManager = LinearLayoutManager( + applicationContext, + LinearLayoutManager.VERTICAL, + false + ) + + recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() { + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + super.getItemOffsets(outRect, view, parent, state) + + outRect.left = 13.3f.dpToPx().toInt() + outRect.right = 13.3f.dpToPx().toInt() + + when (parent.getChildAdapterPosition(view)) { + 0 -> { + outRect.top = 13.3f.dpToPx().toInt() + outRect.bottom = 6.7f.dpToPx().toInt() + } + + adapter.itemCount - 1 -> { + outRect.top = 6.7f.dpToPx().toInt() + outRect.bottom = 13.3f.dpToPx().toInt() + } + + else -> { + outRect.top = 6.7f.dpToPx().toInt() + outRect.bottom = 6.7f.dpToPx().toInt() + } + } + } + }) + + recyclerView.adapter = adapter + } + + @SuppressLint("NotifyDataSetChanged") + private fun bindData() { + viewModel.liveReservationStatusLiveData.observe(this) { + if (adapter.items.size > 0 || it.isNotEmpty()) { + adapter.items.addAll(it) + adapter.notifyDataSetChanged() + + binding.recyclerView.visibility = View.VISIBLE + binding.tvNoItems.visibility = View.GONE + } else { + binding.recyclerView.visibility = View.GONE + binding.tvNoItems.visibility = View.VISIBLE + } + } + + viewModel.toastLiveData.observe(this) { + it?.let { Toast.makeText(this, it, Toast.LENGTH_LONG).show() } + } + + viewModel.isLoading.observe(this) { + if (it) { + loadingDialog.show(screenWidth) + } else { + loadingDialog.dismiss() + } + } + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/LiveReservationStatusAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/LiveReservationStatusAdapter.kt new file mode 100644 index 0000000..99a50a0 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/LiveReservationStatusAdapter.kt @@ -0,0 +1,64 @@ +package kr.co.vividnext.sodalive.live.reservation_status + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import coil.load +import coil.transform.RoundedCornersTransformation +import kr.co.vividnext.sodalive.R +import kr.co.vividnext.sodalive.databinding.ItemLiveReservationStatusBinding +import kr.co.vividnext.sodalive.extensions.dpToPx + +class LiveReservationStatusAdapter( + private val onClickCancel: (GetLiveReservationResponse) -> Unit +) : RecyclerView.Adapter() { + + val items = mutableListOf() + + inner class ViewHolder( + private val binding: ItemLiveReservationStatusBinding, + ) : RecyclerView.ViewHolder(binding.root) { + + fun bind(item: GetLiveReservationResponse) { + binding.tvDate.text = item.beginDateTime + binding.tvNickname.text = item.masterNickname + binding.tvTitle.text = item.title + binding.ivProfile.load(item.coverImageUrl) { + crossfade(true) + placeholder(R.drawable.ic_logo) + transformations(RoundedCornersTransformation(4.7f.dpToPx())) + } + + binding.tvPrice.text = if (item.price > 0) { + "${item.price}코인" + } else { + "무료" + } + + if (item.cancelable) { + binding.tvCancel.setOnClickListener { onClickCancel(item) } + binding.tvCancel.visibility = View.VISIBLE + } else { + binding.tvCancel.visibility = View.GONE + binding.tvNonCancellable.visibility = View.VISIBLE + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder( + ItemLiveReservationStatusBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(items[position]) + } + + override fun getItemCount() = items.count() +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/LiveReservationStatusViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/LiveReservationStatusViewModel.kt new file mode 100644 index 0000000..ad48b02 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/reservation_status/LiveReservationStatusViewModel.kt @@ -0,0 +1,135 @@ +package kr.co.vividnext.sodalive.live.reservation_status + +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.LiveRepository + +class LiveReservationStatusViewModel( + private val repository: LiveRepository +) : BaseViewModel() { + + private val _liveReservationStatusLiveData = MutableLiveData>() + val liveReservationStatusLiveData: LiveData> + get() = _liveReservationStatusLiveData + + private val _toastLiveData = MutableLiveData() + val toastLiveData: LiveData + get() = _toastLiveData + + private var _isLoading = MutableLiveData(false) + val isLoading: LiveData + get() = _isLoading + + var reservationId: Long = 0 + var reason: String = "" + + fun getLiveReservationStatus(isActive: Boolean) { + if (!_isLoading.value!!) { + _isLoading.value = true + compositeDisposable.add( + repository.getReservations(isActive, "Bearer ${SharedPreferenceManager.token}") + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + if (it.success && it.data != null) { + _liveReservationStatusLiveData.postValue(it.data!!) + } else { + if (it.message != null) { + _toastLiveData.postValue(it.message) + } else { + _toastLiveData.postValue( + "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요." + ) + } + } + _isLoading.value = false + }, + { + _isLoading.value = false + it.message?.let { message -> Logger.e(message) } + _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.") + } + ) + ) + } + } + + fun getReservation(onSuccess: (GetLiveReservationResponse) -> Unit) { + if (!_isLoading.value!!) { + _isLoading.value = true + compositeDisposable.add( + repository.getReservation(reservationId, "Bearer ${SharedPreferenceManager.token}") + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + if (it.success && it.data != null) { + onSuccess(it.data) + } else { + if (it.message != null) { + _toastLiveData.postValue(it.message) + } else { + _toastLiveData.postValue( + "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요." + ) + } + } + _isLoading.value = false + }, + { + + _isLoading.value = false + it.message?.let { message -> Logger.e(message) } + _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.") + } + ) + ) + } + } + + fun cancelReservation(onSuccess: () -> Unit) { + if (!_isLoading.value!!) { + if (reason.isBlank()) { + _toastLiveData.postValue("취소이유를 선택해주세요.") + return + } + + _isLoading.value = true + compositeDisposable.add( + repository.cancelReservation( + CancelLiveReservationRequest(reservationId, reason), + "Bearer ${SharedPreferenceManager.token}" + ).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + if (it.success) { + _toastLiveData.postValue("라이브 예약이 취소되었습니다.") + onSuccess() + } 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("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.") + } + ) + ) + } + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/room/LiveRoomActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/room/LiveRoomActivity.kt index d18cfaf..7189700 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/room/LiveRoomActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/room/LiveRoomActivity.kt @@ -562,7 +562,7 @@ class LiveRoomActivity : BaseActivity(ActivityLiveRoomB binding.tvTitle.text = response.title binding.ivCover.load(response.coverImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) } isAvailableDonation = response.isAvailableDonation @@ -625,7 +625,7 @@ class LiveRoomActivity : BaseActivity(ActivityLiveRoomB if (newCoverImageUri != null) { binding.ivCover.load(newCoverImageUri) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) } } @@ -679,7 +679,7 @@ class LiveRoomActivity : BaseActivity(ActivityLiveRoomB binding.tvCreatorNickname.text = response.managerNickname binding.ivCreatorProfile.load(response.managerProfileUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(CircleCropTransformation()) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/room/chat/LiveRoomChat.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/room/chat/LiveRoomChat.kt index 682a0a4..06a4c51 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/room/chat/LiveRoomChat.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/room/chat/LiveRoomChat.kt @@ -160,7 +160,7 @@ data class LiveRoomNormalChat( val itemBinding = binding as ItemLiveRoomChatBinding itemBinding.ivProfile.load(profileUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(23.3f.dpToPx())) } @@ -278,7 +278,7 @@ data class LiveRoomDonationChat( itemBinding.ivProfile.load(profileUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(23.3f.dpToPx())) } itemBinding.tvChat.text = spChat diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/room/create/LiveRoomCreateActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/room/create/LiveRoomCreateActivity.kt index cb80816..30490db 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/room/create/LiveRoomCreateActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/room/create/LiveRoomCreateActivity.kt @@ -105,7 +105,7 @@ class LiveRoomCreateActivity : BaseActivity( binding.ivCover.background = null binding.ivCover.load(fileUri) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(13.3f.dpToPx())) } viewModel.coverImageUri = fileUri @@ -282,7 +282,7 @@ class LiveRoomCreateActivity : BaseActivity( binding.ivCover.background = null binding.ivCover.load(it.coverImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(13.3f.dpToPx())) } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/room/detail/LiveRoomDetailAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/room/detail/LiveRoomDetailAdapter.kt index 2da2766..82f66c7 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/room/detail/LiveRoomDetailAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/room/detail/LiveRoomDetailAdapter.kt @@ -22,7 +22,7 @@ class LiveRoomDetailAdapter( binding.tvNickname.text = item.nickname binding.ivProfile.load(item.profileImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(23.4f.dpToPx())) } binding.root.setOnClickListener { onClick(item) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/room/detail/LiveRoomDetailFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/room/detail/LiveRoomDetailFragment.kt index ba18d11..6a05303 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/room/detail/LiveRoomDetailFragment.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/room/detail/LiveRoomDetailFragment.kt @@ -236,7 +236,7 @@ class LiveRoomDetailFragment( binding.tvManagerIntroduce.text = manager.introduce binding.ivManagerProfile.load(manager.profileImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(CircleCropTransformation()) } @@ -308,7 +308,7 @@ class LiveRoomDetailFragment( val itemView = ItemLiveDetailUserSummaryBinding.inflate(layoutInflater) itemView.ivProfile.load(user.profileImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(16.7f.dpToPx())) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/room/donation/LiveRoomDonationDialog.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/room/donation/LiveRoomDonationDialog.kt index 4a9b464..5abf219 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/room/donation/LiveRoomDonationDialog.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/room/donation/LiveRoomDonationDialog.kt @@ -83,7 +83,7 @@ class LiveRoomDonationDialog( dialogView.ivProfile.load(SharedPreferenceManager.profileImage) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(CircleCropTransformation()) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/room/donation/LiveRoomDonationRankingAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/room/donation/LiveRoomDonationRankingAdapter.kt index 26fe0ff..1a77749 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/room/donation/LiveRoomDonationRankingAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/room/donation/LiveRoomDonationRankingAdapter.kt @@ -45,7 +45,7 @@ class LiveRoomDonationRankingAdapter : binding.ivProfile.load(item.profileImage) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(CircleCropTransformation()) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/room/profile/LiveRoomProfileItem.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/room/profile/LiveRoomProfileItem.kt index efff22e..2fd375c 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/room/profile/LiveRoomProfileItem.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/room/profile/LiveRoomProfileItem.kt @@ -118,7 +118,7 @@ data class LiveRoomProfileItemMaster( itemBinding.tvNickname.text = nickname itemBinding.ivProfile.load(profileUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(CircleCropTransformation()) } if (id != SharedPreferenceManager.userId) { @@ -137,7 +137,7 @@ data class LiveRoomProfileItemManager( itemBinding.tvNickname.text = nickname itemBinding.ivProfile.load(profileUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(CircleCropTransformation()) } if (id != SharedPreferenceManager.userId) { @@ -159,7 +159,7 @@ data class LiveRoomProfileItemUser( itemBinding.tvNickname.text = nickname itemBinding.ivProfile.load(profileUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(CircleCropTransformation()) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/room/profile/LiveRoomProfileListAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/room/profile/LiveRoomProfileListAdapter.kt index 078d558..276ce5f 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/room/profile/LiveRoomProfileListAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/room/profile/LiveRoomProfileListAdapter.kt @@ -19,7 +19,7 @@ class LiveRoomProfileListAdapter : RecyclerView.Adapter dialogView.ivProfile.load(userProfile.profileUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(8.dpToPx())) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/room/tag/LiveTagAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/room/tag/LiveTagAdapter.kt index 504be6d..9e306c5 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/room/tag/LiveTagAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/room/tag/LiveTagAdapter.kt @@ -36,7 +36,7 @@ class LiveTagAdapter( binding.ivTag.load(item.image) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(30f.dpToPx())) } binding.tvTag.text = item.tag diff --git a/app/src/main/java/kr/co/vividnext/sodalive/live/room/update/LiveRoomInfoEditDialog.kt b/app/src/main/java/kr/co/vividnext/sodalive/live/room/update/LiveRoomInfoEditDialog.kt index 5b19e88..94eccb5 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/live/room/update/LiveRoomInfoEditDialog.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/live/room/update/LiveRoomInfoEditDialog.kt @@ -49,7 +49,7 @@ class LiveRoomInfoEditDialog( this.coverImageUri = coverImageUri dialogView.ivCover.load(coverImageUri) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(13.3f.dpToPx())) } } @@ -58,7 +58,7 @@ class LiveRoomInfoEditDialog( this.coverImageUrl = coverImageUrl dialogView.ivCover.load(coverImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(13.3f.dpToPx())) } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/message/SelectMessageRecipientAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/message/SelectMessageRecipientAdapter.kt index 8ffaca7..f536e5b 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/message/SelectMessageRecipientAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/message/SelectMessageRecipientAdapter.kt @@ -20,7 +20,7 @@ class SelectMessageRecipientAdapter( fun bind(item: GetRoomDetailUser) { binding.ivProfile.load(item.profileImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(23.4f.dpToPx())) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/message/text/TextMessageAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/message/text/TextMessageAdapter.kt index 97d46bb..3826b06 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/message/text/TextMessageAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/message/text/TextMessageAdapter.kt @@ -23,7 +23,7 @@ class TextMessageAdapter( if (SharedPreferenceManager.nickname == item.recipientNickname) { binding.ivProfile.load(item.senderProfileImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(23.4f.dpToPx())) } @@ -31,7 +31,7 @@ class TextMessageAdapter( } else { binding.ivProfile.load(item.recipientProfileImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(23.4f.dpToPx())) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/message/text/TextMessageDetailActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/message/text/TextMessageDetailActivity.kt index 3a72144..6c704a7 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/message/text/TextMessageDetailActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/message/text/TextMessageDetailActivity.kt @@ -114,7 +114,7 @@ class TextMessageDetailActivity : BaseActivity if (SharedPreferenceManager.nickname == messageItem?.recipientNickname) { binding.ivProfile.load(messageItem?.senderProfileImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(13.3f.dpToPx())) } @@ -122,7 +122,7 @@ class TextMessageDetailActivity : BaseActivity } else { binding.ivProfile.load(messageItem?.recipientProfileImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(13.3f.dpToPx())) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/message/voice/VoiceMessageAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/message/voice/VoiceMessageAdapter.kt index 1dca904..f81842a 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/message/voice/VoiceMessageAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/message/voice/VoiceMessageAdapter.kt @@ -57,7 +57,7 @@ class VoiceMessageAdapter( if (SharedPreferenceManager.nickname == item.recipientNickname) { binding.ivProfile.load(item.senderProfileImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(23.4f.dpToPx())) } @@ -65,7 +65,7 @@ class VoiceMessageAdapter( } else { binding.ivProfile.load(item.recipientProfileImageUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(23.4f.dpToPx())) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/message/voice/VoiceMessageWriteFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/message/voice/VoiceMessageWriteFragment.kt index 6e37a80..7d81507 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/message/voice/VoiceMessageWriteFragment.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/message/voice/VoiceMessageWriteFragment.kt @@ -103,7 +103,7 @@ class VoiceMessageWriteFragment( private fun setReceiver(userId: Long, nickname: String, profileUrl: String) { binding.ivProfile.load(profileUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(RoundedCornersTransformation(23.4f.dpToPx())) } binding.tvNickname.text = nickname diff --git a/app/src/main/java/kr/co/vividnext/sodalive/mypage/MyPageFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/mypage/MyPageFragment.kt index f1d4c5d..34ff206 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/mypage/MyPageFragment.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/mypage/MyPageFragment.kt @@ -23,6 +23,7 @@ import kr.co.vividnext.sodalive.mypage.auth.AuthVerifyRequest import kr.co.vividnext.sodalive.mypage.auth.BootpayResponse import kr.co.vividnext.sodalive.mypage.can.charge.CanChargeActivity import kr.co.vividnext.sodalive.mypage.can.status.CanStatusActivity +import kr.co.vividnext.sodalive.live.reservation_status.LiveReservationStatusActivity import kr.co.vividnext.sodalive.settings.SettingsActivity import kr.co.vividnext.sodalive.settings.notification.MemberRole import org.koin.android.ext.android.inject @@ -76,7 +77,14 @@ class MyPageFragment : BaseFragment(FragmentMyBinding::inflat ) } - binding.llReservationSuda.setOnClickListener {} + binding.llReservationLive.setOnClickListener { + startActivity( + Intent( + requireActivity(), + LiveReservationStatusActivity::class.java + ) + ) + } binding.rlServiceCenter.setOnClickListener {} @@ -133,7 +141,7 @@ class MyPageFragment : BaseFragment(FragmentMyBinding::inflat binding.ivProfile.load(it.profileUrl) { crossfade(true) - placeholder(R.drawable.bg_placeholder) + placeholder(R.drawable.ic_logo) transformations(CircleCropTransformation()) } binding.tvNickname.text = it.nickname diff --git a/app/src/main/res/drawable/bg_round_corner_6_7_transparent_9970ff.xml b/app/src/main/res/drawable/bg_round_corner_6_7_transparent_9970ff.xml new file mode 100644 index 0000000..5fe5854 --- /dev/null +++ b/app/src/main/res/drawable/bg_round_corner_6_7_transparent_9970ff.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/src/main/res/layout/activity_live_reservation_cancel.xml b/app/src/main/res/layout/activity_live_reservation_cancel.xml new file mode 100644 index 0000000..5841c36 --- /dev/null +++ b/app/src/main/res/layout/activity_live_reservation_cancel.xml @@ -0,0 +1,346 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_live_reservation_status.xml b/app/src/main/res/layout/activity_live_reservation_status.xml new file mode 100644 index 0000000..a1b2913 --- /dev/null +++ b/app/src/main/res/layout/activity_live_reservation_status.xml @@ -0,0 +1,34 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_my.xml b/app/src/main/res/layout/fragment_my.xml index da41b9e..8d40799 100644 --- a/app/src/main/res/layout/fragment_my.xml +++ b/app/src/main/res/layout/fragment_my.xml @@ -233,7 +233,7 @@ android:textSize="18.3sp" /> diff --git a/app/src/main/res/layout/item_live_reservation_status.xml b/app/src/main/res/layout/item_live_reservation_status.xml new file mode 100644 index 0000000..d7a72c3 --- /dev/null +++ b/app/src/main/res/layout/item_live_reservation_status.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +