라이브 후원

- 비밀 후원 기능 추가
This commit is contained in:
klaus 2024-08-24 00:37:53 +09:00
parent 3bad5c5e55
commit adab4aee48
14 changed files with 201 additions and 45 deletions

View File

@ -4,6 +4,14 @@
<selectionStates> <selectionStates>
<SelectionState runConfigName="app"> <SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" /> <option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2024-08-23T14:56:05.594981Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=2cec640c34017ece" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState> </SelectionState>
</selectionStates> </selectionStates>
</component> </component>

View File

@ -69,6 +69,17 @@
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2400" /> <option name="screenY" value="2400" />
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="caiman" />
<option name="id" value="caiman" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro" />
<option name="screenDensity" value="360" />
<option name="screenX" value="960" />
<option name="screenY" value="2142" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="29" /> <option name="api" value="29" />
<option name="brand" value="samsung" /> <option name="brand" value="samsung" />
@ -146,6 +157,17 @@
<option name="screenX" value="720" /> <option name="screenX" value="720" />
<option name="screenY" value="1600" /> <option name="screenY" value="1600" />
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="komodo" />
<option name="id" value="komodo" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9 Pro XL" />
<option name="screenDensity" value="360" />
<option name="screenX" value="1008" />
<option name="screenY" value="2244" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="33" /> <option name="api" value="33" />
<option name="brand" value="google" /> <option name="brand" value="google" />
@ -235,6 +257,17 @@
<option name="screenX" value="1600" /> <option name="screenX" value="1600" />
<option name="screenY" value="2560" /> <option name="screenY" value="2560" />
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData>
<option name="api" value="34" />
<option name="brand" value="google" />
<option name="codename" value="tokay" />
<option name="id" value="tokay" />
<option name="manufacturer" value="Google" />
<option name="name" value="Pixel 9" />
<option name="screenDensity" value="420" />
<option name="screenX" value="1080" />
<option name="screenY" value="2424" />
</PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="29" /> <option name="api" value="29" />
<option name="brand" value="samsung" /> <option name="brand" value="samsung" />

View File

