커뮤니티 유료 게시글 조회, 구매 기능 추가
This commit is contained in:
@@ -20,6 +20,7 @@ import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import coil.load
|
||||
import coil.transform.BlurTransformation
|
||||
import coil.transform.CircleCropTransformation
|
||||
import coil.transform.RoundedCornersTransformation
|
||||
import kr.co.vividnext.sodalive.R
|
||||
@@ -27,7 +28,6 @@ import kr.co.vividnext.sodalive.audio_content.AudioContentActivity
|
||||
import kr.co.vividnext.sodalive.audio_content.AudioContentAdapter
|
||||
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
|
||||
import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse
|
||||
import kr.co.vividnext.sodalive.audio_content.series.SeriesListAdapter
|
||||
import kr.co.vividnext.sodalive.audio_content.series.SeriesListAllActivity
|
||||
import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity
|
||||
import kr.co.vividnext.sodalive.audio_content.upload.AudioContentUploadActivity
|
||||
@@ -831,6 +831,16 @@ class UserProfileActivity : BaseActivity<ActivityUserProfileBinding>(
|
||||
crossfade(true)
|
||||
placeholder(R.drawable.ic_place_holder)
|
||||
transformations(RoundedCornersTransformation(4.7f.dpToPx()))
|
||||
|
||||
if (!item.existOrdered) {
|
||||
transformations(
|
||||
BlurTransformation(
|
||||
this@UserProfileActivity,
|
||||
25f,
|
||||
2.5f
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
layout.tvLikeCount.text = "${item.likeCount}"
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.reactivex.rxjava3.core.Single
|
||||
import kr.co.vividnext.sodalive.audio_content.comment.ModifyCommentRequest
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.PostCommunityPostLikeRequest
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.PurchasePostRequest
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.comment.CreateCommunityPostCommentRequest
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
@@ -91,4 +92,10 @@ interface CreatorCommunityApi {
|
||||
@Query("timezone") timezone: String,
|
||||
@Header("Authorization") authHeader: String
|
||||
): Single<ApiResponse<GetCommunityPostListResponse>>
|
||||
|
||||
@POST("/creator-community/purchase")
|
||||
fun purchaseCommunityPost(
|
||||
@Body request: PurchasePostRequest,
|
||||
@Header("Authorization") authHeader: String
|
||||
): Single<ApiResponse<GetCommunityPostListResponse>>
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.explorer.profile.creator_community
|
||||
|
||||
import kr.co.vividnext.sodalive.audio_content.comment.ModifyCommentRequest
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.PostCommunityPostLikeRequest
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.PurchasePostRequest
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.comment.CreateCommunityPostCommentRequest
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
@@ -98,4 +99,9 @@ class CreatorCommunityRepository(private val api: CreatorCommunityApi) {
|
||||
timezone = TimeZone.getDefault().id,
|
||||
authHeader = token
|
||||
)
|
||||
|
||||
fun purchaseCommunityPost(postId: Long, token: String) = api.purchaseCommunityPost(
|
||||
request = PurchasePostRequest(postId = postId, timezone = TimeZone.getDefault().id),
|
||||
authHeader = token
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,10 +9,12 @@ data class GetCommunityPostListResponse(
|
||||
@SerializedName("creatorProfileUrl") val creatorProfileUrl: String,
|
||||
@SerializedName("imageUrl") val imageUrl: String?,
|
||||
@SerializedName("content") val content: String,
|
||||
@SerializedName("price") val price: Int,
|
||||
@SerializedName("date") val date: String,
|
||||
@SerializedName("isCommentAvailable") val isCommentAvailable: Boolean,
|
||||
@SerializedName("isAdult") val isAdult: Boolean,
|
||||
@SerializedName("isLike") var isLike: Boolean,
|
||||
@SerializedName("existOrdered") val existOrdered: Boolean,
|
||||
@SerializedName("likeCount") val likeCount: Int,
|
||||
@SerializedName("commentCount") val commentCount: Int,
|
||||
@SerializedName("firstComment") val firstComment: GetCommunityPostCommentListItem?,
|
||||
|
||||
@@ -62,6 +62,7 @@ class CreatorCommunityAllActivity : BaseActivity<ActivityCreatorCommunityAllBind
|
||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||
|
||||
adapter = CreatorCommunityAllAdapter(
|
||||
screenWidth = screenWidth,
|
||||
onClickLike = { viewModel.communityPostLike(it) },
|
||||
writeComment = { postId, parentId, comment ->
|
||||
viewModel.registerComment(
|
||||
@@ -111,6 +112,18 @@ class CreatorCommunityAllActivity : BaseActivity<ActivityCreatorCommunityAllBind
|
||||
reason = it
|
||||
)
|
||||
}.show(screenWidth)
|
||||
},
|
||||
onClickPurchaseContent = { postId, can, onSuccess ->
|
||||
PurchaseCommunityPostDialog(
|
||||
activity = this@CreatorCommunityAllActivity,
|
||||
layoutInflater = layoutInflater,
|
||||
can = can,
|
||||
confirmButtonClick = {
|
||||
viewModel.purchaseCommunityPost(postId) {
|
||||
onSuccess(it)
|
||||
}
|
||||
}
|
||||
).show(screenWidth)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ import android.text.style.ClickableSpan
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@@ -19,17 +21,22 @@ import coil.transform.CircleCropTransformation
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||
import kr.co.vividnext.sodalive.databinding.ItemCreatorCommunityAllBinding
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.GetCommunityPostCommentListItem
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.GetCommunityPostListResponse
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
import kr.co.vividnext.sodalive.extensions.loadUrl
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class CreatorCommunityAllAdapter(
|
||||
private val screenWidth: Int,
|
||||
private val onClickLike: (Long) -> Unit,
|
||||
private val writeComment: (Long, Long?, String) -> Unit,
|
||||
private val showCommentBottomSheetDialog: (Long) -> Unit,
|
||||
private val onClickModify: (Long) -> Unit,
|
||||
private val onClickDelete: (Long) -> Unit,
|
||||
private val onClickReport: (Long) -> Unit
|
||||
private val onClickReport: (Long) -> Unit,
|
||||
private val onClickPurchaseContent:
|
||||
(Long, Int, onSuccess: (GetCommunityPostListResponse) -> Unit) -> Unit
|
||||
) : RecyclerView.Adapter<CreatorCommunityAllAdapter.ViewHolder>() {
|
||||
|
||||
val items = mutableListOf<GetCommunityPostListResponse>()
|
||||
@@ -38,7 +45,7 @@ class CreatorCommunityAllAdapter(
|
||||
private val context: Context,
|
||||
private val binding: ItemCreatorCommunityAllBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
@SuppressLint("NotifyDataSetChanged", "SetTextI18n")
|
||||
fun bind(item: GetCommunityPostListResponse, index: Int) {
|
||||
binding.tvDate.text = item.date
|
||||
binding.tvNickname.text = item.creatorNickname
|
||||
@@ -48,19 +55,41 @@ class CreatorCommunityAllAdapter(
|
||||
transformations(CircleCropTransformation())
|
||||
}
|
||||
|
||||
setNoticeAndClickableUrl(binding.tvContent, item.content)
|
||||
binding.tvContent.setOnClickListener {
|
||||
items[index] = items[index].copy(
|
||||
isExpand = !item.isExpand,
|
||||
)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
binding.tvContent.maxLines = if (item.isExpand) {
|
||||
Int.MAX_VALUE
|
||||
} else {
|
||||
3
|
||||
}
|
||||
if (item.price > 0) {
|
||||
if (item.existOrdered) {
|
||||
setContent(item, index)
|
||||
} else {
|
||||
binding.llLike.visibility = View.GONE
|
||||
binding.tvContent.visibility = View.GONE
|
||||
binding.ivContent.visibility = View.GONE
|
||||
binding.llComment.visibility = View.GONE
|
||||
binding.ivSeeMore.visibility = View.GONE
|
||||
binding.llLockPost.visibility = View.VISIBLE
|
||||
|
||||
val lockPostWidth = (screenWidth - 42f.dpToPx()).toInt()
|
||||
val lp = binding.llLockPost.layoutParams as LinearLayout.LayoutParams
|
||||
lp.width = lockPostWidth
|
||||
lp.height = lockPostWidth
|
||||
binding.llLockPost.layoutParams = lp
|
||||
|
||||
binding.tvPurchase.text = "${item.price}캔으로 게시글 보기"
|
||||
binding.tvPurchase.setOnClickListener {
|
||||
onClickPurchaseContent(item.postId, item.price) { post ->
|
||||
items[index] = post
|
||||
setContent(post, index)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setContent(item, index)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setContent(item: GetCommunityPostListResponse, index: Int) {
|
||||
binding.llLockPost.visibility = View.GONE
|
||||
binding.llLike.visibility = View.VISIBLE
|
||||
binding.llComment.visibility = View.VISIBLE
|
||||
binding.ivSeeMore.visibility = View.VISIBLE
|
||||
binding.ivSeeMore.setOnClickListener {
|
||||
showOptionMenu(
|
||||
context = context,
|
||||
@@ -70,55 +99,54 @@ class CreatorCommunityAllAdapter(
|
||||
)
|
||||
}
|
||||
|
||||
binding.ivLike.setImageResource(
|
||||
if (item.isLike) {
|
||||
R.drawable.ic_audio_content_heart_pressed
|
||||
} else {
|
||||
R.drawable.ic_audio_content_heart_normal
|
||||
}
|
||||
setImageContent(binding.ivContent, item.imageUrl)
|
||||
setContentLike(item.isLike, item.likeCount, item.postId, index)
|
||||
setNoticeAndClickableUrl(binding.tvContent, item.content, item.isExpand, index)
|
||||
setContentComment(
|
||||
item.postId,
|
||||
item.commentCount,
|
||||
item.isCommentAvailable,
|
||||
comment = item.firstComment
|
||||
)
|
||||
}
|
||||
|
||||
binding.tvLike.text = "${item.likeCount}"
|
||||
binding.llLike.setOnClickListener {
|
||||
val isLike = !item.isLike
|
||||
|
||||
items[index] = items[index].copy(
|
||||
isLike = !item.isLike,
|
||||
likeCount = if (isLike) item.likeCount + 1 else item.likeCount - 1
|
||||
)
|
||||
notifyDataSetChanged()
|
||||
|
||||
onClickLike(item.postId)
|
||||
}
|
||||
|
||||
if (item.imageUrl != null) {
|
||||
binding.ivContent.visibility = View.VISIBLE
|
||||
binding.ivContent.loadUrl(item.imageUrl) {
|
||||
private fun setImageContent(ivContent: ImageView, imageUrl: String?) {
|
||||
ivContent.visibility = View.VISIBLE
|
||||
if (imageUrl != null) {
|
||||
ivContent.visibility = View.VISIBLE
|
||||
ivContent.loadUrl(imageUrl) {
|
||||
crossfade(true)
|
||||
placeholder(R.drawable.bg_placeholder)
|
||||
}
|
||||
} else {
|
||||
binding.ivContent.visibility = View.GONE
|
||||
ivContent.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
if (item.isCommentAvailable) {
|
||||
private fun setContentComment(
|
||||
postId: Long,
|
||||
commentCount: Int,
|
||||
isCommentAvailable: Boolean,
|
||||
comment: GetCommunityPostCommentListItem?
|
||||
) {
|
||||
if (isCommentAvailable) {
|
||||
binding.llComment.visibility = View.VISIBLE
|
||||
binding.tvCommentCount.text = "${item.commentCount}"
|
||||
binding.tvCommentCount.text = "$commentCount"
|
||||
} else {
|
||||
binding.llComment.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (item.commentCount > 0) {
|
||||
binding.ivCommentProfile.load(item.firstComment!!.profileUrl) {
|
||||
if (commentCount > 0 && comment != null) {
|
||||
binding.ivCommentProfile.load(comment.profileUrl) {
|
||||
crossfade(true)
|
||||
placeholder(R.drawable.bg_placeholder)
|
||||
transformations(CircleCropTransformation())
|
||||
}
|
||||
binding.tvCommentText.text = item.firstComment.comment
|
||||
binding.tvCommentText.text = comment.comment
|
||||
binding.tvCommentText.visibility = View.VISIBLE
|
||||
binding.rlInputComment.visibility = View.GONE
|
||||
|
||||
binding.llComment.setOnClickListener { showCommentBottomSheetDialog(item.postId) }
|
||||
binding.llComment.setOnClickListener { showCommentBottomSheetDialog(postId) }
|
||||
} else {
|
||||
binding.tvCommentText.visibility = View.GONE
|
||||
binding.rlInputComment.visibility = View.VISIBLE
|
||||
@@ -129,16 +157,45 @@ class CreatorCommunityAllAdapter(
|
||||
}
|
||||
|
||||
binding.ivCommentSend.setOnClickListener {
|
||||
val comment = binding.etComment.text.toString()
|
||||
val inputComment = binding.etComment.text.toString()
|
||||
binding.etComment.setText("")
|
||||
writeComment(item.postId, null, comment)
|
||||
writeComment(postId, null, inputComment)
|
||||
}
|
||||
|
||||
binding.llComment.setOnClickListener {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setNoticeAndClickableUrl(textView: TextView, text: String) {
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun setContentLike(isLike: Boolean, likeCount: Int, postId: Long, index: Int) {
|
||||
binding.ivLike.setImageResource(
|
||||
if (isLike) {
|
||||
R.drawable.ic_audio_content_heart_pressed
|
||||
} else {
|
||||
R.drawable.ic_audio_content_heart_normal
|
||||
}
|
||||
)
|
||||
|
||||
binding.tvLike.text = "$likeCount"
|
||||
binding.llLike.setOnClickListener {
|
||||
items[index] = items[index].copy(
|
||||
isLike = !isLike,
|
||||
likeCount = if (!isLike) likeCount + 1 else likeCount - 1
|
||||
)
|
||||
notifyDataSetChanged()
|
||||
|
||||
onClickLike(postId)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun setNoticeAndClickableUrl(
|
||||
textView: TextView,
|
||||
text: String,
|
||||
isExpand: Boolean,
|
||||
index: Int
|
||||
) {
|
||||
textView.visibility = View.VISIBLE
|
||||
textView.text = text
|
||||
|
||||
val spannable = SpannableString(text)
|
||||
@@ -159,6 +216,19 @@ class CreatorCommunityAllAdapter(
|
||||
|
||||
textView.text = spannable
|
||||
textView.movementMethod = LinkMovementMethod.getInstance()
|
||||
|
||||
textView.setOnClickListener {
|
||||
items[index] = items[index].copy(
|
||||
isExpand = !isExpand,
|
||||
)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
textView.maxLines = if (isExpand) {
|
||||
Int.MAX_VALUE
|
||||
} else {
|
||||
3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -220,4 +220,41 @@ class CreatorCommunityAllViewModel(
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun purchaseCommunityPost(postId: Long, onSuccess: (GetCommunityPostListResponse) -> Unit) {
|
||||
if (!_isLoading.value!!) {
|
||||
_isLoading.value = true
|
||||
compositeDisposable.add(
|
||||
repository
|
||||
.purchaseCommunityPost(
|
||||
postId = postId,
|
||||
token = "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("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package kr.co.vividnext.sodalive.explorer.profile.creator_community.all
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
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.DialogPurchaseCommunityPostBinding
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
class PurchaseCommunityPostDialog(
|
||||
activity: Activity,
|
||||
layoutInflater: LayoutInflater,
|
||||
can: Int,
|
||||
confirmButtonClick: () -> Unit,
|
||||
) {
|
||||
|
||||
private val alertDialog: AlertDialog
|
||||
val dialogView = DialogPurchaseCommunityPostBinding.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.tvCan.text = "${can.moneyFormat()}캔으로 보기"
|
||||
dialogView.tvCan.setOnClickListener {
|
||||
alertDialog.dismiss()
|
||||
confirmButtonClick()
|
||||
}
|
||||
dialogView.tvCancel.setOnClickListener { alertDialog.dismiss() }
|
||||
}
|
||||
|
||||
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,9 @@
|
||||
package kr.co.vividnext.sodalive.explorer.profile.creator_community.all
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class PurchasePostRequest(
|
||||
@SerializedName("postId") val postId: Long,
|
||||
@SerializedName("timezone") val timezone: String,
|
||||
@SerializedName("container") val container: String = "aos",
|
||||
)
|
||||
Reference in New Issue
Block a user