오디션 지원 기능 추가
This commit is contained in:
parent
c6ef5970a5
commit
4e14765e94
|
@ -7,11 +7,14 @@ import kr.co.vividnext.sodalive.audition.role.AuditionRoleDetailViewModel
|
||||||
import kr.co.vividnext.sodalive.audition.role.GetAuditionRoleDetailResponse
|
import kr.co.vividnext.sodalive.audition.role.GetAuditionRoleDetailResponse
|
||||||
import kr.co.vividnext.sodalive.audition.vote.VoteAuditionApplicantRequest
|
import kr.co.vividnext.sodalive.audition.vote.VoteAuditionApplicantRequest
|
||||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||||
import kr.co.vividnext.sodalive.live.room.menu.UpdateLiveMenuRequest
|
import okhttp3.MultipartBody
|
||||||
|
import okhttp3.RequestBody
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Header
|
import retrofit2.http.Header
|
||||||
|
import retrofit2.http.Multipart
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
|
import retrofit2.http.Part
|
||||||
import retrofit2.http.Path
|
import retrofit2.http.Path
|
||||||
import retrofit2.http.Query
|
import retrofit2.http.Query
|
||||||
|
|
||||||
|
@ -44,6 +47,14 @@ interface AuditionApi {
|
||||||
@Header("Authorization") authHeader: String
|
@Header("Authorization") authHeader: String
|
||||||
): Single<ApiResponse<GetAuditionApplicantListResponse>>
|
): Single<ApiResponse<GetAuditionApplicantListResponse>>
|
||||||
|
|
||||||
|
@POST("/audition/applicant")
|
||||||
|
@Multipart
|
||||||
|
fun applyAudition(
|
||||||
|
@Part contentFile: MultipartBody.Part,
|
||||||
|
@Part("request") request: RequestBody,
|
||||||
|
@Header("Authorization") authHeader: String
|
||||||
|
): Single<ApiResponse<Any>>
|
||||||
|
|
||||||
@POST("/audition/vote")
|
@POST("/audition/vote")
|
||||||
fun voteApplicant(
|
fun voteApplicant(
|
||||||
@Body request: VoteAuditionApplicantRequest,
|
@Body request: VoteAuditionApplicantRequest,
|
||||||
|
|
|
@ -2,6 +2,8 @@ package kr.co.vividnext.sodalive.audition
|
||||||
|
|
||||||
import kr.co.vividnext.sodalive.audition.role.AuditionRoleDetailViewModel
|
import kr.co.vividnext.sodalive.audition.role.AuditionRoleDetailViewModel
|
||||||
import kr.co.vividnext.sodalive.audition.vote.VoteAuditionApplicantRequest
|
import kr.co.vividnext.sodalive.audition.vote.VoteAuditionApplicantRequest
|
||||||
|
import okhttp3.MultipartBody
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
|
||||||
class AuditionRepository(
|
class AuditionRepository(
|
||||||
private val api: AuditionApi
|
private val api: AuditionApi
|
||||||
|
@ -53,4 +55,14 @@ class AuditionRepository(
|
||||||
request = request,
|
request = request,
|
||||||
authHeader = token
|
authHeader = token
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun applyAudition(
|
||||||
|
contentFile: MultipartBody.Part,
|
||||||
|
request: RequestBody,
|
||||||
|
token: String
|
||||||
|
) = api.applyAudition(
|
||||||
|
contentFile = contentFile,
|
||||||
|
request = request,
|
||||||
|
authHeader = token
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package kr.co.vividnext.sodalive.audition.applicant
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.WindowManager
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import kr.co.vividnext.sodalive.databinding.DialogApplicationMethodBinding
|
||||||
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
|
|
||||||
|
class ApplicationMethodDialog(
|
||||||
|
activity: Activity,
|
||||||
|
layoutInflater: LayoutInflater,
|
||||||
|
onClickFileUpload: () -> Unit,
|
||||||
|
onClickRecord: () -> Unit
|
||||||
|
) {
|
||||||
|
private val alertDialog: AlertDialog
|
||||||
|
|
||||||
|
val dialogView = DialogApplicationMethodBinding.inflate(layoutInflater)
|
||||||
|
|
||||||
|
init {
|
||||||
|
val dialogBuilder = AlertDialog.Builder(activity)
|
||||||
|
dialogBuilder.setView(dialogView.root)
|
||||||
|
|
||||||
|
alertDialog = dialogBuilder.create()
|
||||||
|
alertDialog.setCancelable(false)
|
||||||
|
alertDialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||||
|
|
||||||
|
dialogView.ivClose.setOnClickListener {
|
||||||
|
alertDialog.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogView.llUploadFile.setOnClickListener {
|
||||||
|
alertDialog.dismiss()
|
||||||
|
onClickFileUpload()
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogView.llRecord.setOnClickListener {
|
||||||
|
alertDialog.dismiss()
|
||||||
|
onClickRecord()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun show(width: Int) {
|
||||||
|
alertDialog.show()
|
||||||
|
|
||||||
|
val lp = WindowManager.LayoutParams()
|
||||||
|
lp.copyFrom(alertDialog.window?.attributes)
|
||||||
|
lp.width = width - (26.7f.dpToPx()).toInt()
|
||||||
|
lp.height = WindowManager.LayoutParams.WRAP_CONTENT
|
||||||
|
|
||||||
|
alertDialog.window?.attributes = lp
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package kr.co.vividnext.sodalive.audition.applicant
|
||||||
|
|
||||||
|
import androidx.annotation.Keep
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
data class ApplyAuditionRoleRequest(
|
||||||
|
@SerializedName("roleId") val roleId: Long,
|
||||||
|
@SerializedName("phoneNumber") val phoneNumber: String
|
||||||
|
)
|
|
@ -0,0 +1,83 @@
|
||||||
|
package kr.co.vividnext.sodalive.audition.applicant
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.Toast
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
import kr.co.vividnext.sodalive.databinding.FragmentAuditionApplyDialogBinding
|
||||||
|
|
||||||
|
class AuditionApplyDialogFragment(
|
||||||
|
private val fileName: String,
|
||||||
|
private val onClickApply: (String) -> Unit,
|
||||||
|
private val onClickClose: () -> Unit
|
||||||
|
) : BottomSheetDialogFragment() {
|
||||||
|
private lateinit var binding: FragmentAuditionApplyDialogBinding
|
||||||
|
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
val dialog = super.onCreateDialog(savedInstanceState)
|
||||||
|
|
||||||
|
dialog.setOnShowListener {
|
||||||
|
val d = it as BottomSheetDialog
|
||||||
|
val bottomSheet = d.findViewById<FrameLayout>(
|
||||||
|
com.google.android.material.R.id.design_bottom_sheet
|
||||||
|
)
|
||||||
|
if (bottomSheet != null) {
|
||||||
|
val bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
|
||||||
|
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
bottomSheetBehavior.isDraggable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
binding = FragmentAuditionApplyDialogBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
binding.ivClose.setOnClickListener {
|
||||||
|
onClickClose()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.tvAuditionApply.setOnClickListener {
|
||||||
|
val phoneNumber = binding.etPhoneNumber.text.toString()
|
||||||
|
if (phoneNumber.isBlank() || phoneNumber.length != 11) {
|
||||||
|
Toast.makeText(
|
||||||
|
activity,
|
||||||
|
"잘못된 연락처 입니다.\n다시 입력해 주세요.",
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
} else if (!binding.tvAgree.isSelected) {
|
||||||
|
Toast.makeText(
|
||||||
|
activity,
|
||||||
|
"연락처 수집 및 활용에 동의하셔야 오디션 지원이 가능합니다.",
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
} else {
|
||||||
|
dismiss()
|
||||||
|
onClickApply(binding.etPhoneNumber.text.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.tvAgree.setOnClickListener {
|
||||||
|
it.isSelected = !it.isSelected
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.tvAudioFileName.text = fileName
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,25 +4,33 @@ import android.content.Intent
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.provider.OpenableColumns
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.load
|
import coil.load
|
||||||
import coil.transform.RoundedCornersTransformation
|
import coil.transform.RoundedCornersTransformation
|
||||||
import kr.co.vividnext.sodalive.R
|
import kr.co.vividnext.sodalive.R
|
||||||
|
import kr.co.vividnext.sodalive.audition.applicant.ApplicationMethodDialog
|
||||||
import kr.co.vividnext.sodalive.audition.applicant.AuditionApplicantListAdapter
|
import kr.co.vividnext.sodalive.audition.applicant.AuditionApplicantListAdapter
|
||||||
|
import kr.co.vividnext.sodalive.audition.applicant.AuditionApplyDialogFragment
|
||||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||||
|
import kr.co.vividnext.sodalive.base.SodaDialog
|
||||||
import kr.co.vividnext.sodalive.common.Constants
|
import kr.co.vividnext.sodalive.common.Constants
|
||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||||
|
import kr.co.vividnext.sodalive.common.RealPathUtil
|
||||||
import kr.co.vividnext.sodalive.databinding.ActivityAuditionRoleDetailBinding
|
import kr.co.vividnext.sodalive.databinding.ActivityAuditionRoleDetailBinding
|
||||||
|
import kr.co.vividnext.sodalive.explorer.profile.creator_community.write.RecordingVoiceFragment
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBinding>(
|
class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBinding>(
|
||||||
ActivityAuditionRoleDetailBinding::inflate
|
ActivityAuditionRoleDetailBinding::inflate
|
||||||
) {
|
), RecordingVoiceFragment.OnAudioRecordedListener {
|
||||||
private val viewModel: AuditionRoleDetailViewModel by inject()
|
private val viewModel: AuditionRoleDetailViewModel by inject()
|
||||||
|
|
||||||
private lateinit var loadingDialog: LoadingDialog
|
private lateinit var loadingDialog: LoadingDialog
|
||||||
|
@ -30,6 +38,38 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
||||||
|
|
||||||
private var auditionRoleId: Long = 0
|
private var auditionRoleId: Long = 0
|
||||||
private var isOpenInformation = false
|
private var isOpenInformation = false
|
||||||
|
private var reApplication = false
|
||||||
|
private var isDeleteAudioFile = false
|
||||||
|
|
||||||
|
private val selectAudioActivityResultLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.StartActivityForResult()
|
||||||
|
) { result ->
|
||||||
|
val resultCode = result.resultCode
|
||||||
|
val data = result.data
|
||||||
|
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
val fileUri = data?.data
|
||||||
|
if (fileUri != null) {
|
||||||
|
viewModel.audioFileName = getFileName(fileUri).toString()
|
||||||
|
viewModel.audioFile = File(
|
||||||
|
RealPathUtil.getRealPath(applicationContext, fileUri!!)
|
||||||
|
)
|
||||||
|
showAuditionApplyDialog()
|
||||||
|
} else {
|
||||||
|
Toast.makeText(
|
||||||
|
this,
|
||||||
|
"잘못된 녹음 파일 입니다.\n다시 선택해 주세요.",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Toast.makeText(
|
||||||
|
this,
|
||||||
|
"잘못된 녹음 파일 입니다.\n다시 선택해 주세요.",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
auditionRoleId = intent.getLongExtra(Constants.EXTRA_AUDITION_ROLE_ID, 0)
|
auditionRoleId = intent.getLongExtra(Constants.EXTRA_AUDITION_ROLE_ID, 0)
|
||||||
|
@ -76,6 +116,21 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.tvApplicant.setOnClickListener {
|
||||||
|
if (reApplication) {
|
||||||
|
SodaDialog(
|
||||||
|
activity = this@AuditionRoleDetailActivity,
|
||||||
|
layoutInflater = layoutInflater,
|
||||||
|
title = "재지원 안내",
|
||||||
|
desc = "재지원 시 이전 지원 내역은 삭제되며 받은 투표수는 무효 처리됩니다.",
|
||||||
|
confirmButtonTitle = "확인",
|
||||||
|
confirmButtonClick = { showApplicationMethodDialog() }
|
||||||
|
).show(screenWidth)
|
||||||
|
} else {
|
||||||
|
showApplicationMethodDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
binding.tvSortNewest.setOnClickListener {
|
binding.tvSortNewest.setOnClickListener {
|
||||||
viewModel.setSortType(AuditionRoleDetailViewModel.AuditionApplicantSortType.NEWEST)
|
viewModel.setSortType(AuditionRoleDetailViewModel.AuditionApplicantSortType.NEWEST)
|
||||||
}
|
}
|
||||||
|
@ -144,6 +199,53 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
||||||
recyclerView.adapter = adapter
|
recyclerView.adapter = adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showApplicationMethodDialog() {
|
||||||
|
isDeleteAudioFile = false
|
||||||
|
ApplicationMethodDialog(
|
||||||
|
activity = this@AuditionRoleDetailActivity,
|
||||||
|
layoutInflater = layoutInflater,
|
||||||
|
onClickFileUpload = {
|
||||||
|
isDeleteAudioFile = false
|
||||||
|
val intent = Intent().apply {
|
||||||
|
type = "audio/*"
|
||||||
|
action = Intent.ACTION_GET_CONTENT
|
||||||
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
}
|
||||||
|
selectAudioActivityResultLauncher.launch(
|
||||||
|
Intent.createChooser(
|
||||||
|
intent,
|
||||||
|
"Select Audio"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onClickRecord = {
|
||||||
|
isDeleteAudioFile = true
|
||||||
|
val fragment = RecordingVoiceFragment()
|
||||||
|
fragment.isCancelable = false
|
||||||
|
fragment.show(supportFragmentManager, fragment.tag)
|
||||||
|
}
|
||||||
|
).show(screenWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showAuditionApplyDialog() {
|
||||||
|
val auditionApplyDialogFragment = AuditionApplyDialogFragment(
|
||||||
|
fileName = viewModel.audioFileName,
|
||||||
|
onClickApply = {
|
||||||
|
viewModel.applyAudition(auditionRoleId = auditionRoleId, phoneNumber = it) {
|
||||||
|
if (isDeleteAudioFile) {
|
||||||
|
deleteAudioFile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClickClose = {
|
||||||
|
if (isDeleteAudioFile) {
|
||||||
|
deleteAudioFile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
auditionApplyDialogFragment.show(supportFragmentManager, auditionApplyDialogFragment.tag)
|
||||||
|
}
|
||||||
|
|
||||||
private fun bindData() {
|
private fun bindData() {
|
||||||
viewModel.toastLiveData.observe(this) {
|
viewModel.toastLiveData.observe(this) {
|
||||||
it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
|
it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
|
||||||
|
@ -177,8 +279,10 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
||||||
}
|
}
|
||||||
|
|
||||||
if (roleDetail.isAlreadyApplicant) {
|
if (roleDetail.isAlreadyApplicant) {
|
||||||
|
reApplication = true
|
||||||
binding.tvApplicant.text = "오디션 재지원"
|
binding.tvApplicant.text = "오디션 재지원"
|
||||||
} else {
|
} else {
|
||||||
|
reApplication = false
|
||||||
binding.tvApplicant.text = "오디션 지원하기"
|
binding.tvApplicant.text = "오디션 지원하기"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,4 +322,37 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun deleteAudioFile() {
|
||||||
|
if (viewModel.audioFile != null && viewModel.audioFile!!.exists()) {
|
||||||
|
viewModel.audioFile?.delete()
|
||||||
|
viewModel.audioFileName = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getFileName(uri: Uri): String? {
|
||||||
|
val scheme = uri.scheme
|
||||||
|
var fileName: String? = null
|
||||||
|
|
||||||
|
if (scheme == "content") {
|
||||||
|
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
|
||||||
|
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
|
||||||
|
if (nameIndex != -1 && cursor.moveToFirst()) {
|
||||||
|
fileName = cursor.getString(nameIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (scheme == "file") {
|
||||||
|
val file = File(uri.path ?: "")
|
||||||
|
fileName = file.name
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileName
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAudioRecorded(file: File) {
|
||||||
|
deleteAudioFile()
|
||||||
|
viewModel.audioFile = file
|
||||||
|
viewModel.audioFileName = file.name
|
||||||
|
showAuditionApplyDialog()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,25 @@ package kr.co.vividnext.sodalive.audition.role
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.google.gson.Gson
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.core.Observable
|
import io.reactivex.rxjava3.core.Observable
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
import kr.co.vividnext.sodalive.audition.AuditionRepository
|
import kr.co.vividnext.sodalive.audition.AuditionRepository
|
||||||
|
import kr.co.vividnext.sodalive.audition.applicant.ApplyAuditionRoleRequest
|
||||||
import kr.co.vividnext.sodalive.audition.applicant.GetAuditionRoleApplicantItem
|
import kr.co.vividnext.sodalive.audition.applicant.GetAuditionRoleApplicantItem
|
||||||
import kr.co.vividnext.sodalive.audition.vote.VoteAuditionApplicantRequest
|
import kr.co.vividnext.sodalive.audition.vote.VoteAuditionApplicantRequest
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import okhttp3.MediaType
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.MultipartBody
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import okio.BufferedSink
|
||||||
|
import java.io.File
|
||||||
import java.util.TimeZone
|
import java.util.TimeZone
|
||||||
|
|
||||||
class AuditionRoleDetailViewModel(private val repository: AuditionRepository) : BaseViewModel() {
|
class AuditionRoleDetailViewModel(private val repository: AuditionRepository) : BaseViewModel() {
|
||||||
|
@ -41,6 +50,8 @@ class AuditionRoleDetailViewModel(private val repository: AuditionRepository) :
|
||||||
|
|
||||||
var page = 1
|
var page = 1
|
||||||
var isLast = false
|
var isLast = false
|
||||||
|
var audioFile: File? = null
|
||||||
|
var audioFileName: String = ""
|
||||||
private var auditionRoleId = -1L
|
private var auditionRoleId = -1L
|
||||||
private val pageSize = 10
|
private val pageSize = 10
|
||||||
|
|
||||||
|
@ -171,6 +182,78 @@ class AuditionRoleDetailViewModel(private val repository: AuditionRepository) :
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun applyAudition(auditionRoleId: Long, phoneNumber: String, onSuccess: () -> Unit) {
|
||||||
|
if (audioFile == null) {
|
||||||
|
_toastLiveData.value = "잘못된 녹음 파일 입니다.\n다시 선택해 주세요."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_isLoading.value = true
|
||||||
|
|
||||||
|
val request = ApplyAuditionRoleRequest(roleId = auditionRoleId, phoneNumber = phoneNumber)
|
||||||
|
val requestJson = Gson().toJson(request)
|
||||||
|
|
||||||
|
val contentFile = MultipartBody.Part.createFormData(
|
||||||
|
"contentFile",
|
||||||
|
audioFile!!.name,
|
||||||
|
body = object : RequestBody() {
|
||||||
|
override fun contentType(): MediaType {
|
||||||
|
return "audio/*".toMediaType()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeTo(sink: BufferedSink) {
|
||||||
|
audioFile!!.inputStream().use { inputStream ->
|
||||||
|
val buffer = ByteArray(512)
|
||||||
|
var bytesRead: Int
|
||||||
|
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
|
||||||
|
sink.write(buffer, 0, bytesRead)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun contentLength(): Long {
|
||||||
|
return audioFile!!.length()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
compositeDisposable.add(
|
||||||
|
repository.applyAudition(
|
||||||
|
contentFile = contentFile,
|
||||||
|
request = requestJson.toRequestBody("text/plain".toMediaType()),
|
||||||
|
token = "Bearer ${SharedPreferenceManager.token}"
|
||||||
|
).subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(
|
||||||
|
{
|
||||||
|
_isLoading.value = false
|
||||||
|
if (it.success) {
|
||||||
|
_applicantListLiveData.value = emptyList()
|
||||||
|
page = 1
|
||||||
|
isLast = false
|
||||||
|
getAuditionRoleDetail(auditionRoleId = auditionRoleId)
|
||||||
|
onSuccess()
|
||||||
|
} 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 setSortType(sortType: AuditionApplicantSortType) {
|
fun setSortType(sortType: AuditionApplicantSortType) {
|
||||||
val prevSortType = _sortTypeLiveData.value!!
|
val prevSortType = _sortTypeLiveData.value!!
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 861 B |
|
@ -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_13181b" />
|
||||||
|
<corners android:radius="5.3dp" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="@color/color_13181b" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,105 @@
|
||||||
|
<?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"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/bg_round_corner_10_3_222222"
|
||||||
|
android:paddingVertical="13.3dp"
|
||||||
|
android:paddingHorizontal="16.7dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_close"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_noti_stop"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="33.3dp"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="오디션 지원방식"
|
||||||
|
android:textColor="@color/color_bbbbbb"
|
||||||
|
android:textSize="18.3sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/ll_method_buttons"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="21.3dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/tv_title">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/ll_upload_file"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_round_corner_5_3_13181b_3bb9f1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingVertical="8dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="3dp"
|
||||||
|
android:src="@drawable/ic_upload" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:text="파일 업로드"
|
||||||
|
android:textColor="@color/color_3bb9f1"
|
||||||
|
android:textSize="14.7sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/ll_record"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="13.3dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_round_corner_5_3_13181b_3bb9f1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingVertical="8dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="3dp"
|
||||||
|
android:src="@drawable/ic_mic_color_button" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:text="바로 녹음"
|
||||||
|
android:textColor="@color/color_3bb9f1"
|
||||||
|
android:textSize="14.7sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="13.3dp"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:text="※ 파일은 mp3, aac만 업로드 가능"
|
||||||
|
android:textColor="@color/color_777777"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/ll_method_buttons" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,126 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ScrollView 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"
|
||||||
|
android:background="@color/color_222222">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingHorizontal="13.3dp"
|
||||||
|
android:paddingVertical="16.7dp">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:text="오디션 지원"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="18.3sp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_close"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:src="@drawable/ic_noti_stop" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:text="녹음파일"
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textSize="16.7sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:background="@drawable/bg_round_corner_5_3_13181b"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingHorizontal="13.3dp"
|
||||||
|
android:paddingVertical="8dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_note_square" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_audio_file_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:textColor="@color/color_d2d2d2"
|
||||||
|
android:textSize="13.3sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:text="연락처"
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textSize="16.7sp" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/et_phone_number"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:background="@drawable/bg_round_corner_5_3_13181b"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:hint="합격시 연락받을 연락처를 남겨주세요"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="numberSigned"
|
||||||
|
android:maxEms="12"
|
||||||
|
android:paddingHorizontal="13.3dp"
|
||||||
|
android:paddingVertical="17dp"
|
||||||
|
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,TextFields" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_agree"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:drawablePadding="13.3dp"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="보이스온 오디오 드라마 오디션 합격시 개인 연락을 위한 개인 정보(연락처) 수집 및 활용에 동의합니다.\n오디션 지원자는 개인정보 수집 및 활용 동의에 거부할 권리가 있으며 비동의시 오디션 지원은 취소 됩니다."
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textSize="13.3sp"
|
||||||
|
app:drawableStartCompat="@drawable/ic_select" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_audition_apply"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="35dp"
|
||||||
|
android:background="@drawable/bg_round_corner_8_3bb9f1"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingVertical="13.3dp"
|
||||||
|
android:text="오디션 지원하기"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="13.3sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
Loading…
Reference in New Issue