diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentApi.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentApi.kt index 757857f..57f77cf 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentApi.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentApi.kt @@ -201,4 +201,16 @@ interface AudioContentApi { fun getMainOrderList( @Header("Authorization") authHeader: String ): Single>> + + @POST("/audio-content/pin-to-the-top/{id}") + fun pinContent( + @Path("id") audioContentId: Long, + @Header("Authorization") authHeader: String + ): Single> + + @PUT("/audio-content/unpin-at-the-top/{id}") + fun unpinContent( + @Path("id") audioContentId: Long, + @Header("Authorization") authHeader: String + ): Single> } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentRepository.kt index 6554426..7536911 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentRepository.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentRepository.kt @@ -188,4 +188,13 @@ class AudioContentRepository( fun getMainBannerList(token: String) = api.getMainBannerList(authHeader = token) fun getMainOrderList(token: String) = api.getMainOrderList(authHeader = token) + fun pinContent( + audioContentId: Long, + token: String + ) = api.pinContent(audioContentId, authHeader = token) + + fun unpinContent( + audioContentId: Long, + token: String + ) = api.unpinContent(audioContentId, authHeader = token) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/AudioContentDetailActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/AudioContentDetailActivity.kt index 2305932..6680a76 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/AudioContentDetailActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/AudioContentDetailActivity.kt @@ -13,7 +13,6 @@ import android.view.View import android.widget.RelativeLayout import android.widget.SeekBar import android.widget.Toast -import androidx.appcompat.widget.PopupMenu import androidx.core.content.ContextCompat import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -30,6 +29,7 @@ import kr.co.vividnext.sodalive.audio_content.order.AudioContentOrderConfirmDial import kr.co.vividnext.sodalive.audio_content.order.AudioContentOrderFragment import kr.co.vividnext.sodalive.audio_content.order.OrderType 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.LoadingDialog import kr.co.vividnext.sodalive.common.SharedPreferenceManager @@ -116,10 +116,7 @@ class AudioContentDetailActivity : BaseActivity { - refresh = true - setResult(RESULT_OK) - startActivity( - Intent(applicationContext, AudioContentModifyActivity::class.java) - .apply { - putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, audioContentId) - } - ) - } - - R.id.menu_delete -> { - showDeleteDialog() + private fun showOptionMenu() { + val dialog = AudioContentDetailMenuBottomSheetDialog( + isPin = viewModel.audioContentLiveData.value!!.isPin, + isCreator = viewModel.audioContentLiveData.value!! + .creator.creatorId == SharedPreferenceManager.userId, + onClickPin = { + if (viewModel.audioContentLiveData.value!!.isPin) { + viewModel.unPinContent(audioContentId) + } else { + if (viewModel.audioContentLiveData.value!!.isAvailablePin) { + viewModel.pinContent(audioContentId) + } else { + SodaDialog(this@AudioContentDetailActivity, + layoutInflater, + "고정 한도 도달", + "이 콘텐츠를 고정하시겠어요? " + + "채널에 콘텐츠를 최대 3개까지 고정할 수 있습니다." + + "이 콘텐츠를 고정하면 가장 오래된 콘텐츠가 대체됩니다.", + "확인", + { viewModel.pinContent(audioContentId) }, + "취소", + {} + ).show(screenWidth) } } - - true - } - } else { - inflater.inflate(R.menu.audio_content_detail_user_menu, popup.menu) - - popup.setOnMenuItemClickListener { - when (it.itemId) { - R.id.menu_report -> { - showReportDialog() - } - } - - true - } - } - - popup.show() + }, + onClickModify = { + refresh = true + setResult(RESULT_OK) + startActivity( + Intent(applicationContext, AudioContentModifyActivity::class.java) + .apply { + putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, audioContentId) + } + ) + }, + onClickDelete = { showDeleteDialog() }, + onClickReport = { showReportDialog() } + ) + dialog.show(supportFragmentManager, dialog.tag) } private fun showDeleteDialog() { diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/AudioContentDetailMenuBottomSheetDialog.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/AudioContentDetailMenuBottomSheetDialog.kt new file mode 100644 index 0000000..5e8a4e7 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/AudioContentDetailMenuBottomSheetDialog.kt @@ -0,0 +1,66 @@ +package kr.co.vividnext.sodalive.audio_content.detail + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import kr.co.vividnext.sodalive.R +import kr.co.vividnext.sodalive.databinding.DialogAudioContentDetailMenuBinding + +class AudioContentDetailMenuBottomSheetDialog( + private val isPin: Boolean, + private val isCreator: Boolean, + private val onClickPin: () -> Unit, + private val onClickModify: () -> Unit, + private val onClickDelete: () -> Unit, + private val onClickReport: () -> Unit +) : BottomSheetDialogFragment() { + private lateinit var dialog: DialogAudioContentDetailMenuBinding + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + dialog = DialogAudioContentDetailMenuBinding.inflate(inflater, container, false) + return dialog.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + if (isCreator) { + dialog.tvReport.visibility = View.GONE + dialog.llMenuCreator.visibility = View.VISIBLE + + if (isPin) { + dialog.ivPin.setImageResource(R.drawable.ic_pin_cancel) + dialog.tvPin.text = "내 채널에 고정 취소" + } else { + dialog.ivPin.setImageResource(R.drawable.ic_pin) + dialog.tvPin.text = "내 채널에 고정" + } + + dialog.llPin.setOnClickListener { + dismiss() + onClickPin() + } + dialog.llModify.setOnClickListener { + dismiss() + onClickModify() + } + dialog.llDelete.setOnClickListener { + dismiss() + onClickDelete() + } + } else { + dialog.llMenuCreator.visibility = View.GONE + dialog.tvReport.visibility = View.VISIBLE + dialog.tvReport.setOnClickListener { + dismiss() + onClickReport() + } + } + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/AudioContentDetailViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/AudioContentDetailViewModel.kt index 87dc2a0..49ca169 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/AudioContentDetailViewModel.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/AudioContentDetailViewModel.kt @@ -481,4 +481,74 @@ class AudioContentDetailViewModel( ) ) } + + fun pinContent(audioContentId: Long) { + isLoading.value = true + compositeDisposable.add( + repository.pinContent( + audioContentId, + token = "Bearer ${SharedPreferenceManager.token}" + ) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + isLoading.value = false + + if (it.success) { + _toastLiveData.postValue("고정되었습니다.") + getAudioContentDetail(audioContentId) + } 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 unPinContent(audioContentId: Long) { + isLoading.value = true + compositeDisposable.add( + repository.unpinContent( + audioContentId, + token = "Bearer ${SharedPreferenceManager.token}" + ) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + isLoading.value = false + + if (it.success) { + _toastLiveData.postValue("해제되었습니다.") + getAudioContentDetail(audioContentId) + } else { + if (it.message != null) { + _toastLiveData.postValue(it.message) + } else { + _toastLiveData.postValue( + "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요." + ) + } + } + }, + { + isLoading.value = false + it.message?.let { message -> Logger.e(message) } + _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.") + } + ) + ) + } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/GetAudioContentDetailResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/GetAudioContentDetailResponse.kt index 402bb33..d271452 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/GetAudioContentDetailResponse.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/detail/GetAudioContentDetailResponse.kt @@ -31,6 +31,8 @@ data class GetAudioContentDetailResponse( @SerializedName("likeCount") val likeCount: Int, @SerializedName("commentList") val commentList: List, @SerializedName("commentCount") val commentCount: Int, + @SerializedName("isPin") val isPin: Boolean, + @SerializedName("isAvailablePin") val isAvailablePin: Boolean, @SerializedName("creator") val creator: AudioContentCreator ) diff --git a/app/src/main/res/drawable-xxhdpi/ic_pin.png b/app/src/main/res/drawable-xxhdpi/ic_pin.png new file mode 100644 index 0000000..088bb74 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_pin.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_pin_cancel.png b/app/src/main/res/drawable-xxhdpi/ic_pin_cancel.png new file mode 100644 index 0000000..26586bd Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_pin_cancel.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_trash_can.png b/app/src/main/res/drawable-xxhdpi/ic_trash_can.png new file mode 100644 index 0000000..b3a0532 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_trash_can.png differ diff --git a/app/src/main/res/layout/dialog_audio_content_detail_menu.xml b/app/src/main/res/layout/dialog_audio_content_detail_menu.xml new file mode 100644 index 0000000..c37b227 --- /dev/null +++ b/app/src/main/res/layout/dialog_audio_content_detail_menu.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +