채금 기능 추가

This commit is contained in:
klaus 2023-10-11 02:49:52 +09:00
parent ac6b0c52d0
commit fbad5f9d98
12 changed files with 362 additions and 2 deletions

View File

@ -8,6 +8,7 @@ object Constants {
const val PREF_IS_ADULT = "pref_is_adult"
const val PREF_NICKNAME = "pref_nickname"
const val PREF_USER_ROLE = "pref_user_role"
const val PREF_NO_CHAT_ROOM = "pref_no_chat"
const val PREF_PUSH_TOKEN = "pref_push_token"
const val PREF_PROFILE_IMAGE = "pref_profile_image"
const val PREF_IS_CONTENT_PLAY_LOOP = "pref_is_content_play_loop"

View File

@ -3,6 +3,8 @@ package kr.co.vividnext.sodalive.common
import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import kr.co.vividnext.sodalive.settings.notification.MemberRole
object SharedPreferenceManager {
@ -122,4 +124,18 @@ object SharedPreferenceManager {
set(value) {
sharedPreferences[Constants.PREF_IS_VIEWED_ON_BOARDING_TUTORIAL] = value
}
var noChatRoomList: List<Long>
get() {
val list = sharedPreferences[Constants.PREF_NO_CHAT_ROOM, ""]
val gson = Gson()
val listType = object : TypeToken<List<Long>>() {}.type
val myList = gson.fromJson<List<Long>>(list, listType)
return myList ?: emptyList()
}
set(value) {
val gson = Gson()
val listJson = gson.toJson(value)
sharedPreferences[Constants.PREF_NO_CHAT_ROOM] = listJson
}
}

View File

@ -11,6 +11,7 @@ import android.graphics.Rect
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.CountDownTimer
import android.os.Handler
import android.os.Looper
import android.text.Spannable
@ -107,6 +108,57 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
private var isSpeaker = false
private var isSpeakerFold = false
private var isNoChatting = false
private var remainingNoChattingTime = noChattingTime
private val countDownTimer = object : CountDownTimer(remainingNoChattingTime * 1000, 1000) {
override fun onTick(millisUntilFinished: Long) {
remainingNoChattingTime -= 1
}
override fun onFinish() {
isNoChatting = false
remainingNoChattingTime = noChattingTime
removeNoChatRoom()
Toast.makeText(
applicationContext,
"채팅금지가 해제되었습니다.",
Toast.LENGTH_SHORT
).show()
}
}
private fun startNoChatting() {
hideKeyboard {
binding.etChat.clearFocus()
isNoChatting = true
Toast.makeText(
applicationContext,
"${viewModel.getManagerNickname()}님이 3분간 채팅을 금지하였습니다.",
Toast.LENGTH_SHORT
).show()
countDownTimer.start()
}
}
private fun addNoChatRoom() {
val noChatRoomList = SharedPreferenceManager.noChatRoomList.toMutableList()
noChatRoomList.add(roomId)
SharedPreferenceManager.noChatRoomList = noChatRoomList
}
private fun removeNoChatRoom() {
val noChatRoomList = SharedPreferenceManager.noChatRoomList.toMutableList()
noChatRoomList.remove(roomId)
SharedPreferenceManager.noChatRoomList = noChatRoomList
}
private fun containNoChatRoom(): Boolean {
val noChatRoomList = SharedPreferenceManager.noChatRoomList
return noChatRoomList.contains(roomId)
}
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
onClickQuit()
@ -150,6 +202,17 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
viewModel.getMemberCan()
viewModel.getRoomInfo(roomId)
binding.etChat.setOnFocusChangeListener { view, hasFocus ->
if (isNoChatting && hasFocus) {
Toast.makeText(
applicationContext,
"${remainingNoChattingTime}초 동안 채팅하실 수 없습니다",
Toast.LENGTH_SHORT
).show()
view.clearFocus()
}
}
}
override fun onStart() {
@ -232,6 +295,15 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
changeListenerMessage(memberId)
},
onClickNoChatting = { userId, nickname, profileUrl ->
LiveRoomNoChattingDialog(
activity = this,
layoutInflater = layoutInflater,
nickname = nickname,
profileUrl = profileUrl,
confirmButtonClick = { setNoChatting(userId, nickname) }
).show(screenWidth)
},
onClickKickOut = {
LiveDialog(
activity = this,
@ -304,6 +376,15 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
cancelButtonClick = {}
).show(screenWidth)
},
onClickNoChatting = { userId, nickname, profileUrl ->
LiveRoomNoChattingDialog(
activity = this,
layoutInflater = layoutInflater,
nickname = nickname,
profileUrl = profileUrl,
confirmButtonClick = { setNoChatting(userId, nickname) }
).show(screenWidth)
},
onClickPopupMenu = { userId, nickname, isBlock, view ->
showOptionMenu(
this,
@ -398,6 +479,7 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
agora.deInitAgoraEngine()
}
}
countDownTimer.cancel()
super.onDestroy()
}
@ -967,6 +1049,17 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
}
}
private fun setNoChatting(userId: Long, nickname: String) {
agora.sendRawMessageToPeer(
receiverUid = userId.toString(),
requestType = LiveRoomRequestType.NO_CHATTING
) {
handler.post {
showDialog(content = "${nickname}님을 3분간 채팅금지를 하였습니다.")
}
}
}
private fun showDialog(
content: String,
cancelTitle: String = "",
@ -1008,7 +1101,13 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
val profileUrl = viewModel.getUserProfileUrl(SharedPreferenceManager.userId.toInt())
val rank = viewModel.getUserRank(SharedPreferenceManager.userId)
if (binding.etChat.text.isNotBlank() && nickname.isNotBlank() && profileUrl.isNotBlank()) {
if (isNoChatting) {
Toast.makeText(
applicationContext,
"${remainingNoChattingTime}초 동안 채팅하실 수 없습니다",
Toast.LENGTH_SHORT
).show()
} else if (binding.etChat.text.isNotBlank() && nickname.isNotBlank() && profileUrl.isNotBlank()) {
val message = binding.etChat.text.toString()
chatAdapter.items.add(
LiveRoomNormalChat(
@ -1086,6 +1185,8 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
}
private fun joinChannel(roomInfo: GetRoomInfoResponse) {
loadingDialog.show(width = screenWidth, message = "라이브에 입장하고 있습니다.")
val userId = SharedPreferenceManager.userId
agora.joinRtcChannel(
uid = userId.toInt(),
@ -1194,6 +1295,10 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
}
},
rtmChannelJoinSuccess = {
handler.post {
loadingDialog.dismiss()
}
if (userId == roomInfo.creatorId) {
setBroadcaster()
} else {
@ -1208,6 +1313,10 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
} else {
startService(intent)
}
if (containNoChatRoom()) {
startNoChatting()
}
},
rtmChannelJoinFail = {
agoraConnectFail()
@ -1402,7 +1511,19 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
viewModel.getRoomInfo(roomId = roomId)
return
}
if (rawMessage == LiveRoomRequestType.NO_CHATTING.toString() && !isNoChatting) {
handler.post {
addNoChatRoom()
startNoChatting()
}
return
}
}
}
}
companion object {
private const val noChattingTime = 180L
}
}

