콘텐츠 상세

- 콘텐츠 고정/해제 기능 추가
This commit is contained in:
klaus 2024-01-29 00:33:50 +09:00
parent 0bbb1e070c
commit c23ef771be
10 changed files with 310 additions and 49 deletions

View File

@ -201,4 +201,16 @@ interface AudioContentApi {
fun getMainOrderList( fun getMainOrderList(
@Header("Authorization") authHeader: String @Header("Authorization") authHeader: String
): Single<ApiResponse<List<GetAudioContentMainItem>>> ): Single<ApiResponse<List<GetAudioContentMainItem>>>
@POST("/audio-content/pin-to-the-top/{id}")
fun pinContent(
@Path("id") audioContentId: Long,
@Header("Authorization") authHeader: String
): Single<ApiResponse<Any>>
@PUT("/audio-content/unpin-at-the-top/{id}")
fun unpinContent(
@Path("id") audioContentId: Long,
@Header("Authorization") authHeader: String
): Single<ApiResponse<Any>>
} }

View File

@ -188,4 +188,13 @@ class AudioContentRepository(
fun getMainBannerList(token: String) = api.getMainBannerList(authHeader = token) fun getMainBannerList(token: String) = api.getMainBannerList(authHeader = token)
fun getMainOrderList(token: String) = api.getMainOrderList(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)
} }

View File

@ -13,7 +13,6 @@ import android.view.View
import android.widget.RelativeLayout import android.widget.RelativeLayout
import android.widget.SeekBar import android.widget.SeekBar
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.widget.PopupMenu
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
@ -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.AudioContentOrderFragment
import kr.co.vividnext.sodalive.audio_content.order.OrderType import kr.co.vividnext.sodalive.audio_content.order.OrderType
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.SharedPreferenceManager import kr.co.vividnext.sodalive.common.SharedPreferenceManager
@ -116,10 +116,7 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
binding.tvBack.setOnClickListener { finish() } binding.tvBack.setOnClickListener { finish() }
binding.ivClosePreviewAlert.setOnClickListener { viewModel.toggleShowPreviewAlert() } binding.ivClosePreviewAlert.setOnClickListener { viewModel.toggleShowPreviewAlert() }
binding.ivMenu.setOnClickListener { binding.ivMenu.setOnClickListener {
showOptionMenu( showOptionMenu()
this,
binding.ivMenu,
)
} }
creatorOtherContentAdapter = OtherContentAdapter { creatorOtherContentAdapter = OtherContentAdapter {
@ -260,7 +257,7 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
} }
} }
dialog.show(screenWidth) dialog.show(screenWidth - 26.7f.dpToPx().toInt())
} }
} }
@ -270,51 +267,46 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
} }
} }
private fun showOptionMenu(context: Context, v: View) { private fun showOptionMenu() {
val popup = PopupMenu(context, v) val dialog = AudioContentDetailMenuBottomSheetDialog(
val inflater = popup.menuInflater isPin = viewModel.audioContentLiveData.value!!.isPin,
isCreator = viewModel.audioContentLiveData.value!!
if ( .creator.creatorId == SharedPreferenceManager.userId,
viewModel.audioContentLiveData.value!!.creator.creatorId == onClickPin = {
SharedPreferenceManager.userId if (viewModel.audioContentLiveData.value!!.isPin) {
) { viewModel.unPinContent(audioContentId)
inflater.inflate(R.menu.audio_content_detail_creator_menu, popup.menu) } else {
if (viewModel.audioContentLiveData.value!!.isAvailablePin) {
popup.setOnMenuItemClickListener { viewModel.pinContent(audioContentId)
when (it.itemId) { } else {
R.id.menu_modify -> { SodaDialog(this@AudioContentDetailActivity,
refresh = true layoutInflater,
setResult(RESULT_OK) "고정 한도 도달",
startActivity( "이 콘텐츠를 고정하시겠어요? " +
Intent(applicationContext, AudioContentModifyActivity::class.java) "채널에 콘텐츠를 최대 3개까지 고정할 수 있습니다." +
.apply { "이 콘텐츠를 고정하면 가장 오래된 콘텐츠가 대체됩니다.",
putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, audioContentId) "확인",
} { viewModel.pinContent(audioContentId) },
) "취소",
} {}
).show(screenWidth)
R.id.menu_delete -> {
showDeleteDialog()
} }
} }
},
true onClickModify = {
} refresh = true
} else { setResult(RESULT_OK)
inflater.inflate(R.menu.audio_content_detail_user_menu, popup.menu) startActivity(
Intent(applicationContext, AudioContentModifyActivity::class.java)
popup.setOnMenuItemClickListener { .apply {
when (it.itemId) { putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, audioContentId)
R.id.menu_report -> { }
showReportDialog() )
} },
} onClickDelete = { showDeleteDialog() },
onClickReport = { showReportDialog() }
true )
} dialog.show(supportFragmentManager, dialog.tag)
}
popup.show()
} }
private fun showDeleteDialog() { private fun showDeleteDialog() {

View File

@ -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()
}
}
}
}

View File

@ -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("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
}
)
)
}
} }

View File

@ -31,6 +31,8 @@ data class GetAudioContentDetailResponse(
@SerializedName("likeCount") val likeCount: Int, @SerializedName("likeCount") val likeCount: Int,
@SerializedName("commentList") val commentList: List<GetAudioContentCommentListItem>, @SerializedName("commentList") val commentList: List<GetAudioContentCommentListItem>,
@SerializedName("commentCount") val commentCount: Int, @SerializedName("commentCount") val commentCount: Int,
@SerializedName("isPin") val isPin: Boolean,
@SerializedName("isAvailablePin") val isAvailablePin: Boolean,
@SerializedName("creator") val creator: AudioContentCreator @SerializedName("creator") val creator: AudioContentCreator
) )

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 B

View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingVertical="25dp"
tools:background="@color/black">
<LinearLayout
android:id="@+id/ll_menu_creator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="21dp">
<LinearLayout
android:id="@+id/ll_pin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingVertical="8dp"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/iv_pin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_pin" />
<TextView
android:id="@+id/tv_pin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="13.3dp"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="center"
android:text="내 채널에 고정"
android:textColor="@color/color_e2e2e2"
android:textSize="14.7sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_modify"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="21dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingVertical="8dp"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_make_message" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="13.3dp"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="center"
android:text="수정"
android:textColor="@color/color_e2e2e2"
android:textSize="14.7sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="21dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingVertical="8dp"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_trash_can" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="13.3dp"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="center"
android:text="삭제"
android:textColor="@color/color_e2e2e2"
android:textSize="14.7sp" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tv_report"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/gmarket_sans_medium"
android:paddingHorizontal="21.3dp"
android:paddingVertical="8dp"
android:text="신고하기"
android:textColor="@color/color_e2e2e2"
android:textSize="14.7sp" />
</LinearLayout>