@ -172,13 +172,14 @@ class Agora(
fun sendRawMessageToPeer( fun sendRawMessageToPeer(
receiverUid: String, receiverUid: String,
requestType: LiveRoomRequestType, requestType: LiveRoomRequestType? = null,
rawMessage: ByteArray? = null,
onSuccess: () -> Unit onSuccess: () -> Unit
) { ) {
val option = SendMessageOptions() val option = SendMessageOptions()
val message = rtmClient!!.createMessage() val message = rtmClient!!.createMessage()
message.rawMessage = requestType.toString().toByteArray() message.rawMessage = rawMessage ?: requestType.toString().toByteArray()
rtmClient!!.sendMessageToPeer( rtmClient!!.sendMessageToPeer(
receiverUid, receiverUid,

View File

@ -271,7 +271,7 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
val dialog = LiveRoomDonationDialog( val dialog = LiveRoomDonationDialog(
this, this,
LayoutInflater.from(this) LayoutInflater.from(this)
) { can, message -> ) { can, message, _ ->
if (can <= 0) { if (can <= 0) {
showToast("1캔 이상 후원하실 수 있습니다.") showToast("1캔 이상 후원하실 수 있습니다.")
} else if (message.isBlank()) { } else if (message.isBlank()) {

View File

@ -163,12 +163,14 @@ class LiveRepository(
roomId: Long, roomId: Long,
can: Int, can: Int,
message: String, message: String,
isSecret: Boolean,
token: String token: String
): Single<ApiResponse<LiveRoomDonationResponse>> { ): Single<ApiResponse<LiveRoomDonationResponse>> {
return api.donation( return api.donation(
request = LiveRoomDonationRequest( request = LiveRoomDonationRequest(
roomId = roomId, roomId = roomId,
can = can, can = can,
isSecret = isSecret,
message = message, message = message,
container = "aos" container = "aos"
), ),

View File

@ -464,10 +464,11 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
binding.flDonation.setOnClickListener { binding.flDonation.setOnClickListener {
val dialog = LiveRoomDonationDialog( val dialog = LiveRoomDonationDialog(
this, this,
LayoutInflater.from(this) LayoutInflater.from(this),
) { can, message -> isLiveDonation = true
) { can, message, isSecret ->
if (can > 0) { if (can > 0) {
donation(can, message) donation(can, message, isSecret)
} else { } else {
showToast("1캔 이상 후원하실 수 있습니다.") showToast("1캔 이상 후원하실 수 있습니다.")
} }
@ -1305,13 +1306,21 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
} }
} }
private fun donation(can: Int, message: String) { private fun donation(can: Int, message: String, isSecret: Boolean) {
val rawMessage = "${can}캔을 후원하셨습니다.\uD83D\uDCB0\uD83E\uDE99" val rawMessage = if (isSecret) {
"${can}캔을 비밀후원하셨습니다.\uD83D\uDCB0\uD83E\uDE99"
} else {
"${can}캔을 후원하셨습니다.\uD83D\uDCB0\uD83E\uDE99"
}
viewModel.donation(roomId, can, message) { signature -> viewModel.donation(roomId, can, message, isSecret) { signature ->
val donationRawMessage = Gson().toJson( val donationRawMessage = Gson().toJson(
LiveRoomChatRawMessage( LiveRoomChatRawMessage(
type = LiveRoomChatRawMessageType.DONATION, type = if (isSecret) {
LiveRoomChatRawMessageType.SECRET_DONATION
} else {
LiveRoomChatRawMessageType.DONATION
},
message = rawMessage, message = rawMessage,
can = can, can = can,
signature = signature, signature = signature,
@ -1320,6 +1329,30 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
) )
) )
if (isSecret) {
agora.sendRawMessageToPeer(
receiverUid = viewModel.roomInfoResponse.creatorId.toString(),
rawMessage = donationRawMessage.toByteArray()
) {
handler.post {
val nickname =
viewModel.getUserNickname(SharedPreferenceManager.userId.toInt())
val profileUrl =
viewModel.getUserProfileUrl(SharedPreferenceManager.userId.toInt())
chatAdapter.items.add(
LiveRoomDonationChat(
profileUrl,
nickname,
rawMessage,
can,
donationMessage = message
)
)
invalidateChat()
addSignature(signature)
}
}
} else {
agora.sendRawMessageToGroup( agora.sendRawMessageToGroup(
rawMessage = donationRawMessage.toByteArray(), rawMessage = donationRawMessage.toByteArray(),
onSuccess = { onSuccess = {
@ -1348,6 +1381,7 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
) )
} }
} }
}
private fun spinRoulette(rouletteId: Long) { private fun spinRoulette(rouletteId: Long) {
viewModel.spinRoulette(roomId = roomId, rouletteId = rouletteId) { can, items, randomItem -> viewModel.spinRoulette(roomId = roomId, rouletteId = rouletteId) { can, items, randomItem ->
@ -1491,6 +1525,8 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
viewModel.addDonationCan(rawMessage.can) viewModel.addDonationCan(rawMessage.can)
} }
} }
else -> {}
} }
} else { } else {
val chat = message.text val chat = message.text
@ -1789,6 +1825,35 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
} }
return return
} }
val message = Gson().fromJson(
rawMessage,
LiveRoomChatRawMessage::class.java
)
if (message.type == LiveRoomChatRawMessageType.SECRET_DONATION) {
val nickname = viewModel.getUserNickname(peerId.toInt())
val profileUrl = viewModel.getUserProfileUrl(peerId.toInt())
handler.post {
chatAdapter.items.add(
LiveRoomDonationChat(
profileUrl,
nickname,
message.message,
message.can,
message.donationMessage ?: ""
)
)
invalidateChat()
if (message.signature != null) {
addSignature(message.signature)
} else if (message.signatureImageUrl != null) {
addSignatureImage(message.signatureImageUrl)
}
}
}
} }
} }
} }

View File

@ -521,11 +521,12 @@ class LiveRoomViewModel(
roomId: Long, roomId: Long,
can: Int, can: Int,
message: String, message: String,
isSecret: Boolean,
onSuccess: (LiveRoomDonationResponse?) -> Unit onSuccess: (LiveRoomDonationResponse?) -> Unit
) { ) {
_isLoading.postValue(true) _isLoading.postValue(true)
compositeDisposable.add( compositeDisposable.add(
repository.donation(roomId, can, message, "Bearer ${SharedPreferenceManager.token}") repository.donation(roomId, can, message, isSecret, "Bearer ${SharedPreferenceManager.token}")
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe( .subscribe(

View File

@ -304,6 +304,11 @@ data class LiveRoomDonationChat(
itemBinding.llMessageBg.setPadding(0) itemBinding.llMessageBg.setPadding(0)
itemBinding.llMessageBg.background = null itemBinding.llMessageBg.background = null
if (spChat.contains("비밀")) {
itemBinding.root.setBackgroundResource(
R.drawable.bg_round_corner_6_7_cc333333
)
} else {
itemBinding.root.setBackgroundResource( itemBinding.root.setBackgroundResource(
when { when {
can >= 10000 -> { can >= 10000 -> {
@ -335,6 +340,7 @@ data class LiveRoomDonationChat(
} }
} }
) )
}
itemBinding.root.setPadding(33) itemBinding.root.setPadding(33)
} }
} }

View File

@ -19,6 +19,9 @@ enum class LiveRoomChatRawMessageType {
@SerializedName("DONATION") @SerializedName("DONATION")
DONATION, DONATION,
@SerializedName("SECRET_DONATION")
SECRET_DONATION,
@SerializedName("SET_MANAGER") @SerializedName("SET_MANAGER")
SET_MANAGER, SET_MANAGER,

View File

@ -24,7 +24,8 @@ import kr.co.vividnext.sodalive.mypage.can.charge.CanChargeActivity
class LiveRoomDonationDialog( class LiveRoomDonationDialog(
private val activity: AppCompatActivity, private val activity: AppCompatActivity,
layoutInflater: LayoutInflater, layoutInflater: LayoutInflater,
onClickDonation: (Int, String) -> Unit isLiveDonation: Boolean = false,
onClickDonation: (Int, String, Boolean) -> Unit
) { ) {
private val bottomSheetDialog: BottomSheetDialog = BottomSheetDialog(activity) private val bottomSheetDialog: BottomSheetDialog = BottomSheetDialog(activity)
@ -53,7 +54,7 @@ class LiveRoomDonationDialog(
if (can > 0) { if (can > 0) {
bottomSheetDialog.dismiss() bottomSheetDialog.dismiss()
onClickDonation(can, message) onClickDonation(can, message, dialogView.chkSecret.isChecked)
} else { } else {
Toast.makeText( Toast.makeText(
activity, activity,
@ -70,6 +71,12 @@ class LiveRoomDonationDialog(
} }
} }
dialogView.rlSecret.visibility = if (isLiveDonation) {
View.VISIBLE
} else {
View.GONE
}
setupView() setupView()
} }

View File

@ -7,6 +7,7 @@ import com.google.gson.annotations.SerializedName
data class LiveRoomDonationRequest( data class LiveRoomDonationRequest(
@SerializedName("roomId") val roomId: Long, @SerializedName("roomId") val roomId: Long,
@SerializedName("can") val can: Int, @SerializedName("can") val can: Int,
@SerializedName("isSecret") val isSecret: Boolean,
@SerializedName("message") val message: String, @SerializedName("message") val message: String,
@SerializedName("container") val container: String @SerializedName("container") val container: String
) )

View File

@ -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_cc333333" />
<corners android:radius="6.7dp" />
<stroke
android:width="1dp"
android:color="@color/color_cc333333" />
</shape>

View File

@ -70,6 +70,26 @@
android:layout_marginVertical="16dp" android:layout_marginVertical="16dp"
android:background="@color/color_909090" /> android:background="@color/color_909090" />
<RelativeLayout
android:id="@+id/rl_secret"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="13.3dp"
android:visibility="gone">
<CheckBox
android:id="@+id/chk_secret"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:button="@drawable/ic_select"
android:fontFamily="@font/gmarket_sans_medium"
android:paddingHorizontal="8dp"
android:text="비밀후원"
android:textColor="@color/color_eeeeee" />
</RelativeLayout>
<EditText <EditText
android:id="@+id/et_donation_can" android:id="@+id/et_donation_can"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -55,6 +55,7 @@
<color name="color_cc59548f">#CC59548F</color> <color name="color_cc59548f">#CC59548F</color>
<color name="color_ccd38c38">#CCD38C38</color> <color name="color_ccd38c38">#CCD38C38</color>
<color name="color_ccd85e37">#CCD85E37</color> <color name="color_ccd85e37">#CCD85E37</color>
<color name="color_cc333333">#CC333333</color>
<color name="color_33ffffff">#33FFFFFF</color> <color name="color_33ffffff">#33FFFFFF</color>
<color name="color_303030">#303030</color> <color name="color_303030">#303030</color>
<color name="color_555555">#555555</color> <color name="color_555555">#555555</color>