View File

@ -0,0 +1,58 @@
package kr.co.vividnext.sodalive.live.room
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 coil.load
import coil.transform.CircleCropTransformation
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.databinding.DialogLiveNoChattingBinding
import kr.co.vividnext.sodalive.extensions.dpToPx
class LiveRoomNoChattingDialog(
activity: Activity,
layoutInflater: LayoutInflater,
nickname: String,
profileUrl: String,
confirmButtonClick: () -> Unit,
) {
private val alertDialog: AlertDialog
val dialogView = DialogLiveNoChattingBinding.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.tvConfirm.setOnClickListener {
alertDialog.dismiss()
confirmButtonClick()
}
dialogView.tvNickname.text = nickname
dialogView.ivProfile.load(profileUrl) {
crossfade(true)
placeholder(R.drawable.bg_placeholder)
transformations(CircleCropTransformation())
}
}
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
}
}

View File

@ -8,4 +8,5 @@ enum class LiveRoomRequestType {
@SerializedName("KICK_OUT") KICK_OUT,
@SerializedName("SET_MANAGER") SET_MANAGER,
@SerializedName("RELEASE_MANAGER") RELEASE_MANAGER,
@SerializedName("NO_CHATTING") NO_CHATTING,
}

View File

@ -15,6 +15,7 @@ class LiveRoomProfileAdapter(
private val isStaff: () -> Boolean,
private val onClickInviteSpeaker: (Long) -> Unit,
private val onClickChangeListener: (Long) -> Unit,
private val onClickNoChatting: (Long, String, String) -> Unit,
private val kickOut: (Long) -> Unit,
private val onClickProfile: (Long) -> Unit
) : RecyclerView.Adapter<LiveRoomProfileViewHolder>() {
@ -164,6 +165,7 @@ class LiveRoomProfileAdapter(
managerId = managerId,
onClickInviteSpeaker = onClickInviteSpeaker,
onClickChangeListener = onClickChangeListener,
onClickNoChatting = onClickNoChatting,
kickOut = kickOut,
onClickProfile = onClickProfile
)
@ -233,6 +235,7 @@ class LiveRoomProfileUserViewHolder(
private val managerId: Long,
private val onClickInviteSpeaker: (Long) -> Unit,
private val onClickChangeListener: (Long) -> Unit,
private val onClickNoChatting: (Long, String, String) -> Unit,
private val kickOut: (Long) -> Unit,
private val onClickProfile: (Long) -> Unit
) : LiveRoomProfileViewHolder(binding) {
@ -241,6 +244,7 @@ class LiveRoomProfileUserViewHolder(
item.managerId = managerId
item.onClickInviteSpeaker = onClickInviteSpeaker
item.onClickChangeListener = onClickChangeListener
item.onClickNoChatting = onClickNoChatting
item.kickOut = kickOut
item.onClickProfile = onClickProfile
item.bind(binding)

View File

@ -17,6 +17,7 @@ class LiveRoomProfileDialog(
onClickInviteSpeaker: (Long) -> Unit,
onClickChangeListener: (Long) -> Unit,
onClickKickOut: (Long) -> Unit,
onClickNoChatting: (Long, String, String) -> Unit,
onClickProfile: (Long) -> Unit
) {
private val bottomSheetDialog: BottomSheetDialog = BottomSheetDialog(activity)
@ -25,6 +26,7 @@ class LiveRoomProfileDialog(
isStaff = isStaff,
onClickInviteSpeaker = onClickInviteSpeaker,
onClickChangeListener = onClickChangeListener,
onClickNoChatting = onClickNoChatting,
kickOut = onClickKickOut,
onClickProfile = onClickProfile
)

View File

@ -42,6 +42,7 @@ abstract class LiveRoomProfileItem {
open var managerId = 0L
open var onClickInviteSpeaker: (Long) -> Unit = {}
open var onClickChangeListener: (Long) -> Unit = {}
open var onClickNoChatting: (Long, String, String) -> Unit = { _, _, _ -> }
open var kickOut: (Long) -> Unit = {}
open var onClickProfile: (Long) -> Unit = {}
abstract fun bind(binding: ViewBinding)
@ -197,5 +198,18 @@ data class LiveRoomProfileItemUser(
} else {
itemBinding.llControlButtons.visibility = View.GONE
}
if (managerId == SharedPreferenceManager.userId) {
itemBinding.tvNoChatting.visibility = View.VISIBLE
itemBinding.tvNoChatting.setOnClickListener {
onClickNoChatting(
id,
nickname,
profileUrl
)
}
} else {
itemBinding.tvNoChatting.visibility = View.GONE
}
}
}

View File

@ -28,6 +28,7 @@ class LiveRoomUserProfileDialog(
private val onClickInviteSpeaker: (Long) -> Unit,
private val onClickChangeListener: (Long) -> Unit,
private val onClickKickOut: (Long) -> Unit,
private val onClickNoChatting: (Long, String, String) -> Unit,
private val onClickPopupMenu: (Long, String, Boolean, View) -> Unit,
) {
private val alertDialog: AlertDialog
@ -128,6 +129,7 @@ class LiveRoomUserProfileDialog(
if (userProfile.isManager != null) {
dialogView.tvSetManager.visibility = View.VISIBLE
dialogView.tvNoChatting.visibility = View.VISIBLE
if (userProfile.isManager) {
dialogView.tvSetManager.text = "스탭 해제"
@ -142,8 +144,17 @@ class LiveRoomUserProfileDialog(
alertDialog.dismiss()
}
}
dialogView.tvNoChatting.setOnClickListener {
onClickNoChatting(
userProfile.userId,
userProfile.nickname,
userProfile.profileUrl
)
}
} else {
dialogView.tvSetManager.visibility = View.GONE
dialogView.tvNoChatting.visibility = View.GONE
}
if (

View File

@ -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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/bg_round_corner_10_222222">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
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_profile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="21dp"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_title"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/iv_profile"
android:layout_width="26.7dp"
android:layout_height="26.7dp"
android:contentDescription="@null" />
<TextView
android:id="@+id/tv_nickname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textColor="@color/color_bbbbbb"
android:textSize="16.7sp"
tools:text="델1002" />
</LinearLayout>
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="21dp"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="center"
android:text="3분간 채팅금지를 하겠습니까?"
android:textColor="@color/color_bbbbbb"
android:textSize="15sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ll_profile" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16.7dp"
android:layout_marginTop="21dp"
android:layout_marginBottom="16.7dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_desc">
<TextView
android:id="@+id/tv_cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="13.3dp"
android:layout_weight="1"
android:background="@drawable/bg_round_corner_10_339970ff_9970ff"
android:fontFamily="@font/gmarket_sans_bold"
android:gravity="center"
android:paddingVertical="16dp"
android:text="취소"
android:textColor="@color/color_9970ff"
android:textSize="18.3sp" />
<TextView
android:id="@+id/tv_confirm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/bg_round_corner_10_9970ff"
android:fontFamily="@font/gmarket_sans_bold"
android:gravity="center"
android:paddingVertical="16dp"
android:text="확인"
android:textColor="@color/white"
android:textSize="18.3sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -215,6 +215,19 @@
android:visibility="gone" />
</LinearLayout>
<TextView
android:id="@+id/tv_no_chatting"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="21.3dp"
android:background="@drawable/bg_round_corner_8_transparent_9970ff"
android:fontFamily="@font/gmarket_sans_bold"
android:gravity="center"
android:paddingVertical="13dp"
android:text="3분간 채팅금지"
android:textColor="@color/color_9970ff"
android:visibility="gone" />
<TextView
android:id="@+id/tv_tags"
android:layout_width="match_parent"

View File

@ -69,6 +69,21 @@
android:visibility="gone"
tools:ignore="SmallSp" />
<TextView
android:id="@+id/tv_no_chatting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:background="@drawable/bg_round_corner_6_7_339970ff_9970ff"
android:fontFamily="@font/gmarket_sans_medium"
android:paddingHorizontal="5.5dp"
android:paddingVertical="12dp"
android:text="채금"
android:textColor="@color/white"
android:textSize="10sp"
android:visibility="gone"
tools:ignore="SmallSp" />
<ImageView
android:id="@+id/iv_kick_out"
android:layout_width="wrap_content"
@ -76,7 +91,6 @@
android:layout_marginStart="10dp"
android:contentDescription="@null"
android:src="@drawable/ic_kick_out" />
</LinearLayout>
<View