콘텐츠 업로드

- 예약 업로드를 위해 날짜/시간 선택 추가
This commit is contained in:
2024-01-08 15:09:50 +09:00
parent 5f7ed22711
commit 45e5494653
5 changed files with 442 additions and 44 deletions

View File

@@ -2,6 +2,8 @@ package kr.co.vividnext.sodalive.audio_content.upload
import android.Manifest
import android.annotation.SuppressLint
import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.content.Intent
import android.net.Uri
import android.os.Build
@@ -28,9 +30,15 @@ import kr.co.vividnext.sodalive.common.RealPathUtil
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentUploadBinding
import kr.co.vividnext.sodalive.dialog.LiveDialog
import kr.co.vividnext.sodalive.dialog.SodaLiveTimePickerDialog
import kr.co.vividnext.sodalive.extensions.convertDateFormat
import kr.co.vividnext.sodalive.extensions.dpToPx
import org.koin.android.ext.android.inject
import java.io.File
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBinding>(
ActivityAudioContentUploadBinding::inflate
@@ -111,6 +119,26 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
}
}
private val datePickerDialogListener =
DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
viewModel.releaseDate = String.format("%d-%02d-%02d", year, monthOfYear + 1, dayOfMonth)
viewModel.setReservationDate(
String.format(
"%d.%02d.%02d",
year,
monthOfYear + 1,
dayOfMonth
)
)
}
private val timePickerDialogListener =
TimePickerDialog.OnTimeSetListener { _, hourOfDay, minute ->
val timeString = String.format("%02d:%02d", hourOfDay, minute)
viewModel.releaseTime = timeString
viewModel.setReservationTime(timeString.convertDateFormat("HH:mm", "a hh:mm"))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
checkPermissions()
@@ -173,6 +201,8 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
binding.llOnlyRental.setOnClickListener { viewModel.setIsOnlyRental(true) }
binding.llCommentNo.setOnClickListener { viewModel.setAvailableComment(false) }
binding.llCommentYes.setOnClickListener { viewModel.setAvailableComment(true) }
binding.llActiveNow.setOnClickListener { viewModel.setActiveReservation(false) }
binding.llActiveReservation.setOnClickListener { viewModel.setActiveReservation(true) }
binding.tvCancel.setOnClickListener { finish() }
binding.tvUpload.setOnClickListener {
@@ -189,6 +219,71 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
).show(screenWidth)
}
}
binding.tvReservationDate.setOnClickListener {
val reservationDate = viewModel.releaseDate.split("-")
val datePicker: DatePickerDialog
if (reservationDate.isNotEmpty() && reservationDate.size == 3) {
datePicker = DatePickerDialog(
this,
R.style.DatePickerStyle,
datePickerDialogListener,
reservationDate[0].toInt(),
reservationDate[1].toInt() - 1,
reservationDate[2].toInt()
)
} else {
val dateString = SimpleDateFormat(
"yyyy.MM.dd",
Locale.getDefault()
).format(Date()).split(".")
datePicker = DatePickerDialog(
this,
R.style.DatePickerStyle,
datePickerDialogListener,
dateString[0].toInt(),
dateString[1].toInt() - 1,
dateString[2].toInt()
)
}
datePicker.show()
}
binding.tvReservationTime.setOnClickListener {
val reservationTime = viewModel.releaseTime.split(":")
val timePicker: TimePickerDialog
if (reservationTime.isNotEmpty() && reservationTime.size == 2) {
timePicker = SodaLiveTimePickerDialog(
this,
R.style.TimePickerStyle,
timePickerDialogListener,
reservationTime[0].toInt(),
reservationTime[1].toInt(),
false
)
} else {
val calendar = Calendar.getInstance().apply {
add(Calendar.HOUR_OF_DAY, 1)
}
val initialHour = calendar.get(Calendar.HOUR_OF_DAY)
val initialMinute = calendar.get(Calendar.MINUTE) / 15 * 15
timePicker = SodaLiveTimePickerDialog(
this,
R.style.TimePickerStyle,
timePickerDialogListener,
initialHour,
initialMinute,
false
)
}
timePicker.show()
}
}
private fun checkPermissions() {
@@ -406,6 +501,69 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
}
}
}
viewModel.isActiveReservationLiveData.observe(this) {
if (it) {
checkActiveReservation()
} else {
checkActiveNow()
}
}
viewModel.reservationDateLiveData.observe(this) {
binding.tvReservationDate.text = it
}
viewModel.reservationTimeLiveData.observe(this) {
binding.tvReservationTime.text = it
}
}
private fun checkActiveNow() {
binding.llReservationDatetime.visibility = View.GONE
binding.ivActiveNow.visibility = View.VISIBLE
binding.tvActiveNow.setTextColor(
ContextCompat.getColor(
applicationContext,
R.color.color_eeeeee
)
)
binding.llActiveNow.setBackgroundResource(R.drawable.bg_round_corner_6_7_3bb9f1)
binding.ivActiveReservation.visibility = View.GONE
binding.tvActiveReservation.setTextColor(
ContextCompat.getColor(
applicationContext,
R.color.color_3bb9f1
)
)
binding.llActiveReservation.setBackgroundResource(
R.drawable.bg_round_corner_6_7_13181b
)
}
private fun checkActiveReservation() {
binding.llReservationDatetime.visibility = View.VISIBLE
binding.ivActiveReservation.visibility = View.VISIBLE
binding.tvActiveReservation.setTextColor(
ContextCompat.getColor(
applicationContext,
R.color.color_eeeeee
)
)
binding.llActiveReservation.setBackgroundResource(R.drawable.bg_round_corner_6_7_3bb9f1)
binding.ivActiveNow.visibility = View.GONE
binding.tvActiveNow.setTextColor(
ContextCompat.getColor(
applicationContext,
R.color.color_3bb9f1
)
)
binding.llActiveNow.setBackgroundResource(
R.drawable.bg_round_corner_6_7_13181b
)
}
private fun checkPriceFree() {

View File

@@ -20,6 +20,7 @@ import okio.BufferedSink
import java.io.File
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.TimeZone
class AudioContentUploadViewModel(
private val repository: AudioContentRepository
@@ -49,12 +50,26 @@ class AudioContentUploadViewModel(
val isPriceFreeLiveData: LiveData<Boolean>
get() = _isPriceFreeLiveData
private val _isActiveReservationLiveData = MutableLiveData(false)
val isActiveReservationLiveData: LiveData<Boolean>
get() = _isActiveReservationLiveData
private val _reservationDateLiveData = MutableLiveData("날짜를 선택해주세요")
val reservationDateLiveData: LiveData<String>
get() = _reservationDateLiveData
private val _reservationTimeLiveData = MutableLiveData("시간을 설정해주세요")
val reservationTimeLiveData: LiveData<String>
get() = _reservationTimeLiveData
lateinit var getRealPathFromURI: (Uri) -> String?
var title = ""
var detail = ""
var tags = ""
var price = 0
var releaseDate = ""
var releaseTime = ""
var theme: GetAudioContentThemeResponse? = null
var coverImageUri: Uri? = null
var contentUri: Uri? = null
@@ -81,6 +96,10 @@ class AudioContentUploadViewModel(
_isOnlyRentalLiveData.postValue(isOnlyRental)
}
fun setActiveReservation(isActiveReservation: Boolean) {
_isActiveReservationLiveData.postValue(isActiveReservation)
}
fun uploadAudioContent(onSuccess: () -> Unit) {
if (!_isLoading.value!! && validateData()) {
_isLoading.postValue(true)
@@ -90,6 +109,12 @@ class AudioContentUploadViewModel(
detail = detail,
tags = tags,
price = price,
releaseDate = if (_isActiveReservationLiveData.value!!) {
"$releaseDate $releaseTime"
} else {
null
},
timezone = TimeZone.getDefault().id,
themeId = theme!!.id,
isAdult = _isAdultLiveData.value!!,
isOnlyRental = _isOnlyRentalLiveData.value!!,
@@ -281,6 +306,14 @@ class AudioContentUploadViewModel(
return false
}
if (
_isActiveReservationLiveData.value!! &&
(releaseDate.isBlank() || releaseTime.isBlank())
) {
_toastLiveData.postValue("예약날짜와 시간을 선택해주세요.")
return false
}
return true
}
@@ -307,4 +340,12 @@ class AudioContentUploadViewModel(
return 0
}
}
fun setReservationDate(dateString: String) {
_reservationDateLiveData.postValue(dateString)
}
fun setReservationTime(timeString: String) {
_reservationTimeLiveData.postValue(timeString)
}
}

View File

@@ -7,10 +7,12 @@ data class CreateAudioContentRequest(
@SerializedName("detail") val detail: String,
@SerializedName("tags") val tags: String,
@SerializedName("price") val price: Int,
@SerializedName("releaseDate") val releaseDate: String?,
@SerializedName("timezone") val timezone: String,
@SerializedName("themeId") val themeId: Long,
@SerializedName("isAdult") val isAdult: Boolean,
@SerializedName("isOnlyRental") val isOnlyRental: Boolean,
@SerializedName("isCommentAvailable") val isCommentAvailable: Boolean,
@SerializedName("previewStartTime") val previewStartTime: String? = null,
@SerializedName("previewEndTime") val previewEndTime: String? = null
@SerializedName("previewEndTime") val previewEndTime: String? = null,
)

View File

@@ -0,0 +1,45 @@
package kr.co.vividnext.sodalive.dialog
import android.app.TimePickerDialog
import android.content.Context
import android.widget.TimePicker
class SodaLiveTimePickerDialog(
context: Context,
themeResId: Int,
private val onTimeSetListener: OnTimeSetListener,
hourOfDay: Int,
minute: Int,
is24HourView: Boolean
) : TimePickerDialog(context, themeResId, null, hourOfDay, minute, is24HourView) {
private var timePicker: TimePicker? = null
init {
this.setTitle("Select Time")
setOnShowListener {
timePicker = window?.findViewById(
context.resources.getIdentifier(
"android:id/timePicker",
null,
null
)
)
timePicker?.apply {
setIs24HourView(is24HourView)
setOnTimeChangedListener { _, _, minute ->
// Snap minute to nearest quarter (0, 15, 30, 45)
val snappedMinute = minute / 15 * 15
if (snappedMinute != minute) {
this.minute = snappedMinute
}
}
}
getButton(BUTTON_POSITIVE).setOnClickListener {
timePicker?.let { picker ->
onTimeSetListener.onTimeSet(picker, picker.hour, picker.minute)
}
dismiss()
}
}
}
}