diff --git a/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationDialog.java b/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationDialog.java index 9150ebdde..8ab1f7dcf 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationDialog.java +++ b/app/src/main/java/com/yizhuan/erban/avroom/dialog/RoomOperationDialog.java @@ -26,6 +26,7 @@ import com.yizhuan.erban.common.widget.dialog.DialogManager; import com.yizhuan.erban.ui.widget.marqueeview.Utils; import com.yizhuan.erban.ui.widget.recyclerview.decoration.ColorDecoration; import com.yizhuan.erban.ui.widget.recyclerview.layoutmanager.FullyGridLayoutManager; +import com.yizhuan.erban.vip.VipBroadcastDialog; import com.yizhuan.tutu.room_chat.activity.RoomInviteFansActivity; import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; @@ -114,6 +115,7 @@ public class RoomOperationDialog extends BottomSheetDialog { addInviteFansOptAdapter(); addSuperAdminAction(optAdapter); addSendBroadcastAction(optAdapter); + addVipSendBroadcastAction(optAdapter); rvOPtList.setAdapter(optAdapter); } @@ -529,6 +531,20 @@ public class RoomOperationDialog extends BottomSheetDialog { )); } + /** + * 超管管理 + */ + private void addVipSendBroadcastAction(OptAdapter optAdapter) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + optAdapter.addData(new OptAction(R.drawable.icon_room_vip_send_broadcast, + "房间小喇叭", + () -> VipBroadcastDialog.newInstance().show(context) + )); + } + @Override protected void onStop() { super.onStop(); diff --git a/app/src/main/java/com/yizhuan/erban/vip/VipBroadcastDialog.kt b/app/src/main/java/com/yizhuan/erban/vip/VipBroadcastDialog.kt new file mode 100644 index 000000000..ae03389b1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/vip/VipBroadcastDialog.kt @@ -0,0 +1,94 @@ +package com.yizhuan.erban.vip + +import android.annotation.SuppressLint +import android.os.Bundle +import androidx.core.view.isVisible +import androidx.fragment.app.viewModels +import com.yizhuan.erban.base.BaseActivity +import com.yizhuan.erban.base.BaseDialog +import com.yizhuan.erban.databinding.DialogVipBroadcastBinding +import com.yizhuan.xchat_android_core.utils.CurrentTimeUtils +import com.yizhuan.xchat_android_core.utils.toast +import io.reactivex.Observable +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.Disposable +import java.util.concurrent.TimeUnit + +class VipBroadcastDialog : BaseDialog() { + + companion object { + @JvmStatic + fun newInstance(): VipBroadcastDialog { + val args = Bundle() + val fragment = VipBroadcastDialog() + fragment.arguments = args + return fragment + } + } + + private val viewModel: VipViewModel by viewModels() + private var disposable: Disposable? = null + + @SuppressLint("SetTextI18n") + override fun init() { + binding.ivClose.setOnClickListener { dismissAllowingStateLoss() } + binding.ivSend.setOnClickListener { + if (binding.editContent.text.isNullOrBlank()) { + "请输入喇叭内容".toast() + } else { + viewModel.sendVipBroadcast(binding.editContent.text.toString()) + } + } + + viewModel.sendBroadcastLiveData.observe(viewLifecycleOwner) { + if (it == true) { + dismissAllowingStateLoss() + } + } + + if (activity != null && activity is BaseActivity) { + val manager = (activity as BaseActivity).dialogManager + viewModel.loadingLiveData.observe(viewLifecycleOwner) { + if (it == true) { + manager.showProgressDialog(activity) + } else { + manager.dismissDialog() + } + } + } + + viewModel.getVipBroadcastInfo() + viewModel.vipBroadcastInfoLiveData.observe(viewLifecycleOwner) { beanResult -> + if (beanResult.isSuccess) { + beanResult.data?.let { + binding.clRoot.isVisible = true + binding.tvSendLimit.text = "剩余次数${it.remainCount}/${it.totalCount}" + disposable?.dispose() + disposable = Observable.interval(0, 1, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { _ -> + val remainTime = + (CurrentTimeUtils.getCurrentTime() - it.lastSendTime) / 1000 + if (remainTime > 60) { + binding.tvSendTip.text = "发布后,1分钟内不可使用小喇叭~" + binding.ivSend.isEnabled = true + disposable?.dispose() + } else { + binding.ivSend.isEnabled = false + binding.tvSendTip.text = "${60 - remainTime}后可再次使用喇叭喊话~" + } + } + } + } else { + if (beanResult.code == 8710) { + (requireActivity() as BaseActivity).dialogManager.showOkDialog(beanResult.message) + } else { + beanResult.message.toast() + } + dismissAllowingStateLoss() + } + + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/vip/VipBroadcastView.kt b/app/src/main/java/com/yizhuan/erban/vip/VipBroadcastView.kt new file mode 100644 index 000000000..e729f5086 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/vip/VipBroadcastView.kt @@ -0,0 +1,75 @@ +package com.yizhuan.erban.vip + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.FrameLayout +import androidx.core.view.isGone +import androidx.core.view.isVisible +import androidx.lifecycle.Observer +import com.netease.nim.uikit.common.util.sys.ScreenUtil +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage +import com.yizhuan.erban.databinding.LayoutVipBroadcastViewBinding +import com.yizhuan.erban.ui.utils.ImageLoadUtils +import com.yizhuan.xchat_android_core.im.custom.bean.VipMessageAttachment +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager +import com.yizhuan.xchat_android_core.room.anotherroompk.ShowUserInfoDialogEvent +import com.yizhuan.xchat_android_core.utils.subAndReplaceDot +import com.yizhuan.xchat_android_library.rxbus.RxBus +import io.reactivex.Observable +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.Disposable +import java.util.concurrent.TimeUnit + +class VipBroadcastView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : FrameLayout(context, attrs, defStyleAttr) { + + private val binding = LayoutVipBroadcastViewBinding.inflate(LayoutInflater.from(context)) + private val observer = Observer { addMessage(it) } + private val messages: MutableList by lazy { ArrayList() } + private var disposable: Disposable? = null + + init { + addView(binding.root, LayoutParams(ScreenUtil.dip2px(268f), ScreenUtil.dip2px(32f))) + binding.llRoot.setOnClickListener { + RxBus.get().post(ShowUserInfoDialogEvent(binding.llRoot.tag as String)) + } + AvRoomDataManager.get().vipBroadcastLiveData.observeForever(observer) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + AvRoomDataManager.get().vipBroadcastLiveData.removeObserver(observer) + disposable?.dispose() + } + + private fun addMessage(chatRoomMessage: ChatRoomMessage) { + messages.add(chatRoomMessage) + isVisible = true + if (disposable == null || messages.size == 1) { + disposable = Observable.interval(0, 5, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .doOnDispose { isGone = true } + .takeWhile { messages.size > 0 } + .subscribe { + showMessage(messages.removeAt(0)) + } + } + } + + @SuppressLint("SetTextI18n") + private fun showMessage(chatRoomMessage: ChatRoomMessage?) { + val attachment = chatRoomMessage?.attachment as? VipMessageAttachment ?: return + attachment.vipMessageInfo?.let { + ImageLoadUtils.loadAvatar(it.avatar, binding.ivAvatar) + ImageLoadUtils.loadImage(context, it.vipIcon, binding.ivVipIcon) + binding.tvNick.text = it.nick.subAndReplaceDot(7) + ":" + binding.tvContent.text = it.content + binding.llRoot.tag = it.uid.toString() + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/vip/VipViewModel.kt b/app/src/main/java/com/yizhuan/erban/vip/VipViewModel.kt index 351e6fd07..3cef39747 100644 --- a/app/src/main/java/com/yizhuan/erban/vip/VipViewModel.kt +++ b/app/src/main/java/com/yizhuan/erban/vip/VipViewModel.kt @@ -3,9 +3,12 @@ package com.yizhuan.erban.vip import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.yizhuan.erban.base.BaseViewModel +import com.yizhuan.xchat_android_core.bean.response.BeanResult import com.yizhuan.xchat_android_core.user.UserModel +import com.yizhuan.xchat_android_core.utils.net.ServerException import com.yizhuan.xchat_android_core.utils.toast import com.yizhuan.xchat_android_core.vip.VipAuthInfo +import com.yizhuan.xchat_android_core.vip.VipBroadcastInfo import com.yizhuan.xchat_android_core.vip.VipInfo import com.yizhuan.xchat_android_core.vip.VipModel @@ -33,6 +36,12 @@ class VipViewModel : BaseViewModel() { private val _saveOriginDisguiseResult = MutableLiveData() val saveOriginDisguiseResult = _saveOriginDisguiseResult + private val _sendBroadcastLiveData = MutableLiveData() + val sendBroadcastLiveData: LiveData = _sendBroadcastLiveData + + private val _vipBroadcastInfoLiveData = MutableLiveData>() + val vipBroadcastInfoLiveData: LiveData> = _vipBroadcastInfoLiveData + fun getVipPageInfo() { _loadingLiveData.value = true safeLaunch( @@ -93,6 +102,36 @@ class VipViewModel : BaseViewModel() { ) } + fun getVipBroadcastInfo() { + _loadingLiveData.value = true + safeLaunch( + onError = { + _loadingLiveData.value = false + _vipBroadcastInfoLiveData.value = BeanResult.failed(it) + }, + block = { + _loadingLiveData.value = false + _vipBroadcastInfoLiveData.value = BeanResult.success(VipModel.getVipBroadcastInfo()) + } + ) + } + + fun sendVipBroadcast(content: String) { + _loadingLiveData.value = true + safeLaunch( + onError = { + it.message.toast() + _loadingLiveData.value = false + _sendBroadcastLiveData.value = false + }, + block = { + VipModel.sendVipBroadcast(content) + _loadingLiveData.value = false + _sendBroadcastLiveData.value = true + } + ) + } + fun onItemSelect(position: Int) { _currVipInfoLiveData.value = vipInfosLiveData.value?.getOrNull(position) _pageLiveData.value = position diff --git a/app/src/main/res/drawable-xhdpi/bg_vip_broadcast_content.png b/app/src/main/res/drawable-xhdpi/bg_vip_broadcast_content.png new file mode 100644 index 000000000..71915fc27 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_vip_broadcast_content.png differ diff --git a/app/src/main/res/drawable-xhdpi/bg_vip_broadcast_message.png b/app/src/main/res/drawable-xhdpi/bg_vip_broadcast_message.png new file mode 100644 index 000000000..6c34d60a7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_vip_broadcast_message.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_vip_broadcast_send.png b/app/src/main/res/drawable-xhdpi/ic_vip_broadcast_send.png new file mode 100644 index 000000000..23eca8ac8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_vip_broadcast_send.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_room_vip_send_broadcast.png b/app/src/main/res/drawable-xhdpi/icon_room_vip_send_broadcast.png new file mode 100644 index 000000000..148d1e28a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_room_vip_send_broadcast.png differ diff --git a/app/src/main/res/layout/dialog_vip_broadcast.xml b/app/src/main/res/layout/dialog_vip_broadcast.xml new file mode 100644 index 000000000..dd62cfaab --- /dev/null +++ b/app/src/main/res/layout/dialog_vip_broadcast.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_vip_broadcast_view.xml b/app/src/main/res/layout/layout_vip_broadcast_view.xml new file mode 100644 index 000000000..e9c8d57bc --- /dev/null +++ b/app/src/main/res/layout/layout_vip_broadcast_view.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/module_mini_world/res/layout/fragment_av_room_game.xml b/app/src/module_mini_world/res/layout/fragment_av_room_game.xml index e2f92dbcc..25d6e6d40 100644 --- a/app/src/module_mini_world/res/layout/fragment_av_room_game.xml +++ b/app/src/module_mini_world/res/layout/fragment_av_room_game.xml @@ -160,12 +160,21 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/fl_speedy_message" - android:layout_below="@id/micro_view" + android:layout_below="@id/vip_broadcast_view" android:layout_marginStart="12dp" android:layout_marginTop="@dimen/dp_5" android:layout_marginEnd="90dp" android:layout_marginBottom="@dimen/dp_10" /> + + + + + ( + val isSuccess: Boolean, + val code: Int = 0, + val message: String? = null, + val data: T? = null +) { + companion object { + + fun success(data: T?): BeanResult { + return BeanResult(true, 0, "", data) + } + + fun failed(code: Int, message: String?): BeanResult { + return BeanResult(false, code, message, null) + } + + fun failed(throwable: Throwable): BeanResult { + return if (throwable is ServerException) { + failed(throwable.code, throwable.message) + } else { + failed(-1, "网络异常,请检查你的网络再试!") + } + } + } + +} + + + diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/im/custom/bean/CustomAttachment.java b/core/src/main/java/com/yizhuan/xchat_android_core/im/custom/bean/CustomAttachment.java index 19b53e644..41103c622 100644 --- a/core/src/main/java/com/yizhuan/xchat_android_core/im/custom/bean/CustomAttachment.java +++ b/core/src/main/java/com/yizhuan/xchat_android_core/im/custom/bean/CustomAttachment.java @@ -417,6 +417,7 @@ public class CustomAttachment implements MsgAttachment { public static final int CUSTOM_MSG_VIP_ROOM_OPEN = 851; // 开通贵族房内消息 public static final int CUSTOM_MSG_VIP_ROOM_UPGRADE = 853; // 贵族升级房内消息 public static final int CUSTOM_MSG_VIP_ROOM_ALL_UPGRADE = 856; // 贵族升级全服房间公屏通知消息 + public static final int CUSTOM_MSG_VIP_ROOM_BROADCAST = 857; // 贵族小喇叭消息 public static final int CUSTOM_MSG_VIP_SELF_OPEN = 852; // 开通贵族成功系统消息 public static final int CUSTOM_MSG_VIP_SELF_UPGRADE = 854; // 贵族升级系统消息 diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/manager/AvRoomDataManager.java b/core/src/main/java/com/yizhuan/xchat_android_core/manager/AvRoomDataManager.java index 8ee6c2b40..bd3437c42 100644 --- a/core/src/main/java/com/yizhuan/xchat_android_core/manager/AvRoomDataManager.java +++ b/core/src/main/java/com/yizhuan/xchat_android_core/manager/AvRoomDataManager.java @@ -82,6 +82,8 @@ public final class AvRoomDataManager { @NonNull public final List roomSuperAdminList = new ArrayList<>(); public final MutableLiveData roomPkLiveData = new MutableLiveData<>(); + @NonNull + public final MutableLiveData vipBroadcastLiveData = new MutableLiveData<>(); @Nullable public RoomInfo mCurrentRoomInfo; public BoxSwitchVo mBoxSwitchVo; diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/vip/VipBroadcastInfo.kt b/core/src/main/java/com/yizhuan/xchat_android_core/vip/VipBroadcastInfo.kt new file mode 100644 index 000000000..226dd811e --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/vip/VipBroadcastInfo.kt @@ -0,0 +1,9 @@ +package com.yizhuan.xchat_android_core.vip + +import java.io.Serializable + +data class VipBroadcastInfo( + val lastSendTime: Long = 0L, + val remainCount: Int = 0, + val totalCount: Int = 0, +) : Serializable diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/vip/VipMessageInfo.java b/core/src/main/java/com/yizhuan/xchat_android_core/vip/VipMessageInfo.java index 704e19802..92a3d4217 100644 --- a/core/src/main/java/com/yizhuan/xchat_android_core/vip/VipMessageInfo.java +++ b/core/src/main/java/com/yizhuan/xchat_android_core/vip/VipMessageInfo.java @@ -12,4 +12,6 @@ public class VipMessageInfo { private String preVipName; private long roomUid; private String floatPic; + private String content; + private String vipIcon; } \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/vip/VipModel.kt b/core/src/main/java/com/yizhuan/xchat_android_core/vip/VipModel.kt index 2f04014d3..a2ae55851 100644 --- a/core/src/main/java/com/yizhuan/xchat_android_core/vip/VipModel.kt +++ b/core/src/main/java/com/yizhuan/xchat_android_core/vip/VipModel.kt @@ -2,9 +2,11 @@ package com.yizhuan.xchat_android_core.vip import com.yizhuan.xchat_android_core.base.BaseModel import com.yizhuan.xchat_android_core.bean.response.ServiceResult +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager import com.yizhuan.xchat_android_core.utils.net.launchRequest import com.yizhuan.xchat_android_library.net.rxnet.RxNet import retrofit2.http.GET +import retrofit2.http.Query object VipModel : BaseModel() { @@ -15,11 +17,21 @@ object VipModel : BaseModel() { api.getVipPageInfo() } - suspend fun saveOriginDisguise():Any? = + suspend fun saveOriginDisguise(): Any? = launchRequest { api.saveOriginDisguise() } + suspend fun getVipBroadcastInfo(): VipBroadcastInfo? = + launchRequest { + api.getVipBroadcastInfo(AvRoomDataManager.get().roomUid) + } + + suspend fun sendVipBroadcast(content: String): String? = + launchRequest { + api.sendVipBroadcast(content, AvRoomDataManager.get().roomUid) + } + private interface Api { @@ -38,6 +50,26 @@ object VipModel : BaseModel() { @GET("/vip/recoveryDress") suspend fun saveOriginDisguise(): ServiceResult + + + /** + * 获取用户贵族房间小喇叭信息 + * + * @return + */ + @GET("/vip/getUserVipRoomHorn") + suspend fun getVipBroadcastInfo(@Query("roomUid") roomUid: Long): ServiceResult + + /** + * 发送贵族房内小喇叭 + * + * @return + */ + @GET("/vip/sendRoomHorn") + suspend fun sendVipBroadcast( + @Query("content") content: String, + @Query("roomUid") roomUid: Long + ): ServiceResult } } \ No newline at end of file